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
{{ message }}
Repository navigation
Commit 43edcee
Browse filesBrowse the repository at this point in the historyBrowse files
Carry an approval's persistence choice through elicitation
Codex Computer Use offers `persist: ["session", "always"]` in the terms of
its "Allow Computer Use to use X?" prompt and remembers the app only when
the answer names one. Executor lost the offer on the way in — the terms
projection kept strings only — and the choice on the way out, because every
adapter rebuilt the reply from `action` and `content`. So each accept was a
one-time approval and the same app prompted on every call.
- `ElicitationResponse.meta.persist` carries the choice; the vocabulary is
closed so no host can grant more than the prompt offered.
- `approvalTerms` keeps string lists, so the offered scopes reach the host.
- The MCP plugin, the app-server bridge, and the MCP host (native mode)
pass `_meta` through in both directions.
- The model-mode `resume` tool takes `persist`; the pause output names the
offered scopes and says a bare accept is one-time.
- The HTTP resume API takes `persist`, and the browser approval page offers
the scopes in a select. Nothing is chosen automatically.
Fixes#1962
Carry an approval's persistence choice through elicitation, so Codex Computer Use stops asking to use the same app on every call.
11
+
12
+
Computer Use offers `persist: ["session", "always"]` in the prompt's terms and remembers the app only when the answer names one. Executor dropped the offer on the way in (the terms projection kept strings only) and the choice on the way out (every adapter rebuilt the reply from `action` and `content`), so each accept was one-time. `ElicitationResponse` now has `meta.persist`; the MCP plugin, the app-server bridge, and the MCP host pass it through; the model-mode `resume` tool and the browser approval page let the approver pick from the offered scopes. Nothing is chosen automatically: a bare accept still approves once.
? `Ask the user for values matching requestedSchema. Then call the resume tool with executionId "${paused.id}", action "accept", and content matching requestedSchema. If the user declines, call resume with action "decline" or "cancel".`
217
225
: `This is a model-side confirmation gate; there is no browser form to open. Ask the user whether to approve the paused tool call. If the user approves, call the resume tool with executionId "${paused.id}" and action "accept". If the user declines, call resume with action "decline" or "cancel".`;
226
+
// When the upstream leaves the LIFETIME of an accept to the answer, the
227
+
// caller has to know that a bare accept is a one-time approval — the same
228
+
// prompt returns on the next call — and how to say otherwise.
229
+
constmeta=req.meta;
230
+
constoffered=offeredPersistence(meta);
231
+
constpersistInstructions=
232
+
offered.length>0
233
+
? ` To have an accepted approval remembered, also pass persist as one of ${offered
234
+
.map((scope)=>JSON.stringify(scope))
235
+
.join(", ")}; without it the approval is for this call only.`
236
+
: "";
218
237
constdeadlineInstructions=deadline
219
238
? ` Resume before ${deadline.expiresAt}; this approval window lasts ${formatTtlDuration(deadline.ttlMs)}.`
0 commit comments