Skip to content

refactor(ai): remove redundant runtime type checks on schema-decoded values - #57605

Merged
rekram1-node merged 1 commit into
devfrom
ai-typed-metadata-checks
Oct 21, 2026
Merged

rekram1-node merged 1 commit into
devfrom
ai-typed-metadata-checks

Conversation

@rekram1-node

Copy link
Copy Markdown
Contributor

Problem

Several protocol lowers and response handlers in @opencode/ai re-validated values that were already narrowed by Effect Schema or internal accessors (LLMResponse.toolCalls, ProviderMetadata, MediaPart.metadata, MediaPart.filename, MistralThinkingUnit.text, and ToolChoice validation before ProviderShared.matchToolChoice).

Change

Drop the redundant runtime guards and rely on the existing Schema-decoded types across llm.ts and the protocol adapters:

 LLM.runGenerateObject
-  response.toolCalls.find(event => LLMEvent.is.toolCall(event) && ...)
-  if (!call || !LLMEvent.is.toolCall(call))
+  response.toolCalls.find(event => event.name === GENERATE_OBJECT_TOOL_NAME)
+  if (!call)

 Protocol metadata & event lowers
   open-responses / anthropic-messages / bedrock-converse / gemini / google-interactions
-    ProviderShared.isRecord(providerMetadata?.[key])
+    providerMetadata?.[key]
   anthropic-messages
-    typeof block.content === "object" && block.content !== null && ...
+    ProviderShared.isRecord(block.content) && "type" in block.content
   mistral-chat
-    duplicate request.toolChoice?.type === "tool" && !selected guard
-    typeof unit.text === "string"
+    ProviderShared.matchToolChoice(...)
+    unit.text !== undefined

Out of scope

  • Untrusted unknown values inside Record<string, unknown> metadata payloads still retain property-level typeof or ProviderShared.isRecord checks where their values are not schema-decoded.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. I checked each removed guard against the schema-decoded type it relied on. In packages/ai on the PR head, bun run typecheck passed and bun test gave 1826 passed, 0 failed. The new optional-chained reads still return undefined safely if a metadata entry isn't the expected shape. ProviderShared.matchToolChoice already gives the same Mistral "requires a tool name" error, so removing the guard in mistral-chat.ts loses nothing. The only difference is ordering: if the provider options are also invalid, the options error now comes first.

Public API is unchanged: the changes are internal to packages/ai.

@rekram1-node
rekram1-node merged commit b991ba8 into dev Oct 21, 2026
21 checks passed
@rekram1-node
rekram1-node deleted the ai-typed-metadata-checks branch October 21, 2026 03:51
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