Commit Graph
400 Commits
Author SHA1 Message Date
73f5664ca4 MUL-8263 fix(agents): reject reserved custom arguments on save (#9560)
* fix(agents): reject reserved custom arguments on save

* fix(agents): validate OMP session arguments before saving

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:59:25 +08:00
bcf40040e0 MUL-8233: fix Pi cancellation and guard unconfirmed cleanup (#9557)
* fix(agent): join Pi cancellation cleanup and guard continuation

Co-authored-by: multica-agent <[email protected]>

* fix(agent): preserve Pi completion and negotiate cleanup

Co-authored-by: multica-agent <[email protected]>

* perf(agent): avoid Pi exit delay and index cleanup guards

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:37:13 +08:00
小七 ff6d3207c8 fix(agent): keep per-run usage when Claude resume baseline capture fails (#9567)
When a resume's baseline capture fails, the result event's modelUsage
was stored as the task's usage as-is. On newer Claude Code a resumed
session restores its cumulative counters, so that reported total spans
every prior task in the session: the #8781 inflation returned for every
baseline-unavailable mode. The reported trigger is a custom runtime
profile whose command is a wrapper script that sets CLAUDE_CONFIG_DIR
internally - the daemon resolves the transcript from its own env
(os.Environ() + agent custom_env) and never sees it, so every resume
logged 'claude usage baseline unavailable' and stored the running
session total (observed ~10x on a session's 7th task).

The code already distinguishes a transcript that exists but has no
cost-state (older Claude Code reports per-run totals there; behavior
preserved, pinned by existing tests) from one that cannot be found at
all. For the latter the reported modelUsage is now treated as
non-authoritative: usage keeps the stream-derived per-run totals, and
the reported totals are only recorded for the resume-rejected recapture
where the run is known to have started a fresh session of its own.
Affected modes now degrade to a conservative per-run approximation
instead of silently storing a cumulative total; the WRN stays, reworded
to say what actually happens.

Out of scope, per the adjudication on the issue: per-profile env vars
(schema/feature) and expanding $HOME/~ in custom_env values (makes the
manual workaround portable but leaves the default inflation path live).

Ablation: reverting only server/pkg/agent/claude.go on this branch makes
both new tests fail again with the cumulative total stored
(700/30/800/80 instead of the per-run 70/0/80/8).

Fixes #9564

Generated-by: GLM-5.3-Flash (ZCode)
2026-10-27 12:27:02 +08:00
Dante 2de89ff46e MUL-8244: fix(agent): preserve recovered Antigravity stream responses (#9534)
* fix(agent): tolerate recovered Antigravity stream interruptions

* fix(agent): preserve failed Antigravity interruptions
2026-10-26 16:30:18 +08:00
e8fdcfd226 MUL-6623 feat(agent): add host-local Devin CLI over ACP (#7485)
* feat(agent): add host-local Devin CLI over ACP

Spawn `devin acp` via the shared ACP client. Local CLI only — not
cloud Devin VMs/Playbooks/Secrets. Model via `devin acp --model`.
Catalog from `devin models list --format json` (families/variants).

* fix: skip Devin ACP handshake when browser auth is also offered

* fix: close dim case string so Devin compiles

Missing quote after dim broke runtime_config.go and every Go CI job.

* fix: stop runtimeConfigPath recursion on Devin

Devin is a builtin whose ProtocolFamily is itself. Recursing on that
overflowed the stack and killed backend-tests.

* test(agent): cover Devin model failures and final-answer delivery

Co-authored-by: multica-agent <[email protected]>

* fix(agent): honor Devin model aliases and stored login (MUL-6623)

Co-authored-by: multica-agent <[email protected]>

* fix(agent): drain Kiro panic details before terminating runtime (MUL-6623)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:11:05 +08:00
b5477490e4 MUL-7376: fix(openclaw): preserve agent identity with persistent model overrides (#9223)
* fix(openclaw): carry per-run model override on the run input (INFRA-71)

Reimplement MUL-7376 (#8419) on this fork and address the review points.

Resolve runtime_config.model_override once, at claim time, and carry it on the run input (model_override); the daemon no longer decodes it from mutable agent config.

OpenClaw keeps agent.model as the registered agent id (--agent) and the override as the underlying model (--model); arbitrary --model from custom_args stays blocked. Usage attribution falls back runtime model -> per-run override -> unknown, never the agent id.

Round-trip model_override through the runtime-config schema, serializer, equality check and the runtime-config tab (i18n in all locales). Docs updated.

Co-authored-by: multica-agent <[email protected]>

* docs(openclaw): clarify persistent agent model overrides

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
Co-authored-by: Multica Eve <[email protected]>
2026-10-26 13:41:04 +08:00
Andrei a47a1ced0c MUL-8240: fix(agent): keep Codex commentary out of output on empty final answer (#9521)
* fix(agent): keep Codex commentary out of output on empty final answer

* test: pin empty-output completion and single result delivery
2026-10-26 12:37:34 +08:00
76dfd4a58b MUL-8186: treat process exit as terminal signal on OpenCode 2.x (#9463)
* fix(opencode): treat process exit as the terminal signal on 2.x

OpenCode 2.x stops consuming step events once the session settles, so the
final step_finish is routinely never written. The daemon failed those
completed runs as 'step still open at EOF' / 'continuation never started',
classified them provider_network and auto-retried, repeating side effects.

On built-in 2.x runtimes, waive the two step-bracketing guards and let the
process outcome decide: exit code, error events, prompt write, cancel /
timeout and scanner errors still fail the run. The void-step guard stays.
1.x and custom runtimes are unchanged.

Also decode the 2.x error payload ({type, message}) so failures surface
their real cause instead of 'unknown opencode error'.

Refs #8892, #9456

Co-authored-by: multica-agent <[email protected]>

* fix(opencode): address review on 2.x terminal-signal relaxation

- Clear the void-step flag on 2.x once later text or a tool call shows the
  run recovered, since the recovering step may never report step_finish.
  1.x still requires that step to close.
- Never report stream-level completion (sawTerminalSignal) on 2.x: an
  intermediate step_finish is not proof the run finished, so a failed
  prompt write keeps failing the run.

Refs #9463

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-23 14:45:50 +08:00
04931df162 MUL-8174: fix OpenCode resume after host clock rollback (#9460)
* fix(opencode): retire future-dated resume sessions (MUL-8174)

Co-authored-by: multica-agent <[email protected]>

* fix(opencode): check resume clocks across CLI versions

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-23 14:41:13 +08:00
Multica Eveandmultica-agent 79d801f45c MUL-8188: fail fast on Kiro panic and stop resuming undrivable sessions (#9458)
* fix(kiro): fail fast when the runtime panics mid-turn (MUL-8188)

Kiro can panic inside its agent loop while the ACP process stays alive, so
session/prompt never answered and the task hung until the 2h idle watchdog
or a manual cancel. Watch stderr live for a panic header, abort the prompt,
and surface the panic text. A resumed session that panics before its first
message signals ResumeRejected so the daemon retries once on a fresh session.

Co-authored-by: multica-agent <[email protected]>

* fix(resume): stop re-resuming sessions the runtime cannot drive (MUL-8188)

- taskfailure.UnresumableHistory matches "invalid conversation history",
  so the daemon's fresh-session retry, classifyPoisonedError and
  ResumeUnsafeFailure all treat Kiro's panic as resume-unsafe; the
  GetLastTaskSession / GetLastChatTaskSession text guards mirror it for
  rows written by older daemons.
- A resumed run cancelled after >=5 minutes with zero agent output now
  retires its session: the daemon sends retired_session_id on cancel-ack
  and the server records it on the cancelled row (status CAS, never
  overwrites) and clears a chat pointer still naming it.

Co-authored-by: multica-agent <[email protected]>

* fix(resume): address review on retired sessions (MUL-8188)

- Manual retry no longer revives a retired session: the exact-source rerun
  claim path now checks IsTaskSessionRetired (fails closed), still reuses
  the source workdir, and sets PriorSessionResumeUnavailable.
- Silent-resume retirement measures awakeclock time, so host suspend
  (Windows monotonic clock counts through sleep) cannot retire a healthy
  session; adds a suspend regression test.
- Handler tests use dbfx.Issue/Task and testutil.Call per AGENTS.md.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-23 12:03:19 +08:00
Tim f9036be46a MUL-8184 Fix Hermes reasoning options for non-default models (#9452)
* fix(agent): discover Hermes reasoning options per model

* refactor(agent): extract per-model ACP effort probe

Move the discovery loop out of discoverACPModels into probeACPModelEffort
beside the other ACP effort helpers, and have acpOptionsAfterModelSwitch
return nil when the runtime exposes no post-switch state so callers no
longer re-check the response. Hermes execution only refreshes options when
a thinking level is set, which is the only consumer of the result.

* test(agent): trim Hermes effort regression tests
2026-10-23 07:54:42 +08:00
Multica Eveandmultica-agent 88de9d3713 feat(agent): surface Hermes dependency reinstall at launch (MUL-8124) (#9434)
* feat(agent): surface Hermes dependency reinstall at launch (MUL-8124, GH #9390)

Hermes prints its launch-time dependency sync only to stderr, which the
daemon forwards at Debug, so the 30-60s rebuild that the per-task Hermes
home triggers when the user's home enables a memory plugin with Python
deps was invisible. Log one Warn when Hermes starts reinstalling (with
HERMES_HOME and a hint) and one when the ACP handshake returns, with
the measured startup delay. Task outcome is unchanged.

Document the cause and the memory.provider workaround in troubleshooting.

Co-authored-by: multica-agent <[email protected]>

* fix(agent): log Hermes reinstall finish when stderr lags the handshake (MUL-8124)

stdout and stderr are drained independently, so initialize can return
before the stderr copier reaches the reinstall marker Hermes wrote
first. Finish then saw no detection and the finish log was lost.

Record the handshake result and time in Finish, and emit the finish log
when the second of (marker, handshake) arrives. Measure the delay from
launch to handshake so it no longer depends on pipe ordering. Adds the
reviewer's repro as an Execute-level regression test plus a unit test.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-22 18:59:58 +08:00
4b645a354c fix(agent): clarify opaque Kimi turn failures (MUL-8157) (#9431)
Co-authored-by: Yushen <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-22 16:20:15 +08:00
mrlonely 2b6db0d2b8 fix(cursor): resume stalled provider connections with bounded retries (MUL-7968) (#9180)
* fix(cursor): recover stalled provider connections with session resume

* fix(cursor): exclude diagnostic counts from provider error classification

* fix(cursor): ignore stack locations when classifying transport errors
2026-10-22 09:20:44 +08:00
0fe2ebf02e MUL-8045: feat(runtimes): Qoder Cloud Agent as a managed cloud runtime (#9402)
* feat(runtimes): add Qoder Cloud Agent managed remote execution

* fix(qoder): satisfy migration and localization CI contracts

* fix(qoder): bound execution and scope managed credentials

* fix(qoder): avoid upstream migration number collisions

* fix(qoder): gate issue creation and correlate tool results

* fix(qoder): synchronize guarded issue lifecycle transitions

* test(agent): publish Hermes holder identity atomically

* feat(agents): runtime-first create flow and cloud runtimes section for Qoder Cloud Agent

- Three-step create-agent flow (runtime -> configure -> done) with local,
  remote and cloud sections; Qoder connect form inline in the runtime step
- Runtimes page regrouped into remote and cloud sections with Qoder card
- Generalize Qoder storage to cloud_agent_connection (migrations 586/587)
- Locales for en, zh-Hans, ja, ko, fr; desktop and web routes for done step
- Fix status-picker fixture owner_id and diagnostics route coverage after main merge

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(runtimes): unify runtimes page into machines and cloud services

- One Add menu replaces Add remote runtime, the duplicated Add a computer
  and the web-only Cloud Runtime header button
- Group by machines / cloud services instead of local / remote / cloud, so
  web and desktop share one structure; this device is pinned with a badge
- Cloud services use the machine row anatomy in a single ListGrid table;
  unconnected Qoder is a row with Connect, coming-soon providers are rows
- Empty groups show the next step inline; search and online/offline filter
- Rename computer to machine across runtimes copy in all locales

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* test(runtimes): cover unified runtimes page; pin status and action tracks

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* refactor(runtimes): trim redundant descriptive copy on runtimes page

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(runtimes): keep row actions visible at narrow widths

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* refactor(runtimes): align Qoder add-menu item with other cloud services

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(runtimes): close the Qoder dialog after a first-time connection

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(agents): pick the runtime from one grouped list

The runtime step showed four kinds of cards, a comparison panel and
per-section descriptions. It is now one list in the runtimes-page layout:
machines (this one open, others folded to a row) and cloud services. An
unconnected Qoder opens the runtimes-page connect dialog in place and is
selected once it comes online.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): show owners as 'you' and bare version numbers in the runtime list

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(qoder): disconnect action and dedicated Qoder runtime page

Disconnect removes the encrypted connection and the managed runtime, unbinding
its agents after the admin confirms them. The Qoder row now opens its own page
(status, agents, usage, configuration, pause/resume, disconnect) instead of the
machine layout; generic runtime delete and visibility refuse a managed runtime.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): land on the done page after creating from step 2 on desktop

Desktop's location is the tab URL, which moves to /agents/new/done/<id>
while the configure page is still mounted. Its missing ?runtime= tripped
the skipped-step-1 redirect and replaced the tab back to /agents/new, so
Create looked like it did nothing. Only redirect on the manual route.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): show only settings a Qoder agent can run with

The Qoder bridge fails every task whose agent carries a model, thinking or
speed override, env, custom args, custom skills, MCP config or connected
apps, and it runs issues only. The agent detail page still offered all of
those editors, so one save could break every later run.

For a qoder_cloud agent the page now keeps Instructions under Capabilities,
General / Access / QCA Agent under Settings, drops the model rows and the
header model chip, shows the QCA agent in the summary, and locks the
runtime. Other agents no longer see the Qoder runtime in their picker,
since moving onto it needs a QCA agent the server would otherwise reject.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): hide conversation starters for Qoder agents

Starters only appear in a chat, and the Qoder bridge runs issues only.
The create flow already leaves them out for this runtime.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* feat(runtimes): show the Qoder connection as cards with per-section editing

The Qoder runtime page rendered the whole connection as one always-editable
form. It now summarizes the connection, repositories and limits as read-only
cards; each section opens its own dialog and saves only that section.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(qoder): reuse a follow-up session only with the same repository and credential

Resolve repository credentials before deciding to continue a prior session,
and stamp each session with a fingerprint of its repositories, branches and
tokens. A follow-up continues only when the fingerprint still matches, so a
changed repository, branch or rotated/revoked token never rides into an old
session.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(qoder): keep a paused connection paused when its settings are saved

Saving repositories, limits or the connection no longer re-enables a paused
runtime. Resume goes through a new POST /qoder/resume.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): drop settings a Qoder agent cannot run when creating one

A draft started on another runtime could carry hidden skills, model
overrides and starters into a Qoder agent that then failed every task. The
create request now drops them for Qoder, and the API rejects skills and
execution overrides on Qoder agents at save time.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* chore(db): regenerate sqlc models for cloud_agent_connection

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(runtimes): never list the Qoder runtime under Machines

When the server could not run Qoder (no MULTICA_VCS_SECRET_KEY /
MULTICA_QODER_STATE_DIR), the managed Qoder runtime fell back into the
Machines group as if it were a computer.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* refactor(qoder): drop MULTICA_QODER_STATE_DIR

The managed bridge keeps its run journal encrypted in cloud_agent_connection
and a database advisory lock already elects one supervisor, so the state
directory only held a redundant file lock and acted as a feature switch.
Qoder is now available whenever MULTICA_VCS_SECRET_KEY is set. The
standalone qoder-runtime command still uses its on-disk state_dir.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(qoder): keep the branch in the session fingerprint after a journal restore

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* fix(agents): validate Qoder agents' effective settings on every write

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: 安辰 <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-22 01:33:38 +08:00
Multica Eveandmultica-agent 2b64569138 MUL-8126: feat(agent): steer running Kiro turns via _session/steer (#9396)
* feat(agent): support steering running Kiro turns via _session/steer

Kiro CLI 2.33.0 exposes an undocumented ACP extension, _session/steer,
that queues a message and injects it into the in-flight session/prompt at
the next tool or message boundary. Wire it up as the kiro backend's
Session.Supplement (active only while the prompt is in flight, and only
when the daemon negotiated task supplements), and gate kiro >= 2.33.0 in
SupportsTaskSupplement.

MUL-8126

Co-authored-by: multica-agent <[email protected]>

* fix(supplement): allow kiro in server-side steering whitelists

The capability handshake (StartAgentTaskWithSupplement), direct steering
(CreateTaskSupplement) and composer reply binding (BindCommentTaskSupplement)
each whitelist providers, and none included kiro, so a negotiated Kiro run
never got a capability row and steering stayed unreachable. Add kiro to all
three, regenerate sqlc, and cover kiro in the negotiation and both delivery
path tests. Also widen the kiro supplement test's readiness wait, which was
flaky under full-package parallel load.

MUL-8126

Co-authored-by: multica-agent <[email protected]>

* fix(supplement): allow grok in composer reply binding

BindCommentTaskSupplement was the only steering whitelist without grok, so
a reply from the normal composer to a running Grok turn fell back to the
next run even though direct steering worked. Add grok and cover it in the
composer binding test.

MUL-8126

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-21 19:01:56 +08:00
984d8192ad fix(daemon): preserve Claude effort for unlisted models (MUL-8112) (#9392)
Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-21 16:59:16 +08:00
ZIceandmultica-agent 4152fed89f fix(opencode): discover v2 model thinking variants (ZIC-351) (#9365)
Co-authored-by: multica-agent <[email protected]>
2026-10-21 13:40:24 +08:00
Multica Eveandmultica-agent 74281e313d fix(agent): deliver the copilot prompt on stdin (MUL-8105) (#9380)
* fix(agent): deliver the copilot prompt on stdin; name E2BIG start failures (MUL-8105)

Copilot inlined the whole task prompt as -p <prompt>, so a thread above Linux's 131,072-byte MAX_ARG_STRLEN died at fork/exec with E2BIG (#9362). The prompt now rides stdin, mirroring the OpenCode move in #6552. startOwnedProcessTree also wraps oversized-command-line failures in ErrArgvLimitExceeded with an actionable remedy.

Co-authored-by: multica-agent <[email protected]>

* docs(agent): update copilotBackend comment for stdin prompt delivery (MUL-8105)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-21 12:26:50 +08:00
Basuotianandmultica-agent 5b21b63fa8 fix(codex): attribute default-model usage (#9360)
Co-authored-by: multica-agent <[email protected]>
2026-10-21 09:58:36 +08:00
Dante eb0e0824fd fix(agent): honor Claude supplement handshake budget (#9252) 2026-10-19 02:04:55 -04:00
88f6d6272b MUL-8057: feat(agent): run Meta Muse Code as an MSP runtime (#9309)
* feat(agent): run Meta Muse Code as an MSP runtime

Muse Code speaks MSP (Muse Session Protocol) over `muse serve`: JSON-RPC
2.0 on stdio, like ACP, but with its own method vocabulary. A session opens
with session/start or session/resume, work is submitted with turn/start, and
assistant text, reasoning and tool calls arrive as transcript items.

The adapter maps those items onto the Backend contract, reads the terminal
turn outcome, and reports a notFound resume as ResumeRejected so the daemon
retries on a fresh session instead of losing continuity silently.

Approval is a session property, not a launch flag: `muse serve` has no
--yolo, and the CLI documents --yolo as TUI-only. A fresh session is created
with approvalMode=allowAll and a resumed session re-asserts it with
session/setApprovalMode, which is what lets a claimed task run without
waiting for a human. The container and per-task worktree remain the
isolation boundary, as they are for every other backend.

commandId must be UUIDv7 — Muse derives a turn id from it and rejects
anything else — so the adapter mints time-ordered ids rather than v4.

The model catalog comes from the session-free model/list query and the pick
is applied through session/start modelId.

* feat(runtime-profiles): allow muse as a protocol family

A custom runtime profile may only be based on a protocol family the daemon
supports, and the database enforces the same list. Widening both keeps the
create flow, the server validation and the CHECK constraint in lockstep with
agent.SupportedTypes.

* fix(muse): complete runtime integration and lifecycle handling (MUL-8057)

Co-authored-by: multica-agent <[email protected]>

* docs(muse): document runtime setup and support (MUL-8057)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: yushen <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-19 13:45:42 +08:00
dfa8bdaa53 MUL-8070: feat(cursor): support live-run steering via Cursor hooks (#9322)
* MUL-8070: feat(cursor): support live-run steering via Cursor hooks

Cursor's headless --print mode has no mid-turn input channel, but its
postToolUse/postToolUseFailure hooks can return additional_context that
reaches the model in the same turn. A steerable Cursor run now writes a
managed .cursor/hooks.json whose command is the multica binary in a hidden
relay mode; the relay forwards the hook event to a token-protected loopback
endpoint owned by the run, which hands back pending guidance tagged with a
per-run nonce. The prompt declares that tag so the model treats the context
as genuine user guidance instead of a prompt injection.

Steering is offered only for daemon-managed workdirs on Unix with cursor-agent
2026.10.14+, and the server allowlists cursor for capability negotiation,
supplement creation and composer binding.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* MUL-8070: fix(cursor): confirm steering only on Cursor's receipt and gate on installable hooks

- Count hook-delivered guidance as delivered only when the tool call's
  completed stream event echoes it in hookAdditionalContexts. Guidance
  Cursor dropped for the same call is retried at the next tool boundary;
  guidance without a receipt fails when the turn ends.
- Offer steering only when the workdir can carry the managed hooks.json,
  and fail supplements immediately if installation still fails after
  negotiation.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-18 16:23:05 +08:00
Jiayuan Zhangandmultica-agent 231dedb552 MUL-8034: chore: clean historical comments across the codebase (#9274)
* chore: clean historical comments (MUL-8034)

Co-authored-by: multica-agent <[email protected]>

* docs: preserve pending Composio expiry contract

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-15 21:54:33 +08:00
74ff8aabd7 MUL-7983: fix(agent): handle CodeBuddy startup errors without aborting active runs (#9214)
* fix(agent): fail codebuddy runs that emit a top-level error event

CodeBuddy's startup-failure shape is one top-level {"type":"error"}
line followed by a process that stays alive and silent: with an
inherited SERVER__PORT (a user-scope config shared by several tools),
a second concurrent run of the same agent fails to listen, prints
{"type":"error","error":"listen EADDRINUSE: ..."} and never emits
anything again. The parser had no branch for that event type, so the
run sat at "waiting for agent response" until the idle watchdog
stopped it - 19 of 48 runs hung this way on the reporter's machine.

- type=error is now fatal when no terminal result has been seen: the
  CLI's own message becomes the run error and the hung process is torn
  down immediately instead of idling. A result already seen keeps
  governing the outcome, so a late informational error line cannot
  flip a finished run.
- buildCodebuddyEnv now also forces SERVER__PORT=0 (OS-assigned port
  per run, so concurrent runs never share one) and
  CODEBUDDY_BASH_AUTO_BACKGROUND_DISABLED=1 (CodeBuddy's PowerShell
  tool moves timed-out commands to the background and only honors that
  variable). Both are appended last like the existing background-task
  disable so a caller-provided value cannot outvote them.

Fixes #9200

Generated-by: GLM-5.3-Flash (ZCode)

* fix(agent): keep CodeBuddy running after recoverable errors

MUL-7983

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Yushen <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-13 13:54:24 +08:00
Multica Eveandmultica-agent b115ec80f1 MUL-7851: fix(daemon): don't count host sleep as idle-watchdog silence (#9201)
* fix(daemon): don't count host sleep as agent silence in idle watchdog (#9024)

The idle watchdog stamped activity in wall-clock unix nanos, so a laptop
that slept past the idle window woke up with every in-flight run already
over budget and force-stopped them all on the first tick.

Detect host suspend from the wall-clock gap between watchdog ticks and
credit that time back to lastActivityAt before each check, clamped to now.
Works the same on macOS/Linux (monotonic clock pauses in sleep) and
Windows (monotonic clock keeps counting), and covers the tool-in-flight
budget too since both read the same stamp.

MUL-7851

Co-authored-by: multica-agent <[email protected]>

* fix(daemon): measure idle watchdog on an awake-only clock (#9024)

Review on #9201 showed the tick-gap heuristic still charges sleep to the
agent: a sleep shorter than one tick is never credited, and when the
overdue tick fires on wake (Windows) only gap−tick is credited.

Replace it with pkg/awakeclock, a clock that only advances while the host
is awake: Go's monotonic clock on Linux/macOS (already stops in suspend),
minus host sleep on Windows (GetTickCount64 − QueryUnbiasedInterruptTime).
lastActivityAt, the drain loop stamp, and Cursor's native tool activity
(Session.ToolActivity now returns an awakeclock reading) all share it.

Regression tests cover both review boundaries plus a long sleep, each with
a wall-clock control that proves the scenario reproduces the bug.

MUL-7851

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-12 17:19:58 +08:00
8a2f518d54 fix(agent): MUL-7781 / MUL-7793 interrupt Codex turns after repeated Guardian 429s (#8934)
* fix(agent): stop Codex turns after repeated Guardian 429s

* fix(agent): recognize Codex Guardian rate-limit events

Use the app-server wire method and preserve semantic activity. Distinguish reviewer failures from policy denials, deduplicate recent reviews, and explain manual recovery after interruption.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Yin <[email protected]>
Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-12 14:18:02 +08:00
92d0b6666d MUL-7812: fix(agent): deliver MCP servers to Pi tasks (#9063)
* fix(agent): deliver MCP servers to Pi tasks

Pi skipped untrusted project config in JSON mode, and Multica never wrote .pi/mcp.json, so composed MCP servers never reached the runtime.

Co-authored-by: Cursor <[email protected]>

* fix(agent): hand Pi its MCP servers through a temporary extension

Writing .pi/mcp.json and passing --approve trusted the whole project directory and failed when that file already existed. An explicit --extension loads the servers without project trust.

Co-authored-by: Cursor <[email protected]>

* docs: mark Pi as reading agent MCP configuration

The provider comparison still said Pi skipped the MCP field. Pi now receives that configuration.

Co-authored-by: Cursor <[email protected]>

* fix(agent): harden Pi MCP registration

Co-authored-by: multica-agent <[email protected]>

* fix(agent): allow empty Pi MCP configuration

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: Yushen <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-12 13:26:00 +08:00
ZIceandmultica-agent 00e24a8ede fix(agent): create fresh OMP sessions without resume (#9131)
Co-authored-by: multica-agent <[email protected]>
2026-10-08 18:43:01 -07:00
小七 5063fc9079 MUL-7869: fix(agent): fail kimi runs whose wire log records a failed turn (#9057)
* fix(agent): fail kimi runs whose wire log records a failed turn

kimi's ACP adapter can answer session/prompt successfully while its own
turn failed: the session wire log carries a
{"type":"agent.turn.ended","outcome":"failed",...} record (e.g. a bare
"OAuthConnectionError: OAuth request to https://auth.kimi.com/api/oauth/
token failed" that matches none of the stderr sniffer's terminal
signatures). The run then kept status=completed and published the
intermediate narration as a successfully delivered result, so the daemon
sent no failure signal and retry/continuation policy never saw the
failure (#9054).

Fix: after the run, scan the session wire logs - the same source,
turn-boundary rules, and tolerant-line policy as the usage scan
(scanKimiSessionUsage) - for the main agent's failed agent.turn.ended
record, and promote completed->failed carrying kimi's sanitized
diagnostic. Only the structured outcome verdict counts, so conversation
text echoing failure words cannot flip a healthy run; a delegated
agent's failed turn stays that agent's own task path; timeout, abort,
and already-failed runs keep their own terminal semantics.

Complementary to #8573's zero-output guard: that incident shape had 26
tool calls and nonempty narration, which a zero-output guard
deliberately preserves.

Fixes #9054

Generated-by: GLM-5.3-Flash (ZCode)

* fix(kimi): sanitize the wire diagnostic and scan past oversized records

Review fixes for #9057 (CHANGES_REQUESTED, both repros offline with a
fake ACP; no live provider requests):

P1: kimiWireTurnFailure copied the record's errorMessage into the run's
diagnostic unsanitized. The failure path persists Result.Error, and the
shared redact.Text does not redact a quoted JSON credential shape
(request={"api_key":...}) — the sanitized diagnostic the PR described
was not actually provided. The diagnostic now goes through the same
sanitizeAgentDiagnostic pass as every child-process diagnostic before
it reaches Result.Error.

P2: the scan loop used newAgentStreamScanner, whose bufio.Scanner ends
its scan for good at a line beyond agentStreamMaxLineBytes, and the
loop never checked scanner.Err() — a valid but oversized context.append
record ahead of the terminal event hid the failed outcome and kept the
run completed. kimiWireTurnFailure now reads through
readAgentStreamLine, which consumes and discards an over-bound record
whole and keeps the later records readable, and ends the walk
explicitly on any other read failure (keeping what was read, the same
best-effort policy as a truncated tail).

Regressions, all red before the fix and green after:
- TestScanKimiMainTurnFailureSanitizesWireDiagnostic (P1)
- TestScanKimiMainTurnFailureReadsPastOversizedRecord (P2, scan level)
- TestKimiBackendWireTurnFailurePastOversizedRecord (P2, backend e2e
  with the fake ACP: red as got "completed" (error=""), the review's
  exact repro shape)
- TestReadAgentStreamLineSkipsOversizedAndContinues /
  TestReadAgentStreamLineReturnsUnterminatedTail (helper contract; the
  first caught a boundary miss where the cap was crossed only on the
  final buffer chunk)

Generated-by: GLM-5.3-Flash (ZCode)
2026-10-08 10:13:54 -07:00
bb14e8763c feat(issues): add multi_text and multi_url custom property types (MUL-7496) (#8559)
* feat(issues): add multi_text and multi_url custom property types

Workspaces could only hold list-shaped values as preset option lists
(multi_select) or member references (multi_actor). There was no way to
keep a list of free-form strings or links on an issue, so teams with
"related docs / spec links / aliases" needs had to either cram them into
one text field (no structure, nothing clickable) or burn one select
option per link.

This adds two property types:

- multi_text: an ordered list of free-form text entries
- multi_url: an ordered list of http(s) URLs

Each entry is validated exactly like a single text / url value
(length caps, http(s)-only for URLs), duplicates are dropped, insertion
order is preserved, and values are capped at 20 entries to respect the
16KB properties-bag budget. Values ride the existing jsonb bag, so the
jsonb_path_ops GIN index, the @> containment filter, and the client
value schema all keep working unchanged.

Filtering matches any single list element exactly (equality) plus "No
value" — the containment form the filter compiler already emits for
array elements, so no new server predicate is needed. List types
deliberately get no sort order and cannot group, like the other
multi-value types.

On the web, list values render as chips; multi_url chips are clickable
and open in a new tab, and the editor popover offers a per-entry open
button, so several related documents or links stay directly reachable
from the issue. The filter menu reuses the scalar input (equality-only
plus "No value"). CLI: comma-separated --value form for both types,
element-equality --property filtering, and display_values rows.

Server-side allowlist widened by migration 500 (check constraint
re-added NOT VALID then validated, same pattern as migration 341).

* fix(properties): address list property review nits

Co-authored-by: multica-agent <[email protected]>

* fix(properties): scope list drafts to the edited issue

Co-authored-by: multica-agent <[email protected]>

* test(agent): avoid fork races when writing zeroclaw fixtures

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Bohan-J <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-07 13:33:02 +08:00
Xichang(Seacen) Zhao c4fea18618 fix(agent): keep an Antigravity answer a trailing transport error cut off (#8983)
antigravityCompletedDespiteTrailingNetworkError exists to preserve a finished
answer when agy fails a follow-up round trip after producing it, but it
recognised exactly one error spelling. agy also reports an exhausted retry as
`API error (attempt N): request failed: Post "...": EOF`, which fell through and
discarded a response already sitting in result.response with its agent_response
step at DONE.

Match the transport cause rather than one sentence. The classifier stays narrow
on purpose: reportTaskResult documents failing closed so a provider 429 or
out-of-credit run can never be shown as Completed, and quota, capacity,
overload, policy and auth rejections all arrive as an HTTP response rather than
a failed round trip. agy's own `request failed:` prefix is excluded too — only
one spelling has been observed and nothing rules out agy reusing it for a
status error.
2026-10-06 23:15:37 -06:00
Ray Walker a5b2c361a9 MUL-7855 fix(pi): fail a run whose agent_end reports an error (#9028)
* fix(pi): fail a run whose agent_end reports an error

Pi 0.74.0 and earlier report a failure raised outside a model stream,
such as a provider API key command that fails, only on agent_end. The
stream carries no turn_end, error or auto_retry_end event, and print
mode exits 0, so the adapter recorded the run as completed with no
output. Pi resolves a command-backed API key again on every model
request, so the same path can also end a run part-way, after tool work.

Decode agent_end and record its last assistant message's stopReason
"error" through the existing turn-error guard, with errorMessage as the
reason. An automatic retry or a later successful turn still clears it,
as with turn_end.

* fix(pi): fail a run whose event stream overflows the scanner

The pi backend never checked scanner.Err(). A line over the shared 32 MiB bound ended the read loop, and the run then either recorded completed (when the rest of the line fit in the pipe buffer and pi exited) or hung until its timeout, with pi blocked writing to the unread pipe. agent_end repeats every message of the run, so on a long run it is the line most likely to overflow, and it can carry the run's terminal state.

Close stdout on a scanner error so pi cannot block on the full pipe, and fail the run with "pi stdout read error", keeping any provider error pi already reported. This matches the other stream backends.
2026-10-03 20:40:06 -06:00
mrlonely b2561aad61 fix(codex): exclude historical turns from resume responses (#9020) 2026-10-02 07:25:26 -07:00
mrlonely ba30324e10 fix(codex): add GPT-6.1 Sol fallback and current model pricing (MUL-7834) (#8996) 2026-09-30 21:39:07 -07:00
Bohan Jiangandmultica-agent 138134d341 fix(agent): pass Hermes custom args before the acp subcommand (MUL-7748) (#8882)
* fix(agent): pass Hermes custom args before the acp subcommand

Hermes only accepts its global flags (--provider, --yolo, -m, ...) ahead
of a subcommand, so the daemon's `hermes acp <custom args>` exited with
an argparse usage error before the ACP handshake and every run of a
Hermes agent with custom_args failed. Assemble `<prefix> <custom args>
acp` instead, keep the profile resolver and overlay stripping on the
same argv, and drop a trailing custom arg left without its value so it
cannot capture `acp` and hang the task in interactive chat.

Fixes #8878 (MUL-7748)

Co-authored-by: multica-agent <[email protected]>

* fix(agent): keep acp's own flags after the Hermes subcommand

Hermes' acp subparser declares --accept-hooks, --version, --check,
--setup, --setup-browser and --yes/-y, and argparse only accepts them
after the subcommand: moving them ahead of `acp` turned an agent with
custom_args ["--yes"], which launched before, into a usage error.
Lay custom args out around `acp` instead — global flags (with their
values) before it, acp's own flags after it — and map profile
stripping back through that layout so custom args keep their
configured order.

Co-authored-by: multica-agent <[email protected]>

* fix(agent): resolve Hermes flag abbreviations like argparse

Hermes keeps argparse's allow_abbrev, so custom args must be classified
the way its parsers resolve them, not by string equality. Behind `acp`
a `--y` is `--yes`; moved in front, the root parser reads it as
`--yolo` and turns off dangerous-command approval, while `--ye` went
from valid to a usage error. Keep every token the acp subparser would
take as its own option (exact, abbreviated or ambiguous) behind the
subcommand, and treat abbreviated value flags (`--prov`) as value flags
when pairing and when guarding against a bare flag capturing `acp`.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-09-27 22:21:50 +08:00
Bohan Jiangandmultica-agent 12f8f3f311 feat(agent): list Claude Opus 5.5 and GPT-6 Sol/Luna in the fallback catalogs (#8840)
Since the fallback catalogs only feed the model picker (#8811), listing
current models there is cheap. Add the models the installed CLIs now
advertise but the static lists were missing:

- Claude: claude-opus-5-5 (Claude Code 2.1.280 list_models default)
- Codex: gpt-6-sol (low..ultra) and gpt-6-luna (low..max), both default
  medium, from codex-cli 0.155.1 `debug models`; live discovery labels
  them "GPT-6 Sol" / "GPT-6 Luna" like GPT-6 Astra

MUL-7691

Co-authored-by: multica-agent <[email protected]>
2026-09-25 14:43:00 +08:00
Bohan Jiangandmultica-agent 1aa815a738 fix(daemon): stop validating saved model settings against fallback catalogs (#8811)
When model discovery fails, providers substitute a static catalog so the
picker stays usable. The daemon then validated saved thinking levels and
service tiers against that stand-in, silently dropping values the static
list did not know about — which forced hand-maintained model and per-model
effort tables to chase every new release.

Only a verified catalog (discovered, non-empty) may now reject, rewrite, or
drop a saved model, thinking level, or service tier. Fallback and empty
catalogs pass the saved values through to the CLI for every provider. The
checks that describe the binary rather than its models stay: a Claude CLI
without --effort (or without the saved value in its --effort list) still
drops the level, and Codex's explicit standard tier still follows the CLI
version.

- Catalog.Verified / Catalog.CLIThinkingLevels; missingFromFallbackCatalog removed
- claudeModelEffortAllow removed: the fallback picker offers the --help superset
- ModelKnownIncompatibleWithProvider no longer consults static lists (prefix-only, same result)

MUL-7691

Co-authored-by: multica-agent <[email protected]>
2026-09-25 14:33:58 +08:00
Kevin Kwok ec70b224d7 MUL-7675: feat(grok): support live-run steering via Grok Build ACP (#8796)
* feat(grok): support steering active Grok Build runs

* test(grok): cover steering before first agent output

* fix(grok): bound interject acknowledgement time
2026-09-24 16:43:10 +08:00
54520de957 MUL-7646: fix(claude): report per-run usage for resumed sessions (#8792)
* fix(claude): report per-run usage for resumed sessions

Co-authored-by: multica-agent <[email protected]>

* fix(claude): preserve usage when counters reset

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-09-24 13:44:51 +08:00
mrlonely 0516dd57c3 MUL-7625: feat(antigravity): stream live tool execution events (#8734)
* feat(antigravity): stream live tool execution events

* chore(i18n): remove obsolete French Antigravity live notice

* fix(antigravity): preserve tool events under backpressure

* fix(antigravity): retain tool errors in bounded previews

* fix(antigravity): normalize tool parameters for transcript UI

* fix(antigravity): move tool aliases and normalize file content
2026-09-23 19:02:44 +08:00
Yincan Huangandmultica-agent 7be175346e MUL-7613: fix(agent): refresh live model catalogs (#8722)
* fix(agent): refresh live model catalogs

Co-authored-by: multica-agent <[email protected]>

* fix(agent): preserve live-only Codex settings on catalog fallback

Co-authored-by: multica-agent <[email protected]>

* fix(agent): retain Codex explicit-standard CLI version gate

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-09-23 16:57:36 +08:00
93ae552ba9 feat: add messages to active Claude Code and Codex runs (MUL-7565) (#8682)
* feat: add live run supplements (MUL-7565)

Co-authored-by: multica-agent <[email protected]>

* fix: address MUL-7565 review feedback

Co-authored-by: multica-agent <[email protected]>

* fix: resolve MUL-7565 supplement panel and receipt review

Co-authored-by: multica-agent <[email protected]>

* refactor: remove MUL-7565 supplement ordinals

Co-authored-by: multica-agent <[email protected]>

* fix: close supplement composer after run remount

* fix: exclude task supplements from completion reconciliation

* fix: build a persistent binary for local daemon launches

* feat: support Claude task supplements through SDK hooks

* refactor: simplify task supplement delivery

* test: remove redundant task supplement coverage

* fix: remove redundant supplement delivery notices

* refactor: extract local daemon launcher fix to its own PR

* fix: preserve ordinary comment size compatibility

* fix: accept empty task start acknowledgements

* fix: bound task start response decoding and retries

---------

Co-authored-by: Forge-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
Co-authored-by: yushen <[email protected]>
2026-09-23 16:10:07 +08:00
Bohan Jiangandmultica-agent f41fae6b08 fix(cursor): own Windows background shells by launch Job membership (MUL-7417) (#8638)
* fix(cursor): own Windows background shells by launch Job membership (MUL-7417)

captureCursorBackgroundProcess on Windows walked a machine-wide PID->PPID
snapshot to prove a reported shell descends from the launch and to find
its pre-existing children. Windows keeps a child's recorded PPID after
the parent exits and reuses the PID, so the walk could reach a process
owned by someone else; opening it failed with 'Access is denied' or
'not an owned descendant' and the whole capture aborted. The daemon then
fell back to the idle watchdog and a Cursor run that later went quiet
took the 10-minute watchdog path instead of completing. In CI this was
TestCursorBackgroundLifecycle/multiple failing about 2 runs in 43.

Take candidates from the launch's own Job Object instead
(QueryInformationJobObject / JobObjectBasicProcessIdList). Descendants
inherit the Job at creation and cannot leave it, so membership is the
ownership proof: the parent-chain walk goes away, the PPID snapshot is
used only to attach a member's pre-existing children, and a member that
exits or is reused between listing and open is skipped instead of
failing the capture. Creation ordering still tells a real child from
one that points at a reused parent PID.

Restore TestCaptureCursorBackgroundLateDescendant on Windows; it was
excluded for exactly this race.

ci.yml runs the Windows Cursor step with -count=20 on this PR only to
show the race is gone; it is reverted before merge.

Co-authored-by: multica-agent <[email protected]>

* ci: restore -count=1 on the Windows Cursor background step

The -count=20 stress run on this PR passed (run 35580440594, windows-execenv);
the per-merge step goes back to a single pass.

Co-authored-by: multica-agent <[email protected]>

* fix(cursor): complete the Job member list and refuse unopenable live members (MUL-7417)

Review follow-ups on #8638:

- cursorJobProcessIDs grew its buffer only on ERROR_MORE_DATA. The kernel
  can also return success with NumberOfProcessIdsInList short of
  NumberOfAssignedProcesses, which a Job over the initial capacity or one
  growing during the query would hit; the short list then passed for the
  membership and could reject the target or leave children out. Retry
  until the counts agree, fail explicitly if they never do, and make the
  initial capacity a package var so a three-process tree exercises the
  growth path in a test.

- The child walk skipped every open failure as 'exited or reused'. A live
  member whose DACL denies PROCESS_SET_QUOTA|PROCESS_TERMINATE also fails
  to open, and skipping it left the capture reporting success with that
  member outside the tool Job. Skip only PIDs proven to carry no member
  (handle outside the launch Job, or no longer listed after a re-query,
  confirmed by one more open); otherwise fail the capture so the caller
  takes its existing watchdog fallback. OpenProcess goes through a
  package var so a test can make a live member unopenable.

Windows-only tests cover both, plus the plain claim-and-terminate path
for a shell with a pre-existing child.

Co-authored-by: multica-agent <[email protected]>

* test(cursor): name the Job list growth test so the Windows CI filter runs it

The windows-execenv step selects 'TestCursorBackground|TestCaptureCursorBackground';
TestCursorJobProcessIDsGrowsPastInitialCapacity matched neither and never ran.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-09-21 18:36:34 +08:00
Multica Eveandmultica-agent 8c9f865e3e MUL-7480: Revert comment steering feature (#8648)
* Revert "MUL-7480: Link delivered steers to final replies (#8623)"

This reverts commit 3de6275eb3.

Co-authored-by: multica-agent <[email protected]>

* Revert "fix: preserve active task intent in steer frames (#8621)"

This reverts commit b866dacd1c.

Co-authored-by: multica-agent <[email protected]>

* Revert "MUL-7480: Steer active agent turns from comments (#8605)"

This reverts commit 8ce795b007.

Co-authored-by: multica-agent <[email protected]>

* chore(db): remove reverted comment steer schema

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
2026-09-21 18:29:50 +08:00
LinYushen 7d7e3e59a6 Revert "Revert "fix: preserve active task intent in steer frames (#8621)" (#8…" (#8646)
This reverts commit d993257f60.
2026-09-21 18:00:16 +08:00
LinYushen d993257f60 Revert "fix: preserve active task intent in steer frames (#8621)" (#8644)
This reverts commit b866dacd1c.
2026-09-21 17:58:43 +08:00
b866dacd1c fix: preserve active task intent in steer frames (#8621)
Co-authored-by: Forge-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-09-21 13:45:06 +08:00
8ce795b007 MUL-7480: Steer active agent turns from comments (#8605)
* feat: steer active agent turns from comments (MUL-7480)

Co-authored-by: multica-agent <[email protected]>

* fix: make comment steering hint driven

Co-authored-by: multica-agent <[email protected]>

* fix: harden active comment steering races

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Forge-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-09-20 19:00:53 +08:00
Bohan Jiang 80aa31c1ab MUL-7520 fix(agent): support OpenCode 2.x runtimes (#8596)
OpenCode 2.0 changed four things the daemon depends on. Two fail loudly —
`--dir` and `--variant` both exit 1 on an unrecognized flag, which is why every
task on a 2.x runtime died in ~130ms with empty output (GH #8586). Two are
silent: MCP config had no working channel left, and `opencode run` became a thin
client in front of a resident service, so signalling the client's process group
no longer stopped the run.

- `--dir` is dropped on 2.x; the workdir comes from cmd.Dir + PWD.
- The thinking level folds into the model string as `provider/model#variant`.
- Cancellation calls POST /api/session/<id>/interrupt in front of the existing
  SIGTERM→SIGKILL, which is the only thing that stops a 2.x run.
- Runs carrying Multica-managed MCP servers are refused with an error naming
  every source, rather than started without them: 2.x accepts MCP only through a
  file in the task workdir, where the agent's own commits would capture the
  credentials. Restoring MCP is tracked separately.

The 1.x path is unchanged, pinned by argv and MCP regression tests. Verified
against @opencode/cli 2.0.10 and opencode-ai 1.18.31 on macOS/arm64; Windows
cancellation is not yet verified end to end.
2026-09-20 17:10:32 +08:00