mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-08 01:16:45 +08:00
admin-workspace-create2
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b30a3ae55c |
MUL-6164 feat(runtime): take an unusable agent CLI offline and refuse its triggers with the fix (#6966)
* fix(daemon): take a runtime offline when its CLI cannot be executed (MUL-6164) A CLI that cannot exec was classified as a transient probe failure, so the runtime stayed online and every task it claimed died at fork/exec. The user in MUL-6164 hit the same error once per task with no signal that the runtime was the problem — an npm placeholder stub passes exec.LookPath, so nothing else the daemon checks can tell it apart from a working install. ENOEXEC (and its Windows spelling, ERROR_BAD_EXE_FORMAT) is a fact about the bytes on disk, not a hiccup: it will reproduce until someone reinstalls. Give it its own probe verdict and route it down the track below-minimum already uses — claim barrier, seq-stamped hold, deregistration — so the provider goes offline with its reason instead of collecting failed tasks. Recovery needs no new machinery: a demoted provider has no runtime, which puts it back in providersMissingRuntimes, and the first healthy probe clears the hold and lets converge register it again, with no restart. One thing the below-minimum track did not need: a confirmation window. The repair we tell users to run overwrites the bin entry in place, so a probe landing mid-copy sees a truncated file. Demotion therefore requires two sightings a window apart; a genuinely broken install pays one extra probe round, and a spurious verdict would in any case recover on its own. detectBuiltinRuntimes' second return value is now "providers condemned this round, with the evidence against them" rather than "below-minimum versions" — same shape, both kinds, and the value is the reason /health already shows. Co-authored-by: multica-agent <[email protected]> * feat(runtime): refuse triggers for an unusable agent CLI instead of queueing them silently (MUL-6164) Taking the runtime offline stopped the per-task failures, but it replaced them with silence: the next @mention or assignment queued as if the machine were merely asleep, and nothing ran for two hours until queued_expired. Waiting only makes sense when waiting is a plan — a sleeping laptop comes back on its own; a CLI that cannot be executed does not. dispatch/reason.go already draws exactly that line between runtime_offline ("bring the machine back, queued work waits") and agent_runtime_required ("nothing will ever claim this"), and warns that collapsing the two sends users to fix the wrong thing. This adds the third member of that family, runtime_unusable, and routes the new verdict to it end to end: - The daemon reports WHY on deregistration — a stable code plus the repair command read from the package's own manifest, since only that side knows the path. Stored on agent_runtime.metadata, which registration overwrites wholesale, so a repaired runtime drops the explanation structurally. - AgentReadiness now returns a verdict (available / waitable / blocked) instead of a bool plus prose, and the direct-agent trigger paths start consulting it — blocking ONLY on the blocked verdict, so an offline machine still queues. agentReadinessReasonCode, which re-derived the same code from agent state, is gone: one source, no drift. - Every path that refuses without a human watching the response leaves the reason on the issue: an assignment, or another agent's @mention. The interactive surfaces already carry the code back to the composer, which now localizes it in all four languages. Below-minimum keeps today's behaviour deliberately. It is equally futile to wait on, but changing when THAT refuses a trigger is a separate product decision. Co-authored-by: multica-agent <[email protected]> * fix(runtime): keep the unusable verdict through a late register, and repair Windows (MUL-6164 review) Two ways the refusal path failed to reach the user. The verdict could be erased by an older answer. A register whose request was still in flight across the demotion upserts the runtime row afterwards, and that upsert overwrites metadata wholesale — including the reason just stored. The local hold refuses the response correctly, but the cleanup that took the revived row offline again sent no reason, so the server ended up "offline, cause unknown". Every admission path reads that as "the machine will come back" and queues, which is exactly the behaviour this change exists to remove. The demotion record now keeps the structured cause and the revived-row cleanup re-attaches it per row. The regression test drives the real interleave — a register held inside the server handler across the verdict — and fails without the fix. The repair command was POSIX-only. Windows had just gained detection (ERROR_BAD_EXE_FORMAT), so a Windows user was correctly refused and then handed `cd 'C:\...' && node install.cjs`: cmd.exe treats the quotes literally and PowerShell 5.1 has no `&&`. The command is now rendered for the shell of the machine that reported it — Set-Location on two lines for PowerShell, with PowerShell's own quote escaping — and carries that shell so the notice fences it truthfully instead of labelling everything bash. Also corrected the notice's own docs: it is written for every author, not only unattended ones. The chip and toast carry the reason code but not the repair command, so a human needs the durable copy too. The behaviour was already this; the comment claimed otherwise. Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: Bohan-J <[email protected]> Co-authored-by: multica-agent <[email protected]> |
||
|
|
f51ee62b53 |
MUL-6164 fix(agent): diagnose an unrunnable agent CLI instead of leaking "exec format error" (#6963)
* fix(agent): diagnose an unrunnable agent CLI instead of leaking "exec format error" (MUL-6164) npm-distributed agent CLIs ship a placeholder text stub at their bin entry point and rely on a postinstall script to overwrite it with the platform-native binary. npm 12 blocks install scripts unless allowlisted, pnpm 10 needs `pnpm approve-builds`, and --ignore-scripts / --omit=optional do the same — all of them leave the stub in place with its executable bit set. exec.LookPath accepts it, execve rejects it, so the CLI reads as installed everywhere the daemon looks and only fails at launch with a bare "start claude: fork/exec <path>: exec format error". Add ExplainExecError: on ENOEXEC it names the path, the owning npm package, and the exact repair command read out of that package's own scripts.postinstall. The executable path is recovered from the error itself, so this is one provider-agnostic call at each boundary — the shared version probe and the daemon's single backend.Execute site — rather than a wrap in every backend. claude and opencode ship this layout today; a CLI added later is covered without a code change. Also classify "exec format error" as runtime_missing_executable: a stub that cannot exec means this host has no usable CLI, and that reason already tells the daemon a fresh-session retry cannot help. Co-authored-by: multica-agent <[email protected]> * fix(agent): keep the ENOEXEC diagnosis to one copy (MUL-6164 review) The openclaw preflight explained the error, then returned it through openclawBackend.Execute into the daemon's launch boundary, which explained it again — %w keeps ENOEXEC reachable, so the second pass fired and the user got the same paragraph twice. Drop the openclaw wrap: its error already travels through the daemon boundary, so the extra site bought nothing. Make ExplainExecError idempotent as well, so the next nested boundary cannot reintroduce the same regression silently. Also quote the package root properly in the repair command — it is meant to be pasted into a shell, and a path holding a quote or a space has to survive that. The chat copy for runtime_missing_executable said the CLI "couldn't be found / check it's on PATH", which is the opposite of this failure: the file is right there on PATH and cannot run. Reworded to cover both across all four locales; the compact labels ("Runner CLI not installed") are left for the follow-up that reworks the reason's presentation. Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: Bohan-J <[email protected]> Co-authored-by: multica-agent <[email protected]> |