@tanstack/ai-grok 0.0.1 → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +113 -28
- package/dist/esm/adapters/image.d.ts +77 -0
- package/dist/esm/adapters/image.js +63 -0
- package/dist/esm/adapters/image.js.map +1 -0
- package/dist/esm/adapters/summarize.d.ts +75 -0
- package/dist/esm/adapters/summarize.js +81 -0
- package/dist/esm/adapters/summarize.js.map +1 -0
- package/dist/esm/adapters/text.d.ts +96 -0
- package/dist/esm/adapters/text.js +300 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/image/image-provider-options.d.ts +66 -0
- package/dist/esm/image/image-provider-options.js +39 -0
- package/dist/esm/image/image-provider-options.js.map +1 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/message-types.d.ts +64 -0
- package/dist/esm/model-meta.d.ts +223 -0
- package/dist/esm/model-meta.js +47 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/text-provider-options.d.ts +66 -0
- package/dist/esm/text/text-provider-options.js +6 -0
- package/dist/esm/text/text-provider-options.js.map +1 -0
- package/dist/esm/tools/function-tool.d.ts +15 -0
- package/dist/esm/tools/function-tool.js +27 -0
- package/dist/esm/tools/function-tool.js.map +1 -0
- package/dist/esm/tools/index.d.ts +2 -0
- package/dist/esm/tools/tool-converter.d.ts +7 -0
- package/dist/esm/tools/tool-converter.js +10 -0
- package/dist/esm/tools/tool-converter.js.map +1 -0
- package/dist/esm/utils/client.d.ts +18 -0
- package/dist/esm/utils/client.js +26 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/schema-converter.d.ts +24 -0
- package/dist/esm/utils/schema-converter.js +71 -0
- package/dist/esm/utils/schema-converter.js.map +1 -0
- package/package.json +50 -7
- package/src/adapters/image.ts +176 -0
- package/src/adapters/summarize.ts +174 -0
- package/src/adapters/text.ts +506 -0
- package/src/image/image-provider-options.ts +118 -0
- package/src/index.ts +55 -0
- package/src/message-types.ts +67 -0
- package/src/model-meta.ts +298 -0
- package/src/text/text-provider-options.ts +77 -0
- package/src/tools/function-tool.ts +45 -0
- package/src/tools/index.ts +5 -0
- package/src/tools/tool-converter.ts +17 -0
- package/src/utils/client.ts +45 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/schema-converter.ts +110 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
declare const GROK_4_1_FAST_REASONING: {
|
|
2
|
+
readonly name: "grok-4-1-fast-reasoning";
|
|
3
|
+
readonly context_window: 2000000;
|
|
4
|
+
readonly supports: {
|
|
5
|
+
readonly input: ["text", "image"];
|
|
6
|
+
readonly output: ["text"];
|
|
7
|
+
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
8
|
+
};
|
|
9
|
+
readonly pricing: {
|
|
10
|
+
readonly input: {
|
|
11
|
+
readonly normal: 0.2;
|
|
12
|
+
readonly cached: 0.05;
|
|
13
|
+
};
|
|
14
|
+
readonly output: {
|
|
15
|
+
readonly normal: 0.5;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
declare const GROK_4_1_FAST_NON_REASONING: {
|
|
20
|
+
readonly name: "grok-4-1-fast-non-reasoning";
|
|
21
|
+
readonly context_window: 2000000;
|
|
22
|
+
readonly supports: {
|
|
23
|
+
readonly input: ["text", "image"];
|
|
24
|
+
readonly output: ["text"];
|
|
25
|
+
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
26
|
+
};
|
|
27
|
+
readonly pricing: {
|
|
28
|
+
readonly input: {
|
|
29
|
+
readonly normal: 0.2;
|
|
30
|
+
readonly cached: 0.05;
|
|
31
|
+
};
|
|
32
|
+
readonly output: {
|
|
33
|
+
readonly normal: 0.5;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
declare const GROK_CODE_FAST_1: {
|
|
38
|
+
readonly name: "grok-code-fast-1";
|
|
39
|
+
readonly context_window: 256000;
|
|
40
|
+
readonly supports: {
|
|
41
|
+
readonly input: ["text"];
|
|
42
|
+
readonly output: ["text"];
|
|
43
|
+
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
44
|
+
};
|
|
45
|
+
readonly pricing: {
|
|
46
|
+
readonly input: {
|
|
47
|
+
readonly normal: 0.2;
|
|
48
|
+
readonly cached: 0.02;
|
|
49
|
+
};
|
|
50
|
+
readonly output: {
|
|
51
|
+
readonly normal: 1.5;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
declare const GROK_4_FAST_REASONING: {
|
|
56
|
+
readonly name: "grok-4-fast-reasoning";
|
|
57
|
+
readonly context_window: 2000000;
|
|
58
|
+
readonly supports: {
|
|
59
|
+
readonly input: ["text", "image"];
|
|
60
|
+
readonly output: ["text"];
|
|
61
|
+
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
62
|
+
};
|
|
63
|
+
readonly pricing: {
|
|
64
|
+
readonly input: {
|
|
65
|
+
readonly normal: 0.2;
|
|
66
|
+
readonly cached: 0.05;
|
|
67
|
+
};
|
|
68
|
+
readonly output: {
|
|
69
|
+
readonly normal: 0.5;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
declare const GROK_4_FAST_NON_REASONING: {
|
|
74
|
+
readonly name: "grok-4-fast-non-reasoning";
|
|
75
|
+
readonly context_window: 2000000;
|
|
76
|
+
readonly supports: {
|
|
77
|
+
readonly input: ["text", "image"];
|
|
78
|
+
readonly output: ["text"];
|
|
79
|
+
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
80
|
+
};
|
|
81
|
+
readonly pricing: {
|
|
82
|
+
readonly input: {
|
|
83
|
+
readonly normal: 0.2;
|
|
84
|
+
readonly cached: 0.05;
|
|
85
|
+
};
|
|
86
|
+
readonly output: {
|
|
87
|
+
readonly normal: 0.5;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
declare const GROK_4: {
|
|
92
|
+
readonly name: "grok-4";
|
|
93
|
+
readonly context_window: 256000;
|
|
94
|
+
readonly supports: {
|
|
95
|
+
readonly input: ["text", "image"];
|
|
96
|
+
readonly output: ["text"];
|
|
97
|
+
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
98
|
+
};
|
|
99
|
+
readonly pricing: {
|
|
100
|
+
readonly input: {
|
|
101
|
+
readonly normal: 3;
|
|
102
|
+
readonly cached: 0.75;
|
|
103
|
+
};
|
|
104
|
+
readonly output: {
|
|
105
|
+
readonly normal: 15;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
declare const GROK_3_MINI: {
|
|
110
|
+
readonly name: "grok-3-mini";
|
|
111
|
+
readonly context_window: 131072;
|
|
112
|
+
readonly supports: {
|
|
113
|
+
readonly input: ["text"];
|
|
114
|
+
readonly output: ["text"];
|
|
115
|
+
readonly capabilities: ["reasoning", "structured_outputs", "tool_calling"];
|
|
116
|
+
};
|
|
117
|
+
readonly pricing: {
|
|
118
|
+
readonly input: {
|
|
119
|
+
readonly normal: 0.3;
|
|
120
|
+
readonly cached: 0.075;
|
|
121
|
+
};
|
|
122
|
+
readonly output: {
|
|
123
|
+
readonly normal: 0.5;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
declare const GROK_3: {
|
|
128
|
+
readonly name: "grok-3";
|
|
129
|
+
readonly context_window: 131072;
|
|
130
|
+
readonly supports: {
|
|
131
|
+
readonly input: ["text"];
|
|
132
|
+
readonly output: ["text"];
|
|
133
|
+
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
134
|
+
};
|
|
135
|
+
readonly pricing: {
|
|
136
|
+
readonly input: {
|
|
137
|
+
readonly normal: 3;
|
|
138
|
+
readonly cached: 0.75;
|
|
139
|
+
};
|
|
140
|
+
readonly output: {
|
|
141
|
+
readonly normal: 15;
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
declare const GROK_2_VISION: {
|
|
146
|
+
readonly name: "grok-2-vision-1212";
|
|
147
|
+
readonly context_window: 32768;
|
|
148
|
+
readonly supports: {
|
|
149
|
+
readonly input: ["text", "image"];
|
|
150
|
+
readonly output: ["text"];
|
|
151
|
+
readonly capabilities: ["structured_outputs", "tool_calling"];
|
|
152
|
+
};
|
|
153
|
+
readonly pricing: {
|
|
154
|
+
readonly input: {
|
|
155
|
+
readonly normal: 2;
|
|
156
|
+
};
|
|
157
|
+
readonly output: {
|
|
158
|
+
readonly normal: 10;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Grok Chat Models
|
|
164
|
+
* Based on xAI's available models as of 2025
|
|
165
|
+
*/
|
|
166
|
+
export declare const GROK_CHAT_MODELS: readonly ["grok-4-1-fast-reasoning", "grok-4-1-fast-non-reasoning", "grok-code-fast-1", "grok-4-fast-reasoning", "grok-4-fast-non-reasoning", "grok-4", "grok-3", "grok-3-mini", "grok-2-vision-1212"];
|
|
167
|
+
/**
|
|
168
|
+
* Grok Image Generation Models
|
|
169
|
+
*/
|
|
170
|
+
export declare const GROK_IMAGE_MODELS: readonly ["grok-2-image-1212"];
|
|
171
|
+
/**
|
|
172
|
+
* Type-only map from Grok chat model name to its supported input modalities.
|
|
173
|
+
* Used for type inference when constructing multimodal messages.
|
|
174
|
+
*/
|
|
175
|
+
export type GrokModelInputModalitiesByName = {
|
|
176
|
+
[GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.input;
|
|
177
|
+
[GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.input;
|
|
178
|
+
[GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.input;
|
|
179
|
+
[GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.input;
|
|
180
|
+
[GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.input;
|
|
181
|
+
[GROK_4.name]: typeof GROK_4.supports.input;
|
|
182
|
+
[GROK_3.name]: typeof GROK_3.supports.input;
|
|
183
|
+
[GROK_3_MINI.name]: typeof GROK_3_MINI.supports.input;
|
|
184
|
+
[GROK_2_VISION.name]: typeof GROK_2_VISION.supports.input;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Type-only map from Grok chat model name to its provider options type.
|
|
188
|
+
* Since Grok uses OpenAI-compatible API, we reuse OpenAI provider options.
|
|
189
|
+
*/
|
|
190
|
+
export type GrokChatModelProviderOptionsByName = {
|
|
191
|
+
[K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Grok-specific provider options
|
|
195
|
+
* Based on OpenAI-compatible API options
|
|
196
|
+
*/
|
|
197
|
+
export interface GrokProviderOptions {
|
|
198
|
+
/** Temperature for response generation (0-2) */
|
|
199
|
+
temperature?: number;
|
|
200
|
+
/** Maximum tokens in the response */
|
|
201
|
+
max_tokens?: number;
|
|
202
|
+
/** Top-p sampling parameter */
|
|
203
|
+
top_p?: number;
|
|
204
|
+
/** Frequency penalty (-2.0 to 2.0) */
|
|
205
|
+
frequency_penalty?: number;
|
|
206
|
+
/** Presence penalty (-2.0 to 2.0) */
|
|
207
|
+
presence_penalty?: number;
|
|
208
|
+
/** Stop sequences */
|
|
209
|
+
stop?: string | Array<string>;
|
|
210
|
+
/** A unique identifier representing your end-user */
|
|
211
|
+
user?: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Resolve provider options for a specific model.
|
|
215
|
+
* If the model has explicit options in the map, use those; otherwise use base options.
|
|
216
|
+
*/
|
|
217
|
+
export type ResolveProviderOptions<TModel extends string> = TModel extends keyof GrokChatModelProviderOptionsByName ? GrokChatModelProviderOptionsByName[TModel] : GrokProviderOptions;
|
|
218
|
+
/**
|
|
219
|
+
* Resolve input modalities for a specific model.
|
|
220
|
+
* If the model has explicit modalities in the map, use those; otherwise use text only.
|
|
221
|
+
*/
|
|
222
|
+
export type ResolveInputModalities<TModel extends string> = TModel extends keyof GrokModelInputModalitiesByName ? GrokModelInputModalitiesByName[TModel] : readonly ['text'];
|
|
223
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const GROK_4_1_FAST_REASONING = {
|
|
2
|
+
name: "grok-4-1-fast-reasoning"
|
|
3
|
+
};
|
|
4
|
+
const GROK_4_1_FAST_NON_REASONING = {
|
|
5
|
+
name: "grok-4-1-fast-non-reasoning"
|
|
6
|
+
};
|
|
7
|
+
const GROK_CODE_FAST_1 = {
|
|
8
|
+
name: "grok-code-fast-1"
|
|
9
|
+
};
|
|
10
|
+
const GROK_4_FAST_REASONING = {
|
|
11
|
+
name: "grok-4-fast-reasoning"
|
|
12
|
+
};
|
|
13
|
+
const GROK_4_FAST_NON_REASONING = {
|
|
14
|
+
name: "grok-4-fast-non-reasoning"
|
|
15
|
+
};
|
|
16
|
+
const GROK_4 = {
|
|
17
|
+
name: "grok-4"
|
|
18
|
+
};
|
|
19
|
+
const GROK_3_MINI = {
|
|
20
|
+
name: "grok-3-mini"
|
|
21
|
+
};
|
|
22
|
+
const GROK_3 = {
|
|
23
|
+
name: "grok-3"
|
|
24
|
+
};
|
|
25
|
+
const GROK_2_VISION = {
|
|
26
|
+
name: "grok-2-vision-1212"
|
|
27
|
+
};
|
|
28
|
+
const GROK_2_IMAGE = {
|
|
29
|
+
name: "grok-2-image-1212"
|
|
30
|
+
};
|
|
31
|
+
const GROK_CHAT_MODELS = [
|
|
32
|
+
GROK_4_1_FAST_REASONING.name,
|
|
33
|
+
GROK_4_1_FAST_NON_REASONING.name,
|
|
34
|
+
GROK_CODE_FAST_1.name,
|
|
35
|
+
GROK_4_FAST_REASONING.name,
|
|
36
|
+
GROK_4_FAST_NON_REASONING.name,
|
|
37
|
+
GROK_4.name,
|
|
38
|
+
GROK_3.name,
|
|
39
|
+
GROK_3_MINI.name,
|
|
40
|
+
GROK_2_VISION.name
|
|
41
|
+
];
|
|
42
|
+
const GROK_IMAGE_MODELS = [GROK_2_IMAGE.name];
|
|
43
|
+
export {
|
|
44
|
+
GROK_CHAT_MODELS,
|
|
45
|
+
GROK_IMAGE_MODELS
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=model-meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-meta.js","sources":["../../src/model-meta.ts"],"sourcesContent":["/**\n * Model metadata interface for documentation and type inference\n */\ninterface ModelMeta {\n name: string\n supports: {\n input: Array<'text' | 'image' | 'audio' | 'video' | 'document'>\n output: Array<'text' | 'image' | 'audio' | 'video'>\n capabilities?: Array<'reasoning' | 'tool_calling' | 'structured_outputs'>\n }\n max_input_tokens?: number\n max_output_tokens?: number\n context_window?: number\n knowledge_cutoff?: string\n pricing?: {\n input: {\n normal: number\n cached?: number\n }\n output: {\n normal: number\n }\n }\n}\n\nconst GROK_4_1_FAST_REASONING = {\n name: 'grok-4-1-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_1_FAST_NON_REASONING = {\n name: 'grok-4-1-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_CODE_FAST_1 = {\n name: 'grok-code-fast-1',\n context_window: 256_000,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.02,\n },\n output: {\n normal: 1.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_REASONING = {\n name: 'grok-4-fast-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4_FAST_NON_REASONING = {\n name: 'grok-4-fast-non-reasoning',\n context_window: 2_000_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.2,\n cached: 0.05,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_4 = {\n name: 'grok-4',\n context_window: 256_000,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3_MINI = {\n name: 'grok-3-mini',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['reasoning', 'structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 0.3,\n cached: 0.075,\n },\n output: {\n normal: 0.5,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_3 = {\n name: 'grok-3',\n context_window: 131_072,\n supports: {\n input: ['text'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 3,\n cached: 0.75,\n },\n output: {\n normal: 15,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_VISION = {\n name: 'grok-2-vision-1212',\n context_window: 32_768,\n supports: {\n input: ['text', 'image'],\n output: ['text'],\n capabilities: ['structured_outputs', 'tool_calling'],\n },\n pricing: {\n input: {\n normal: 2,\n },\n output: {\n normal: 10,\n },\n },\n} as const satisfies ModelMeta\n\nconst GROK_2_IMAGE = {\n name: 'grok-2-image-1212',\n supports: {\n input: ['text'],\n output: ['image'],\n },\n pricing: {\n input: {\n normal: 0.07,\n },\n output: {\n normal: 0.07,\n },\n },\n} as const satisfies ModelMeta\n\n/**\n * Grok Chat Models\n * Based on xAI's available models as of 2025\n */\nexport const GROK_CHAT_MODELS = [\n GROK_4_1_FAST_REASONING.name,\n GROK_4_1_FAST_NON_REASONING.name,\n GROK_CODE_FAST_1.name,\n GROK_4_FAST_REASONING.name,\n GROK_4_FAST_NON_REASONING.name,\n GROK_4.name,\n GROK_3.name,\n GROK_3_MINI.name,\n GROK_2_VISION.name,\n] as const\n\n/**\n * Grok Image Generation Models\n */\nexport const GROK_IMAGE_MODELS = [GROK_2_IMAGE.name] as const\n\n/**\n * Type-only map from Grok chat model name to its supported input modalities.\n * Used for type inference when constructing multimodal messages.\n */\nexport type GrokModelInputModalitiesByName = {\n [GROK_4_1_FAST_REASONING.name]: typeof GROK_4_1_FAST_REASONING.supports.input\n [GROK_4_1_FAST_NON_REASONING.name]: typeof GROK_4_1_FAST_NON_REASONING.supports.input\n [GROK_CODE_FAST_1.name]: typeof GROK_CODE_FAST_1.supports.input\n [GROK_4_FAST_REASONING.name]: typeof GROK_4_FAST_REASONING.supports.input\n [GROK_4_FAST_NON_REASONING.name]: typeof GROK_4_FAST_NON_REASONING.supports.input\n [GROK_4.name]: typeof GROK_4.supports.input\n [GROK_3.name]: typeof GROK_3.supports.input\n [GROK_3_MINI.name]: typeof GROK_3_MINI.supports.input\n [GROK_2_VISION.name]: typeof GROK_2_VISION.supports.input\n}\n\n/**\n * Type-only map from Grok chat model name to its provider options type.\n * Since Grok uses OpenAI-compatible API, we reuse OpenAI provider options.\n */\nexport type GrokChatModelProviderOptionsByName = {\n [K in (typeof GROK_CHAT_MODELS)[number]]: GrokProviderOptions\n}\n\n/**\n * Grok-specific provider options\n * Based on OpenAI-compatible API options\n */\nexport interface GrokProviderOptions {\n /** Temperature for response generation (0-2) */\n temperature?: number\n /** Maximum tokens in the response */\n max_tokens?: number\n /** Top-p sampling parameter */\n top_p?: number\n /** Frequency penalty (-2.0 to 2.0) */\n frequency_penalty?: number\n /** Presence penalty (-2.0 to 2.0) */\n presence_penalty?: number\n /** Stop sequences */\n stop?: string | Array<string>\n /** A unique identifier representing your end-user */\n user?: string\n}\n\n// ===========================\n// Type Resolution Helpers\n// ===========================\n\n/**\n * Resolve provider options for a specific model.\n * If the model has explicit options in the map, use those; otherwise use base options.\n */\nexport type ResolveProviderOptions<TModel extends string> =\n TModel extends keyof GrokChatModelProviderOptionsByName\n ? GrokChatModelProviderOptionsByName[TModel]\n : GrokProviderOptions\n\n/**\n * Resolve input modalities for a specific model.\n * If the model has explicit modalities in the map, use those; otherwise use text only.\n */\nexport type ResolveInputModalities<TModel extends string> =\n TModel extends keyof GrokModelInputModalitiesByName\n ? GrokModelInputModalitiesByName[TModel]\n : readonly ['text']\n"],"names":[],"mappings":"AAyBA,MAAM,0BAA0B;AAAA,EAC9B,MAAM;AAgBR;AAEA,MAAM,8BAA8B;AAAA,EAClC,MAAM;AAgBR;AAEA,MAAM,mBAAmB;AAAA,EACvB,MAAM;AAgBR;AAEA,MAAM,wBAAwB;AAAA,EAC5B,MAAM;AAgBR;AAEA,MAAM,4BAA4B;AAAA,EAChC,MAAM;AAgBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAgBR;AAEA,MAAM,cAAc;AAAA,EAClB,MAAM;AAgBR;AAEA,MAAM,SAAS;AAAA,EACb,MAAM;AAgBR;AAEA,MAAM,gBAAgB;AAAA,EACpB,MAAM;AAeR;AAEA,MAAM,eAAe;AAAA,EACnB,MAAM;AAaR;AAMO,MAAM,mBAAmB;AAAA,EAC9B,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,0BAA0B;AAAA,EAC1B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,cAAc;AAChB;AAKO,MAAM,oBAAoB,CAAC,aAAa,IAAI;"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FunctionTool } from '../tools/function-tool.js';
|
|
2
|
+
/**
|
|
3
|
+
* Grok Text Provider Options
|
|
4
|
+
*
|
|
5
|
+
* Grok uses an OpenAI-compatible Chat Completions API.
|
|
6
|
+
* However, not all OpenAI features may be supported by Grok.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Base provider options for Grok text/chat models
|
|
10
|
+
*/
|
|
11
|
+
export interface GrokBaseOptions {
|
|
12
|
+
/**
|
|
13
|
+
* A unique identifier representing your end-user.
|
|
14
|
+
* Can help xAI to monitor and detect abuse.
|
|
15
|
+
*/
|
|
16
|
+
user?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Grok-specific provider options for text/chat
|
|
20
|
+
* Based on OpenAI-compatible API options
|
|
21
|
+
*/
|
|
22
|
+
export interface GrokTextProviderOptions extends GrokBaseOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Temperature for response generation (0-2)
|
|
25
|
+
* Higher values make output more random, lower values more focused
|
|
26
|
+
*/
|
|
27
|
+
temperature?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Top-p sampling parameter (0-1)
|
|
30
|
+
* Alternative to temperature, nucleus sampling
|
|
31
|
+
*/
|
|
32
|
+
top_p?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Maximum tokens in the response
|
|
35
|
+
*/
|
|
36
|
+
max_tokens?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Frequency penalty (-2.0 to 2.0)
|
|
39
|
+
*/
|
|
40
|
+
frequency_penalty?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Presence penalty (-2.0 to 2.0)
|
|
43
|
+
*/
|
|
44
|
+
presence_penalty?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Stop sequences
|
|
47
|
+
*/
|
|
48
|
+
stop?: string | Array<string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Internal options interface for validation
|
|
52
|
+
* Used internally by the adapter
|
|
53
|
+
*/
|
|
54
|
+
export interface InternalTextProviderOptions extends GrokTextProviderOptions {
|
|
55
|
+
model: string;
|
|
56
|
+
stream?: boolean;
|
|
57
|
+
tools?: Array<FunctionTool>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* External provider options (what users pass in)
|
|
61
|
+
*/
|
|
62
|
+
export type ExternalTextProviderOptions = GrokTextProviderOptions;
|
|
63
|
+
/**
|
|
64
|
+
* Validates text provider options
|
|
65
|
+
*/
|
|
66
|
+
export declare function validateTextProviderOptions(_options: InternalTextProviderOptions): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-provider-options.js","sources":["../../../src/text/text-provider-options.ts"],"sourcesContent":["import type { FunctionTool } from '../tools/function-tool'\n\n/**\n * Grok Text Provider Options\n *\n * Grok uses an OpenAI-compatible Chat Completions API.\n * However, not all OpenAI features may be supported by Grok.\n */\n\n/**\n * Base provider options for Grok text/chat models\n */\nexport interface GrokBaseOptions {\n /**\n * A unique identifier representing your end-user.\n * Can help xAI to monitor and detect abuse.\n */\n user?: string\n}\n\n/**\n * Grok-specific provider options for text/chat\n * Based on OpenAI-compatible API options\n */\nexport interface GrokTextProviderOptions extends GrokBaseOptions {\n /**\n * Temperature for response generation (0-2)\n * Higher values make output more random, lower values more focused\n */\n temperature?: number\n /**\n * Top-p sampling parameter (0-1)\n * Alternative to temperature, nucleus sampling\n */\n top_p?: number\n /**\n * Maximum tokens in the response\n */\n max_tokens?: number\n /**\n * Frequency penalty (-2.0 to 2.0)\n */\n frequency_penalty?: number\n /**\n * Presence penalty (-2.0 to 2.0)\n */\n presence_penalty?: number\n /**\n * Stop sequences\n */\n stop?: string | Array<string>\n}\n\n/**\n * Internal options interface for validation\n * Used internally by the adapter\n */\nexport interface InternalTextProviderOptions extends GrokTextProviderOptions {\n model: string\n stream?: boolean\n tools?: Array<FunctionTool>\n}\n\n/**\n * External provider options (what users pass in)\n */\nexport type ExternalTextProviderOptions = GrokTextProviderOptions\n\n/**\n * Validates text provider options\n */\nexport function validateTextProviderOptions(\n _options: InternalTextProviderOptions,\n): void {\n // Basic validation can be added here if needed\n // For now, Grok API will handle validation\n}\n"],"names":[],"mappings":"AAuEO,SAAS,4BACd,UACM;AAGR;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Tool } from '@tanstack/ai';
|
|
2
|
+
import { default as OpenAI } from 'openai';
|
|
3
|
+
export type FunctionTool = OpenAI.Chat.Completions.ChatCompletionTool;
|
|
4
|
+
/**
|
|
5
|
+
* Converts a standard Tool to Grok ChatCompletionTool format.
|
|
6
|
+
*
|
|
7
|
+
* Tool schemas are already converted to JSON Schema in the ai layer.
|
|
8
|
+
* We apply Grok-specific transformations for strict mode:
|
|
9
|
+
* - All properties in required array
|
|
10
|
+
* - Optional fields made nullable
|
|
11
|
+
* - additionalProperties: false
|
|
12
|
+
*
|
|
13
|
+
* This enables strict mode for all tools automatically.
|
|
14
|
+
*/
|
|
15
|
+
export declare function convertFunctionToolToAdapterFormat(tool: Tool): FunctionTool;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { makeGrokStructuredOutputCompatible } from "../utils/schema-converter.js";
|
|
2
|
+
function convertFunctionToolToAdapterFormat(tool) {
|
|
3
|
+
const inputSchema = tool.inputSchema ?? {
|
|
4
|
+
type: "object",
|
|
5
|
+
properties: {},
|
|
6
|
+
required: []
|
|
7
|
+
};
|
|
8
|
+
const jsonSchema = makeGrokStructuredOutputCompatible(
|
|
9
|
+
inputSchema,
|
|
10
|
+
inputSchema.required || []
|
|
11
|
+
);
|
|
12
|
+
jsonSchema.additionalProperties = false;
|
|
13
|
+
return {
|
|
14
|
+
type: "function",
|
|
15
|
+
function: {
|
|
16
|
+
name: tool.name,
|
|
17
|
+
description: tool.description,
|
|
18
|
+
parameters: jsonSchema,
|
|
19
|
+
strict: true
|
|
20
|
+
// Always use strict mode since our schema converter handles the requirements
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
convertFunctionToolToAdapterFormat
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=function-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"function-tool.js","sources":["../../../src/tools/function-tool.ts"],"sourcesContent":["import { makeGrokStructuredOutputCompatible } from '../utils/schema-converter'\nimport type { JSONSchema, Tool } from '@tanstack/ai'\nimport type OpenAI from 'openai'\n\n// Use Chat Completions API tool format (not Responses API)\nexport type FunctionTool = OpenAI.Chat.Completions.ChatCompletionTool\n\n/**\n * Converts a standard Tool to Grok ChatCompletionTool format.\n *\n * Tool schemas are already converted to JSON Schema in the ai layer.\n * We apply Grok-specific transformations for strict mode:\n * - All properties in required array\n * - Optional fields made nullable\n * - additionalProperties: false\n *\n * This enables strict mode for all tools automatically.\n */\nexport function convertFunctionToolToAdapterFormat(tool: Tool): FunctionTool {\n // Tool schemas are already converted to JSON Schema in the ai layer\n // Apply Grok-specific transformations for strict mode\n const inputSchema = (tool.inputSchema ?? {\n type: 'object',\n properties: {},\n required: [],\n }) as JSONSchema\n\n const jsonSchema = makeGrokStructuredOutputCompatible(\n inputSchema,\n inputSchema.required || [],\n )\n\n // Ensure additionalProperties is false for strict mode\n jsonSchema.additionalProperties = false\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n strict: true, // Always use strict mode since our schema converter handles the requirements\n },\n } satisfies FunctionTool\n}\n"],"names":[],"mappings":";AAkBO,SAAS,mCAAmC,MAA0B;AAG3E,QAAM,cAAe,KAAK,eAAe;AAAA,IACvC,MAAM;AAAA,IACN,YAAY,CAAA;AAAA,IACZ,UAAU,CAAA;AAAA,EAAC;AAGb,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,YAAY,YAAY,CAAA;AAAA,EAAC;AAI3B,aAAW,uBAAuB;AAElC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,YAAY;AAAA,MACZ,QAAQ;AAAA;AAAA,IAAA;AAAA,EACV;AAEJ;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FunctionTool } from './function-tool.js';
|
|
2
|
+
import { Tool } from '@tanstack/ai';
|
|
3
|
+
/**
|
|
4
|
+
* Converts an array of standard Tools to Grok-specific format
|
|
5
|
+
* Grok uses OpenAI-compatible API, so we primarily support function tools
|
|
6
|
+
*/
|
|
7
|
+
export declare function convertToolsToProviderFormat(tools: Array<Tool>): Array<FunctionTool>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { convertFunctionToolToAdapterFormat } from "./function-tool.js";
|
|
2
|
+
function convertToolsToProviderFormat(tools) {
|
|
3
|
+
return tools.map((tool) => {
|
|
4
|
+
return convertFunctionToolToAdapterFormat(tool);
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
convertToolsToProviderFormat
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=tool-converter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-converter.js","sources":["../../../src/tools/tool-converter.ts"],"sourcesContent":["import { convertFunctionToolToAdapterFormat } from './function-tool'\nimport type { FunctionTool } from './function-tool'\nimport type { Tool } from '@tanstack/ai'\n\n/**\n * Converts an array of standard Tools to Grok-specific format\n * Grok uses OpenAI-compatible API, so we primarily support function tools\n */\nexport function convertToolsToProviderFormat(\n tools: Array<Tool>,\n): Array<FunctionTool> {\n return tools.map((tool) => {\n // For Grok, all tools are converted as function tools\n // Grok uses OpenAI-compatible API which primarily supports function tools\n return convertFunctionToolToAdapterFormat(tool)\n })\n}\n"],"names":[],"mappings":";AAQO,SAAS,6BACd,OACqB;AACrB,SAAO,MAAM,IAAI,CAAC,SAAS;AAGzB,WAAO,mCAAmC,IAAI;AAAA,EAChD,CAAC;AACH;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { default as OpenAI_SDK } from 'openai';
|
|
2
|
+
export interface GrokClientConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
baseURL?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Creates a Grok SDK client instance using OpenAI SDK with xAI's base URL
|
|
8
|
+
*/
|
|
9
|
+
export declare function createGrokClient(config: GrokClientConfig): OpenAI_SDK;
|
|
10
|
+
/**
|
|
11
|
+
* Gets Grok API key from environment variables
|
|
12
|
+
* @throws Error if XAI_API_KEY is not found
|
|
13
|
+
*/
|
|
14
|
+
export declare function getGrokApiKeyFromEnv(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Generates a unique ID with a prefix
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateId(prefix: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import OpenAI_SDK from "openai";
|
|
2
|
+
function createGrokClient(config) {
|
|
3
|
+
return new OpenAI_SDK({
|
|
4
|
+
apiKey: config.apiKey,
|
|
5
|
+
baseURL: config.baseURL || "https://api.x.ai/v1"
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
function getGrokApiKeyFromEnv() {
|
|
9
|
+
const env = typeof globalThis !== "undefined" && globalThis.window?.env ? globalThis.window.env : typeof process !== "undefined" ? process.env : void 0;
|
|
10
|
+
const key = env?.XAI_API_KEY;
|
|
11
|
+
if (!key) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"XAI_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
return key;
|
|
17
|
+
}
|
|
18
|
+
function generateId(prefix) {
|
|
19
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
createGrokClient,
|
|
23
|
+
generateId,
|
|
24
|
+
getGrokApiKeyFromEnv
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../src/utils/client.ts"],"sourcesContent":["import OpenAI_SDK from 'openai'\n\nexport interface GrokClientConfig {\n apiKey: string\n baseURL?: string\n}\n\n/**\n * Creates a Grok SDK client instance using OpenAI SDK with xAI's base URL\n */\nexport function createGrokClient(config: GrokClientConfig): OpenAI_SDK {\n return new OpenAI_SDK({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.x.ai/v1',\n })\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 const env =\n typeof globalThis !== 'undefined' && (globalThis as any).window?.env\n ? (globalThis as any).window.env\n : typeof process !== 'undefined'\n ? process.env\n : undefined\n const key = env?.XAI_API_KEY\n\n if (!key) {\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 return key\n}\n\n/**\n * Generates a unique ID with a prefix\n */\nexport function generateId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"names":[],"mappings":";AAUO,SAAS,iBAAiB,QAAsC;AACrE,SAAO,IAAI,WAAW;AAAA,IACpB,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO,WAAW;AAAA,EAAA,CAC5B;AACH;AAMO,SAAS,uBAA+B;AAC7C,QAAM,MACJ,OAAO,eAAe,eAAgB,WAAmB,QAAQ,MAC5D,WAAmB,OAAO,MAC3B,OAAO,YAAY,cACjB,QAAQ,MACR;AACR,QAAM,MAAM,KAAK;AAEjB,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AACT;AAKO,SAAS,WAAW,QAAwB;AACjD,SAAO,GAAG,MAAM,IAAI,KAAK,KAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AAC3E;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively transform null values to undefined in an object.
|
|
3
|
+
*
|
|
4
|
+
* This is needed because Grok's structured output (via OpenAI-compatible API) requires all fields to be
|
|
5
|
+
* in the `required` array, with optional fields made nullable (type: ["string", "null"]).
|
|
6
|
+
* When Grok returns null for optional fields, we need to convert them back to
|
|
7
|
+
* undefined to match the original Zod schema expectations.
|
|
8
|
+
*
|
|
9
|
+
* @param obj - Object to transform
|
|
10
|
+
* @returns Object with nulls converted to undefined
|
|
11
|
+
*/
|
|
12
|
+
export declare function transformNullsToUndefined<T>(obj: T): T;
|
|
13
|
+
/**
|
|
14
|
+
* Transform a JSON schema to be compatible with Grok's structured output requirements (OpenAI-compatible).
|
|
15
|
+
* Grok requires:
|
|
16
|
+
* - All properties must be in the `required` array
|
|
17
|
+
* - Optional fields should have null added to their type union
|
|
18
|
+
* - additionalProperties must be false for objects
|
|
19
|
+
*
|
|
20
|
+
* @param schema - JSON schema to transform
|
|
21
|
+
* @param originalRequired - Original required array (to know which fields were optional)
|
|
22
|
+
* @returns Transformed schema compatible with Grok structured output
|
|
23
|
+
*/
|
|
24
|
+
export declare function makeGrokStructuredOutputCompatible(schema: Record<string, any>, originalRequired?: Array<string>): Record<string, any>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
function transformNullsToUndefined(obj) {
|
|
2
|
+
if (obj === null) {
|
|
3
|
+
return void 0;
|
|
4
|
+
}
|
|
5
|
+
if (Array.isArray(obj)) {
|
|
6
|
+
return obj.map((item) => transformNullsToUndefined(item));
|
|
7
|
+
}
|
|
8
|
+
if (typeof obj === "object") {
|
|
9
|
+
const result = {};
|
|
10
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
11
|
+
const transformed = transformNullsToUndefined(value);
|
|
12
|
+
if (transformed !== void 0) {
|
|
13
|
+
result[key] = transformed;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
return obj;
|
|
19
|
+
}
|
|
20
|
+
function makeGrokStructuredOutputCompatible(schema, originalRequired = []) {
|
|
21
|
+
const result = { ...schema };
|
|
22
|
+
if (result.type === "object" && result.properties) {
|
|
23
|
+
const properties = { ...result.properties };
|
|
24
|
+
const allPropertyNames = Object.keys(properties);
|
|
25
|
+
for (const propName of allPropertyNames) {
|
|
26
|
+
const prop = properties[propName];
|
|
27
|
+
const wasOptional = !originalRequired.includes(propName);
|
|
28
|
+
if (prop.type === "object" && prop.properties) {
|
|
29
|
+
properties[propName] = makeGrokStructuredOutputCompatible(
|
|
30
|
+
prop,
|
|
31
|
+
prop.required || []
|
|
32
|
+
);
|
|
33
|
+
} else if (prop.type === "array" && prop.items) {
|
|
34
|
+
properties[propName] = {
|
|
35
|
+
...prop,
|
|
36
|
+
items: makeGrokStructuredOutputCompatible(
|
|
37
|
+
prop.items,
|
|
38
|
+
prop.items.required || []
|
|
39
|
+
)
|
|
40
|
+
};
|
|
41
|
+
} else if (wasOptional) {
|
|
42
|
+
if (prop.type && !Array.isArray(prop.type)) {
|
|
43
|
+
properties[propName] = {
|
|
44
|
+
...prop,
|
|
45
|
+
type: [prop.type, "null"]
|
|
46
|
+
};
|
|
47
|
+
} else if (Array.isArray(prop.type) && !prop.type.includes("null")) {
|
|
48
|
+
properties[propName] = {
|
|
49
|
+
...prop,
|
|
50
|
+
type: [...prop.type, "null"]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
result.properties = properties;
|
|
56
|
+
result.required = allPropertyNames;
|
|
57
|
+
result.additionalProperties = false;
|
|
58
|
+
}
|
|
59
|
+
if (result.type === "array" && result.items) {
|
|
60
|
+
result.items = makeGrokStructuredOutputCompatible(
|
|
61
|
+
result.items,
|
|
62
|
+
result.items.required || []
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
makeGrokStructuredOutputCompatible,
|
|
69
|
+
transformNullsToUndefined
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=schema-converter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-converter.js","sources":["../../../src/utils/schema-converter.ts"],"sourcesContent":["/**\n * Recursively transform null values to undefined in an object.\n *\n * This is needed because Grok's structured output (via OpenAI-compatible API) requires all fields to be\n * in the `required` array, with optional fields made nullable (type: [\"string\", \"null\"]).\n * When Grok returns null for optional fields, we need to convert them back to\n * undefined to match the original Zod schema expectations.\n *\n * @param obj - Object to transform\n * @returns Object with nulls converted to undefined\n */\nexport function transformNullsToUndefined<T>(obj: T): T {\n if (obj === null) {\n return undefined as unknown as T\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => transformNullsToUndefined(item)) as unknown as T\n }\n\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const transformed = transformNullsToUndefined(value)\n // Only include the key if the value is not undefined\n // This makes { notes: null } become {} (field absent) instead of { notes: undefined }\n if (transformed !== undefined) {\n result[key] = transformed\n }\n }\n return result as T\n }\n\n return obj\n}\n\n/**\n * Transform a JSON schema to be compatible with Grok's structured output requirements (OpenAI-compatible).\n * Grok requires:\n * - All properties must be in the `required` array\n * - Optional fields should have null added to their type union\n * - additionalProperties must be false for objects\n *\n * @param schema - JSON schema to transform\n * @param originalRequired - Original required array (to know which fields were optional)\n * @returns Transformed schema compatible with Grok structured output\n */\nexport function makeGrokStructuredOutputCompatible(\n schema: Record<string, any>,\n originalRequired: Array<string> = [],\n): Record<string, any> {\n const result = { ...schema }\n\n // Handle object types\n if (result.type === 'object' && result.properties) {\n const properties = { ...result.properties }\n const allPropertyNames = Object.keys(properties)\n\n // Transform each property\n for (const propName of allPropertyNames) {\n const prop = properties[propName]\n const wasOptional = !originalRequired.includes(propName)\n\n // Recursively transform nested objects/arrays\n if (prop.type === 'object' && prop.properties) {\n properties[propName] = makeGrokStructuredOutputCompatible(\n prop,\n prop.required || [],\n )\n } else if (prop.type === 'array' && prop.items) {\n properties[propName] = {\n ...prop,\n items: makeGrokStructuredOutputCompatible(\n prop.items,\n prop.items.required || [],\n ),\n }\n } else if (wasOptional) {\n // Make optional fields nullable by adding null to the type\n if (prop.type && !Array.isArray(prop.type)) {\n properties[propName] = {\n ...prop,\n type: [prop.type, 'null'],\n }\n } else if (Array.isArray(prop.type) && !prop.type.includes('null')) {\n properties[propName] = {\n ...prop,\n type: [...prop.type, 'null'],\n }\n }\n }\n }\n\n result.properties = properties\n // ALL properties must be required for Grok structured output\n result.required = allPropertyNames\n // additionalProperties must be false\n result.additionalProperties = false\n }\n\n // Handle array types with object items\n if (result.type === 'array' && result.items) {\n result.items = makeGrokStructuredOutputCompatible(\n result.items,\n result.items.required || [],\n )\n }\n\n return result\n}\n"],"names":[],"mappings":"AAWO,SAAS,0BAA6B,KAAW;AACtD,MAAI,QAAQ,MAAM;AAChB,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,CAAC,SAAS,0BAA0B,IAAI,CAAC;AAAA,EAC1D;AAEA,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,SAAkC,CAAA;AACxC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAA8B,GAAG;AACzE,YAAM,cAAc,0BAA0B,KAAK;AAGnD,UAAI,gBAAgB,QAAW;AAC7B,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAaO,SAAS,mCACd,QACA,mBAAkC,IACb;AACrB,QAAM,SAAS,EAAE,GAAG,OAAA;AAGpB,MAAI,OAAO,SAAS,YAAY,OAAO,YAAY;AACjD,UAAM,aAAa,EAAE,GAAG,OAAO,WAAA;AAC/B,UAAM,mBAAmB,OAAO,KAAK,UAAU;AAG/C,eAAW,YAAY,kBAAkB;AACvC,YAAM,OAAO,WAAW,QAAQ;AAChC,YAAM,cAAc,CAAC,iBAAiB,SAAS,QAAQ;AAGvD,UAAI,KAAK,SAAS,YAAY,KAAK,YAAY;AAC7C,mBAAW,QAAQ,IAAI;AAAA,UACrB;AAAA,UACA,KAAK,YAAY,CAAA;AAAA,QAAC;AAAA,MAEtB,WAAW,KAAK,SAAS,WAAW,KAAK,OAAO;AAC9C,mBAAW,QAAQ,IAAI;AAAA,UACrB,GAAG;AAAA,UACH,OAAO;AAAA,YACL,KAAK;AAAA,YACL,KAAK,MAAM,YAAY,CAAA;AAAA,UAAC;AAAA,QAC1B;AAAA,MAEJ,WAAW,aAAa;AAEtB,YAAI,KAAK,QAAQ,CAAC,MAAM,QAAQ,KAAK,IAAI,GAAG;AAC1C,qBAAW,QAAQ,IAAI;AAAA,YACrB,GAAG;AAAA,YACH,MAAM,CAAC,KAAK,MAAM,MAAM;AAAA,UAAA;AAAA,QAE5B,WAAW,MAAM,QAAQ,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,MAAM,GAAG;AAClE,qBAAW,QAAQ,IAAI;AAAA,YACrB,GAAG;AAAA,YACH,MAAM,CAAC,GAAG,KAAK,MAAM,MAAM;AAAA,UAAA;AAAA,QAE/B;AAAA,MACF;AAAA,IACF;AAEA,WAAO,aAAa;AAEpB,WAAO,WAAW;AAElB,WAAO,uBAAuB;AAAA,EAChC;AAGA,MAAI,OAAO,SAAS,WAAW,OAAO,OAAO;AAC3C,WAAO,QAAQ;AAAA,MACb,OAAO;AAAA,MACP,OAAO,MAAM,YAAY,CAAA;AAAA,IAAC;AAAA,EAE9B;AAEA,SAAO;AACT;"}
|