@tanstack/ai-grok 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
- import { OpenAICompatibleImageAdapter } from '@tanstack/openai-base';
1
+ import { default as OpenAI } from 'openai';
2
+ import { BaseImageAdapter } from '@tanstack/ai/adapters';
3
+ import { ImageGenerationOptions, ImageGenerationResult } from '@tanstack/ai';
2
4
  import { GrokImageModel } from '../model-meta.js';
3
5
  import { GrokImageModelProviderOptionsByName, GrokImageModelSizeByName, GrokImageProviderOptions } from '../image/image-provider-options.js';
4
6
  import { GrokClientConfig } from '../utils.js';
@@ -18,16 +20,12 @@ export interface GrokImageConfig extends GrokClientConfig {
18
20
  * - Size validation per model
19
21
  * - Number of images validation
20
22
  */
21
- export declare class GrokImageAdapter<TModel extends GrokImageModel> extends OpenAICompatibleImageAdapter<TModel, GrokImageProviderOptions, GrokImageModelProviderOptionsByName, GrokImageModelSizeByName> {
23
+ export declare class GrokImageAdapter<TModel extends GrokImageModel> extends BaseImageAdapter<TModel, GrokImageProviderOptions, GrokImageModelProviderOptionsByName, GrokImageModelSizeByName> {
22
24
  readonly kind: "image";
23
25
  readonly name: "grok";
26
+ protected client: OpenAI;
24
27
  constructor(config: GrokImageConfig, model: TModel);
25
- protected validatePrompt(options: {
26
- prompt: string;
27
- model: string;
28
- }): void;
29
- protected validateImageSize(model: string, size: string | undefined): void;
30
- protected validateNumberOfImages(model: string, numberOfImages: number | undefined): void;
28
+ generateImages(options: ImageGenerationOptions<GrokImageProviderOptions>): Promise<ImageGenerationResult>;
31
29
  }
32
30
  /**
33
31
  * Creates a Grok image adapter with explicit API key.
@@ -1,20 +1,66 @@
1
- import { OpenAICompatibleImageAdapter } from "@tanstack/openai-base";
1
+ import OpenAI from "openai";
2
+ import { BaseImageAdapter } from "@tanstack/ai/adapters";
3
+ import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
4
+ import { generateId } from "@tanstack/ai-utils";
2
5
  import { withGrokDefaults, getGrokApiKeyFromEnv } from "../utils/client.js";
3
6
  import { validatePrompt, validateImageSize, validateNumberOfImages } from "../image/image-provider-options.js";
4
- class GrokImageAdapter extends OpenAICompatibleImageAdapter {
7
+ class GrokImageAdapter extends BaseImageAdapter {
5
8
  constructor(config, model) {
6
- super(withGrokDefaults(config), model, "grok");
9
+ super(model, {});
7
10
  this.kind = "image";
8
11
  this.name = "grok";
12
+ this.client = new OpenAI(withGrokDefaults(config));
9
13
  }
10
- validatePrompt(options) {
11
- validatePrompt(options);
12
- }
13
- validateImageSize(model, size) {
14
+ async generateImages(options) {
15
+ const { model, prompt, numberOfImages, size, modelOptions } = options;
16
+ validatePrompt({ prompt });
14
17
  validateImageSize(model, size);
15
- }
16
- validateNumberOfImages(model, numberOfImages) {
17
18
  validateNumberOfImages(model, numberOfImages);
19
+ const request = {
20
+ model,
21
+ prompt,
22
+ n: numberOfImages ?? 1,
23
+ size,
24
+ ...modelOptions
25
+ };
26
+ try {
27
+ options.logger.request(
28
+ `activity=image provider=${this.name} model=${model} n=${request.n ?? 1} size=${request.size ?? "default"}`,
29
+ { provider: this.name, model }
30
+ );
31
+ const response = await this.client.images.generate({
32
+ ...request,
33
+ stream: false
34
+ });
35
+ const images = (response.data ?? []).flatMap(
36
+ (item) => {
37
+ const revisedPrompt = item.revised_prompt;
38
+ if (item.b64_json) {
39
+ return [{ b64Json: item.b64_json, revisedPrompt }];
40
+ }
41
+ if (item.url) {
42
+ return [{ url: item.url, revisedPrompt }];
43
+ }
44
+ return [];
45
+ }
46
+ );
47
+ return {
48
+ id: generateId(this.name),
49
+ model,
50
+ images,
51
+ usage: response.usage ? {
52
+ inputTokens: response.usage.input_tokens,
53
+ outputTokens: response.usage.output_tokens,
54
+ totalTokens: response.usage.total_tokens
55
+ } : void 0
56
+ };
57
+ } catch (error) {
58
+ options.logger.errors(`${this.name}.generateImages fatal`, {
59
+ error: toRunErrorPayload(error, `${this.name}.generateImages failed`),
60
+ source: `${this.name}.generateImages`
61
+ });
62
+ throw error;
63
+ }
18
64
  }
19
65
  }
20
66
  function createGrokImage(model, apiKey, config) {
@@ -1 +1 @@
1
- {"version":3,"file":"image.js","sources":["../../../src/adapters/image.ts"],"sourcesContent":["import { OpenAICompatibleImageAdapter } from '@tanstack/openai-base'\nimport { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'\nimport {\n validateImageSize,\n validateNumberOfImages,\n validatePrompt,\n} from '../image/image-provider-options'\nimport type { GrokImageModel } from '../model-meta'\nimport type {\n GrokImageModelProviderOptionsByName,\n GrokImageModelSizeByName,\n GrokImageProviderOptions,\n} from '../image/image-provider-options'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok image adapter\n */\nexport interface GrokImageConfig extends GrokClientConfig {}\n\n/**\n * Grok Image Generation Adapter\n *\n * Tree-shakeable adapter for Grok image generation functionality.\n * Supports grok-2-image-1212 model.\n *\n * Features:\n * - Model-specific type-safe provider options\n * - Size validation per model\n * - Number of images validation\n */\nexport class GrokImageAdapter<\n TModel extends GrokImageModel,\n> extends OpenAICompatibleImageAdapter<\n TModel,\n GrokImageProviderOptions,\n GrokImageModelProviderOptionsByName,\n GrokImageModelSizeByName\n> {\n readonly kind = 'image' as const\n readonly name = 'grok' as const\n\n constructor(config: GrokImageConfig, model: TModel) {\n super(withGrokDefaults(config), model, 'grok')\n }\n\n protected override validatePrompt(options: {\n prompt: string\n model: string\n }): void {\n validatePrompt(options)\n }\n\n protected override validateImageSize(\n model: string,\n size: string | undefined,\n ): void {\n validateImageSize(model, size)\n }\n\n protected override validateNumberOfImages(\n model: string,\n numberOfImages: number | undefined,\n ): void {\n validateNumberOfImages(model, numberOfImages)\n }\n}\n\n/**\n * Creates a Grok image adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-2-image-1212')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok image adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokImage('grok-2-image-1212', \"xai-...\");\n *\n * const result = await generateImage({\n * adapter,\n * prompt: 'A cute baby sea otter'\n * });\n * ```\n */\nexport function createGrokImage<TModel extends GrokImageModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokImageConfig, 'apiKey'>,\n): GrokImageAdapter<TModel> {\n return new GrokImageAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok image adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-2-image-1212')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok image adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokImage('grok-2-image-1212');\n *\n * const result = await generateImage({\n * adapter,\n * prompt: 'A beautiful sunset over mountains'\n * });\n * ```\n */\nexport function grokImage<TModel extends GrokImageModel>(\n model: TModel,\n config?: Omit<GrokImageConfig, 'apiKey'>,\n): GrokImageAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokImage(model, apiKey, config)\n}\n"],"names":[],"mappings":";;;AA+BO,MAAM,yBAEH,6BAKR;AAAA,EAIA,YAAY,QAAyB,OAAe;AAClD,UAAM,iBAAiB,MAAM,GAAG,OAAO,MAAM;AAJ/C,SAAS,OAAO;AAChB,SAAS,OAAO;AAAA,EAIhB;AAAA,EAEmB,eAAe,SAGzB;AACP,mBAAe,OAAO;AAAA,EACxB;AAAA,EAEmB,kBACjB,OACA,MACM;AACN,sBAAkB,OAAO,IAAI;AAAA,EAC/B;AAAA,EAEmB,uBACjB,OACA,gBACM;AACN,2BAAuB,OAAO,cAAc;AAAA,EAC9C;AACF;AAqBO,SAAS,gBACd,OACA,QACA,QAC0B;AAC1B,SAAO,IAAI,iBAAiB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AAC1D;AA0BO,SAAS,UACd,OACA,QAC0B;AAC1B,QAAM,SAAS,qBAAA;AACf,SAAO,gBAAgB,OAAO,QAAQ,MAAM;AAC9C;"}
1
+ {"version":3,"file":"image.js","sources":["../../../src/adapters/image.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { BaseImageAdapter } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { generateId } from '@tanstack/ai-utils'\nimport { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'\nimport {\n validateImageSize,\n validateNumberOfImages,\n validatePrompt,\n} from '../image/image-provider-options'\nimport type {\n GeneratedImage,\n ImageGenerationOptions,\n ImageGenerationResult,\n} from '@tanstack/ai'\nimport type OpenAI_SDK from 'openai'\nimport type { GrokImageModel } from '../model-meta'\nimport type {\n GrokImageModelProviderOptionsByName,\n GrokImageModelSizeByName,\n GrokImageProviderOptions,\n} from '../image/image-provider-options'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok image adapter\n */\nexport interface GrokImageConfig extends GrokClientConfig {}\n\n/**\n * Grok Image Generation Adapter\n *\n * Tree-shakeable adapter for Grok image generation functionality.\n * Supports grok-2-image-1212 model.\n *\n * Features:\n * - Model-specific type-safe provider options\n * - Size validation per model\n * - Number of images validation\n */\nexport class GrokImageAdapter<\n TModel extends GrokImageModel,\n> extends BaseImageAdapter<\n TModel,\n GrokImageProviderOptions,\n GrokImageModelProviderOptionsByName,\n GrokImageModelSizeByName\n> {\n readonly kind = 'image' as const\n readonly name = 'grok' as const\n\n protected client: OpenAI\n\n constructor(config: GrokImageConfig, model: TModel) {\n super(model, {})\n this.client = new OpenAI(withGrokDefaults(config))\n }\n\n async generateImages(\n options: ImageGenerationOptions<GrokImageProviderOptions>,\n ): Promise<ImageGenerationResult> {\n const { model, prompt, numberOfImages, size, modelOptions } = options\n\n validatePrompt({ prompt, model })\n validateImageSize(model, size)\n validateNumberOfImages(model, numberOfImages)\n\n const request: OpenAI_SDK.Images.ImageGenerateParams = {\n model,\n prompt,\n n: numberOfImages ?? 1,\n size: size as OpenAI_SDK.Images.ImageGenerateParams['size'],\n ...modelOptions,\n }\n\n try {\n options.logger.request(\n `activity=image provider=${this.name} model=${model} n=${request.n ?? 1} size=${request.size ?? 'default'}`,\n { provider: this.name, model },\n )\n const response = await this.client.images.generate({\n ...request,\n stream: false,\n })\n\n const images: Array<GeneratedImage> = (response.data ?? []).flatMap(\n (item): Array<GeneratedImage> => {\n const revisedPrompt = item.revised_prompt\n if (item.b64_json) {\n return [{ b64Json: item.b64_json, revisedPrompt }]\n }\n if (item.url) {\n return [{ url: item.url, revisedPrompt }]\n }\n return []\n },\n )\n\n return {\n id: generateId(this.name),\n model,\n images,\n usage: response.usage\n ? {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens,\n }\n : undefined,\n }\n } catch (error: unknown) {\n options.logger.errors(`${this.name}.generateImages fatal`, {\n error: toRunErrorPayload(error, `${this.name}.generateImages failed`),\n source: `${this.name}.generateImages`,\n })\n throw error\n }\n }\n}\n\n/**\n * Creates a Grok image adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-2-image-1212')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok image adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokImage('grok-2-image-1212', \"xai-...\");\n *\n * const result = await generateImage({\n * adapter,\n * prompt: 'A cute baby sea otter'\n * });\n * ```\n */\nexport function createGrokImage<TModel extends GrokImageModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokImageConfig, 'apiKey'>,\n): GrokImageAdapter<TModel> {\n return new GrokImageAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok image adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-2-image-1212')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok image adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokImage('grok-2-image-1212');\n *\n * const result = await generateImage({\n * adapter,\n * prompt: 'A beautiful sunset over mountains'\n * });\n * ```\n */\nexport function grokImage<TModel extends GrokImageModel>(\n model: TModel,\n config?: Omit<GrokImageConfig, 'apiKey'>,\n): GrokImageAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokImage(model, apiKey, config)\n}\n"],"names":[],"mappings":";;;;;;AAwCO,MAAM,yBAEH,iBAKR;AAAA,EAMA,YAAY,QAAyB,OAAe;AAClD,UAAM,OAAO,EAAE;AANjB,SAAS,OAAO;AAChB,SAAS,OAAO;AAMd,SAAK,SAAS,IAAI,OAAO,iBAAiB,MAAM,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,eACJ,SACgC;AAChC,UAAM,EAAE,OAAO,QAAQ,gBAAgB,MAAM,iBAAiB;AAE9D,mBAAe,EAAE,OAAc,CAAC;AAChC,sBAAkB,OAAO,IAAI;AAC7B,2BAAuB,OAAO,cAAc;AAE5C,UAAM,UAAiD;AAAA,MACrD;AAAA,MACA;AAAA,MACA,GAAG,kBAAkB;AAAA,MACrB;AAAA,MACA,GAAG;AAAA,IAAA;AAGL,QAAI;AACF,cAAQ,OAAO;AAAA,QACb,2BAA2B,KAAK,IAAI,UAAU,KAAK,MAAM,QAAQ,KAAK,CAAC,SAAS,QAAQ,QAAQ,SAAS;AAAA,QACzG,EAAE,UAAU,KAAK,MAAM,MAAA;AAAA,MAAM;AAE/B,YAAM,WAAW,MAAM,KAAK,OAAO,OAAO,SAAS;AAAA,QACjD,GAAG;AAAA,QACH,QAAQ;AAAA,MAAA,CACT;AAED,YAAM,UAAiC,SAAS,QAAQ,CAAA,GAAI;AAAA,QAC1D,CAAC,SAAgC;AAC/B,gBAAM,gBAAgB,KAAK;AAC3B,cAAI,KAAK,UAAU;AACjB,mBAAO,CAAC,EAAE,SAAS,KAAK,UAAU,eAAe;AAAA,UACnD;AACA,cAAI,KAAK,KAAK;AACZ,mBAAO,CAAC,EAAE,KAAK,KAAK,KAAK,eAAe;AAAA,UAC1C;AACA,iBAAO,CAAA;AAAA,QACT;AAAA,MAAA;AAGF,aAAO;AAAA,QACL,IAAI,WAAW,KAAK,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA,OAAO,SAAS,QACZ;AAAA,UACE,aAAa,SAAS,MAAM;AAAA,UAC5B,cAAc,SAAS,MAAM;AAAA,UAC7B,aAAa,SAAS,MAAM;AAAA,QAAA,IAE9B;AAAA,MAAA;AAAA,IAER,SAAS,OAAgB;AACvB,cAAQ,OAAO,OAAO,GAAG,KAAK,IAAI,yBAAyB;AAAA,QACzD,OAAO,kBAAkB,OAAO,GAAG,KAAK,IAAI,wBAAwB;AAAA,QACpE,QAAQ,GAAG,KAAK,IAAI;AAAA,MAAA,CACrB;AACD,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAqBO,SAAS,gBACd,OACA,QACA,QAC0B;AAC1B,SAAO,IAAI,iBAAiB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AAC1D;AA0BO,SAAS,UACd,OACA,QAC0B;AAC1B,QAAM,SAAS,qBAAA;AACf,SAAO,gBAAgB,OAAO,QAAQ,MAAM;AAC9C;"}
@@ -1,4 +1,5 @@
1
- import { OpenAICompatibleSummarizeAdapter } from '@tanstack/openai-base';
1
+ import { ChatStreamSummarizeAdapter, InferTextProviderOptions } from '@tanstack/ai/adapters';
2
+ import { GrokTextAdapter } from './text.js';
2
3
  import { GROK_CHAT_MODELS } from '../model-meta.js';
3
4
  import { GrokClientConfig } from '../utils.js';
4
5
  /**
@@ -6,28 +7,8 @@ import { GrokClientConfig } from '../utils.js';
6
7
  */
7
8
  export interface GrokSummarizeConfig extends GrokClientConfig {
8
9
  }
9
- /**
10
- * Grok-specific provider options for summarization
11
- */
12
- export interface GrokSummarizeProviderOptions {
13
- /** Temperature for response generation (0-2) */
14
- temperature?: number;
15
- /** Maximum tokens in the response */
16
- maxTokens?: number;
17
- }
18
10
  /** Model type for Grok summarization */
19
11
  export type GrokSummarizeModel = (typeof GROK_CHAT_MODELS)[number];
20
- /**
21
- * Grok Summarize Adapter
22
- *
23
- * A thin wrapper around the text adapter that adds summarization-specific prompting.
24
- * Delegates all API calls to the GrokTextAdapter.
25
- */
26
- export declare class GrokSummarizeAdapter<TModel extends GrokSummarizeModel> extends OpenAICompatibleSummarizeAdapter<TModel, GrokSummarizeProviderOptions> {
27
- readonly kind: "summarize";
28
- readonly name: "grok";
29
- constructor(config: GrokSummarizeConfig, model: TModel);
30
- }
31
12
  /**
32
13
  * Creates a Grok summarize adapter with explicit API key.
33
14
  * Type resolution happens here at the call site.
@@ -42,7 +23,7 @@ export declare class GrokSummarizeAdapter<TModel extends GrokSummarizeModel> ext
42
23
  * const adapter = createGrokSummarize('grok-3', "xai-...");
43
24
  * ```
44
25
  */
45
- export declare function createGrokSummarize<TModel extends GrokSummarizeModel>(model: TModel, apiKey: string, config?: Omit<GrokSummarizeConfig, 'apiKey'>): GrokSummarizeAdapter<TModel>;
26
+ export declare function createGrokSummarize<TModel extends GrokSummarizeModel>(model: TModel, apiKey: string, config?: Omit<GrokSummarizeConfig, 'apiKey'>): ChatStreamSummarizeAdapter<TModel, InferTextProviderOptions<GrokTextAdapter<TModel>>>;
46
27
  /**
47
28
  * Creates a Grok summarize adapter with automatic API key detection from environment variables.
48
29
  * Type resolution happens here at the call site.
@@ -67,4 +48,4 @@ export declare function createGrokSummarize<TModel extends GrokSummarizeModel>(m
67
48
  * });
68
49
  * ```
69
50
  */
70
- export declare function grokSummarize<TModel extends GrokSummarizeModel>(model: TModel, config?: Omit<GrokSummarizeConfig, 'apiKey'>): GrokSummarizeAdapter<TModel>;
51
+ export declare function grokSummarize<TModel extends GrokSummarizeModel>(model: TModel, config?: Omit<GrokSummarizeConfig, 'apiKey'>): ChatStreamSummarizeAdapter<TModel, InferTextProviderOptions<GrokTextAdapter<TModel>>>;
@@ -1,30 +1,19 @@
1
- import { OpenAICompatibleSummarizeAdapter } from "@tanstack/openai-base";
1
+ import { ChatStreamSummarizeAdapter } from "@tanstack/ai/adapters";
2
2
  import "@tanstack/ai-utils";
3
3
  import { getGrokApiKeyFromEnv } from "../utils/client.js";
4
+ import "@tanstack/openai-base";
4
5
  import { GrokTextAdapter } from "./text.js";
5
- class GrokSummarizeAdapter extends OpenAICompatibleSummarizeAdapter {
6
- constructor(config, model) {
7
- super(
8
- new GrokTextAdapter(
9
- config,
10
- model
11
- ),
12
- model,
13
- "grok"
14
- );
15
- this.kind = "summarize";
16
- this.name = "grok";
17
- }
18
- }
19
6
  function createGrokSummarize(model, apiKey, config) {
20
- return new GrokSummarizeAdapter({ apiKey, ...config }, model);
7
+ return new ChatStreamSummarizeAdapter(
8
+ new GrokTextAdapter({ apiKey, ...config }, model),
9
+ model,
10
+ "grok"
11
+ );
21
12
  }
22
13
  function grokSummarize(model, config) {
23
- const apiKey = getGrokApiKeyFromEnv();
24
- return createGrokSummarize(model, apiKey, config);
14
+ return createGrokSummarize(model, getGrokApiKeyFromEnv(), config);
25
15
  }
26
16
  export {
27
- GrokSummarizeAdapter,
28
17
  createGrokSummarize,
29
18
  grokSummarize
30
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"summarize.js","sources":["../../../src/adapters/summarize.ts"],"sourcesContent":["import { OpenAICompatibleSummarizeAdapter } from '@tanstack/openai-base'\nimport { getGrokApiKeyFromEnv } from '../utils'\nimport { GrokTextAdapter } from './text'\nimport type { ChatStreamCapable } from '@tanstack/openai-base'\nimport type { GROK_CHAT_MODELS } from '../model-meta'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok summarize adapter\n */\nexport interface GrokSummarizeConfig extends GrokClientConfig {}\n\n/**\n * Grok-specific provider options for summarization\n */\nexport interface GrokSummarizeProviderOptions {\n /** Temperature for response generation (0-2) */\n temperature?: number\n /** Maximum tokens in the response */\n maxTokens?: number\n}\n\n/** Model type for Grok summarization */\nexport type GrokSummarizeModel = (typeof GROK_CHAT_MODELS)[number]\n\n/**\n * Grok Summarize Adapter\n *\n * A thin wrapper around the text adapter that adds summarization-specific prompting.\n * Delegates all API calls to the GrokTextAdapter.\n */\nexport class GrokSummarizeAdapter<\n TModel extends GrokSummarizeModel,\n> extends OpenAICompatibleSummarizeAdapter<\n TModel,\n GrokSummarizeProviderOptions\n> {\n readonly kind = 'summarize' as const\n readonly name = 'grok' as const\n\n constructor(config: GrokSummarizeConfig, model: TModel) {\n // The text adapter accepts richer provider options than the summarize adapter needs,\n // but we only pass basic options (model, messages, systemPrompts, etc.) at call time.\n super(\n new GrokTextAdapter(\n config,\n model,\n ) as unknown as ChatStreamCapable<GrokSummarizeProviderOptions>,\n model,\n 'grok',\n )\n }\n}\n\n/**\n * Creates a Grok summarize adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok summarize adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokSummarize('grok-3', \"xai-...\");\n * ```\n */\nexport function createGrokSummarize<TModel extends GrokSummarizeModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokSummarizeConfig, 'apiKey'>,\n): GrokSummarizeAdapter<TModel> {\n return new GrokSummarizeAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok summarize adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok summarize adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokSummarize('grok-3');\n *\n * await summarize({\n * adapter,\n * text: \"Long article text...\"\n * });\n * ```\n */\nexport function grokSummarize<TModel extends GrokSummarizeModel>(\n model: TModel,\n config?: Omit<GrokSummarizeConfig, 'apiKey'>,\n): GrokSummarizeAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokSummarize(model, apiKey, config)\n}\n"],"names":[],"mappings":";;;;AA+BO,MAAM,6BAEH,iCAGR;AAAA,EAIA,YAAY,QAA6B,OAAe;AAGtD;AAAA,MACE,IAAI;AAAA,QACF;AAAA,QACA;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA;AAZJ,SAAS,OAAO;AAChB,SAAS,OAAO;AAAA,EAahB;AACF;AAgBO,SAAS,oBACd,OACA,QACA,QAC8B;AAC9B,SAAO,IAAI,qBAAqB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AAC9D;AA0BO,SAAS,cACd,OACA,QAC8B;AAC9B,QAAM,SAAS,qBAAA;AACf,SAAO,oBAAoB,OAAO,QAAQ,MAAM;AAClD;"}
1
+ {"version":3,"file":"summarize.js","sources":["../../../src/adapters/summarize.ts"],"sourcesContent":["import { ChatStreamSummarizeAdapter } from '@tanstack/ai/adapters'\nimport { getGrokApiKeyFromEnv } from '../utils'\nimport { GrokTextAdapter } from './text'\nimport type { InferTextProviderOptions } from '@tanstack/ai/adapters'\nimport type { GROK_CHAT_MODELS } from '../model-meta'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok summarize adapter\n */\nexport interface GrokSummarizeConfig extends GrokClientConfig {}\n\n/** Model type for Grok summarization */\nexport type GrokSummarizeModel = (typeof GROK_CHAT_MODELS)[number]\n\n/**\n * Creates a Grok summarize adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok summarize adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokSummarize('grok-3', \"xai-...\");\n * ```\n */\nexport function createGrokSummarize<TModel extends GrokSummarizeModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokSummarizeConfig, 'apiKey'>,\n): ChatStreamSummarizeAdapter<\n TModel,\n InferTextProviderOptions<GrokTextAdapter<TModel>>\n> {\n return new ChatStreamSummarizeAdapter(\n new GrokTextAdapter({ apiKey, ...config }, model),\n model,\n 'grok',\n )\n}\n\n/**\n * Creates a Grok summarize adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok summarize adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokSummarize('grok-3');\n *\n * await summarize({\n * adapter,\n * text: \"Long article text...\"\n * });\n * ```\n */\nexport function grokSummarize<TModel extends GrokSummarizeModel>(\n model: TModel,\n config?: Omit<GrokSummarizeConfig, 'apiKey'>,\n): ChatStreamSummarizeAdapter<\n TModel,\n InferTextProviderOptions<GrokTextAdapter<TModel>>\n> {\n return createGrokSummarize(model, getGrokApiKeyFromEnv(), config)\n}\n"],"names":[],"mappings":";;;;;AA6BO,SAAS,oBACd,OACA,QACA,QAIA;AACA,SAAO,IAAI;AAAA,IACT,IAAI,gBAAgB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AAAA,IAChD;AAAA,IACA;AAAA,EAAA;AAEJ;AA0BO,SAAS,cACd,OACA,QAIA;AACA,SAAO,oBAAoB,OAAO,qBAAA,GAAwB,MAAM;AAClE;"}
@@ -1,4 +1,5 @@
1
- import { OpenAICompatibleChatCompletionsTextAdapter } from '@tanstack/openai-base';
1
+ import { default as OpenAI } from 'openai';
2
+ import { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base';
2
3
  import { GROK_CHAT_MODELS, GrokChatModelToolCapabilitiesByName, ResolveInputModalities, ResolveProviderOptions } from '../model-meta.js';
3
4
  import { Modality } from '@tanstack/ai';
4
5
  import { GrokMessageMetadataByModality } from '../message-types.js';
@@ -22,14 +23,24 @@ export type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../
22
23
  * Tree-shakeable adapter for Grok chat/text completion functionality.
23
24
  * Uses OpenAI-compatible Chat Completions API (not Responses API).
24
25
  *
25
- * Delegates implementation to {@link OpenAICompatibleChatCompletionsTextAdapter}
26
- * from `@tanstack/openai-base` and threads Grok-specific tool-capability typing
27
- * through the 5th generic of the base class.
26
+ * Delegates implementation to {@link OpenAIBaseChatCompletionsTextAdapter}
27
+ * from `@tanstack/openai-base` and threads Grok-specific tool-capability
28
+ * typing through the 5th generic of the base class.
28
29
  */
29
- export declare class GrokTextAdapter<TModel extends (typeof GROK_CHAT_MODELS)[number], TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>, TToolCapabilities extends ReadonlyArray<string> = ResolveToolCapabilities<TModel>> extends OpenAICompatibleChatCompletionsTextAdapter<TModel, TProviderOptions, TInputModalities, GrokMessageMetadataByModality, TToolCapabilities> {
30
+ export declare class GrokTextAdapter<TModel extends (typeof GROK_CHAT_MODELS)[number], TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>, TToolCapabilities extends ReadonlyArray<string> = ResolveToolCapabilities<TModel>> extends OpenAIBaseChatCompletionsTextAdapter<TModel, TProviderOptions, TInputModalities, GrokMessageMetadataByModality, TToolCapabilities> {
30
31
  readonly kind: "text";
31
32
  readonly name: "grok";
32
33
  constructor(config: GrokTextConfig, model: TModel);
34
+ /**
35
+ * Surfaces xAI reasoning deltas on Grok reasoning models. The DeepSeek-style
36
+ * convention puts the chain-of-thought on `delta.reasoning_content`; some
37
+ * Grok variants also populate `delta.reasoning`. Reading both keeps
38
+ * reasoning flowing through the base's REASONING_* lifecycle for both
39
+ * `chatStream` and `structuredOutputStream`.
40
+ */
41
+ protected extractReasoning(chunk: OpenAI.Chat.Completions.ChatCompletionChunk): {
42
+ text: string;
43
+ } | undefined;
33
44
  }
34
45
  /**
35
46
  * Creates a Grok text adapter with explicit API key.
@@ -1,11 +1,27 @@
1
- import { OpenAICompatibleChatCompletionsTextAdapter } from "@tanstack/openai-base";
1
+ import OpenAI from "openai";
2
+ import { OpenAIBaseChatCompletionsTextAdapter } from "@tanstack/openai-base";
2
3
  import { withGrokDefaults, getGrokApiKeyFromEnv } from "../utils/client.js";
3
- class GrokTextAdapter extends OpenAICompatibleChatCompletionsTextAdapter {
4
+ class GrokTextAdapter extends OpenAIBaseChatCompletionsTextAdapter {
4
5
  constructor(config, model) {
5
- super(withGrokDefaults(config), model, "grok");
6
+ super(model, "grok", new OpenAI(withGrokDefaults(config)));
6
7
  this.kind = "text";
7
8
  this.name = "grok";
8
9
  }
10
+ /**
11
+ * Surfaces xAI reasoning deltas on Grok reasoning models. The DeepSeek-style
12
+ * convention puts the chain-of-thought on `delta.reasoning_content`; some
13
+ * Grok variants also populate `delta.reasoning`. Reading both keeps
14
+ * reasoning flowing through the base's REASONING_* lifecycle for both
15
+ * `chatStream` and `structuredOutputStream`.
16
+ */
17
+ extractReasoning(chunk) {
18
+ const delta = chunk.choices[0]?.delta;
19
+ const raw = delta?.reasoning_content ?? delta?.reasoning;
20
+ if (typeof raw === "string" && raw.length > 0) {
21
+ return { text: raw };
22
+ }
23
+ return void 0;
24
+ }
9
25
  }
10
26
  function createGrokText(model, apiKey, config) {
11
27
  return new GrokTextAdapter({ apiKey, ...config }, model);
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { OpenAICompatibleChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'\nimport type {\n GROK_CHAT_MODELS,\n GrokChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type { Modality } from '@tanstack/ai'\nimport type { GrokMessageMetadataByModality } from '../message-types'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Resolve tool capabilities for a specific Grok model.\n */\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GrokChatModelToolCapabilitiesByName\n ? NonNullable<GrokChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Configuration for Grok text adapter\n */\nexport interface GrokTextConfig extends GrokClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Grok Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Grok chat/text completion functionality.\n * Uses OpenAI-compatible Chat Completions API (not Responses API).\n *\n * Delegates implementation to {@link OpenAICompatibleChatCompletionsTextAdapter}\n * from `@tanstack/openai-base` and threads Grok-specific tool-capability typing\n * through the 5th generic of the base class.\n */\nexport class GrokTextAdapter<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAICompatibleChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n GrokMessageMetadataByModality,\n TToolCapabilities\n> {\n readonly kind = 'text' as const\n readonly name = 'grok' as const\n\n constructor(config: GrokTextConfig, model: TModel) {\n super(withGrokDefaults(config), model, 'grok')\n }\n}\n\n/**\n * Creates a Grok text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokText('grok-3', \"xai-...\");\n * // adapter has type-safe providerOptions for grok-3\n * ```\n */\nexport function createGrokText<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n return new GrokTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok text adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokText('grok-3');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function grokText<TModel extends (typeof GROK_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokText(model, apiKey, config)\n}\n"],"names":[],"mappings":";;AAwCO,MAAM,wBAOH,2CAMR;AAAA,EAIA,YAAY,QAAwB,OAAe;AACjD,UAAM,iBAAiB,MAAM,GAAG,OAAO,MAAM;AAJ/C,SAAS,OAAO;AAChB,SAAS,OAAO;AAAA,EAIhB;AACF;AAiBO,SAAS,eAGd,OACA,QACA,QACyB;AACzB,SAAO,IAAI,gBAAgB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AACzD;AA0BO,SAAS,SACd,OACA,QACyB;AACzB,QAAM,SAAS,qBAAA;AACf,SAAO,eAAe,OAAO,QAAQ,MAAM;AAC7C;"}
1
+ {"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'\nimport type {\n GROK_CHAT_MODELS,\n GrokChatModelToolCapabilitiesByName,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\nimport type { Modality } from '@tanstack/ai'\nimport type { GrokMessageMetadataByModality } from '../message-types'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Resolve tool capabilities for a specific Grok model.\n */\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof GrokChatModelToolCapabilitiesByName\n ? NonNullable<GrokChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Configuration for Grok text adapter\n */\nexport interface GrokTextConfig extends GrokClientConfig {}\n\n/**\n * Alias for TextProviderOptions for external use\n */\nexport type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../text/text-provider-options'\n\n/**\n * Grok Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Grok chat/text completion functionality.\n * Uses OpenAI-compatible Chat Completions API (not Responses API).\n *\n * Delegates implementation to {@link OpenAIBaseChatCompletionsTextAdapter}\n * from `@tanstack/openai-base` and threads Grok-specific tool-capability\n * typing through the 5th generic of the base class.\n */\nexport class GrokTextAdapter<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAIBaseChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n GrokMessageMetadataByModality,\n TToolCapabilities\n> {\n readonly kind = 'text' as const\n readonly name = 'grok' as const\n\n constructor(config: GrokTextConfig, model: TModel) {\n super(model, 'grok', new OpenAI(withGrokDefaults(config)))\n }\n\n /**\n * Surfaces xAI reasoning deltas on Grok reasoning models. The DeepSeek-style\n * convention puts the chain-of-thought on `delta.reasoning_content`; some\n * Grok variants also populate `delta.reasoning`. Reading both keeps\n * reasoning flowing through the base's REASONING_* lifecycle for both\n * `chatStream` and `structuredOutputStream`.\n */\n protected override extractReasoning(\n chunk: OpenAI.Chat.Completions.ChatCompletionChunk,\n ): { text: string } | undefined {\n const delta = chunk.choices[0]?.delta as\n | { reasoning?: unknown; reasoning_content?: unknown }\n | undefined\n const raw = delta?.reasoning_content ?? delta?.reasoning\n if (typeof raw === 'string' && raw.length > 0) {\n return { text: raw }\n }\n return undefined\n }\n}\n\n/**\n * Creates a Grok text adapter with explicit API key.\n * Type resolution happens here at the call site.\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok text adapter instance with resolved types\n *\n * @example\n * ```typescript\n * const adapter = createGrokText('grok-3', \"xai-...\");\n * // adapter has type-safe providerOptions for grok-3\n * ```\n */\nexport function createGrokText<\n TModel extends (typeof GROK_CHAT_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n return new GrokTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok text adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @param model - The model name (e.g., 'grok-3', 'grok-4')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok text adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokText('grok-3');\n *\n * const stream = chat({\n * adapter,\n * messages: [{ role: \"user\", content: \"Hello!\" }]\n * });\n * ```\n */\nexport function grokText<TModel extends (typeof GROK_CHAT_MODELS)[number]>(\n model: TModel,\n config?: Omit<GrokTextConfig, 'apiKey'>,\n): GrokTextAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokText(model, apiKey, config)\n}\n"],"names":[],"mappings":";;;AAyCO,MAAM,wBAOH,qCAMR;AAAA,EAIA,YAAY,QAAwB,OAAe;AACjD,UAAM,OAAO,QAAQ,IAAI,OAAO,iBAAiB,MAAM,CAAC,CAAC;AAJ3D,SAAS,OAAO;AAChB,SAAS,OAAO;AAAA,EAIhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASmB,iBACjB,OAC8B;AAC9B,UAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG;AAGhC,UAAM,MAAM,OAAO,qBAAqB,OAAO;AAC/C,QAAI,OAAO,QAAQ,YAAY,IAAI,SAAS,GAAG;AAC7C,aAAO,EAAE,MAAM,IAAA;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACF;AAiBO,SAAS,eAGd,OACA,QACA,QACyB;AACzB,SAAO,IAAI,gBAAgB,EAAE,QAAQ,GAAG,OAAA,GAAU,KAAK;AACzD;AA0BO,SAAS,SACd,OACA,QACyB;AACzB,QAAM,SAAS,qBAAA;AACf,SAAO,eAAe,OAAO,QAAQ,MAAM;AAC7C;"}
@@ -1,5 +1,5 @@
1
1
  export { GrokTextAdapter, createGrokText, grokText, type GrokTextConfig, type GrokTextProviderOptions, } from './adapters/text.js';
2
- export { GrokSummarizeAdapter, createGrokSummarize, grokSummarize, type GrokSummarizeConfig, type GrokSummarizeProviderOptions, type GrokSummarizeModel, } from './adapters/summarize.js';
2
+ export { createGrokSummarize, grokSummarize, type GrokSummarizeConfig, type GrokSummarizeModel, } from './adapters/summarize.js';
3
3
  export { GrokImageAdapter, createGrokImage, grokImage, type GrokImageConfig, } from './adapters/image.js';
4
4
  export type { GrokImageProviderOptions, GrokImageModelProviderOptionsByName, } from './image/image-provider-options.js';
5
5
  export { GrokSpeechAdapter, createGrokSpeech, grokSpeech, type GrokSpeechConfig, } from './adapters/tts.js';
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { GrokTextAdapter, createGrokText, grokText } from "./adapters/text.js";
2
- import { GrokSummarizeAdapter, createGrokSummarize, grokSummarize } from "./adapters/summarize.js";
2
+ import { createGrokSummarize, grokSummarize } from "./adapters/summarize.js";
3
3
  import { GrokImageAdapter, createGrokImage, grokImage } from "./adapters/image.js";
4
4
  import { GrokSpeechAdapter, createGrokSpeech, grokSpeech } from "./adapters/tts.js";
5
5
  import { GrokTranscriptionAdapter, createGrokTranscription, grokTranscription } from "./adapters/transcription.js";
@@ -14,7 +14,6 @@ export {
14
14
  GROK_TTS_MODELS,
15
15
  GrokImageAdapter,
16
16
  GrokSpeechAdapter,
17
- GrokSummarizeAdapter,
18
17
  GrokTextAdapter,
19
18
  GrokTranscriptionAdapter,
20
19
  createGrokImage,
@@ -1,5 +1,6 @@
1
- import { OpenAICompatibleClientConfig } from '@tanstack/openai-base';
2
- export interface GrokClientConfig extends OpenAICompatibleClientConfig {
1
+ import { ClientOptions } from 'openai';
2
+ export interface GrokClientConfig extends Omit<ClientOptions, 'apiKey'> {
3
+ apiKey: string;
3
4
  }
4
5
  /**
5
6
  * Gets Grok API key from environment variables
@@ -10,4 +11,4 @@ export declare function getGrokApiKeyFromEnv(): string;
10
11
  * Returns a Grok client config with the default xAI base URL applied
11
12
  * when not already set.
12
13
  */
13
- export declare function withGrokDefaults(config: GrokClientConfig): OpenAICompatibleClientConfig;
14
+ export declare function withGrokDefaults(config: GrokClientConfig): GrokClientConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sources":["../../../src/utils/client.ts"],"sourcesContent":["import { getApiKeyFromEnv } from '@tanstack/ai-utils'\nimport type { OpenAICompatibleClientConfig } from '@tanstack/openai-base'\n\nexport interface GrokClientConfig extends OpenAICompatibleClientConfig {}\n\n/**\n * Gets Grok API key from environment variables\n * @throws Error if XAI_API_KEY is not found\n */\nexport function getGrokApiKeyFromEnv(): string {\n try {\n return getApiKeyFromEnv('XAI_API_KEY')\n } catch {\n throw new Error(\n 'XAI_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key.',\n )\n }\n}\n\n/**\n * Returns a Grok client config with the default xAI base URL applied\n * when not already set.\n */\nexport function withGrokDefaults(\n config: GrokClientConfig,\n): OpenAICompatibleClientConfig {\n return {\n ...config,\n baseURL: config.baseURL || 'https://api.x.ai/v1',\n }\n}\n"],"names":[],"mappings":";AASO,SAAS,uBAA+B;AAC7C,MAAI;AACF,WAAO,iBAAiB,aAAa;AAAA,EACvC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AAMO,SAAS,iBACd,QAC8B;AAC9B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,OAAO,WAAW;AAAA,EAAA;AAE/B;"}
1
+ {"version":3,"file":"client.js","sources":["../../../src/utils/client.ts"],"sourcesContent":["import { getApiKeyFromEnv } from '@tanstack/ai-utils'\nimport type { ClientOptions } from 'openai'\n\nexport interface GrokClientConfig extends Omit<ClientOptions, 'apiKey'> {\n apiKey: string\n}\n\n/**\n * Gets Grok API key from environment variables\n * @throws Error if XAI_API_KEY is not found\n */\nexport function getGrokApiKeyFromEnv(): string {\n try {\n return getApiKeyFromEnv('XAI_API_KEY')\n } catch {\n throw new Error(\n 'XAI_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key.',\n )\n }\n}\n\n/**\n * Returns a Grok client config with the default xAI base URL applied\n * when not already set.\n */\nexport function withGrokDefaults(config: GrokClientConfig): GrokClientConfig {\n return {\n ...config,\n baseURL: config.baseURL || 'https://api.x.ai/v1',\n }\n}\n"],"names":[],"mappings":";AAWO,SAAS,uBAA+B;AAC7C,MAAI;AACF,WAAO,iBAAiB,aAAa;AAAA,EACvC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AAMO,SAAS,iBAAiB,QAA4C;AAC3E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,OAAO,WAAW;AAAA,EAAA;AAE/B;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-grok",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "Grok (xAI) adapter for TanStack AI",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -34,18 +34,19 @@
34
34
  "adapter"
35
35
  ],
36
36
  "dependencies": {
37
+ "openai": "^6.9.1",
37
38
  "@tanstack/ai-utils": "0.2.0",
38
- "@tanstack/openai-base": "0.2.0"
39
+ "@tanstack/openai-base": "0.3.0"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@vitest/coverage-v8": "4.0.14",
42
43
  "vite": "^7.2.7",
43
- "@tanstack/ai": "0.15.0",
44
- "@tanstack/ai-client": "0.9.0"
44
+ "@tanstack/ai": "0.17.0",
45
+ "@tanstack/ai-client": "0.9.2"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "zod": "^4.0.0",
48
- "@tanstack/ai": "^0.15.0"
49
+ "@tanstack/ai": "^0.17.0"
49
50
  },
50
51
  "scripts": {
51
52
  "build": "vite build",
@@ -1,10 +1,19 @@
1
- import { OpenAICompatibleImageAdapter } from '@tanstack/openai-base'
1
+ import OpenAI from 'openai'
2
+ import { BaseImageAdapter } from '@tanstack/ai/adapters'
3
+ import { toRunErrorPayload } from '@tanstack/ai/adapter-internals'
4
+ import { generateId } from '@tanstack/ai-utils'
2
5
  import { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'
3
6
  import {
4
7
  validateImageSize,
5
8
  validateNumberOfImages,
6
9
  validatePrompt,
7
10
  } from '../image/image-provider-options'
11
+ import type {
12
+ GeneratedImage,
13
+ ImageGenerationOptions,
14
+ ImageGenerationResult,
15
+ } from '@tanstack/ai'
16
+ import type OpenAI_SDK from 'openai'
8
17
  import type { GrokImageModel } from '../model-meta'
9
18
  import type {
10
19
  GrokImageModelProviderOptionsByName,
@@ -31,7 +40,7 @@ export interface GrokImageConfig extends GrokClientConfig {}
31
40
  */
32
41
  export class GrokImageAdapter<
33
42
  TModel extends GrokImageModel,
34
- > extends OpenAICompatibleImageAdapter<
43
+ > extends BaseImageAdapter<
35
44
  TModel,
36
45
  GrokImageProviderOptions,
37
46
  GrokImageModelProviderOptionsByName,
@@ -40,29 +49,72 @@ export class GrokImageAdapter<
40
49
  readonly kind = 'image' as const
41
50
  readonly name = 'grok' as const
42
51
 
52
+ protected client: OpenAI
53
+
43
54
  constructor(config: GrokImageConfig, model: TModel) {
44
- super(withGrokDefaults(config), model, 'grok')
55
+ super(model, {})
56
+ this.client = new OpenAI(withGrokDefaults(config))
45
57
  }
46
58
 
47
- protected override validatePrompt(options: {
48
- prompt: string
49
- model: string
50
- }): void {
51
- validatePrompt(options)
52
- }
59
+ async generateImages(
60
+ options: ImageGenerationOptions<GrokImageProviderOptions>,
61
+ ): Promise<ImageGenerationResult> {
62
+ const { model, prompt, numberOfImages, size, modelOptions } = options
53
63
 
54
- protected override validateImageSize(
55
- model: string,
56
- size: string | undefined,
57
- ): void {
64
+ validatePrompt({ prompt, model })
58
65
  validateImageSize(model, size)
59
- }
60
-
61
- protected override validateNumberOfImages(
62
- model: string,
63
- numberOfImages: number | undefined,
64
- ): void {
65
66
  validateNumberOfImages(model, numberOfImages)
67
+
68
+ const request: OpenAI_SDK.Images.ImageGenerateParams = {
69
+ model,
70
+ prompt,
71
+ n: numberOfImages ?? 1,
72
+ size: size as OpenAI_SDK.Images.ImageGenerateParams['size'],
73
+ ...modelOptions,
74
+ }
75
+
76
+ try {
77
+ options.logger.request(
78
+ `activity=image provider=${this.name} model=${model} n=${request.n ?? 1} size=${request.size ?? 'default'}`,
79
+ { provider: this.name, model },
80
+ )
81
+ const response = await this.client.images.generate({
82
+ ...request,
83
+ stream: false,
84
+ })
85
+
86
+ const images: Array<GeneratedImage> = (response.data ?? []).flatMap(
87
+ (item): Array<GeneratedImage> => {
88
+ const revisedPrompt = item.revised_prompt
89
+ if (item.b64_json) {
90
+ return [{ b64Json: item.b64_json, revisedPrompt }]
91
+ }
92
+ if (item.url) {
93
+ return [{ url: item.url, revisedPrompt }]
94
+ }
95
+ return []
96
+ },
97
+ )
98
+
99
+ return {
100
+ id: generateId(this.name),
101
+ model,
102
+ images,
103
+ usage: response.usage
104
+ ? {
105
+ inputTokens: response.usage.input_tokens,
106
+ outputTokens: response.usage.output_tokens,
107
+ totalTokens: response.usage.total_tokens,
108
+ }
109
+ : undefined,
110
+ }
111
+ } catch (error: unknown) {
112
+ options.logger.errors(`${this.name}.generateImages fatal`, {
113
+ error: toRunErrorPayload(error, `${this.name}.generateImages failed`),
114
+ source: `${this.name}.generateImages`,
115
+ })
116
+ throw error
117
+ }
66
118
  }
67
119
  }
68
120
 
@@ -1,7 +1,7 @@
1
- import { OpenAICompatibleSummarizeAdapter } from '@tanstack/openai-base'
1
+ import { ChatStreamSummarizeAdapter } from '@tanstack/ai/adapters'
2
2
  import { getGrokApiKeyFromEnv } from '../utils'
3
3
  import { GrokTextAdapter } from './text'
4
- import type { ChatStreamCapable } from '@tanstack/openai-base'
4
+ import type { InferTextProviderOptions } from '@tanstack/ai/adapters'
5
5
  import type { GROK_CHAT_MODELS } from '../model-meta'
6
6
  import type { GrokClientConfig } from '../utils'
7
7
 
@@ -10,48 +10,9 @@ import type { GrokClientConfig } from '../utils'
10
10
  */
11
11
  export interface GrokSummarizeConfig extends GrokClientConfig {}
12
12
 
13
- /**
14
- * Grok-specific provider options for summarization
15
- */
16
- export interface GrokSummarizeProviderOptions {
17
- /** Temperature for response generation (0-2) */
18
- temperature?: number
19
- /** Maximum tokens in the response */
20
- maxTokens?: number
21
- }
22
-
23
13
  /** Model type for Grok summarization */
24
14
  export type GrokSummarizeModel = (typeof GROK_CHAT_MODELS)[number]
25
15
 
26
- /**
27
- * Grok Summarize Adapter
28
- *
29
- * A thin wrapper around the text adapter that adds summarization-specific prompting.
30
- * Delegates all API calls to the GrokTextAdapter.
31
- */
32
- export class GrokSummarizeAdapter<
33
- TModel extends GrokSummarizeModel,
34
- > extends OpenAICompatibleSummarizeAdapter<
35
- TModel,
36
- GrokSummarizeProviderOptions
37
- > {
38
- readonly kind = 'summarize' as const
39
- readonly name = 'grok' as const
40
-
41
- constructor(config: GrokSummarizeConfig, model: TModel) {
42
- // The text adapter accepts richer provider options than the summarize adapter needs,
43
- // but we only pass basic options (model, messages, systemPrompts, etc.) at call time.
44
- super(
45
- new GrokTextAdapter(
46
- config,
47
- model,
48
- ) as unknown as ChatStreamCapable<GrokSummarizeProviderOptions>,
49
- model,
50
- 'grok',
51
- )
52
- }
53
- }
54
-
55
16
  /**
56
17
  * Creates a Grok summarize adapter with explicit API key.
57
18
  * Type resolution happens here at the call site.
@@ -70,8 +31,15 @@ export function createGrokSummarize<TModel extends GrokSummarizeModel>(
70
31
  model: TModel,
71
32
  apiKey: string,
72
33
  config?: Omit<GrokSummarizeConfig, 'apiKey'>,
73
- ): GrokSummarizeAdapter<TModel> {
74
- return new GrokSummarizeAdapter({ apiKey, ...config }, model)
34
+ ): ChatStreamSummarizeAdapter<
35
+ TModel,
36
+ InferTextProviderOptions<GrokTextAdapter<TModel>>
37
+ > {
38
+ return new ChatStreamSummarizeAdapter(
39
+ new GrokTextAdapter({ apiKey, ...config }, model),
40
+ model,
41
+ 'grok',
42
+ )
75
43
  }
76
44
 
77
45
  /**
@@ -101,7 +69,9 @@ export function createGrokSummarize<TModel extends GrokSummarizeModel>(
101
69
  export function grokSummarize<TModel extends GrokSummarizeModel>(
102
70
  model: TModel,
103
71
  config?: Omit<GrokSummarizeConfig, 'apiKey'>,
104
- ): GrokSummarizeAdapter<TModel> {
105
- const apiKey = getGrokApiKeyFromEnv()
106
- return createGrokSummarize(model, apiKey, config)
72
+ ): ChatStreamSummarizeAdapter<
73
+ TModel,
74
+ InferTextProviderOptions<GrokTextAdapter<TModel>>
75
+ > {
76
+ return createGrokSummarize(model, getGrokApiKeyFromEnv(), config)
107
77
  }
@@ -1,4 +1,5 @@
1
- import { OpenAICompatibleChatCompletionsTextAdapter } from '@tanstack/openai-base'
1
+ import OpenAI from 'openai'
2
+ import { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'
2
3
  import { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'
3
4
  import type {
4
5
  GROK_CHAT_MODELS,
@@ -34,9 +35,9 @@ export type { ExternalTextProviderOptions as GrokTextProviderOptions } from '../
34
35
  * Tree-shakeable adapter for Grok chat/text completion functionality.
35
36
  * Uses OpenAI-compatible Chat Completions API (not Responses API).
36
37
  *
37
- * Delegates implementation to {@link OpenAICompatibleChatCompletionsTextAdapter}
38
- * from `@tanstack/openai-base` and threads Grok-specific tool-capability typing
39
- * through the 5th generic of the base class.
38
+ * Delegates implementation to {@link OpenAIBaseChatCompletionsTextAdapter}
39
+ * from `@tanstack/openai-base` and threads Grok-specific tool-capability
40
+ * typing through the 5th generic of the base class.
40
41
  */
41
42
  export class GrokTextAdapter<
42
43
  TModel extends (typeof GROK_CHAT_MODELS)[number],
@@ -45,7 +46,7 @@ export class GrokTextAdapter<
45
46
  ResolveInputModalities<TModel>,
46
47
  TToolCapabilities extends ReadonlyArray<string> =
47
48
  ResolveToolCapabilities<TModel>,
48
- > extends OpenAICompatibleChatCompletionsTextAdapter<
49
+ > extends OpenAIBaseChatCompletionsTextAdapter<
49
50
  TModel,
50
51
  TProviderOptions,
51
52
  TInputModalities,
@@ -56,7 +57,27 @@ export class GrokTextAdapter<
56
57
  readonly name = 'grok' as const
57
58
 
58
59
  constructor(config: GrokTextConfig, model: TModel) {
59
- super(withGrokDefaults(config), model, 'grok')
60
+ super(model, 'grok', new OpenAI(withGrokDefaults(config)))
61
+ }
62
+
63
+ /**
64
+ * Surfaces xAI reasoning deltas on Grok reasoning models. The DeepSeek-style
65
+ * convention puts the chain-of-thought on `delta.reasoning_content`; some
66
+ * Grok variants also populate `delta.reasoning`. Reading both keeps
67
+ * reasoning flowing through the base's REASONING_* lifecycle for both
68
+ * `chatStream` and `structuredOutputStream`.
69
+ */
70
+ protected override extractReasoning(
71
+ chunk: OpenAI.Chat.Completions.ChatCompletionChunk,
72
+ ): { text: string } | undefined {
73
+ const delta = chunk.choices[0]?.delta as
74
+ | { reasoning?: unknown; reasoning_content?: unknown }
75
+ | undefined
76
+ const raw = delta?.reasoning_content ?? delta?.reasoning
77
+ if (typeof raw === 'string' && raw.length > 0) {
78
+ return { text: raw }
79
+ }
80
+ return undefined
60
81
  }
61
82
  }
62
83
 
package/src/index.ts CHANGED
@@ -11,13 +11,11 @@ export {
11
11
  type GrokTextProviderOptions,
12
12
  } from './adapters/text'
13
13
 
14
- // Summarize adapter - for text summarization
14
+ // Summarize - thin factory functions over @tanstack/ai's ChatStreamSummarizeAdapter
15
15
  export {
16
- GrokSummarizeAdapter,
17
16
  createGrokSummarize,
18
17
  grokSummarize,
19
18
  type GrokSummarizeConfig,
20
- type GrokSummarizeProviderOptions,
21
19
  type GrokSummarizeModel,
22
20
  } from './adapters/summarize'
23
21
 
@@ -1,7 +1,9 @@
1
1
  import { getApiKeyFromEnv } from '@tanstack/ai-utils'
2
- import type { OpenAICompatibleClientConfig } from '@tanstack/openai-base'
2
+ import type { ClientOptions } from 'openai'
3
3
 
4
- export interface GrokClientConfig extends OpenAICompatibleClientConfig {}
4
+ export interface GrokClientConfig extends Omit<ClientOptions, 'apiKey'> {
5
+ apiKey: string
6
+ }
5
7
 
6
8
  /**
7
9
  * Gets Grok API key from environment variables
@@ -21,9 +23,7 @@ export function getGrokApiKeyFromEnv(): string {
21
23
  * Returns a Grok client config with the default xAI base URL applied
22
24
  * when not already set.
23
25
  */
24
- export function withGrokDefaults(
25
- config: GrokClientConfig,
26
- ): OpenAICompatibleClientConfig {
26
+ export function withGrokDefaults(config: GrokClientConfig): GrokClientConfig {
27
27
  return {
28
28
  ...config,
29
29
  baseURL: config.baseURL || 'https://api.x.ai/v1',