@opencode-ai/ai 0.0.0-beta-18050 → 0.0.0-beta-18138
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/utils/partial-json-options.d.ts +62 -0
- package/dist/protocols/utils/partial-json-options.js +52 -0
- package/dist/protocols/utils/partial-json.d.ts +8 -0
- package/dist/protocols/utils/partial-json.js +224 -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: {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* allow partial strings like `"hello \u12` to be parsed as `"hello `
|
|
3
|
+
*/
|
|
4
|
+
export declare const STR = 1;
|
|
5
|
+
/**
|
|
6
|
+
* allow partial numbers like `123.` to be parsed as `123`
|
|
7
|
+
*/
|
|
8
|
+
export declare const NUM = 2;
|
|
9
|
+
/**
|
|
10
|
+
* allow partial arrays like `[1, 2,` to be parsed as `[1, 2]`
|
|
11
|
+
*/
|
|
12
|
+
export declare const ARR = 4;
|
|
13
|
+
/**
|
|
14
|
+
* allow partial objects like `{"a": 1, "b":` to be parsed as `{"a": 1}`
|
|
15
|
+
*/
|
|
16
|
+
export declare const OBJ = 8;
|
|
17
|
+
/**
|
|
18
|
+
* allow `nu` to be parsed as `null`
|
|
19
|
+
*/
|
|
20
|
+
export declare const NULL = 16;
|
|
21
|
+
/**
|
|
22
|
+
* allow `tr` to be parsed as `true`, and `fa` to be parsed as `false`
|
|
23
|
+
*/
|
|
24
|
+
export declare const BOOL = 32;
|
|
25
|
+
/**
|
|
26
|
+
* allow `Na` to be parsed as `NaN`
|
|
27
|
+
*/
|
|
28
|
+
export declare const NAN = 64;
|
|
29
|
+
/**
|
|
30
|
+
* allow `Inf` to be parsed as `Infinity`
|
|
31
|
+
*/
|
|
32
|
+
export declare const INFINITY = 128;
|
|
33
|
+
/**
|
|
34
|
+
* allow `-Inf` to be parsed as `-Infinity`
|
|
35
|
+
*/
|
|
36
|
+
export declare const _INFINITY = 256;
|
|
37
|
+
export declare const INF: number;
|
|
38
|
+
export declare const SPECIAL: number;
|
|
39
|
+
export declare const ATOM: number;
|
|
40
|
+
export declare const COLLECTION: number;
|
|
41
|
+
export declare const ALL: number;
|
|
42
|
+
/**
|
|
43
|
+
* Control what types you allow to be partially parsed.
|
|
44
|
+
* The default is to allow all types to be partially parsed, which in most cases is the best option.
|
|
45
|
+
*/
|
|
46
|
+
export declare const Allow: {
|
|
47
|
+
STR: number;
|
|
48
|
+
NUM: number;
|
|
49
|
+
ARR: number;
|
|
50
|
+
OBJ: number;
|
|
51
|
+
NULL: number;
|
|
52
|
+
BOOL: number;
|
|
53
|
+
NAN: number;
|
|
54
|
+
INFINITY: number;
|
|
55
|
+
_INFINITY: number;
|
|
56
|
+
INF: number;
|
|
57
|
+
SPECIAL: number;
|
|
58
|
+
ATOM: number;
|
|
59
|
+
COLLECTION: number;
|
|
60
|
+
ALL: number;
|
|
61
|
+
};
|
|
62
|
+
export default Allow;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Adapted from partial-json by the Promplate Dev Team:
|
|
3
|
+
* https://github.com/promplate/partial-json-parser-js/blob/main/src/options.ts
|
|
4
|
+
* Licensed under the MIT License; see partial-json.ts for the complete notice.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* allow partial strings like `"hello \u12` to be parsed as `"hello `
|
|
8
|
+
*/
|
|
9
|
+
export const STR = 0b000000001;
|
|
10
|
+
/**
|
|
11
|
+
* allow partial numbers like `123.` to be parsed as `123`
|
|
12
|
+
*/
|
|
13
|
+
export const NUM = 0b000000010;
|
|
14
|
+
/**
|
|
15
|
+
* allow partial arrays like `[1, 2,` to be parsed as `[1, 2]`
|
|
16
|
+
*/
|
|
17
|
+
export const ARR = 0b000000100;
|
|
18
|
+
/**
|
|
19
|
+
* allow partial objects like `{"a": 1, "b":` to be parsed as `{"a": 1}`
|
|
20
|
+
*/
|
|
21
|
+
export const OBJ = 0b000001000;
|
|
22
|
+
/**
|
|
23
|
+
* allow `nu` to be parsed as `null`
|
|
24
|
+
*/
|
|
25
|
+
export const NULL = 0b000010000;
|
|
26
|
+
/**
|
|
27
|
+
* allow `tr` to be parsed as `true`, and `fa` to be parsed as `false`
|
|
28
|
+
*/
|
|
29
|
+
export const BOOL = 0b000100000;
|
|
30
|
+
/**
|
|
31
|
+
* allow `Na` to be parsed as `NaN`
|
|
32
|
+
*/
|
|
33
|
+
export const NAN = 0b001000000;
|
|
34
|
+
/**
|
|
35
|
+
* allow `Inf` to be parsed as `Infinity`
|
|
36
|
+
*/
|
|
37
|
+
export const INFINITY = 0b010000000;
|
|
38
|
+
/**
|
|
39
|
+
* allow `-Inf` to be parsed as `-Infinity`
|
|
40
|
+
*/
|
|
41
|
+
export const _INFINITY = 0b100000000;
|
|
42
|
+
export const INF = INFINITY | _INFINITY;
|
|
43
|
+
export const SPECIAL = NULL | BOOL | INF | NAN;
|
|
44
|
+
export const ATOM = STR | NUM | SPECIAL;
|
|
45
|
+
export const COLLECTION = ARR | OBJ;
|
|
46
|
+
export const ALL = ATOM | COLLECTION;
|
|
47
|
+
/**
|
|
48
|
+
* Control what types you allow to be partially parsed.
|
|
49
|
+
* The default is to allow all types to be partially parsed, which in most cases is the best option.
|
|
50
|
+
*/
|
|
51
|
+
export const Allow = { STR, NUM, ARR, OBJ, NULL, BOOL, NAN, INFINITY, _INFINITY, INF, SPECIAL, ATOM, COLLECTION, ALL };
|
|
52
|
+
export default Allow;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./partial-json-options.js";
|
|
2
|
+
export declare class PartialJSON extends Error {
|
|
3
|
+
}
|
|
4
|
+
export declare class MalformedJSON extends Error {
|
|
5
|
+
}
|
|
6
|
+
/** Parse complete or incomplete JSON, restricted by the supplied partial-value flags. */
|
|
7
|
+
export declare function parseJSON(jsonString: string, allowPartial?: number): unknown;
|
|
8
|
+
export declare const parse: typeof parseJSON;
|