You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ACP Session.#executePrompt sends turns via chat.sendMessageStream() directly, bypassing GeminiClient.sendMessageStream() and all the per-turn middleware attached there. Hooks have been individually wired into Session.ts over time, but non-hook middleware is still missing.
Goal: bring the ACP path to full parity with the React TUI / non-interactive paths so features don't silently no-op in ACP.
Current gap matrix
Comparing client.ts:590-1020 (GeminiClient) vs Session.ts (ACP):
Auto-memory: managed memory recall (MemoryManager.recall) never runs in ACP. Projects relying on managed memory see the model missing context.
IDE context: VSCode companion users don't get cursor/selection/diff hints piped into the turn.
Loop detector: infinite-tool-call loops aren't caught; ACP users can burn through tokens silently.
Arena control-signal: arena sessions can't be cancelled via control channel mid-turn.
Retry history cleanup: retried turns may leave orphaned user entries in history.
Two paths forward
Option A — keep copying middleware into Session.ts
Continue the pattern from PR #3479: for each missing slice, reimplement in Session.ts. Low per-step risk but drift continues.
Option B — switch ACP to geminiClient.sendMessageStream
Structurally correct. Requires:
Delete Session.ts's hand-rolled UserPromptSubmit hook (L359–401) and #handleStopHookLoop to avoid double-firing.
Adapt the event stream: GeminiClient yields ServerGeminiStreamEvent, ACP currently consumes raw StreamEvent (chat stream chunks). Need a translation layer.
Handle SendMessageType.{UserQuery,Cron,Hook,Retry,Notification} branch semantics properly (Session.ts currently doesn't distinguish).
This is effectively a subset of #3247 (full unification refactor).
Option C — extract middleware as a primitive
Move the per-turn middleware (system reminders, IDE context, loop detector, auto-memory prefetch) out of GeminiClient.sendMessageStream into a pure function / class that both GeminiClient and Session import. Then ACP keeps its own loop but gets the middleware for free.
Recommendation
Start with Option C for the cheapest, lowest-risk convergence; Option B can come later as part of #3247.
What would you like to be added?
The ACP
Session.#executePromptsends turns viachat.sendMessageStream()directly, bypassingGeminiClient.sendMessageStream()and all the per-turn middleware attached there. Hooks have been individually wired intoSession.tsover time, but non-hook middleware is still missing.Goal: bring the ACP path to full parity with the React TUI / non-interactive paths so features don't silently no-op in ACP.
Current gap matrix
Comparing
client.ts:590-1020(GeminiClient) vsSession.ts(ACP):UserPromptSubmithookStop/StopFailurehooksPre/Post ToolUsehooksNotificationhookstripOrphanedUserEntriesFromHistoryon RetryUser-facing symptoms of each gap
MemoryManager.recall) never runs in ACP. Projects relying on managed memory see the model missing context.Two paths forward
Option A — keep copying middleware into
Session.tsContinue the pattern from PR #3479: for each missing slice, reimplement in Session.ts. Low per-step risk but drift continues.
Option B — switch ACP to
geminiClient.sendMessageStreamStructurally correct. Requires:
UserPromptSubmithook (L359–401) and#handleStopHookLoopto avoid double-firing.GeminiClientyieldsServerGeminiStreamEvent, ACP currently consumes rawStreamEvent(chat stream chunks). Need a translation layer.SendMessageType.{UserQuery,Cron,Hook,Retry,Notification}branch semantics properly (Session.ts currently doesn't distinguish).This is effectively a subset of #3247 (full unification refactor).
Option C — extract middleware as a primitive
Move the per-turn middleware (system reminders, IDE context, loop detector, auto-memory prefetch) out of
GeminiClient.sendMessageStreaminto a pure function / class that bothGeminiClientandSessionimport. Then ACP keeps its own loop but gets the middleware for free.Recommendation
Start with Option C for the cheapest, lowest-risk convergence; Option B can come later as part of #3247.
Related
Relevant files
packages/core/src/core/client.ts:590-1020—GeminiClient.sendMessageStreammiddleware (reference)packages/cli/src/acp-integration/session/Session.ts:289, 857— ACP prompt entry pointspackages/cli/src/acp-integration/session/Session.ts:1106+—#buildInitialSystemReminders(to be extended or superseded)