fix(adapters): report why a turn produced nothing instead of nothing - #664
Merged
Merged
Conversation
Three rounds of the GUI matrix have ended with every agent reaching the LLM call and then reporting `No agent reply within 300s`, with no other information anywhere. The gateway and the credentials are both verified now — the same key and base URL drive the claude CLI to a correct answer from a shell on the same box — so what is left is that a failing turn has nothing to say for itself. Two reasons for that, both here. claude.js collected the child's stderr into `pp.stderrBuf` and read it back in exactly no place. When the CLI died before emitting its first JSON event there was no `result` to quote, so the channel got "No response generated. Please try again." and the daemon log got an exit code — while the actual account of what happened sat in a string nobody looked at. When it hung instead, the watchdog killed it at 300s and said "became unresponsive", again dropping the buffer. codex, gemini and opencode all log their stderr on exit; claude now does too, and also uses it on the two paths where it is the only thing there is: the watchdog kill and the silent exit. The "no response" fallback carries the exit code rather than nothing. Secrets are stripped on the way out — a CLI failing on auth tends to echo the key it was handed. The redaction rule already existed as identical private statics on codex and opencode; a third copy of a security- relevant rule is one too many, so it moves to adapters/utils.js and both delegate. Redaction runs over the whole buffer before the tail is cut, so a key cannot survive by being split across the boundary. The other reason is a dead heat. Every adapter gives up at exactly 300s — claude's stdout watchdog (20 x 15s), codex's direct-LLM request timeout, opencode's TIMEOUT_MS, gemini's idle monitor — and respond.spec polled for exactly 300s. The adapter posts its diagnosis to the channel at the moment the test stops listening, which is why every failure has read as the contentless timeout while the real reason was a second away. The spec now waits past it, so the adapter's own message becomes the assertion's failure text.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #663. With the gateway and the credentials both verified, every cell in the matrix now reaches the LLM call and then reports
No agent reply within 300s— and nothing else, anywhere. The same key and base URL drive the claude CLI to a correct answer from a shell on the same box, so what is left is that a failing turn has nothing to say for itself. Two reasons, both fixed here.1. claude.js collected stderr and read it back nowhere
pp.stderrBufis written on everystderrchunk and appears in exactly no other place in the file. So:resultto quote → the channel getsNo response generated. Please try again.and the daemon log gets an exit code. The actual account of what happened is in a string nobody looks at.Agent process became unresponsive, dropping the buffer again.codex, gemini and opencode all log their stderr on exit. claude now does too, and additionally uses it on the two paths where it is the only thing there is — the watchdog kill and the silent exit. The "no response" fallback now carries the exit code instead of nothing.
Secrets are stripped on the way out. A CLI failing on auth tends to echo the key it was handed, and this text goes both to the daemon log and to a workspace message. The rule already existed as byte-identical private statics on
CodexAdapterandOpenCodeAdapter; a third copy of a security-relevant rule is one too many, so it moves toadapters/utils.jsasredactSecretsand both delegate. Redaction runs over the whole buffer before the tail is cut, so a key cannot survive by being split across the boundary — there is a test for that.2. A dead heat at exactly 300s
timeout: 300000= 300sTIMEOUT_MS = 300000= 300srespond.spec.tspolled for exactly 300s.So the adapter posts its diagnosis to the channel at the same moment the test stops listening. That is why three rounds of reports have carried the contentless timeout while the real reason was a second away.
sendErrorposts as an ordinary agent chat message, so waiting past the adapters makes that message the assertion's own failure text — the report's note column gets the real error instead ofNo agent reply within 300s.Poll raised to 360s, per-test budget to install + 13 min to match.
Testing
npm testin agent-connector — 1517 pass, 0 fail (5 new)npm run typecheck+npx vitest runin launcher — clean, 476 passNote on when this reaches the nightly
The launcher pins
@openagents-org/agent-launcher@0.2.177, so the adapter half of this only affects the matrix after a core release and a launcher bump. Therespond.spec.tshalf takes effect on the next run.Not addressed
openclaw doctor --fixlegacy credential migration.Approval mode overridden … folder is not trusted.🤖 Generated with Claude Code