mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-11 02:46:45 +08:00
* fix(agent): raise the agent stream scanner cap to 32 MiB and share it (MUL-5722) Codex serializes an entire thread into the single `thread/resume` response line, so a long thread crossed the per-backend 10 MiB bufio.Scanner cap and failed the resume with "bufio.Scanner: token too long". Because that classifies as agent_error.process_failure, the session pointer survives and every later turn resumes the same oversized thread — the task is stuck for good. This is GH#4520 recurring: #4563 bounded the hang and the orphan process, but the cap follow-up it promised was never done. Raise the bound to 32 MiB and route every line-delimited agent transport through one newAgentStreamScanner constructor. The cap was copy-pasted into 17 sites and had already drifted (pi at 32 MiB, everything else at 10 MiB), which is how #4563's fix reached only one backend. The three tests that deliberately overflow the scanner now size their payloads from the constant, so raising the cap again cannot silently downgrade them into plain oversized-line passes. This is the containment layer only. A thread can still outgrow any fixed cap, and the recovery path is still missing: overflow is reported as a transport error, which blocks the thread/start fallback, and codex never sets ResumeRejected so the daemon's fresh-session retry does not fire either. Those remain open on MUL-5722. Co-authored-by: multica-agent <[email protected]> * fix(agent): route the QwenPaw ACP stream through the shared scanner (MUL-5722) QwenPaw (#5986) landed on main after this branch was cut, carrying its own bufio.Scanner with the old 10 MiB cap. Merging as-is would have left one backend still on the cliff this PR exists to remove — the same way #4563's fix originally reached only one backend. Rebased onto main and routed it through newAgentStreamScanner. No stray per-backend cap remains: the only bufio.NewScanner calls left in the package are the model-listing and codex session-file parsers, which are deliberately out of scope. Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: Bohan-J <[email protected]> Co-authored-by: multica-agent <[email protected]>
37 lines
1.7 KiB
Go
37 lines
1.7 KiB
Go
package agent
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
)
|
|
|
|
// agentStreamMaxLineBytes bounds a single line read from an agent CLI's
|
|
// event stream. Agent transports are line-delimited JSON, and one line can
|
|
// carry a whole conversation: Codex app-server serializes an entire thread
|
|
// into the single `thread/resume` response, and providers that re-send a
|
|
// growing message partial on every delta (Pi) or embed a large tool result
|
|
// in one event grow the same way. Crossing this bound makes scanner.Scan()
|
|
// return false with bufio.ErrTooLong, which the backends can only report as
|
|
// a transport failure — the session itself is fine, we just cannot read it.
|
|
//
|
|
// 32 MiB was picked as the follow-up to GH#4520, where the previous 10 MiB
|
|
// bound broke `thread/resume` for long Codex threads (MUL-5722). It is
|
|
// headroom, not a guarantee: a thread can still outgrow any fixed cap, so
|
|
// the recovery path matters more than the number.
|
|
const agentStreamMaxLineBytes = 32 * 1024 * 1024
|
|
|
|
// agentStreamInitialBufferBytes is the scanner's starting allocation. Lines
|
|
// above it still grow up to agentStreamMaxLineBytes; this only decides how
|
|
// much is reserved before the first grow, so ordinary events never realloc.
|
|
const agentStreamInitialBufferBytes = 1024 * 1024
|
|
|
|
// newAgentStreamScanner returns a bufio.Scanner sized for agent event
|
|
// streams. Every backend reading a line-delimited agent transport must go
|
|
// through this constructor: the bound used to be copy-pasted per backend and
|
|
// silently drifted, which is how GH#4520's fix reached only one of them.
|
|
func newAgentStreamScanner(r io.Reader) *bufio.Scanner {
|
|
scanner := bufio.NewScanner(r)
|
|
scanner.Buffer(make([]byte, 0, agentStreamInitialBufferBytes), agentStreamMaxLineBytes)
|
|
return scanner
|
|
}
|