@opencode-ai/ai 0.0.0-beta-18045 → 0.0.0-beta-18135
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/dist/protocols/anthropic-messages.d.ts +259 -17
- package/dist/protocols/anthropic-messages.js +337 -24
- package/dist/protocols/gemini.d.ts +4 -31
- package/dist/protocols/gemini.js +23 -4
- package/dist/protocols/open-responses.d.ts +8 -4
- package/dist/protocols/open-responses.js +73 -38
- package/dist/protocols/openai-chat.d.ts +25 -11
- package/dist/protocols/openai-chat.js +124 -8
- package/dist/protocols/openai-compatible-chat.d.ts +3 -1
- package/dist/protocols/openai-compatible-responses.d.ts +1 -1
- package/dist/protocols/openai-responses.d.ts +5 -5
- package/dist/protocols/openai-responses.js +21 -5
- package/dist/protocols/utils/bedrock-media.d.ts +1 -0
- package/dist/protocols/xai-responses.d.ts +1 -1
- package/dist/protocols/xai-responses.js +2 -10
- package/dist/providers/amazon-bedrock-mantle.d.ts +4 -2
- package/dist/providers/anthropic-compatible.d.ts +75 -4
- package/dist/providers/anthropic.d.ts +75 -4
- package/dist/providers/azure.d.ts +4 -2
- package/dist/providers/cloudflare.d.ts +9 -3
- package/dist/providers/google-vertex-chat.d.ts +3 -1
- package/dist/providers/google-vertex-messages.d.ts +75 -4
- package/dist/providers/google-vertex-responses.d.ts +1 -1
- package/dist/providers/google-vertex.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/openai-compatible-responses.d.ts +1 -1
- package/dist/providers/openai-compatible.d.ts +3 -1
- package/dist/providers/openai.d.ts +4 -2
- package/dist/providers/openrouter.d.ts +11 -3
- package/dist/providers/xai.d.ts +3 -1
- package/dist/schema/messages.d.ts +4 -0
- package/dist/schema/messages.js +2 -0
- package/dist/schema/options.d.ts +5 -0
- package/dist/schema/options.js +5 -0
- package/package.json +3 -3
|
@@ -33,7 +33,12 @@ const OpenAIChatFunction = Schema.Struct({
|
|
|
33
33
|
});
|
|
34
34
|
const OpenAIChatTool = Schema.Struct({
|
|
35
35
|
type: Schema.tag("function"),
|
|
36
|
-
function:
|
|
36
|
+
function: Schema.Struct({
|
|
37
|
+
name: Schema.String,
|
|
38
|
+
description: Schema.String,
|
|
39
|
+
parameters: JsonObject,
|
|
40
|
+
strict: Schema.optional(Schema.Boolean),
|
|
41
|
+
}),
|
|
37
42
|
cache_control: Schema.optional(OpenAIChatCacheControl),
|
|
38
43
|
});
|
|
39
44
|
const OpenAIChatAssistantToolCall = Schema.Struct({
|
|
@@ -103,6 +108,7 @@ export const bodyFields = {
|
|
|
103
108
|
store: Schema.optional(Schema.Boolean),
|
|
104
109
|
prompt_cache_key: Schema.optional(Schema.String),
|
|
105
110
|
reasoning_effort: Schema.optional(OpenAIOptions.OpenAIReasoningEffort),
|
|
111
|
+
tool_stream: Schema.optional(Schema.Boolean),
|
|
106
112
|
max_completion_tokens: Schema.optional(Schema.Number),
|
|
107
113
|
max_tokens: Schema.optional(Schema.Number),
|
|
108
114
|
temperature: Schema.optional(Schema.Number),
|
|
@@ -170,12 +176,13 @@ export const OpenAIChatEvent = Schema.Struct({
|
|
|
170
176
|
usage: optionalNull(OpenAIChatUsage),
|
|
171
177
|
error: optionalNull(OpenAIChatError),
|
|
172
178
|
});
|
|
173
|
-
const lowerTool = (tool, inputSchema, options) => ({
|
|
179
|
+
const lowerTool = (tool, inputSchema, options, supportsStrictMode) => ({
|
|
174
180
|
type: "function",
|
|
175
181
|
function: {
|
|
176
182
|
name: tool.name,
|
|
177
183
|
description: tool.description,
|
|
178
184
|
parameters: inputSchema,
|
|
185
|
+
...(supportsStrictMode ? { strict: false } : {}),
|
|
179
186
|
},
|
|
180
187
|
cache_control: options.cacheControl?.(tool.cache),
|
|
181
188
|
});
|
|
@@ -413,11 +420,110 @@ const hasToolHistory = (messages) => {
|
|
|
413
420
|
}
|
|
414
421
|
return false;
|
|
415
422
|
};
|
|
416
|
-
|
|
423
|
+
// Derive `max_tokens` vs `max_completion_tokens` from provider/baseURL when
|
|
424
|
+
// explicit `compatibility.maxTokensField` is not set. Aligned with
|
|
425
|
+
// models.dev provider naming: DeepSeek, Moonshot AI, Together AI, ZAI
|
|
426
|
+
// (Zhipu + Coding Plan variants), Nvidia, Cerebras, Chutes, etc. still
|
|
427
|
+
// require `max_tokens`.
|
|
428
|
+
const detectMaxTokensField = (provider, baseURL) => {
|
|
429
|
+
const p = provider.toLowerCase();
|
|
430
|
+
const url = (baseURL ?? "").toLowerCase();
|
|
431
|
+
if (p === "deepseek" ||
|
|
432
|
+
url.includes("deepseek.com") ||
|
|
433
|
+
p === "moonshotai" ||
|
|
434
|
+
url.includes("api.moonshot.ai") ||
|
|
435
|
+
p === "togetherai" ||
|
|
436
|
+
url.includes("api.together.") ||
|
|
437
|
+
p === "zai" ||
|
|
438
|
+
p === "zai-coding-plan" ||
|
|
439
|
+
p === "zhipuai" ||
|
|
440
|
+
p === "zhipuai-coding-plan" ||
|
|
441
|
+
url.includes("api.z.ai") ||
|
|
442
|
+
url.includes("open.bigmodel.cn") ||
|
|
443
|
+
p === "nvidia" ||
|
|
444
|
+
url.includes("integrate.api.nvidia.com") ||
|
|
445
|
+
p === "cerebras" ||
|
|
446
|
+
url.includes("cerebras.ai") ||
|
|
447
|
+
url.includes("llm.chutes.ai") ||
|
|
448
|
+
p === "chutes" ||
|
|
449
|
+
p === "cloudflare-ai-gateway" ||
|
|
450
|
+
url.includes("gateway.ai.cloudflare.com") ||
|
|
451
|
+
p === "cloudflare-workers-ai" ||
|
|
452
|
+
url.includes("api.cloudflare.com"))
|
|
453
|
+
return "max_tokens";
|
|
454
|
+
return "max_completion_tokens";
|
|
455
|
+
};
|
|
456
|
+
const detectSupportsStore = (provider, baseURL) => {
|
|
457
|
+
const p = provider.toLowerCase();
|
|
458
|
+
const url = (baseURL ?? "").toLowerCase();
|
|
459
|
+
const isNvidia = p === "nvidia" || url.includes("integrate.api.nvidia.com");
|
|
460
|
+
const isMoonshot = p === "moonshotai" || p === "moonshotai-cn" || url.includes("api.moonshot.");
|
|
461
|
+
const isTogether = p === "togetherai" || p === "together" || url.includes("api.together.");
|
|
462
|
+
const isZai = p === "zai" ||
|
|
463
|
+
p === "zai-coding-plan" ||
|
|
464
|
+
p === "zhipuai" ||
|
|
465
|
+
p === "zhipuai-coding-plan" ||
|
|
466
|
+
url.includes("api.z.ai") ||
|
|
467
|
+
url.includes("open.bigmodel.cn");
|
|
468
|
+
const isDeepSeek = p === "deepseek" || url.includes("deepseek.com");
|
|
469
|
+
const isCerebras = p === "cerebras" || url.includes("cerebras.ai");
|
|
470
|
+
const isXai = p === "xai" || url.includes("api.x.ai");
|
|
471
|
+
const isChutes = p === "chutes" || url.includes("chutes.ai");
|
|
472
|
+
const isCloudflareWorkersAI = p === "cloudflare-workers-ai" || url.includes("api.cloudflare.com");
|
|
473
|
+
const isCloudflareAiGateway = p === "cloudflare-ai-gateway" || url.includes("gateway.ai.cloudflare.com");
|
|
474
|
+
const isVercelAiGateway = p === "vercel-ai-gateway" || url.includes("ai-gateway.vercel.sh") || url.includes("vercel.sh");
|
|
475
|
+
const isAntLing = p === "ant-ling" || url.includes("api.ant-ling.com");
|
|
476
|
+
const isOpencode = p === "opencode" || url.includes("opencode.ai");
|
|
477
|
+
const isNonStandard = isNvidia ||
|
|
478
|
+
isCerebras ||
|
|
479
|
+
isXai ||
|
|
480
|
+
isTogether ||
|
|
481
|
+
isChutes ||
|
|
482
|
+
isDeepSeek ||
|
|
483
|
+
isZai ||
|
|
484
|
+
isMoonshot ||
|
|
485
|
+
isOpencode ||
|
|
486
|
+
isCloudflareWorkersAI ||
|
|
487
|
+
isCloudflareAiGateway ||
|
|
488
|
+
isVercelAiGateway ||
|
|
489
|
+
isAntLing;
|
|
490
|
+
return !isNonStandard;
|
|
491
|
+
};
|
|
492
|
+
const detectSupportsUsageInStreaming = () => true;
|
|
493
|
+
const detectSupportsStrictMode = (provider, baseURL) => {
|
|
494
|
+
const p = provider.toLowerCase();
|
|
495
|
+
const url = (baseURL ?? "").toLowerCase();
|
|
496
|
+
const isMoonshot = p === "moonshotai" || p === "moonshotai-cn" || url.includes("api.moonshot.");
|
|
497
|
+
const isTogether = p === "togetherai" || p === "together" || url.includes("api.together.");
|
|
498
|
+
const isCloudflareAiGateway = p === "cloudflare-ai-gateway" || url.includes("gateway.ai.cloudflare.com");
|
|
499
|
+
const isNvidia = p === "nvidia" || url.includes("integrate.api.nvidia.com");
|
|
500
|
+
return !isMoonshot && !isTogether && !isCloudflareAiGateway && !isNvidia;
|
|
501
|
+
};
|
|
502
|
+
const detectZaiToolStream = (provider, baseURL, modelID) => {
|
|
503
|
+
const p = provider.toLowerCase();
|
|
504
|
+
const url = (baseURL ?? "").toLowerCase();
|
|
505
|
+
const isZai = p === "zai" ||
|
|
506
|
+
p === "zai-coding-plan" ||
|
|
507
|
+
p === "zhipuai" ||
|
|
508
|
+
p === "zhipuai-coding-plan" ||
|
|
509
|
+
url.includes("api.z.ai") ||
|
|
510
|
+
url.includes("open.bigmodel.cn");
|
|
511
|
+
if (!isZai)
|
|
512
|
+
return false;
|
|
513
|
+
const id = modelID.toLowerCase();
|
|
514
|
+
if (id === "glm-4.5" || id === "glm-4.5-air" || id === "glm-4.5-flash" || id === "glm-4.5v")
|
|
515
|
+
return false;
|
|
516
|
+
return true;
|
|
517
|
+
};
|
|
518
|
+
const lowerOptions = (request, supportsStore) => {
|
|
417
519
|
const options = OpenAIOptions.resolve(request);
|
|
418
520
|
const cacheKey = ProviderShared.clampPromptCacheKey(request.promptCacheKey);
|
|
419
521
|
return {
|
|
420
|
-
...(options.store !== undefined ? { store: options.store } : {}),
|
|
522
|
+
...(supportsStore && options.store !== undefined ? { store: options.store } : {}),
|
|
523
|
+
// For providers that support `store`, ensure stateless `store:false` is sent
|
|
524
|
+
// even when no explicit `providerOptions.store` was supplied, mirroring the
|
|
525
|
+
// native OpenAI Chat default. Non-standard providers omit `store` entirely.
|
|
526
|
+
...(supportsStore && options.store === undefined ? { store: false } : {}),
|
|
421
527
|
...(cacheKey ? { prompt_cache_key: cacheKey } : {}),
|
|
422
528
|
...(options.reasoningEffort ? { reasoning_effort: options.reasoningEffort } : {}),
|
|
423
529
|
};
|
|
@@ -430,8 +536,17 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
|
|
|
430
536
|
return yield* ProviderShared.invalidRequest(`OpenAI Chat reasoning field conflicts with reserved field ${reasoningField}`);
|
|
431
537
|
const generation = request.generation;
|
|
432
538
|
const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
|
|
433
|
-
const
|
|
539
|
+
const provider = String(request.model.provider);
|
|
540
|
+
const baseURL = request.model.route.endpoint.baseURL;
|
|
541
|
+
const detectedMaxTokensField = detectMaxTokensField(provider, baseURL);
|
|
542
|
+
const maxTokensField = request.model.compatibility?.maxTokensField ?? detectedMaxTokensField;
|
|
543
|
+
const supportsStore = request.model.compatibility?.supportsStore ?? detectSupportsStore(provider, baseURL);
|
|
544
|
+
const supportsUsageInStreaming = request.model.compatibility?.supportsUsageInStreaming ?? detectSupportsUsageInStreaming();
|
|
545
|
+
const supportsStrictMode = request.model.compatibility?.supportsStrictMode ?? detectSupportsStrictMode(provider, baseURL);
|
|
546
|
+
const zaiToolStream = request.model.compatibility?.zaiToolStream ??
|
|
547
|
+
detectZaiToolStream(provider, baseURL, request.model.id);
|
|
434
548
|
const hasHistory = hasToolHistory(request.messages);
|
|
549
|
+
const hasActiveTools = request.tools.length > 0;
|
|
435
550
|
return {
|
|
436
551
|
model: request.model.id,
|
|
437
552
|
messages: yield* lowerMessages(request, options),
|
|
@@ -439,10 +554,11 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
|
|
|
439
554
|
? hasHistory
|
|
440
555
|
? []
|
|
441
556
|
: undefined
|
|
442
|
-
: request.tools.map((tool) => lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility), options)),
|
|
557
|
+
: request.tools.map((tool) => lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility), options, supportsStrictMode)),
|
|
443
558
|
tool_choice: request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined,
|
|
444
559
|
stream: true,
|
|
445
|
-
stream_options: { include_usage: true },
|
|
560
|
+
...(supportsUsageInStreaming ? { stream_options: { include_usage: true } } : {}),
|
|
561
|
+
...(zaiToolStream && hasActiveTools ? { tool_stream: true } : {}),
|
|
446
562
|
...(maxTokensField === "max_completion_tokens"
|
|
447
563
|
? { max_completion_tokens: generation?.maxTokens }
|
|
448
564
|
: { max_tokens: generation?.maxTokens }),
|
|
@@ -452,7 +568,7 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
|
|
|
452
568
|
presence_penalty: generation?.presencePenalty,
|
|
453
569
|
seed: generation?.seed,
|
|
454
570
|
stop: generation?.stop,
|
|
455
|
-
...lowerOptions(request),
|
|
571
|
+
...lowerOptions(request, supportsStore),
|
|
456
572
|
};
|
|
457
573
|
});
|
|
458
574
|
// =============================================================================
|
|
@@ -73,11 +73,12 @@ export declare const route: Route<{
|
|
|
73
73
|
readonly max_tokens?: number | undefined;
|
|
74
74
|
readonly tools?: readonly {
|
|
75
75
|
readonly function: {
|
|
76
|
-
readonly name: string;
|
|
77
76
|
readonly description: string;
|
|
77
|
+
readonly name: string;
|
|
78
78
|
readonly parameters: {
|
|
79
79
|
readonly [x: string]: unknown;
|
|
80
80
|
};
|
|
81
|
+
readonly strict?: boolean | undefined;
|
|
81
82
|
};
|
|
82
83
|
readonly type: "function";
|
|
83
84
|
readonly cache_control?: {
|
|
@@ -101,6 +102,7 @@ export declare const route: Route<{
|
|
|
101
102
|
} | undefined;
|
|
102
103
|
readonly prompt_cache_key?: string | undefined;
|
|
103
104
|
readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
|
|
105
|
+
readonly tool_stream?: boolean | undefined;
|
|
104
106
|
readonly frequency_penalty?: number | undefined;
|
|
105
107
|
readonly presence_penalty?: number | undefined;
|
|
106
108
|
}, import("../route/transport/http.js").HttpPrepared<string>>;
|
|
@@ -94,6 +94,7 @@ export declare const route: Route<{
|
|
|
94
94
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
95
95
|
} | undefined;
|
|
96
96
|
readonly temperature?: number | undefined;
|
|
97
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
97
98
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
98
99
|
readonly type: "function";
|
|
99
100
|
readonly name: string;
|
|
@@ -117,7 +118,6 @@ export declare const route: Route<{
|
|
|
117
118
|
readonly presence_penalty?: number | undefined;
|
|
118
119
|
readonly safety_identifier?: string | undefined;
|
|
119
120
|
readonly top_logprobs?: number | undefined;
|
|
120
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
121
121
|
readonly max_output_tokens?: number | undefined;
|
|
122
122
|
readonly max_tool_calls?: number | undefined;
|
|
123
123
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -230,6 +230,7 @@ export declare const protocol: Protocol<{
|
|
|
230
230
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
231
231
|
} | undefined;
|
|
232
232
|
readonly temperature?: number | undefined;
|
|
233
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
233
234
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
234
235
|
readonly type: "function";
|
|
235
236
|
readonly name: string;
|
|
@@ -255,7 +256,6 @@ export declare const protocol: Protocol<{
|
|
|
255
256
|
readonly presence_penalty?: number | undefined;
|
|
256
257
|
readonly safety_identifier?: string | undefined;
|
|
257
258
|
readonly top_logprobs?: number | undefined;
|
|
258
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
259
259
|
readonly max_output_tokens?: number | undefined;
|
|
260
260
|
readonly max_tool_calls?: number | undefined;
|
|
261
261
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -413,6 +413,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
413
413
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
414
414
|
} | undefined;
|
|
415
415
|
readonly temperature?: number | undefined;
|
|
416
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
416
417
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
417
418
|
readonly type: "function";
|
|
418
419
|
readonly name: string;
|
|
@@ -438,7 +439,6 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
438
439
|
readonly presence_penalty?: number | undefined;
|
|
439
440
|
readonly safety_identifier?: string | undefined;
|
|
440
441
|
readonly top_logprobs?: number | undefined;
|
|
441
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
442
442
|
readonly max_output_tokens?: number | undefined;
|
|
443
443
|
readonly max_tool_calls?: number | undefined;
|
|
444
444
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -542,6 +542,7 @@ export declare const channelTransport: (options: import("./open-responses-channe
|
|
|
542
542
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
543
543
|
} | undefined;
|
|
544
544
|
readonly temperature?: number | undefined;
|
|
545
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
545
546
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
546
547
|
readonly type: "function";
|
|
547
548
|
readonly name: string;
|
|
@@ -567,7 +568,6 @@ export declare const channelTransport: (options: import("./open-responses-channe
|
|
|
567
568
|
readonly presence_penalty?: number | undefined;
|
|
568
569
|
readonly safety_identifier?: string | undefined;
|
|
569
570
|
readonly top_logprobs?: number | undefined;
|
|
570
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
571
571
|
readonly max_output_tokens?: number | undefined;
|
|
572
572
|
readonly max_tool_calls?: number | undefined;
|
|
573
573
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -671,6 +671,7 @@ export declare const transport: import("../route/transport/index.js").Transport<
|
|
|
671
671
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
672
672
|
} | undefined;
|
|
673
673
|
readonly temperature?: number | undefined;
|
|
674
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
674
675
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
675
676
|
readonly type: "function";
|
|
676
677
|
readonly name: string;
|
|
@@ -696,7 +697,6 @@ export declare const transport: import("../route/transport/index.js").Transport<
|
|
|
696
697
|
readonly presence_penalty?: number | undefined;
|
|
697
698
|
readonly safety_identifier?: string | undefined;
|
|
698
699
|
readonly top_logprobs?: number | undefined;
|
|
699
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
700
700
|
readonly max_output_tokens?: number | undefined;
|
|
701
701
|
readonly max_tool_calls?: number | undefined;
|
|
702
702
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -800,6 +800,7 @@ export declare const route: Route<{
|
|
|
800
800
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
801
801
|
} | undefined;
|
|
802
802
|
readonly temperature?: number | undefined;
|
|
803
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
803
804
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
804
805
|
readonly type: "function";
|
|
805
806
|
readonly name: string;
|
|
@@ -825,7 +826,6 @@ export declare const route: Route<{
|
|
|
825
826
|
readonly presence_penalty?: number | undefined;
|
|
826
827
|
readonly safety_identifier?: string | undefined;
|
|
827
828
|
readonly top_logprobs?: number | undefined;
|
|
828
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
829
829
|
readonly max_output_tokens?: number | undefined;
|
|
830
830
|
readonly max_tool_calls?: number | undefined;
|
|
831
831
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -43,9 +43,27 @@ const OpenAIResponsesBody = Schema.Struct({
|
|
|
43
43
|
...OpenAIResponsesCoreFields,
|
|
44
44
|
stream: Schema.Literal(true),
|
|
45
45
|
});
|
|
46
|
+
// Replayed items are paired with stored server state by id, so a foreign or
|
|
47
|
+
// synthetic token can fail request validation even when `call_id` pairing is
|
|
48
|
+
// intact. Only resend ids in each item kind's own grammar; hosted tool
|
|
49
|
+
// references keep generic validation because every hosted tool mints its own
|
|
50
|
+
// prefix. The same allowlist approach codex uses before resending history
|
|
51
|
+
// (codex-rs core/src/client.rs, `prepare_response_items_for_request`).
|
|
52
|
+
const ITEM_ID_PREFIXES = {
|
|
53
|
+
message: ["msg_"],
|
|
54
|
+
reasoning: ["rs_"],
|
|
55
|
+
"function-call": ["fc_"],
|
|
56
|
+
// Every hosted tool mints its own id prefix, so references keep generic
|
|
57
|
+
// validation only.
|
|
58
|
+
reference: [],
|
|
59
|
+
};
|
|
46
60
|
const extension = {
|
|
47
61
|
id: ADAPTER,
|
|
48
62
|
name: NAME,
|
|
63
|
+
acceptsItemID: (kind, id) => {
|
|
64
|
+
const prefixes = ITEM_ID_PREFIXES[kind];
|
|
65
|
+
return prefixes.length === 0 || prefixes.some((prefix) => id.startsWith(prefix));
|
|
66
|
+
},
|
|
49
67
|
};
|
|
50
68
|
const nativeImageToolInput = (tool) => {
|
|
51
69
|
const native = tool.native?.openai;
|
|
@@ -75,8 +93,10 @@ const lowerToolChoice = (toolChoice, tools) => ProviderShared.matchToolChoice(NA
|
|
|
75
93
|
const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request) {
|
|
76
94
|
const body = yield* OpenResponses.fromRequestWithExtension(LLMRequest.update(request, { tools: [], toolChoice: undefined }), extension);
|
|
77
95
|
const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
|
|
96
|
+
const parallelToolCalls = OpenResponses.resolveParallelToolCalls(request);
|
|
78
97
|
return {
|
|
79
98
|
...body,
|
|
99
|
+
...(parallelToolCalls === undefined ? {} : { parallel_tool_calls: parallelToolCalls }),
|
|
80
100
|
tools: request.tools.length === 0
|
|
81
101
|
? undefined
|
|
82
102
|
: yield* Effect.forEach(request.tools, (tool) => lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility))),
|
|
@@ -117,14 +137,10 @@ const HOSTED_TOOLS = {
|
|
|
117
137
|
},
|
|
118
138
|
};
|
|
119
139
|
const step = (state, event) => {
|
|
120
|
-
if (event.type === "response.reasoning_text.delta"
|
|
140
|
+
if (event.type === "response.reasoning_text.delta")
|
|
121
141
|
return event.item_id
|
|
122
142
|
? Effect.succeed(OpenResponses.onReasoningDelta(state, event, event.item_id))
|
|
123
143
|
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
|
|
124
|
-
if (event.type === "response.reasoning_text.done" || event.type === "response.reasoning_summary.done")
|
|
125
|
-
return event.item_id
|
|
126
|
-
? Effect.succeed(OpenResponses.onReasoningDone(state, event))
|
|
127
|
-
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
|
|
128
144
|
if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
|
|
129
145
|
return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
|
|
130
146
|
return OpenResponses.step(state, event);
|
|
@@ -29,6 +29,7 @@ export declare const lower: (part: {
|
|
|
29
29
|
readonly metadata?: {
|
|
30
30
|
readonly [x: string]: unknown;
|
|
31
31
|
} | undefined;
|
|
32
|
+
readonly cache?: import("../../schema/options.js").CacheHint | undefined;
|
|
32
33
|
readonly filename?: string | undefined;
|
|
33
34
|
}) => Effect.Effect<{
|
|
34
35
|
readonly document: {
|
|
@@ -89,6 +89,7 @@ export declare const protocol: Protocol<{
|
|
|
89
89
|
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
90
90
|
} | undefined;
|
|
91
91
|
readonly temperature?: number | undefined;
|
|
92
|
+
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
92
93
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
93
94
|
readonly type: "function";
|
|
94
95
|
readonly name: string;
|
|
@@ -112,7 +113,6 @@ export declare const protocol: Protocol<{
|
|
|
112
113
|
readonly presence_penalty?: number | undefined;
|
|
113
114
|
readonly safety_identifier?: string | undefined;
|
|
114
115
|
readonly top_logprobs?: number | undefined;
|
|
115
|
-
readonly service_tier?: import("./utils/open-responses-options.js").ServiceTier | undefined;
|
|
116
116
|
readonly max_output_tokens?: number | undefined;
|
|
117
117
|
readonly max_tool_calls?: number | undefined;
|
|
118
118
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
2
1
|
import { Protocol } from "../route/protocol.js";
|
|
3
2
|
import { OpenResponses } from "./open-responses.js";
|
|
4
|
-
import { ProviderShared } from "./shared.js";
|
|
5
3
|
import { ResponsesHostedTools } from "./utils/responses-hosted-tools.js";
|
|
6
4
|
const ADAPTER = "xai-responses";
|
|
7
5
|
const NAME = "xAI Responses";
|
|
@@ -23,15 +21,9 @@ const HOSTED_TOOLS = {
|
|
|
23
21
|
input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
|
|
24
22
|
},
|
|
25
23
|
};
|
|
24
|
+
// Grok speaks the standard Responses reasoning dialect (`reasoning_summary_text.*`,
|
|
25
|
+
// handled by the baseline); only its hosted tool vocabulary differs.
|
|
26
26
|
const step = (state, event) => {
|
|
27
|
-
if (event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary.delta")
|
|
28
|
-
return event.item_id
|
|
29
|
-
? Effect.succeed(OpenResponses.onReasoningDelta(state, event, event.item_id))
|
|
30
|
-
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
|
|
31
|
-
if (event.type === "response.reasoning_text.done" || event.type === "response.reasoning_summary.done")
|
|
32
|
-
return event.item_id
|
|
33
|
-
? Effect.succeed(OpenResponses.onReasoningDone(state, event))
|
|
34
|
-
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
|
|
35
27
|
if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
|
|
36
28
|
return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
|
|
37
29
|
return OpenResponses.step(state, event);
|
|
@@ -85,11 +85,12 @@ export declare const routes: (RouteDef<{
|
|
|
85
85
|
readonly max_tokens?: number | undefined;
|
|
86
86
|
readonly tools?: readonly {
|
|
87
87
|
readonly function: {
|
|
88
|
-
readonly name: string;
|
|
89
88
|
readonly description: string;
|
|
89
|
+
readonly name: string;
|
|
90
90
|
readonly parameters: {
|
|
91
91
|
readonly [x: string]: unknown;
|
|
92
92
|
};
|
|
93
|
+
readonly strict?: boolean | undefined;
|
|
93
94
|
};
|
|
94
95
|
readonly type: "function";
|
|
95
96
|
readonly cache_control?: {
|
|
@@ -113,6 +114,7 @@ export declare const routes: (RouteDef<{
|
|
|
113
114
|
} | undefined;
|
|
114
115
|
readonly prompt_cache_key?: string | undefined;
|
|
115
116
|
readonly reasoning_effort?: import("../protocols/utils/open-responses-options.js").ReasoningEffort | undefined;
|
|
117
|
+
readonly tool_stream?: boolean | undefined;
|
|
116
118
|
readonly frequency_penalty?: number | undefined;
|
|
117
119
|
readonly presence_penalty?: number | undefined;
|
|
118
120
|
}, import("../route/transport/http.js").HttpPrepared<string>> | RouteDef<{
|
|
@@ -214,6 +216,7 @@ export declare const routes: (RouteDef<{
|
|
|
214
216
|
readonly verbosity?: import("../protocols/utils/open-responses-options.js").TextVerbosity | undefined;
|
|
215
217
|
} | undefined;
|
|
216
218
|
readonly temperature?: number | undefined;
|
|
219
|
+
readonly service_tier?: import("../protocols/utils/open-responses-options.js").ServiceTier | undefined;
|
|
217
220
|
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
218
221
|
readonly type: "function";
|
|
219
222
|
readonly name: string;
|
|
@@ -239,7 +242,6 @@ export declare const routes: (RouteDef<{
|
|
|
239
242
|
readonly presence_penalty?: number | undefined;
|
|
240
243
|
readonly safety_identifier?: string | undefined;
|
|
241
244
|
readonly top_logprobs?: number | undefined;
|
|
242
|
-
readonly service_tier?: import("../protocols/utils/open-responses-options.js").ServiceTier | undefined;
|
|
243
245
|
readonly max_output_tokens?: number | undefined;
|
|
244
246
|
readonly max_tool_calls?: number | undefined;
|
|
245
247
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
@@ -41,22 +41,46 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
41
41
|
readonly type: "base64";
|
|
42
42
|
readonly media_type: string;
|
|
43
43
|
readonly data: string;
|
|
44
|
+
} | {
|
|
45
|
+
readonly type: "url";
|
|
46
|
+
readonly url: string;
|
|
47
|
+
} | {
|
|
48
|
+
readonly type: "file";
|
|
49
|
+
readonly file_id: string;
|
|
44
50
|
};
|
|
45
51
|
readonly cache_control?: {
|
|
46
52
|
readonly type: "ephemeral";
|
|
47
53
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
48
54
|
} | undefined;
|
|
55
|
+
readonly transformations?: {
|
|
56
|
+
readonly oversized_image?: "error" | "downsize" | undefined;
|
|
57
|
+
} | undefined;
|
|
49
58
|
} | {
|
|
50
59
|
readonly type: "document";
|
|
51
60
|
readonly source: {
|
|
52
61
|
readonly type: "base64";
|
|
53
62
|
readonly media_type: "application/pdf";
|
|
54
63
|
readonly data: string;
|
|
64
|
+
} | {
|
|
65
|
+
readonly type: "text";
|
|
66
|
+
readonly media_type: "text/plain";
|
|
67
|
+
readonly data: string;
|
|
68
|
+
} | {
|
|
69
|
+
readonly type: "url";
|
|
70
|
+
readonly url: string;
|
|
71
|
+
} | {
|
|
72
|
+
readonly type: "file";
|
|
73
|
+
readonly file_id: string;
|
|
55
74
|
};
|
|
75
|
+
readonly title?: string | undefined;
|
|
76
|
+
readonly context?: string | undefined;
|
|
56
77
|
readonly cache_control?: {
|
|
57
78
|
readonly type: "ephemeral";
|
|
58
79
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
59
80
|
} | undefined;
|
|
81
|
+
readonly citations?: {
|
|
82
|
+
readonly enabled: boolean;
|
|
83
|
+
} | undefined;
|
|
60
84
|
} | {
|
|
61
85
|
readonly type: "tool_result";
|
|
62
86
|
readonly content: string | readonly ({
|
|
@@ -72,22 +96,46 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
72
96
|
readonly type: "base64";
|
|
73
97
|
readonly media_type: string;
|
|
74
98
|
readonly data: string;
|
|
99
|
+
} | {
|
|
100
|
+
readonly type: "url";
|
|
101
|
+
readonly url: string;
|
|
102
|
+
} | {
|
|
103
|
+
readonly type: "file";
|
|
104
|
+
readonly file_id: string;
|
|
75
105
|
};
|
|
76
106
|
readonly cache_control?: {
|
|
77
107
|
readonly type: "ephemeral";
|
|
78
108
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
79
109
|
} | undefined;
|
|
110
|
+
readonly transformations?: {
|
|
111
|
+
readonly oversized_image?: "error" | "downsize" | undefined;
|
|
112
|
+
} | undefined;
|
|
80
113
|
} | {
|
|
81
114
|
readonly type: "document";
|
|
82
115
|
readonly source: {
|
|
83
116
|
readonly type: "base64";
|
|
84
117
|
readonly media_type: "application/pdf";
|
|
85
118
|
readonly data: string;
|
|
119
|
+
} | {
|
|
120
|
+
readonly type: "text";
|
|
121
|
+
readonly media_type: "text/plain";
|
|
122
|
+
readonly data: string;
|
|
123
|
+
} | {
|
|
124
|
+
readonly type: "url";
|
|
125
|
+
readonly url: string;
|
|
126
|
+
} | {
|
|
127
|
+
readonly type: "file";
|
|
128
|
+
readonly file_id: string;
|
|
86
129
|
};
|
|
130
|
+
readonly title?: string | undefined;
|
|
131
|
+
readonly context?: string | undefined;
|
|
87
132
|
readonly cache_control?: {
|
|
88
133
|
readonly type: "ephemeral";
|
|
89
134
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
90
135
|
} | undefined;
|
|
136
|
+
readonly citations?: {
|
|
137
|
+
readonly enabled: boolean;
|
|
138
|
+
} | undefined;
|
|
91
139
|
})[];
|
|
92
140
|
readonly tool_use_id: string;
|
|
93
141
|
readonly cache_control?: {
|
|
@@ -134,11 +182,11 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
134
182
|
} | {
|
|
135
183
|
readonly type: "thinking";
|
|
136
184
|
readonly thinking: string;
|
|
185
|
+
readonly signature: string;
|
|
137
186
|
readonly cache_control?: {
|
|
138
187
|
readonly type: "ephemeral";
|
|
139
188
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
140
189
|
} | undefined;
|
|
141
|
-
readonly signature?: string | undefined;
|
|
142
190
|
} | {
|
|
143
191
|
readonly data: string;
|
|
144
192
|
readonly type: "redacted_thinking";
|
|
@@ -159,6 +207,9 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
159
207
|
}[];
|
|
160
208
|
})[];
|
|
161
209
|
readonly stream: true;
|
|
210
|
+
readonly metadata?: {
|
|
211
|
+
readonly user_id?: string | null | undefined;
|
|
212
|
+
} | undefined;
|
|
162
213
|
readonly tools?: readonly {
|
|
163
214
|
readonly description: string;
|
|
164
215
|
readonly name: string;
|
|
@@ -189,18 +240,38 @@ export declare const routes: import("../route/client.js").Route<{
|
|
|
189
240
|
} | {
|
|
190
241
|
readonly type: "disabled";
|
|
191
242
|
} | undefined;
|
|
243
|
+
readonly service_tier?: "auto" | "standard_only" | undefined;
|
|
244
|
+
readonly container?: string | {
|
|
245
|
+
readonly id?: string | null | undefined;
|
|
246
|
+
readonly skills?: readonly {
|
|
247
|
+
readonly [x: string]: unknown;
|
|
248
|
+
}[] | null | undefined;
|
|
249
|
+
} | null | undefined;
|
|
250
|
+
readonly inference_geo?: string | null | undefined;
|
|
251
|
+
readonly cache_control?: {
|
|
252
|
+
readonly type: "ephemeral";
|
|
253
|
+
readonly ttl?: "1h" | "5m" | undefined;
|
|
254
|
+
} | undefined;
|
|
255
|
+
readonly output_config?: {
|
|
256
|
+
readonly format?: {
|
|
257
|
+
readonly type: "json_schema";
|
|
258
|
+
readonly schema: {
|
|
259
|
+
readonly [x: string]: unknown;
|
|
260
|
+
};
|
|
261
|
+
} | null | undefined;
|
|
262
|
+
readonly effort?: string | undefined;
|
|
263
|
+
} | undefined;
|
|
192
264
|
readonly tool_choice?: {
|
|
193
265
|
readonly type: "auto" | "none" | "any";
|
|
266
|
+
readonly disable_parallel_tool_use?: boolean | undefined;
|
|
194
267
|
} | {
|
|
195
268
|
readonly type: "tool";
|
|
196
269
|
readonly name: string;
|
|
270
|
+
readonly disable_parallel_tool_use?: boolean | undefined;
|
|
197
271
|
} | undefined;
|
|
198
272
|
readonly top_p?: number | undefined;
|
|
199
273
|
readonly top_k?: number | undefined;
|
|
200
274
|
readonly stop_sequences?: readonly string[] | undefined;
|
|
201
|
-
readonly output_config?: {
|
|
202
|
-
readonly effort?: string | undefined;
|
|
203
|
-
} | undefined;
|
|
204
275
|
}, import("../route/transport/http.js").HttpPrepared<string>>[];
|
|
205
276
|
export declare const configure: (input: Config) => {
|
|
206
277
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|