From 7a8cb3101d427314c2391d49fa52ab4fac0286ee Mon Sep 17 00:00:00 2001 From: Tom Beckenham <34339192+tombeckenham@users.noreply.github.com> Date: Fri, 26 Jun 2026 18:19:09 +1000 Subject: [PATCH 1/2] fix(ai-grok): make grok provider options assignable to summarize() adapter param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GrokTextProviderOptions was an `interface ... extends Record`, giving it an explicit index signature. Under strictFunctionTypes the SummarizeAdapter constraint is checked contravariantly, requiring `object` to be assignable to the provider options — which fails for an index-signature type, so grokSummarize was not assignable to summarize()'s adapter param for any model. Redefine the options as an all-optional type-alias intersection matching the OpenAI text adapter, and widen the text adapter's provider-options generic to `Record` (the intersection satisfies that but not `Record`). Adds a call-site type-level regression guard in the included ai-grok package, closing the CI gap from #820. Closes #821 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../grok-summarize-adapter-assignability.md | 16 ++++++++++++++ packages/ai-grok/src/adapters/text.ts | 6 +++++- .../ai-grok/src/text/text-provider-options.ts | 21 +++++++++++++++---- packages/ai-grok/tests/grok-adapter.test.ts | 15 ++++++++++++- 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 .changeset/grok-summarize-adapter-assignability.md diff --git a/.changeset/grok-summarize-adapter-assignability.md b/.changeset/grok-summarize-adapter-assignability.md new file mode 100644 index 000000000..7f3a327fc --- /dev/null +++ b/.changeset/grok-summarize-adapter-assignability.md @@ -0,0 +1,16 @@ +--- +'@tanstack/ai-grok': patch +--- + +Fix `grokSummarize`/`createGrokSummarize` not being assignable to `summarize()`'s +`adapter` param for any current Grok model (`grok-4.3`, `grok-build-0.1`). + +`GrokTextProviderOptions` was declared as an `interface` extending +`Record`, giving it an explicit index signature. Under +`strictFunctionTypes`, the `SummarizeAdapter` constraint is checked +contravariantly, which requires `object` to be assignable to the provider +options — but `object` is not assignable to an index-signature type, so the +check failed (Grok-only; OpenAI's all-optional, no-index-signature options +passed). The options are now a type-alias intersection matching the OpenAI +shape, and the text adapter's provider-options constraint is widened to +`Record` to mirror `OpenAITextAdapter`. diff --git a/packages/ai-grok/src/adapters/text.ts b/packages/ai-grok/src/adapters/text.ts index 1e8e3fb15..37e9557cb 100644 --- a/packages/ai-grok/src/adapters/text.ts +++ b/packages/ai-grok/src/adapters/text.ts @@ -43,7 +43,11 @@ export type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../ */ export class GrokTextAdapter< TModel extends (typeof GROK_CHAT_MODELS)[number], - TProviderOptions extends Record = + // Use `Record` (not `unknown`) to match the OpenAI text + // adapter: the resolved Grok provider options are a type-alias intersection + // with no explicit index signature, which is assignable to + // `Record` but not `Record`. See issue #821. + TProviderOptions extends Record = ResolveProviderOptions, TInputModalities extends ReadonlyArray = ResolveInputModalities, diff --git a/packages/ai-grok/src/text/text-provider-options.ts b/packages/ai-grok/src/text/text-provider-options.ts index 9cc319df4..dd430ac96 100644 --- a/packages/ai-grok/src/text/text-provider-options.ts +++ b/packages/ai-grok/src/text/text-provider-options.ts @@ -29,11 +29,9 @@ export interface GrokBaseOptions { } /** - * Grok-specific provider options for text/chat - * Based on xAI Responses API options + * Sampling and response controls for Grok text/chat models. */ -export interface GrokTextProviderOptions - extends GrokBaseOptions, Record { +export interface GrokSamplingOptions { /** * Temperature for response generation (0-2) * Higher values make output more random, lower values more focused @@ -62,6 +60,21 @@ export interface GrokTextProviderOptions reasoning?: GrokReasoning } +/** + * Grok-specific provider options for text/chat + * Based on xAI Responses API options. + * + * Declared as a type-alias intersection of interfaces with all-optional props + * (matching the OpenAI text adapter), NOT an `interface ... extends + * Record`. An explicit index signature makes `object` + * un-assignable to these options, which breaks the contravariantly-checked + * `summarize()` adapter constraint (`SummarizeAdapter`); see + * issue #821. Without the index signature these options no longer satisfy a + * `Record` constraint, so the text adapter's provider-options + * generic is widened to `Record` to match OpenAI. + */ +export type GrokTextProviderOptions = GrokBaseOptions & GrokSamplingOptions + export type GrokBuildProviderOptions = Omit< GrokTextProviderOptions, 'reasoning' diff --git a/packages/ai-grok/tests/grok-adapter.test.ts b/packages/ai-grok/tests/grok-adapter.test.ts index 4b50cb898..72cbbfba7 100644 --- a/packages/ai-grok/tests/grok-adapter.test.ts +++ b/packages/ai-grok/tests/grok-adapter.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { resolveDebugOption } from '@tanstack/ai/adapter-internals' -import { EventType } from '@tanstack/ai' +import { EventType, summarize } from '@tanstack/ai' import { createGrokText, grokText } from '../src/adapters/text' import { createGrokImage, grokImage } from '../src/adapters/image' import { createGrokSummarize, grokSummarize } from '../src/adapters/summarize' @@ -498,5 +498,18 @@ describe('Grok adapters', () => { 'XAI_API_KEY is required', ) }) + + it('grokSummarize is assignable to summarize() adapter param for every model (#821)', () => { + // Type-level regression guard: the SummarizeAdapter constraint only + // instantiates at the summarize() call site, so constructing the adapter + // (covered above) is not enough. This closure is type-checked but never + // executed — passing CI's test:types is the assertion. + const _typeCheck = () => { + void summarize({ adapter: grokSummarize('grok-4.3'), text: '' }) + void summarize({ adapter: grokSummarize('grok-build-0.1'), text: '' }) + } + + expect(_typeCheck).toBeInstanceOf(Function) + }) }) }) From 604cc3d9c7d1bce7768ad0a74dbec125cf6a2e29 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 08:20:53 +0000 Subject: [PATCH 2/2] ci: apply automated fixes --- packages/ai-grok/src/adapters/text.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ai-grok/src/adapters/text.ts b/packages/ai-grok/src/adapters/text.ts index 37e9557cb..366676a45 100644 --- a/packages/ai-grok/src/adapters/text.ts +++ b/packages/ai-grok/src/adapters/text.ts @@ -47,8 +47,7 @@ export class GrokTextAdapter< // adapter: the resolved Grok provider options are a type-alias intersection // with no explicit index signature, which is assignable to // `Record` but not `Record`. See issue #821. - TProviderOptions extends Record = - ResolveProviderOptions, + TProviderOptions extends Record = ResolveProviderOptions, TInputModalities extends ReadonlyArray = ResolveInputModalities, TToolCapabilities extends ReadonlyArray =