refactor: migrate Swift HTTPTransport and CLI from /v1/runs to /v1/messages#8410
Conversation
…ssages Co-Authored-By: Claude <noreply@anthropic.com>
👀 Where to focus your review
Risk level: Medium — the CLI polling model changed fundamentally from run-status-driven to message-poll-driven, which could affect perceived responsiveness and completion detection in edge cases. |
| pendingSecret: secret | ||
| ? { | ||
| requestId: secret.requestId, | ||
| } | ||
| : null, |
There was a problem hiding this comment.
🔴 Server returns incomplete pending-secret data, causing CLI to display 'undefined' fields
When the CLI polls GET /v1/pending-interactions, the server only returns { requestId } for pending secrets (approval-routes.ts:232-235), but the CLI's PendingSecret interface requires service, field, and label as mandatory string properties. The PendingInteraction stored server-side for secrets (registered at assistant/src/runtime/routes/conversation-routes.ts:176-180) doesn't capture any secret metadata — only kind: 'secret', session, and conversationId.
When the CLI receives this incomplete response and calls handleSecretPromptFn at line 1108, it accesses secret.label, secret.service, and secret.field, all of which are undefined at runtime.
Root Cause and Impact
The server-side PendingInteraction type for secrets doesn't store the secret metadata (service, field, label, description, placeholder, purpose, allowOneTimeSend). The original secret_request IPC message (assistant/src/daemon/ipc-contract/messages.ts:117-127) has all these fields, but they're discarded during registration at conversation-routes.ts:176-180.
As a result, the CLI's secret prompt displays:
"Secret needed: undefined"(line 1108:secret.label)"Service: undefined / undefined"(line 1109:secret.service/secret.field)- The
showSecretInputcall (line 1131) passesundefinedas the label - The
allowOneTimeSenddelivery selection (line 1119) never triggers since the field is missing
Impact: The entire secret prompt UX in the CLI is broken — users see nonsensical "undefined" labels and have no context about what secret is being requested.
Prompt for agents
Two changes are needed to fix the missing secret metadata:
1. In assistant/src/runtime/pending-interactions.ts, add a SecretDetails interface (similar to ConfirmationDetails) with fields: service, field, label, description?, placeholder?, purpose?, allowOneTimeSend?. Add an optional secretDetails property to the PendingInteraction interface.
2. In assistant/src/runtime/routes/conversation-routes.ts around line 176, when registering a secret interaction, capture the secret metadata from the msg object:
pendingInteractions.register(msg.requestId, {
session,
conversationId,
kind: 'secret',
secretDetails: {
service: msg.service,
field: msg.field,
label: msg.label,
description: msg.description,
placeholder: msg.placeholder,
purpose: msg.purpose,
allowOneTimeSend: msg.allowOneTimeSend,
},
});
3. In assistant/src/runtime/routes/approval-routes.ts lines 232-236, return the secret details in the response:
pendingSecret: secret
? {
requestId: secret.requestId,
service: secret.secretDetails?.service,
field: secret.secretDetails?.field,
label: secret.secretDetails?.label,
description: secret.secretDetails?.description,
placeholder: secret.secretDetails?.placeholder,
purpose: secret.secretDetails?.purpose,
allowOneTimeSend: secret.secretDetails?.allowOneTimeSend,
}
: null,
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1cfaa03d8c
ℹ️ 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".
| ? { | ||
| requestId: secret.requestId, | ||
| } |
There was a problem hiding this comment.
Include secret metadata in pending-interactions payload
The new polling response only returns requestId for pendingSecret, but the CLI secret flow expects fields like label, service, and field (and ultimately passes label into UI rendering). With this shape, a secret_request discovered via GET /pending-interactions produces undefined prompt data and can break the prompt UX for polling clients instead of presenting a usable secret request.
Useful? React with 👍 / 👎.
| h.addMessage(msg); | ||
| chatLogRef.current.push({ role: "assistant", content: msg.content }); | ||
| if (!runId) { | ||
| h.setBusy(false); | ||
| h.hideSpinner(); | ||
| return; | ||
| } | ||
| h.setBusy(false); | ||
| h.hideSpinner(); | ||
| return; |
There was a problem hiding this comment.
Correlate completion to the submitted turn before returning
This loop now exits on the first unseen assistant message, regardless of which user turn it belongs to. If /v1/messages accepts this input while the conversation is already processing another turn (queue-if-busy), the CLI will treat the earlier turn's assistant reply as completion, clear busy state, and return before the current request is answered.
Useful? React with 👍 / 👎.
PR 4/6: remove-runs plan. Migrates Swift and CLI clients to new message/approval endpoints.
Summary
Swift HTTPTransport: Changed
createRun()(POST /v1/runs) tosendMessage()(POST /v1/messages). UpdatedsendDecision()to POST /v1/confirm with{ requestId, decision }. UpdatedsendSecret()to POST /v1/secret with{ requestId, value }. RemovedactiveRunIdproperty and all run-related state tracking.CLI: Replaced
createRun()withsendMessage()(POST /v1/messages). ReplacedsubmitDecision()with POST /v1/confirm. ReplacedaddTrustRule()with POST /v1/trust-rules. RemovedgetRun()status polling and all run-related types (CreateRunResponse,GetRunResponse). Added polling via newGET /v1/pending-interactionsendpoint for approval discovery.Server: Added
GET /v1/pending-interactions?conversationKey=...endpoint so polling-based clients (CLI) can discover pending confirmations/secrets without SSE.Test plan
cd cli && bunx tsc --noEmitpassescd clients/macos && ./build.shsucceeds