Skip to content

fix(kap-server): accept question ids containing colons on resolve - #2585

Merged
sailist merged 2 commits into
MoonshotAI:mainfrom
sailist:fix/question-colon-id-resolve
Aug 4, 2026
Merged

fix(kap-server): accept question ids containing colons on resolve#2585
sailist merged 2 commits into
MoonshotAI:mainfrom
sailist:fix/question-colon-id-resolve

Conversation

@sailist

@sailist sailist commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problem is explained below.

Problem

When using certain OpenAI-compatible providers/gateways, submitting an answer to an interactive question prompt (AskUserQuestion) fails with 40001 unsupported action, and the user can never get the answer through. Dismissing the same prompt works fine.

Root cause: the question id is derived from the LLM tool_call id, and some providers emit ids containing a colon (e.g. AskUserQuestion:0). The REST route POST /sessions/{sid}/questions/{qid} parses the path tail with the shared :action suffix convention (split on the last colon), so the bare resolve URL .../questions/AskUserQuestion:0 is misread as id AskUserQuestion + action 0, which is not a supported action. Dismiss works because .../AskUserQuestion:0:dismiss splits off a valid trailing :dismiss. Official providers never hit this because their tool_call ids contain no colons.

What changed

  • In the questions resolve handler, when the action-suffix parse comes back invalid, the full unparsed tail is first matched against the session's pending question list: a hit proceeds as a normal resolve; a miss keeps the original 40001 behavior. The change is confined to this one handler — the dismiss path and all other :action routes are untouched.
  • Added two regression tests: resolving a question whose id comes from a colon-bearing tool_call id (the real-world reproduction), and a colon tail matching no pending question still returning 40001.
  • Added maxRetries to the test home cleanup to absorb the async query-store shard flush (ENOTEMPTY on macOS), matching the existing pattern in fs.test.ts.

This approach fits Kimi Code because it is a server-side compatibility fallback: no wire-contract change, no client changes, and it also covers in-flight sessions whose pending questions already carry colon-bearing ids.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

Some OpenAI-compatible providers emit tool_call ids like
`AskUserQuestion:0`, which the question service adopts as the question
id. The action-suffix parse then rejected the bare resolve POST as an
unsupported action (40001), so clients could never submit answers.

When the suffix parse fails, fall back to matching the full tail
against the pending question list before emitting 40001. Also add
maxRetries to the test home cleanup to absorb the async query-store
shard flush (ENOTEMPTY on macOS), matching fs.test.ts.
@changeset-bot

changeset-bot Bot commented Aug 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b35eb4d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@moonshot-ai/kap-server Patch
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71b5bef101

ℹ️ 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".

Comment on lines +194 to +199
if (interaction.listPending('question').some((i) => i.id === tail)) {
questionId = tail;
action = 'resolve';
} else {
reply.send(errEnvelope(ErrorCode.VALIDATION_FAILED, parsed.reason, req.id));
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve duplicate resolve handling for colon IDs

When a colon-bearing question is resolved successfully, a retry of the same bare resolve URL (for example after a dropped response) now hits this parsed.kind === 'invalid' branch again, finds no pending question, and returns 40001 before the existing isRecentlyResolved(questionId) idempotency check can run. That makes the fixed provider shape lose the route's documented duplicate-resolve behavior (40902 within the recently-resolved window); check interaction.isRecentlyResolved(tail) in this fallback before emitting the validation error.

Useful? React with 👍 / 👎.

@pkg-pr-new

pkg-pr-new Bot commented Aug 4, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@b35eb4d
npx https://pkg.pr.new/@moonshot-ai/kimi-code@b35eb4d

commit: b35eb4d

…tions

A retried bare resolve of a colon-bearing question id re-entered the
invalid-suffix fallback after the question settled, found no pending
match, and returned 40001 — bypassing the recently-resolved idempotency
window. Accept the tail in the fallback when it is recently resolved so
the shared duplicate-resolve path emits 40902 as documented.
@sailist
sailist merged commit c396873 into MoonshotAI:main Aug 4, 2026
14 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 4, 2026
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.

1 participant