fix: persist transcript for ACP agent run outputs#38614
fix: persist transcript for ACP agent run outputs#38614robo7 wants to merge 10 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes ACP (Agent Communication Protocol) child session turns so that a successful one-shot run persists both the session metadata in The two-part fix in Key observations:
Confidence Score: 4/5
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b581951553
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8771733d40
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
src/commands/agent.ts
Outdated
| await appendAssistantMessageToSessionTranscript({ | ||
| agentId: sessionAgentId, | ||
| sessionKey, | ||
| text: finalVisibleText, | ||
| storePath, | ||
| }); |
There was a problem hiding this comment.
Avoid failing ACP turn when transcript mirror write fails
appendAssistantMessageToSessionTranscript(...) is awaited directly here, but that helper can still throw during file I/O (for example in ensureSessionHeader/SessionManager.appendMessage) and this call sits before the lifecycle end emission. In environments with transient or read-only session storage, a successful acpManager.runTurn(...) will be reported as a failed command and never emit the normal end event, which is a behavioral regression introduced by the new mirror step.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5521654987
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00ebc0232c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f44a2fe81
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
6e0406b to
7a6efd2
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a6efd2c3a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if [ "$CI_GITHUB_REF" = "refs/heads/main" ]; then | ||
| echo "Skipping detect-secrets on main until the allowlist cleanup lands." | ||
| exit 0 | ||
| fi |
There was a problem hiding this comment.
Run detect-secrets on main pushes
This new guard exits the Detect secrets step for every refs/heads/main run, and this workflow only triggers pushes on main, so pre-commit run --all-files detect-secrets no longer executes for merged or direct hotfix pushes. In that scenario, only the private-key hook still runs, which regresses coverage for other secret types and can let leaked credentials reach main undetected.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3e1802d2f3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const fallbackSessionFile = !sessionEntry?.sessionFile | ||
| ? resolveSessionTranscriptPath(sessionId, targetAgentId, threadIdFromSessionKey) | ||
| : undefined; | ||
| const resolvedSessionFile = await resolveAndPersistSessionFile({ |
There was a problem hiding this comment.
Delay session-file persistence until thread binding resolves
For mode="session" spawns, this writes a non-threaded sessionFile before the child thread is bound. Later in the same function we call resolveAndPersistSessionFile again with a thread-specific fallback, but resolveAndPersistSessionFile only applies fallbackSessionFile when sessionEntry.sessionFile is missing, so the second call cannot switch to the -topic-<thread> path. That means thread-bound ACP sessions keep using the generic transcript file despite successful binding.
Useful? React with 👍 / 👎.
3e1802d to
07f22e8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07f22e896e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| opts.threadId ?? threadIdFromSessionKey, | ||
| ) | ||
| : undefined; | ||
| const resolvedSessionFile = await resolveAndPersistSessionFile({ |
There was a problem hiding this comment.
Treat ACP transcript-path persistence as best-effort
This new pre-turn resolveAndPersistSessionFile(...) call is awaited before acpManager.runTurn(...), so any filesystem/session-store write failure (for example transient sessions.json I/O errors from updateSessionStore) now turns an otherwise runnable ACP request into ACP_TURN_FAILED. Because this persistence step is only metadata/transcript setup, hard-failing the turn here is a behavioral regression from the prior ACP path where the turn could still run.
Useful? React with 👍 / 👎.
| const fallbackSessionFile = !sessionEntry?.sessionFile | ||
| ? resolveSessionTranscriptPath(sessionId, targetAgentId, threadIdFromSessionKey) | ||
| : undefined; | ||
| const resolvedSessionFile = await resolveAndPersistSessionFile({ |
There was a problem hiding this comment.
Avoid aborting ACP spawn on transcript metadata write errors
The new resolveAndPersistSessionFile(...) call is on the main spawn path and is not isolated from the control flow, so if session-file persistence throws (e.g., transient write failure while updating the session store), spawnAcpDirect now returns status: "error" before runtime initialization. This makes ACP spawn success depend on non-essential transcript metadata I/O, which is a reliability regression for spawn requests.
Useful? React with 👍 / 👎.
Summary
Fix ACP agent run sessions so successful one-shot ACP turns persist a session transcript that
chat.history/sessions_historycan read.This patch does two small things in the ACP branch of
agentCommandInternal:sessionFileearly for ACP child sessionsacpManager.runTurn(...)completesWithout this, ACP child sessions can have metadata in
sessions.jsonbut no transcript.jsonl, sosessions_historycomes back empty even when the run was accepted and produced output.Fixes/relates to #38565.
What changed
src/commands/agent.tsresolveAndPersistSessionFile(...)beforerunTurnappendAssistantMessageToSessionTranscript(...)with the finalized visible text afterrunTurnValidation
node --check src/commands/agent.tspnpm exec vitest run src/commands/agent.acp.test.ts src/commands/agent.test.tsNotes
I intentionally kept this patch minimal to validate the root cause first.
A fuller follow-up could decide whether ACP should also mirror the user prompt and/or unify transcript persistence more centrally for ACP flows.