anomalyco / anomalyco/opencode

Object.prototype stream key breaks the tool-call stream with an untyped defect

Open
#44,625 0 comments 0 reactions 1 assignee View on GitHub

@jlongster is already working on this.

Since Aug 24, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

The tool-call accumulator in packages/llm/src/protocols/utils/tool-stream.ts stores pending calls in a plain object keyed by the provider's stream id:

type State<K extends StreamKey> = Partial<Record<K, PendingTool>>
const empty = () => ({})

On the OpenAI Responses protocol that key is event.item_id, a free-form string from the server (Schema.optional(Schema.String)). If it is an Object.prototype member name — toString, constructor, valueOf, hasOwnProperty — then tools[key] returns the inherited function instead of undefined, which is truthy. appendExisting, finish and finishWithInput therefore skip their if (!tool) return ... guards and build an event with id/name undefined.

The schema constructor then throws Expected string, got undefined synchronously, outside the Effect error channel, so the stream dies with a defect instead of yielding a typed provider-output error.

Reproduced against dev (3f2e0e8):

appendExisting("toString")  -> throw: Expected string, got undefined  (tool-stream.ts:89)
finish("constructor")       -> throw: Expected string, got undefined  (tool-stream.ts:171)
appendOrStart("toString")   -> OK (its id/name guard catches it)

The value comes from the remote provider response (any OpenAI-compatible server, proxy or gateway), not from local input.

Happy to send a PR: reading pending calls through an own-property check (Object.hasOwn) fixes it without changing the state shape.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.