Skip to content

fix(ai): drop invalid item ids when replaying responses history - #44587

Merged
rekram1-node merged 1 commit into
v2from
item-id-hygiene
Aug 24, 2026
Merged

rekram1-node merged 1 commit into
v2from
item-id-hygiene

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Summary

When replaying conversation history to a Responses API, persisted item ids (msg_, rs_, fc_, hosted tool ids) were resent verbatim from provider metadata. A malformed, oversized, or foreign id can fail request validation server-side even when call_id pairing is intact — for example after switching models mid-session or when synthetic ids end up in history.

Changes

  • Baseline shape validation (open-responses.ts): itemID() now only accepts ids matching /^[A-Za-z0-9_-]{1,64}$/. Dropped ids are treated exactly like absent ones at every lowering site:
    • function_call items are resent without an id
    • assistant message groups lose their id (grouping splits so distinct original items stay distinct)
    • hosted tool results skip the item_reference synthesis
    • reasoning items, which cannot be expressed without an id, are skipped entirely
  • Per-provider grammar hook: new optional Extension.acceptsItemID(kind, id) lets provider routes enforce their own id grammar. The OpenAI route uses it to resend only msg_/rs_/fc_-prefixed ids for messages/reasoning/function calls; hosted tool references keep shape-only validation since every hosted tool mints its own prefix.
  • The provider-neutral baseline (used by compatible deployments) enforces shape only, never a specific grammar.

This mirrors the allowlist approach codex uses before resending history (codex-rs core/src/client.rs, prepare_response_items_for_request strips ids without a recognized prefix).

Tests

  • New: drops ids failing the OpenAI per-kind grammar (prefix + length) and skips unreplayable reasoning items
  • New: keeps well-formed hosted references while dropping malformed ones under storage
  • New: baseline keeps well-formed foreign grammars but drops shape violations
  • Updated: function-call stream fixtures now use realistic fc_-prefixed item ids

Full packages/ai suite passes; the six OpenRouter failures are pre-existing on v2.

Replaying history resends persisted item ids verbatim. A malformed,
oversized, or foreign id can fail request validation server-side even
when call_id pairing is intact.

The Open Responses baseline now validates item id shape ([A-Za-z0-9_-],
max 64 chars) and drops anything else at every lowering site: function
call items, reasoning items (which are skipped entirely when the id is
unusable), assistant message groups, and hosted tool item_reference
synthesis. A new optional Extension.acceptsItemID hook lets provider
routes enforce their own id grammar; the OpenAI route uses it to only
resend msg_/rs_/fc_ prefixed ids per item kind while hosted tool
references keep shape-only validation.
@rekram1-node
rekram1-node merged commit 8b65bd5 into v2 Aug 24, 2026
9 checks passed
@rekram1-node
rekram1-node deleted the item-id-hygiene branch August 24, 2026 04:08
jinhuang712 pushed a commit to jinhuang712/opencode that referenced this pull request Sep 26, 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