Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
87f305c9 fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x (#459)
* fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x
Gemini 3.x models emit thoughtSignature as a Part-level sibling of
functionCall (per @google/genai Part type), not nested inside
functionCall. The adapter was reading from functionCall.thoughtSignature
(which does not exist in the SDK types) and writing it back nested,
causing the API to reject subsequent tool-call turns with
400 INVALID_ARGUMENT: "Function call is missing a thought_signature".
Read side: check part.thoughtSignature first, fall back to
functionCall.thoughtSignature for Gemini 2.x compatibility.
Write side: emit thoughtSignature as a Part-level sibling of
functionCall instead of nesting it inside.
Closes #403
Related: #218, #401, #404
* ci: apply automated fixes
* refactor: use typed Part interface instead of any casts
Per review feedback: use the @google/genai typed `Part` interface
directly instead of `as any` casts.
- Read side: `part.thoughtSignature` is properly typed on `Part`, so
the cast is removed entirely. The Gemini 2.x fallback to
`functionCall.thoughtSignature` is also removed since the SDK has
never typed it there and Gemini has always emitted it at Part level.
- Write side: construct a typed `Part` and conditionally assign
`thoughtSignature`, avoiding the `as Part` cast on a spread literal.
The only remaining `as any` in this area is the pre-existing
functionResponse cast, which is unrelated to this fix.
* feat(ai): typed metadata on tool calls + thread through pipeline
Renames `providerMetadata` to `metadata` and types it per-adapter via a
new `TToolCallMetadata` generic on `BaseTextAdapter`, mirroring the
existing typed-metadata pattern on content parts (`ImagePart<TMetadata>`,
etc.).
Also threads metadata through the client-side UIMessage pipeline so it
round-trips with each tool call, fixing the silent drop surfaced in
#403/#404 (incorporates that PR's plumbing under the new name).
Gemini adapter now declares `TToolCallMetadata = GeminiToolCallMetadata`,
giving consumers typed `toolCall.metadata?.thoughtSignature` end-to-end.
Per maintainer feedback on #459 (AlemTuzlak): use `metadata` (typed
per-adapter generic) rather than the previous `providerMetadata` bag.
The `ToolCallStartEvent` event remains non-generic with
`metadata?: Record<string, unknown>` because making it generic breaks
the AGUIEvent discriminated-union narrowing.
Breaking: consumers reading `toolCall.providerMetadata` or
`toolCallStartEvent.providerMetadata` should rename to `metadata`.
Co-authored-by: houmark <noreply@github.com>
* test: thread toolCallMetadata through mock adapters
Added the new TToolCallMetadata generic to BaseTextAdapter requires
mock adapters in tests/test-utils.ts and tests/type-check.test.ts to
include toolCallMetadata in their `~types` block.
* fix(ai): preserve metadata in ProcessorResult.toolCalls + event-client mirror
CodeRabbit review feedback:
- StreamProcessor.getCompletedToolCalls() rebuilt ToolCall objects
without forwarding `metadata`, dropping Gemini's thoughtSignature for
callers using process()/getResult().toolCalls (the streaming UI path
was already covered).
- ai-event-client mirrored ToolCall as generic but left ToolCallPart
without metadata, leaving the part-level type out of sync with the
core types in @tanstack/ai.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: houmark <noreply@github.com> 87f305c9 fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x (#459)
* fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x
Gemini 3.x models emit thoughtSignature as a Part-level sibling of
functionCall (per @google/genai Part type), not nested inside
functionCall. The adapter was reading from functionCall.thoughtSignature
(which does not exist in the SDK types) and writing it back nested,
causing the API to reject subsequent tool-call turns with
400 INVALID_ARGUMENT: "Function call is missing a thought_signature".
Read side: check part.thoughtSignature first, fall back to
functionCall.thoughtSignature for Gemini 2.x compatibility.
Write side: emit thoughtSignature as a Part-level sibling of
functionCall instead of nesting it inside.
Closes #403
Related: #218, #401, #404
* ci: apply automated fixes
* refactor: use typed Part interface instead of any casts
Per review feedback: use the @google/genai typed `Part` interface
directly instead of `as any` casts.
- Read side: `part.thoughtSignature` is properly typed on `Part`, so
the cast is removed entirely. The Gemini 2.x fallback to
`functionCall.thoughtSignature` is also removed since the SDK has
never typed it there and Gemini has always emitted it at Part level.
- Write side: construct a typed `Part` and conditionally assign
`thoughtSignature`, avoiding the `as Part` cast on a spread literal.
The only remaining `as any` in this area is the pre-existing
functionResponse cast, which is unrelated to this fix.
* feat(ai): typed metadata on tool calls + thread through pipeline
Renames `providerMetadata` to `metadata` and types it per-adapter via a
new `TToolCallMetadata` generic on `BaseTextAdapter`, mirroring the
existing typed-metadata pattern on content parts (`ImagePart<TMetadata>`,
etc.).
Also threads metadata through the client-side UIMessage pipeline so it
round-trips with each tool call, fixing the silent drop surfaced in
#403/#404 (incorporates that PR's plumbing under the new name).
Gemini adapter now declares `TToolCallMetadata = GeminiToolCallMetadata`,
giving consumers typed `toolCall.metadata?.thoughtSignature` end-to-end.
Per maintainer feedback on #459 (AlemTuzlak): use `metadata` (typed
per-adapter generic) rather than the previous `providerMetadata` bag.
The `ToolCallStartEvent` event remains non-generic with
`metadata?: Record<string, unknown>` because making it generic breaks
the AGUIEvent discriminated-union narrowing.
Breaking: consumers reading `toolCall.providerMetadata` or
`toolCallStartEvent.providerMetadata` should rename to `metadata`.
Co-authored-by: houmark <noreply@github.com>
* test: thread toolCallMetadata through mock adapters
Added the new TToolCallMetadata generic to BaseTextAdapter requires
mock adapters in tests/test-utils.ts and tests/type-check.test.ts to
include toolCallMetadata in their `~types` block.
* fix(ai): preserve metadata in ProcessorResult.toolCalls + event-client mirror
CodeRabbit review feedback:
- StreamProcessor.getCompletedToolCalls() rebuilt ToolCall objects
without forwarding `metadata`, dropping Gemini's thoughtSignature for
callers using process()/getResult().toolCalls (the streaming UI path
was already covered).
- ai-event-client mirrored ToolCall as generic but left ToolCallPart
without metadata, leaving the part-level type out of sync with the
core types in @tanstack/ai.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: houmark <noreply@github.com> 87f305c9 fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x (#459)
* fix(ai-gemini): read/write thoughtSignature at Part level for Gemini 3.x
Gemini 3.x models emit thoughtSignature as a Part-level sibling of
functionCall (per @google/genai Part type), not nested inside
functionCall. The adapter was reading from functionCall.thoughtSignature
(which does not exist in the SDK types) and writing it back nested,
causing the API to reject subsequent tool-call turns with
400 INVALID_ARGUMENT: "Function call is missing a thought_signature".
Read side: check part.thoughtSignature first, fall back to
functionCall.thoughtSignature for Gemini 2.x compatibility.
Write side: emit thoughtSignature as a Part-level sibling of
functionCall instead of nesting it inside.
Closes #403
Related: #218, #401, #404
* ci: apply automated fixes
* refactor: use typed Part interface instead of any casts
Per review feedback: use the @google/genai typed `Part` interface
directly instead of `as any` casts.
- Read side: `part.thoughtSignature` is properly typed on `Part`, so
the cast is removed entirely. The Gemini 2.x fallback to
`functionCall.thoughtSignature` is also removed since the SDK has
never typed it there and Gemini has always emitted it at Part level.
- Write side: construct a typed `Part` and conditionally assign
`thoughtSignature`, avoiding the `as Part` cast on a spread literal.
The only remaining `as any` in this area is the pre-existing
functionResponse cast, which is unrelated to this fix.
* feat(ai): typed metadata on tool calls + thread through pipeline
Renames `providerMetadata` to `metadata` and types it per-adapter via a
new `TToolCallMetadata` generic on `BaseTextAdapter`, mirroring the
existing typed-metadata pattern on content parts (`ImagePart<TMetadata>`,
etc.).
Also threads metadata through the client-side UIMessage pipeline so it
round-trips with each tool call, fixing the silent drop surfaced in
#403/#404 (incorporates that PR's plumbing under the new name).
Gemini adapter now declares `TToolCallMetadata = GeminiToolCallMetadata`,
giving consumers typed `toolCall.metadata?.thoughtSignature` end-to-end.
Per maintainer feedback on #459 (AlemTuzlak): use `metadata` (typed
per-adapter generic) rather than the previous `providerMetadata` bag.
The `ToolCallStartEvent` event remains non-generic with
`metadata?: Record<string, unknown>` because making it generic breaks
the AGUIEvent discriminated-union narrowing.
Breaking: consumers reading `toolCall.providerMetadata` or
`toolCallStartEvent.providerMetadata` should rename to `metadata`.
Co-authored-by: houmark <noreply@github.com>
* test: thread toolCallMetadata through mock adapters
Added the new TToolCallMetadata generic to BaseTextAdapter requires
mock adapters in tests/test-utils.ts and tests/type-check.test.ts to
include toolCallMetadata in their `~types` block.
* fix(ai): preserve metadata in ProcessorResult.toolCalls + event-client mirror
CodeRabbit review feedback:
- StreamProcessor.getCompletedToolCalls() rebuilt ToolCall objects
without forwarding `metadata`, dropping Gemini's thoughtSignature for
callers using process()/getResult().toolCalls (the streaming UI path
was already covered).
- ai-event-client mirrored ToolCall as generic but left ToolCallPart
without metadata, leaving the part-level type out of sync with the
core types in @tanstack/ai.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: houmark <noreply@github.com>