Parent tracking issue: #22702
Context
Interactive agent steps like tool confirmations and loop detection overrides should be driven by the protocol using the existing elicitation_request / elicitation_response mechanism. This ensures the TUI remains a "dumb" renderer of requests rather than managing complex backend state.
The existing ElicitationResponse type already supports action: 'accept' | 'decline' | 'cancel'. We can leverage this for tool approvals by making the content field optional for simple accept/decline flows. To correlate an approval elicitation back to the specific tool call, we will use a request ID convention.
Tasks
Relevant Files
- `packages/core/src/agent/types.ts`: Update `ElicitationResponse` type.
- `packages/core/src/agent/legacy-agent-session.ts`: Update to emit elicitations and handle responses in `send()`.
- `packages/cli/src/ui/hooks/useAgentStream.ts`: Implement UI handlers for protocol-driven elicitations.
Acceptance Criteria
- All interactive pauses are protocol-driven via elicitations.
- Tool approvals can be responded to using only the `action` field.
- The UI correlates approvals to tools using the `toolApproval:{id}` convention.
- The UI remains completely decoupled from `Scheduler` and `LoopDetectionService` internals.
Parent tracking issue: #22702
Context
Interactive agent steps like tool confirmations and loop detection overrides should be driven by the protocol using the existing
elicitation_request/elicitation_responsemechanism. This ensures the TUI remains a "dumb" renderer of requests rather than managing complex backend state.The existing
ElicitationResponsetype already supportsaction: 'accept' | 'decline' | 'cancel'. We can leverage this for tool approvals by making thecontentfield optional for simple accept/decline flows. To correlate an approval elicitation back to the specific tool call, we will use a request ID convention.Tasks
ElicitationResponsetype:contentfield optional (content?: Record<string, unknown>).elicitation_requestemission inLegacyAgentProtocol:Schedulerpauses to an elicitation request. Use a correlation prefix for the ID:toolApproval:{toolRequestId}.requestedSchemato define the "Keep" and "Disable" options.LegacyAgentProtocol.send()to interceptelicitation_responsepayloads and route them back to the internal services (Scheduler,LoopDetectionService) waiting for them.useAgentStream.tsto:elicitation_requestevents.ToolConfirmationQueuewhen it detects thetoolApproval:prefix).agent.send({ elicitations: [{ requestId, action: 'accept' }] }).Relevant Files
Acceptance Criteria