Skip to content

feat(ai): export ToolCallState type#13443

Open
21lakshh wants to merge 5 commits intovercel:mainfrom
21lakshh:feat/export-tool-call-state-type
Open

feat(ai): export ToolCallState type#13443
21lakshh wants to merge 5 commits intovercel:mainfrom
21lakshh:feat/export-tool-call-state-type

Conversation

@21lakshh
Copy link
Copy Markdown

Background

Currently, the state property within UIToolInvocation and DynamicToolUIPart is typed using inline literal strings (e.g., { state: 'input-streaming'; ... }). While this correctly enables TypeScript's discriminated union narrowing (allowing TypeScript to know part.output is available when state === 'output-available'), it creates a major pain point for developers using the SDK.

Because the union of these literal strings is never exported as a standalone named type, developers cannot cleanly reference the possible states in their own code.

Without an exported ToolCallState type, developers are forced to use brittle workarounds when building UI components that handle tool calls. Specifically, it prevents them from doing common patterns like:

  1. Typing Component Props: You cannot safely type a component that renders based on state ({ state: ToolCallState }).
  2. Creating Reusable Helper Functions: You cannot create type-safe helper functions to group states together (e.g., isTerminalState(state)).
  3. Defining Types for Handlers/Mutations: You cannot easily pass state handlers around your application layer (type MutationHandler = (state: ToolCallState) => void).

Summary

  • Extracted the 7 inline literal strings into an exported ToolCallState string union type in packages/ai/src/ui/ui-messages.ts.
  • Re-exported ToolCallState from the ui barrel files (packages/ai/src/ui/index.ts -> packages/ai/src/index.ts).
  • Added formal type tests in ui-messages.test-d.ts to ensure the union matches expectations.
  • Updated the official UIMessage documentation in content/ to document the new ToolCallState union.
  • Kept the existing exact discriminated union design perfectly intact. The literal types remain strictly enforced in the UIToolInvocation union, ensuring existing TypeScript narrowing behavior works exactly identically to before.

Manual Verification

  • Ran pnpm type-check:full across the entire workspace to ensure no internal code breaks.
  • Validated that import { type ToolCallState } from 'ai' works correctly in a consuming app context.
  • Used Vitest --typecheck to enforce that a purposefully missing literal string from ToolCallState correctly flags a type mismatch error.

Checklist

  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

@tigent tigent bot added ai/ui anything UI related documentation Improvements or additions to documentation feature New feature or request labels Mar 15, 2026
@21lakshh
Copy link
Copy Markdown
Author

21lakshh commented Apr 9, 2026

@gr2m could you check this out please been a while :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai/ui anything UI related documentation Improvements or additions to documentation feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant