@gullabs/xai 0.8.0 → 0.9.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/README.md +28 -6
- package/dist/index.cjs +154 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +154 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -35,6 +35,20 @@ type XaiProviderOptions = {
|
|
|
35
35
|
tools?: Array<XaiWebSearchTool | XaiXSearchTool>;
|
|
36
36
|
/** xAI-only; Gemini has no parallel-tool knob. */
|
|
37
37
|
parallelToolCalls?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Responses API `tool_choice` for the server-side search tools; `required`
|
|
40
|
+
* forces at least one search. Requires `tools`, and cannot be combined
|
|
41
|
+
* with the request-level `toolChoice`.
|
|
42
|
+
*/
|
|
43
|
+
toolChoice?: 'auto' | 'required' | 'none';
|
|
44
|
+
/**
|
|
45
|
+
* Responses API `max_turns`: the cap on agentic tool-calling turns for the
|
|
46
|
+
* server-side search tools. A turn can run several searches, so this is
|
|
47
|
+
* not a search count. Requires `tools`. As of 2026-10-02 xAI did not
|
|
48
|
+
* enforce it on grok-4.5 / 4.6 / 4.7; assert on
|
|
49
|
+
* `usage.details.web_search_calls` rather than trusting the cap.
|
|
50
|
+
*/
|
|
51
|
+
maxTurns?: number;
|
|
38
52
|
};
|
|
39
53
|
declare module '@gullabs/core' {
|
|
40
54
|
interface ProviderOptionsMap {
|
|
@@ -164,6 +178,7 @@ interface XaiResponseCreateParams {
|
|
|
164
178
|
type: 'function';
|
|
165
179
|
name: string;
|
|
166
180
|
};
|
|
181
|
+
max_turns?: number;
|
|
167
182
|
parallel_tool_calls?: boolean;
|
|
168
183
|
}
|
|
169
184
|
/** A single summary-text segment of a `type: 'reasoning'` output item. */
|
|
@@ -621,6 +636,12 @@ declare const Grok45ConfigSchema: z.ZodObject<{
|
|
|
621
636
|
type: z.ZodLiteral<"web_search">;
|
|
622
637
|
}, z.core.$strict>]>], null>]>>;
|
|
623
638
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
639
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
640
|
+
auto: "auto";
|
|
641
|
+
required: "required";
|
|
642
|
+
none: "none";
|
|
643
|
+
}>>;
|
|
644
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
624
645
|
}, z.core.$strict>>;
|
|
625
646
|
}, z.core.$strict>>;
|
|
626
647
|
}, z.core.$strict>;
|
|
@@ -758,6 +779,12 @@ declare const Grok46ConfigSchema: z.ZodObject<{
|
|
|
758
779
|
type: z.ZodLiteral<"web_search">;
|
|
759
780
|
}, z.core.$strict>]>], null>]>>;
|
|
760
781
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
782
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
783
|
+
auto: "auto";
|
|
784
|
+
required: "required";
|
|
785
|
+
none: "none";
|
|
786
|
+
}>>;
|
|
787
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
761
788
|
}, z.core.$strict>>;
|
|
762
789
|
}, z.core.$strict>>;
|
|
763
790
|
}, z.core.$strict>;
|
|
@@ -896,6 +923,12 @@ declare const Grok47ConfigSchema: z.ZodObject<{
|
|
|
896
923
|
type: z.ZodLiteral<"web_search">;
|
|
897
924
|
}, z.core.$strict>]>], null>]>>;
|
|
898
925
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
926
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
927
|
+
auto: "auto";
|
|
928
|
+
required: "required";
|
|
929
|
+
none: "none";
|
|
930
|
+
}>>;
|
|
931
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
899
932
|
}, z.core.$strict>>;
|
|
900
933
|
}, z.core.$strict>>;
|
|
901
934
|
}, z.core.$strict>;
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,20 @@ type XaiProviderOptions = {
|
|
|
35
35
|
tools?: Array<XaiWebSearchTool | XaiXSearchTool>;
|
|
36
36
|
/** xAI-only; Gemini has no parallel-tool knob. */
|
|
37
37
|
parallelToolCalls?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Responses API `tool_choice` for the server-side search tools; `required`
|
|
40
|
+
* forces at least one search. Requires `tools`, and cannot be combined
|
|
41
|
+
* with the request-level `toolChoice`.
|
|
42
|
+
*/
|
|
43
|
+
toolChoice?: 'auto' | 'required' | 'none';
|
|
44
|
+
/**
|
|
45
|
+
* Responses API `max_turns`: the cap on agentic tool-calling turns for the
|
|
46
|
+
* server-side search tools. A turn can run several searches, so this is
|
|
47
|
+
* not a search count. Requires `tools`. As of 2026-10-02 xAI did not
|
|
48
|
+
* enforce it on grok-4.5 / 4.6 / 4.7; assert on
|
|
49
|
+
* `usage.details.web_search_calls` rather than trusting the cap.
|
|
50
|
+
*/
|
|
51
|
+
maxTurns?: number;
|
|
38
52
|
};
|
|
39
53
|
declare module '@gullabs/core' {
|
|
40
54
|
interface ProviderOptionsMap {
|
|
@@ -164,6 +178,7 @@ interface XaiResponseCreateParams {
|
|
|
164
178
|
type: 'function';
|
|
165
179
|
name: string;
|
|
166
180
|
};
|
|
181
|
+
max_turns?: number;
|
|
167
182
|
parallel_tool_calls?: boolean;
|
|
168
183
|
}
|
|
169
184
|
/** A single summary-text segment of a `type: 'reasoning'` output item. */
|
|
@@ -621,6 +636,12 @@ declare const Grok45ConfigSchema: z.ZodObject<{
|
|
|
621
636
|
type: z.ZodLiteral<"web_search">;
|
|
622
637
|
}, z.core.$strict>]>], null>]>>;
|
|
623
638
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
639
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
640
|
+
auto: "auto";
|
|
641
|
+
required: "required";
|
|
642
|
+
none: "none";
|
|
643
|
+
}>>;
|
|
644
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
624
645
|
}, z.core.$strict>>;
|
|
625
646
|
}, z.core.$strict>>;
|
|
626
647
|
}, z.core.$strict>;
|
|
@@ -758,6 +779,12 @@ declare const Grok46ConfigSchema: z.ZodObject<{
|
|
|
758
779
|
type: z.ZodLiteral<"web_search">;
|
|
759
780
|
}, z.core.$strict>]>], null>]>>;
|
|
760
781
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
782
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
783
|
+
auto: "auto";
|
|
784
|
+
required: "required";
|
|
785
|
+
none: "none";
|
|
786
|
+
}>>;
|
|
787
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
761
788
|
}, z.core.$strict>>;
|
|
762
789
|
}, z.core.$strict>>;
|
|
763
790
|
}, z.core.$strict>;
|
|
@@ -896,6 +923,12 @@ declare const Grok47ConfigSchema: z.ZodObject<{
|
|
|
896
923
|
type: z.ZodLiteral<"web_search">;
|
|
897
924
|
}, z.core.$strict>]>], null>]>>;
|
|
898
925
|
parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
926
|
+
toolChoice: z.ZodOptional<z.ZodEnum<{
|
|
927
|
+
auto: "auto";
|
|
928
|
+
required: "required";
|
|
929
|
+
none: "none";
|
|
930
|
+
}>>;
|
|
931
|
+
maxTurns: z.ZodOptional<z.ZodNumber>;
|
|
899
932
|
}, z.core.$strict>>;
|
|
900
933
|
}, z.core.$strict>>;
|
|
901
934
|
}, z.core.$strict>;
|
package/dist/index.js
CHANGED
|
@@ -115,6 +115,14 @@ var XaiProviderOptionsSchema = z.strictObject({
|
|
|
115
115
|
parallelToolCalls: z.boolean().optional().meta({
|
|
116
116
|
title: "Parallel Tool Calls",
|
|
117
117
|
description: "xAI Responses parallel_tool_calls. Not a generic contract field."
|
|
118
|
+
}),
|
|
119
|
+
toolChoice: z.enum(["auto", "required", "none"]).optional().meta({
|
|
120
|
+
title: "Server Tool Choice",
|
|
121
|
+
description: "xAI Responses `tool_choice` for the server-side search tools; `required` forces at least one search, `none` disables them. Requires `tools`. Cannot be combined with function tools, file attachments or the request-level toolChoice."
|
|
122
|
+
}),
|
|
123
|
+
maxTurns: z.number().int().min(1).optional().meta({
|
|
124
|
+
title: "Max Turns",
|
|
125
|
+
description: "xAI Responses `max_turns`: cap on agentic tool-calling turns for the server-side search tools. Requires `tools`. A turn can run several searches. Not enforced by xAI as of 2026-10-02."
|
|
118
126
|
})
|
|
119
127
|
}).meta({
|
|
120
128
|
title: "xAI Provider Options",
|
|
@@ -262,6 +270,7 @@ var grok45ModelDescriptor = {
|
|
|
262
270
|
sampling: "tunable",
|
|
263
271
|
caching: { explicit: false, minTokens: 0 },
|
|
264
272
|
grounding: true,
|
|
273
|
+
structuredOutputWithTools: true,
|
|
265
274
|
functionCalling: true,
|
|
266
275
|
serviceTiers: ["priority"]
|
|
267
276
|
},
|
|
@@ -307,6 +316,7 @@ var grok47ModelDescriptor = {
|
|
|
307
316
|
sampling: "tunable",
|
|
308
317
|
caching: { explicit: false, minTokens: 0 },
|
|
309
318
|
grounding: true,
|
|
319
|
+
structuredOutputWithTools: true,
|
|
310
320
|
functionCalling: true,
|
|
311
321
|
statelessReasoningReplay: true,
|
|
312
322
|
serviceTiers: ["priority"]
|
|
@@ -321,6 +331,89 @@ var xaiModelDescriptors = [
|
|
|
321
331
|
grok47ModelDescriptor
|
|
322
332
|
];
|
|
323
333
|
var xaiRegistry = createModelRegistry(xaiModelDescriptors);
|
|
334
|
+
var JSON_SCHEMA_TYPES = /* @__PURE__ */ new Set([
|
|
335
|
+
"string",
|
|
336
|
+
"number",
|
|
337
|
+
"integer",
|
|
338
|
+
"boolean",
|
|
339
|
+
"object",
|
|
340
|
+
"array",
|
|
341
|
+
"null"
|
|
342
|
+
]);
|
|
343
|
+
var SINGLE_SCHEMA_KEYWORDS = [
|
|
344
|
+
"additionalProperties",
|
|
345
|
+
"additionalItems",
|
|
346
|
+
"items",
|
|
347
|
+
"contains",
|
|
348
|
+
"not",
|
|
349
|
+
"if",
|
|
350
|
+
"then",
|
|
351
|
+
"else",
|
|
352
|
+
"propertyNames",
|
|
353
|
+
"unevaluatedProperties",
|
|
354
|
+
"unevaluatedItems",
|
|
355
|
+
"contentSchema"
|
|
356
|
+
];
|
|
357
|
+
var SCHEMA_ARRAY_KEYWORDS = ["items", "prefixItems", "anyOf", "oneOf", "allOf"];
|
|
358
|
+
var SCHEMA_MAP_KEYWORDS = [
|
|
359
|
+
"properties",
|
|
360
|
+
"patternProperties",
|
|
361
|
+
"dependentSchemas",
|
|
362
|
+
// Draft-07 `dependencies`: schema-valued entries are walked; array-valued
|
|
363
|
+
// entries are property-name lists and are skipped by the object check.
|
|
364
|
+
"dependencies",
|
|
365
|
+
"$defs",
|
|
366
|
+
"definitions"
|
|
367
|
+
];
|
|
368
|
+
function isPlainObject(value) {
|
|
369
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
370
|
+
}
|
|
371
|
+
function badSchema(message) {
|
|
372
|
+
return new LlmError(message, { kind: "bad_request", retryable: false, provider: "xai" });
|
|
373
|
+
}
|
|
374
|
+
function assertNode(node, path) {
|
|
375
|
+
const at = path.length > 0 ? path : "<root>";
|
|
376
|
+
if ("nullable" in node) {
|
|
377
|
+
throw badSchema(
|
|
378
|
+
`xAI structured output takes standard JSON Schema, which has no \`nullable\` keyword (found at \`${at}\`). xAI ignores it, so the field would be required and non-null. List 'null' in \`type\` instead, e.g. type: ['string', 'null'].`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
const type = node["type"];
|
|
382
|
+
if (type !== void 0) {
|
|
383
|
+
const names = Array.isArray(type) ? type : [type];
|
|
384
|
+
for (const name of names) {
|
|
385
|
+
if (typeof name !== "string" || !JSON_SCHEMA_TYPES.has(name)) {
|
|
386
|
+
throw badSchema(
|
|
387
|
+
`xAI structured output takes standard JSON Schema; \`type\` ${JSON.stringify(
|
|
388
|
+
name
|
|
389
|
+
)} at \`${at}\` is not a JSON Schema type. Use lowercase string, number, integer, boolean, object, array or null.`
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const child = (segment) => path.length > 0 ? `${path}.${segment}` : segment;
|
|
395
|
+
for (const keyword of SCHEMA_MAP_KEYWORDS) {
|
|
396
|
+
const map = node[keyword];
|
|
397
|
+
if (!isPlainObject(map)) continue;
|
|
398
|
+
for (const [key, member] of Object.entries(map)) {
|
|
399
|
+
if (isPlainObject(member)) assertNode(member, child(`${keyword}.${key}`));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
for (const keyword of SCHEMA_ARRAY_KEYWORDS) {
|
|
403
|
+
const members = node[keyword];
|
|
404
|
+
if (!Array.isArray(members)) continue;
|
|
405
|
+
members.forEach((member, index) => {
|
|
406
|
+
if (isPlainObject(member)) assertNode(member, child(`${keyword}[${index}]`));
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
for (const keyword of SINGLE_SCHEMA_KEYWORDS) {
|
|
410
|
+
const member = node[keyword];
|
|
411
|
+
if (isPlainObject(member)) assertNode(member, child(keyword));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function assertXaiOutputJsonSchema(schema) {
|
|
415
|
+
if (isPlainObject(schema)) assertNode(schema, "");
|
|
416
|
+
}
|
|
324
417
|
var xaiPricingVersion = "xai-2026-09-25";
|
|
325
418
|
var XAI_TOOL_RATE_MICRO_USD = {
|
|
326
419
|
web_search_calls: 5e3,
|
|
@@ -537,7 +630,14 @@ function mapPart(p) {
|
|
|
537
630
|
return assertNever(p);
|
|
538
631
|
}
|
|
539
632
|
}
|
|
540
|
-
var XAI_PROVIDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
633
|
+
var XAI_PROVIDER_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
634
|
+
"promptCacheKey",
|
|
635
|
+
"tools",
|
|
636
|
+
"parallelToolCalls",
|
|
637
|
+
"toolChoice",
|
|
638
|
+
"maxTurns"
|
|
639
|
+
]);
|
|
640
|
+
var XAI_SERVER_TOOL_CHOICES = /* @__PURE__ */ new Set(["auto", "required", "none"]);
|
|
541
641
|
function mapXaiProviderOptions(xaiOpts, model) {
|
|
542
642
|
if (xaiOpts === void 0) {
|
|
543
643
|
return {};
|
|
@@ -552,7 +652,7 @@ function mapXaiProviderOptions(xaiOpts, model) {
|
|
|
552
652
|
throw badXaiRequest(
|
|
553
653
|
`providerOptions.xai contains unsupported keys [${unknownKeys.join(
|
|
554
654
|
", "
|
|
555
|
-
)}] for model "${model}". Allowed keys: promptCacheKey, tools, parallelToolCalls.`
|
|
655
|
+
)}] for model "${model}". Allowed keys: promptCacheKey, tools, parallelToolCalls, toolChoice, maxTurns.`
|
|
556
656
|
);
|
|
557
657
|
}
|
|
558
658
|
const mapped = {};
|
|
@@ -575,6 +675,34 @@ function mapXaiProviderOptions(xaiOpts, model) {
|
|
|
575
675
|
}
|
|
576
676
|
mapped.parallelToolCalls = xaiOpts["parallelToolCalls"];
|
|
577
677
|
}
|
|
678
|
+
const toolChoice = xaiOpts["toolChoice"];
|
|
679
|
+
if (toolChoice !== void 0) {
|
|
680
|
+
if (typeof toolChoice !== "string" || !XAI_SERVER_TOOL_CHOICES.has(toolChoice)) {
|
|
681
|
+
throw badXaiRequest(
|
|
682
|
+
`providerOptions.xai.toolChoice must be "auto", "required" or "none" for model "${model}".`
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
if (mapped.tools === void 0 || mapped.tools.length === 0) {
|
|
686
|
+
throw badXaiRequest(
|
|
687
|
+
`providerOptions.xai.toolChoice requires a non-empty providerOptions.xai.tools for model "${model}".`
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
mapped.toolChoice = toolChoice;
|
|
691
|
+
}
|
|
692
|
+
const maxTurns = xaiOpts["maxTurns"];
|
|
693
|
+
if (maxTurns !== void 0) {
|
|
694
|
+
if (typeof maxTurns !== "number" || !Number.isInteger(maxTurns) || maxTurns < 1) {
|
|
695
|
+
throw badXaiRequest(
|
|
696
|
+
`providerOptions.xai.maxTurns must be an integer >= 1 for model "${model}".`
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
if (mapped.tools === void 0 || mapped.tools.length === 0) {
|
|
700
|
+
throw badXaiRequest(
|
|
701
|
+
`providerOptions.xai.maxTurns requires a non-empty providerOptions.xai.tools for model "${model}".`
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
mapped.maxTurns = maxTurns;
|
|
705
|
+
}
|
|
578
706
|
return mapped;
|
|
579
707
|
}
|
|
580
708
|
function parseXaiReplayState(value, model) {
|
|
@@ -944,6 +1072,7 @@ function xaiAdapter(opts) {
|
|
|
944
1072
|
const structuredOutputRequested = req.outputJsonSchema !== void 0;
|
|
945
1073
|
if (structuredOutputRequested) {
|
|
946
1074
|
const schema = req.outputJsonSchema;
|
|
1075
|
+
assertXaiOutputJsonSchema(schema);
|
|
947
1076
|
const name = isPlainRecord(schema) && typeof schema["title"] === "string" && schema["title"].length > 0 ? schema["title"] : "structured_output";
|
|
948
1077
|
params.text = {
|
|
949
1078
|
format: { type: "json_schema", name, schema, strict: true }
|
|
@@ -970,6 +1099,27 @@ function xaiAdapter(opts) {
|
|
|
970
1099
|
);
|
|
971
1100
|
}
|
|
972
1101
|
params.tools = searchTools;
|
|
1102
|
+
if (xaiProviderConfig.toolChoice !== void 0) {
|
|
1103
|
+
if (req.toolChoice !== void 0) {
|
|
1104
|
+
throw badXaiRequest(
|
|
1105
|
+
`providerOptions.xai.toolChoice and toolChoice cannot both be set for model "${model}"; xAI accepts one tool_choice per request.`
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
if (req.tools !== void 0 && req.tools.length > 0) {
|
|
1109
|
+
throw badXaiRequest(
|
|
1110
|
+
`providerOptions.xai.toolChoice applies to the server-side search tools only and cannot be combined with function tools for model "${model}".`
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
if (hasFileRef) {
|
|
1114
|
+
throw badXaiRequest(
|
|
1115
|
+
`providerOptions.xai.toolChoice cannot be combined with file attachments for model "${model}"; xAI's implicit attachment_search would count as the tool call.`
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
params.tool_choice = xaiProviderConfig.toolChoice;
|
|
1119
|
+
}
|
|
1120
|
+
if (xaiProviderConfig.maxTurns !== void 0) {
|
|
1121
|
+
params.max_turns = xaiProviderConfig.maxTurns;
|
|
1122
|
+
}
|
|
973
1123
|
}
|
|
974
1124
|
if (req.tools !== void 0 && req.tools.length > 0) {
|
|
975
1125
|
if (req.modelDescriptor?.capabilities?.functionCalling !== true) {
|
|
@@ -1055,7 +1205,8 @@ function xaiAdapter(opts) {
|
|
|
1055
1205
|
const finishReason = mapFinishReason(response);
|
|
1056
1206
|
const expectedToolCounters = expectedServerToolCounters(
|
|
1057
1207
|
xaiProviderConfig.tools);
|
|
1058
|
-
|
|
1208
|
+
const noServerToolRan = response.usage["num_server_side_tools_used"] === 0 && response.usage["server_side_tool_usage_details"] === void 0;
|
|
1209
|
+
if ((expectedToolCounters.length > 0 || hasFileRef) && !noServerToolRan) {
|
|
1059
1210
|
usage.details["server_tools_requested"] = 1;
|
|
1060
1211
|
if (xaiProviderConfig.tools?.some((tool) => tool["type"] === "x_search") === true) {
|
|
1061
1212
|
usage.details["x_search_requested"] = 1;
|