Skip to content

feat: support asynchronous user questions through AIR - #484

Open
nikita-ashihmin wants to merge 5 commits into
mainfrom
nikita.ashikhmin/async-user-questions
Open

feat: support asynchronous user questions through AIR#484
nikita-ashihmin wants to merge 5 commits into
mainfrom
nikita.ashikhmin/async-user-questions

Conversation

@nikita-ashihmin

@nikita-ashihmin nikita-ashihmin commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Codex asynchronous questions now reach clients through the AIR asyncQuestions capability and _session/async_question/request. The question RPC waits for the user while the agent continues working. Answers become user input through the existing steering queue, joining an active turn or starting a new one. Clients without the capability receive ordinary question text.

Adds the client contract and examples in docs/async-questions.md. Pending questions survive normal turn completion, but cancellation and session shutdown invalidate them. History does not reopen forms. Steering retries only an explicit “no active turn” rejection, avoiding duplicate input after an uncertain transport failure.

Validation:

  • npm run typecheck
  • npm test: 575 passed, 26 skipped
  • npm run bundle:all
  • npm run codex-test:async-questions: passed with locked Codex 0.153.3 and gpt-6-astra; real async question, AIR RPC, late answer, new-turn input, and model confirmation.
  • Regression tests reproduce and cover prompt RPC cancellation, late questions after session cancellation, and transport failure after turn completion.
  • All JSON documentation examples parse successfully.

Live validation is reproducible after npm ci with an authenticated Codex account. The smoke test asserts the actual question RPC and reply payload; a successful prompt alone does not count as a pass. AIR clients must implement the documented form before advertising the capability.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The reply payload envelope is built from user-provided answers and should defensively avoid tag-delimiter injection/ambiguity (see stored security comment).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds first-class support for Codex “asynchronous user questions” by negotiating an AIR asyncQuestions capability, sending a dedicated client RPC (_session/async_question/request) without blocking the notification stream, and delivering the user’s answers back to Codex via the existing steering queue (joining an active turn or starting a new one).

Changes:

  • Introduces CodexAsyncQuestionHandler + AIR capability wiring to open async-question RPCs and feed answers back as steering input, with cancellation/close/provider-restart handling.
  • Updates steering pipeline to propagate AbortSignal through SteeringQueue and steering execution so queued async answers can be cancelled cleanly.
  • Adds tests + snapshots and documents the client contract and examples in docs/async-questions.md.
File summaries
File Description
src/SteeringQueue.ts Adds optional AbortSignal propagation through queued steering requests.
src/CodexEventHandler.ts Ensures async-question agent messages are emitted even if they arrive only as completed items (no deltas), while deduplicating against deltas.
src/CodexAsyncQuestionHandler.ts New handler that opens _session/async_question/request, validates responses, and delivers answers via steering with cancellation support.
src/CodexAcpServer.ts Wires handler into capability negotiation, prompt lifecycle, cancellation/close, and provider/process shutdown paths; tightens steering retry semantics.
src/AsyncQuestionExtension.ts Defines the AIR asyncQuestions request/response types and method name constant.
src/AirExtension.ts Adds AIR_ASYNC_QUESTIONS_KEY capability constant.
src/AcpExtensions.ts Re-exports async-question extension types for consumers.
src/tests/CodexACPAgent/async-questions.test.ts Comprehensive event-driven coverage for negotiation, dedupe, late answers, cancellation, and transport failure behaviors.
src/tests/CodexACPAgent/initialize.test.ts Updates advertised AIR capability list to include asyncQuestions.
src/tests/CodexACPAgent/snapshots/* Adds snapshots for request/updates and late-answer input payload.
src/tests/acp-test-utils.ts Adds fixture support for overriding extension RPC responses.
readme-dev.md Links dev docs to the new async-question contract.
docs/async-questions.md Documents the client contract, lifecycle, cancellation semantics, and examples.
Review details
  • Files reviewed: 14/14 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +110 to +113
const result = await this.deliver({
sessionId: request.sessionId,
prompt: [{type: "text", text: `<send_user_message_question_reply>\n${JSON.stringify(replies)}\n</send_user_message_question_reply>`}],
}, signal);

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The concurrency behavior is well tested, but the live Codex question exchange remains unverified because smoke testing was blocked.

Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation is consistent with the protocol lifecycle and includes comprehensive regression and live-validation coverage.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Async questions emitted by native subagents are filtered out before the AIR request handler.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread src/CodexAcpServer.ts
Comment on lines +2824 to +2826
if (!activePrompt.signal.aborted && !this.sessionIsClosing(params.sessionId)
&& "threadId" in event.params && event.params.threadId === params.sessionId) {
this.asyncQuestions.handleNotification(event, this.clientCapabilities);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants