@opencode/ai 2.0.20 → 2.0.21
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/cache-policy.js +15 -3
- package/dist/protocols/alibaba-chat.d.ts +16 -10
- package/dist/protocols/openai-chat.d.ts +114 -71
- package/dist/protocols/openai-chat.js +31 -32
- package/dist/protocols/openai-compatible-chat.d.ts +16 -10
- package/dist/protocols/zai-chat.d.ts +16 -10
- package/dist/provider-error.js +4 -0
- package/dist/providers/alibaba.d.ts +16 -10
- package/dist/providers/amazon-bedrock-mantle.d.ts +16 -10
- package/dist/providers/azure.d.ts +16 -10
- package/dist/providers/baseten.d.ts +32 -20
- package/dist/providers/cerebras.d.ts +32 -20
- package/dist/providers/cloudflare-ai-gateway.d.ts +32 -20
- package/dist/providers/cloudflare-ai-gateway.js +43 -35
- package/dist/providers/cloudflare-workers-ai.d.ts +32 -20
- package/dist/providers/deepinfra.d.ts +32 -20
- package/dist/providers/deepseek.d.ts +32 -20
- package/dist/providers/fireworks.d.ts +32 -20
- package/dist/providers/google-vertex-chat.d.ts +16 -10
- package/dist/providers/groq.d.ts +32 -20
- package/dist/providers/meta.d.ts +16 -10
- package/dist/providers/minimax.d.ts +16 -10
- package/dist/providers/moonshot.d.ts +16 -10
- package/dist/providers/openai-compatible.d.ts +16 -10
- package/dist/providers/openai.d.ts +16 -10
- package/dist/providers/openrouter.d.ts +64 -40
- package/dist/providers/togetherai.d.ts +32 -20
- package/dist/providers/xai.d.ts +16 -10
- package/dist/providers/zai-coding-plan.d.ts +16 -10
- package/dist/providers/zai.d.ts +16 -10
- package/package.json +3 -3
package/dist/cache-policy.js
CHANGED
|
@@ -48,6 +48,18 @@ const RESPECTS_INLINE_HINTS = new Set([
|
|
|
48
48
|
"bedrock-converse",
|
|
49
49
|
"openrouter",
|
|
50
50
|
]);
|
|
51
|
+
// OpenRouter upstreams other than Anthropic and Alibaba Qwen cache without breakpoints. Gemini uses only the last
|
|
52
|
+
// breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs more than none. Qwen ignores
|
|
53
|
+
// breakpoints on tool definitions and caches tools with the system prompt.
|
|
54
|
+
const openRouterPolicy = (modelID) => {
|
|
55
|
+
// `~anthropic/claude-sonnet-latest` style IDs are OpenRouter aliases for the latest model in a family.
|
|
56
|
+
const id = modelID.replace(/^~/, "");
|
|
57
|
+
if (id.startsWith("anthropic/"))
|
|
58
|
+
return AUTO;
|
|
59
|
+
if (id.startsWith("qwen/"))
|
|
60
|
+
return { system: true, messages: { tail: 1 } };
|
|
61
|
+
return NONE;
|
|
62
|
+
};
|
|
51
63
|
const makeHint = (ttlSeconds) => ttlSeconds !== undefined ? new CacheHint({ type: "ephemeral", ttlSeconds }) : new CacheHint({ type: "ephemeral" });
|
|
52
64
|
const markLastTool = (tools, hint, budget) => {
|
|
53
65
|
const target = tools.at(-1);
|
|
@@ -128,9 +140,9 @@ const countHints = (request) => countToolHints(request.tools) +
|
|
|
128
140
|
export const applyCachePolicy = (request) => {
|
|
129
141
|
if (!RESPECTS_INLINE_HINTS.has(request.model.route.id))
|
|
130
142
|
return request;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
const policy = request.model.route.id === "openrouter" && (request.cache === undefined || request.cache === "auto")
|
|
144
|
+
? openRouterPolicy(request.model.id)
|
|
145
|
+
: resolve(request.cache);
|
|
134
146
|
if (!policy.tools && !policy.system && !policy.messages)
|
|
135
147
|
return request;
|
|
136
148
|
const hint = makeHint(policy.ttlSeconds);
|
|
@@ -80,15 +80,18 @@ export declare const protocol: Protocol<{
|
|
|
80
80
|
})[];
|
|
81
81
|
} | {
|
|
82
82
|
readonly [x: string]: unknown;
|
|
83
|
-
readonly content: string |
|
|
83
|
+
readonly content: string | readonly {
|
|
84
|
+
readonly type: "text";
|
|
85
|
+
readonly text: string;
|
|
86
|
+
readonly cache_control?: {
|
|
87
|
+
readonly type: "ephemeral";
|
|
88
|
+
readonly ttl?: string | undefined;
|
|
89
|
+
} | undefined;
|
|
90
|
+
}[] | null;
|
|
84
91
|
readonly role: "assistant";
|
|
85
92
|
readonly reasoning?: string | undefined;
|
|
86
93
|
readonly reasoning_content?: string | undefined;
|
|
87
94
|
readonly reasoning_text?: string | undefined;
|
|
88
|
-
readonly cache_control?: {
|
|
89
|
-
readonly type: "ephemeral";
|
|
90
|
-
readonly ttl?: string | undefined;
|
|
91
|
-
} | undefined;
|
|
92
95
|
readonly tool_calls?: readonly {
|
|
93
96
|
readonly function: {
|
|
94
97
|
readonly name: string;
|
|
@@ -104,13 +107,16 @@ export declare const protocol: Protocol<{
|
|
|
104
107
|
}[] | undefined;
|
|
105
108
|
readonly reasoning_details?: unknown;
|
|
106
109
|
} | {
|
|
107
|
-
readonly content: string;
|
|
108
110
|
readonly role: "tool";
|
|
109
111
|
readonly tool_call_id: string;
|
|
110
|
-
readonly
|
|
111
|
-
readonly type: "
|
|
112
|
-
readonly
|
|
113
|
-
|
|
112
|
+
readonly content: string | readonly {
|
|
113
|
+
readonly type: "text";
|
|
114
|
+
readonly text: string;
|
|
115
|
+
readonly cache_control?: {
|
|
116
|
+
readonly type: "ephemeral";
|
|
117
|
+
readonly ttl?: string | undefined;
|
|
118
|
+
} | undefined;
|
|
119
|
+
}[];
|
|
114
120
|
})[];
|
|
115
121
|
readonly stream: true;
|
|
116
122
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -12,6 +12,7 @@ declare const OpenAIChatCacheControl: Schema.Struct<{
|
|
|
12
12
|
readonly type: Schema.Literal<"ephemeral">;
|
|
13
13
|
readonly ttl: Schema.optional<Schema.String>;
|
|
14
14
|
}>;
|
|
15
|
+
type OpenAIChatCacheControl = Schema.Schema.Type<typeof OpenAIChatCacheControl>;
|
|
15
16
|
declare const ExtraContent: Schema.Struct<{
|
|
16
17
|
readonly google: Schema.Struct<{
|
|
17
18
|
readonly thought_signature: Schema.String;
|
|
@@ -94,7 +95,14 @@ export declare const bodyFields: {
|
|
|
94
95
|
}>]>>]>;
|
|
95
96
|
}>, Schema.StructWithRest<Schema.Struct<{
|
|
96
97
|
readonly role: Schema.Literal<"assistant">;
|
|
97
|
-
readonly content: Schema.NullOr<Schema.String
|
|
98
|
+
readonly content: Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.$Array<Schema.Struct<{
|
|
99
|
+
readonly type: Schema.Literal<"text">;
|
|
100
|
+
readonly text: Schema.String;
|
|
101
|
+
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
102
|
+
readonly type: Schema.Literal<"ephemeral">;
|
|
103
|
+
readonly ttl: Schema.optional<Schema.String>;
|
|
104
|
+
}>>;
|
|
105
|
+
}>>]>>;
|
|
98
106
|
readonly tool_calls: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
99
107
|
readonly id: Schema.String;
|
|
100
108
|
readonly type: Schema.tag<"function">;
|
|
@@ -112,18 +120,17 @@ export declare const bodyFields: {
|
|
|
112
120
|
readonly reasoning: Schema.optional<Schema.String>;
|
|
113
121
|
readonly reasoning_text: Schema.optional<Schema.String>;
|
|
114
122
|
readonly reasoning_details: Schema.optional<Schema.Unknown>;
|
|
115
|
-
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
116
|
-
readonly type: Schema.Literal<"ephemeral">;
|
|
117
|
-
readonly ttl: Schema.optional<Schema.String>;
|
|
118
|
-
}>>;
|
|
119
123
|
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>, Schema.Struct<{
|
|
120
124
|
readonly role: Schema.Literal<"tool">;
|
|
121
125
|
readonly tool_call_id: Schema.String;
|
|
122
|
-
readonly content: Schema.String
|
|
123
|
-
|
|
124
|
-
readonly
|
|
125
|
-
readonly
|
|
126
|
-
|
|
126
|
+
readonly content: Schema.Union<readonly [Schema.String, Schema.$Array<Schema.Struct<{
|
|
127
|
+
readonly type: Schema.Literal<"text">;
|
|
128
|
+
readonly text: Schema.String;
|
|
129
|
+
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
130
|
+
readonly type: Schema.Literal<"ephemeral">;
|
|
131
|
+
readonly ttl: Schema.optional<Schema.String>;
|
|
132
|
+
}>>;
|
|
133
|
+
}>>]>;
|
|
127
134
|
}>]>>;
|
|
128
135
|
tools: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
129
136
|
readonly type: Schema.tag<"function">;
|
|
@@ -207,7 +214,14 @@ declare const OpenAIChatBody: Schema.Struct<{
|
|
|
207
214
|
}>]>>]>;
|
|
208
215
|
}>, Schema.StructWithRest<Schema.Struct<{
|
|
209
216
|
readonly role: Schema.Literal<"assistant">;
|
|
210
|
-
readonly content: Schema.NullOr<Schema.String
|
|
217
|
+
readonly content: Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.$Array<Schema.Struct<{
|
|
218
|
+
readonly type: Schema.Literal<"text">;
|
|
219
|
+
readonly text: Schema.String;
|
|
220
|
+
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
221
|
+
readonly type: Schema.Literal<"ephemeral">;
|
|
222
|
+
readonly ttl: Schema.optional<Schema.String>;
|
|
223
|
+
}>>;
|
|
224
|
+
}>>]>>;
|
|
211
225
|
readonly tool_calls: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
212
226
|
readonly id: Schema.String;
|
|
213
227
|
readonly type: Schema.tag<"function">;
|
|
@@ -225,18 +239,17 @@ declare const OpenAIChatBody: Schema.Struct<{
|
|
|
225
239
|
readonly reasoning: Schema.optional<Schema.String>;
|
|
226
240
|
readonly reasoning_text: Schema.optional<Schema.String>;
|
|
227
241
|
readonly reasoning_details: Schema.optional<Schema.Unknown>;
|
|
228
|
-
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
229
|
-
readonly type: Schema.Literal<"ephemeral">;
|
|
230
|
-
readonly ttl: Schema.optional<Schema.String>;
|
|
231
|
-
}>>;
|
|
232
242
|
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>, Schema.Struct<{
|
|
233
243
|
readonly role: Schema.Literal<"tool">;
|
|
234
244
|
readonly tool_call_id: Schema.String;
|
|
235
|
-
readonly content: Schema.String
|
|
236
|
-
|
|
237
|
-
readonly
|
|
238
|
-
readonly
|
|
239
|
-
|
|
245
|
+
readonly content: Schema.Union<readonly [Schema.String, Schema.$Array<Schema.Struct<{
|
|
246
|
+
readonly type: Schema.Literal<"text">;
|
|
247
|
+
readonly text: Schema.String;
|
|
248
|
+
readonly cache_control: Schema.optional<Schema.Struct<{
|
|
249
|
+
readonly type: Schema.Literal<"ephemeral">;
|
|
250
|
+
readonly ttl: Schema.optional<Schema.String>;
|
|
251
|
+
}>>;
|
|
252
|
+
}>>]>;
|
|
240
253
|
}>]>>;
|
|
241
254
|
tools: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
242
255
|
readonly type: Schema.tag<"function">;
|
|
@@ -360,7 +373,7 @@ export interface ParserState {
|
|
|
360
373
|
readonly requireFinishReason: boolean;
|
|
361
374
|
}
|
|
362
375
|
interface LoweringOptions {
|
|
363
|
-
readonly cacheControl?: (cache: CacheHint | undefined) =>
|
|
376
|
+
readonly cacheControl?: (cache: CacheHint | undefined) => OpenAIChatCacheControl | undefined;
|
|
364
377
|
readonly toolCallID?: (id: string) => string;
|
|
365
378
|
}
|
|
366
379
|
export declare const fromRequest: (request: LLMRequest<import("../schema/options.js").LanguageModel<{
|
|
@@ -425,15 +438,18 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
425
438
|
})[];
|
|
426
439
|
} | {
|
|
427
440
|
readonly [x: string]: unknown;
|
|
428
|
-
readonly content: string |
|
|
441
|
+
readonly content: string | readonly {
|
|
442
|
+
readonly type: "text";
|
|
443
|
+
readonly text: string;
|
|
444
|
+
readonly cache_control?: {
|
|
445
|
+
readonly type: "ephemeral";
|
|
446
|
+
readonly ttl?: string | undefined;
|
|
447
|
+
} | undefined;
|
|
448
|
+
}[] | null;
|
|
429
449
|
readonly role: "assistant";
|
|
430
450
|
readonly reasoning?: string | undefined;
|
|
431
451
|
readonly reasoning_content?: string | undefined;
|
|
432
452
|
readonly reasoning_text?: string | undefined;
|
|
433
|
-
readonly cache_control?: {
|
|
434
|
-
readonly type: "ephemeral";
|
|
435
|
-
readonly ttl?: string | undefined;
|
|
436
|
-
} | undefined;
|
|
437
453
|
readonly tool_calls?: readonly {
|
|
438
454
|
readonly function: {
|
|
439
455
|
readonly name: string;
|
|
@@ -449,13 +465,16 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
449
465
|
}[] | undefined;
|
|
450
466
|
readonly reasoning_details?: unknown;
|
|
451
467
|
} | {
|
|
452
|
-
readonly content: string;
|
|
453
468
|
readonly role: "tool";
|
|
454
469
|
readonly tool_call_id: string;
|
|
455
|
-
readonly
|
|
456
|
-
readonly type: "
|
|
457
|
-
readonly
|
|
458
|
-
|
|
470
|
+
readonly content: string | readonly {
|
|
471
|
+
readonly type: "text";
|
|
472
|
+
readonly text: string;
|
|
473
|
+
readonly cache_control?: {
|
|
474
|
+
readonly type: "ephemeral";
|
|
475
|
+
readonly ttl?: string | undefined;
|
|
476
|
+
} | undefined;
|
|
477
|
+
}[];
|
|
459
478
|
})[];
|
|
460
479
|
tools: {
|
|
461
480
|
readonly function: {
|
|
@@ -539,15 +558,18 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
539
558
|
})[];
|
|
540
559
|
} | {
|
|
541
560
|
readonly [x: string]: unknown;
|
|
542
|
-
readonly content: string |
|
|
561
|
+
readonly content: string | readonly {
|
|
562
|
+
readonly type: "text";
|
|
563
|
+
readonly text: string;
|
|
564
|
+
readonly cache_control?: {
|
|
565
|
+
readonly type: "ephemeral";
|
|
566
|
+
readonly ttl?: string | undefined;
|
|
567
|
+
} | undefined;
|
|
568
|
+
}[] | null;
|
|
543
569
|
readonly role: "assistant";
|
|
544
570
|
readonly reasoning?: string | undefined;
|
|
545
571
|
readonly reasoning_content?: string | undefined;
|
|
546
572
|
readonly reasoning_text?: string | undefined;
|
|
547
|
-
readonly cache_control?: {
|
|
548
|
-
readonly type: "ephemeral";
|
|
549
|
-
readonly ttl?: string | undefined;
|
|
550
|
-
} | undefined;
|
|
551
573
|
readonly tool_calls?: readonly {
|
|
552
574
|
readonly function: {
|
|
553
575
|
readonly name: string;
|
|
@@ -563,13 +585,16 @@ export declare const fromRequest: (request: LLMRequest<import("../schema/options
|
|
|
563
585
|
}[] | undefined;
|
|
564
586
|
readonly reasoning_details?: unknown;
|
|
565
587
|
} | {
|
|
566
|
-
readonly content: string;
|
|
567
588
|
readonly role: "tool";
|
|
568
589
|
readonly tool_call_id: string;
|
|
569
|
-
readonly
|
|
570
|
-
readonly type: "
|
|
571
|
-
readonly
|
|
572
|
-
|
|
590
|
+
readonly content: string | readonly {
|
|
591
|
+
readonly type: "text";
|
|
592
|
+
readonly text: string;
|
|
593
|
+
readonly cache_control?: {
|
|
594
|
+
readonly type: "ephemeral";
|
|
595
|
+
readonly ttl?: string | undefined;
|
|
596
|
+
} | undefined;
|
|
597
|
+
}[];
|
|
573
598
|
})[];
|
|
574
599
|
tools: {
|
|
575
600
|
readonly function: {
|
|
@@ -646,15 +671,18 @@ export declare const protocol: Protocol<{
|
|
|
646
671
|
})[];
|
|
647
672
|
} | {
|
|
648
673
|
readonly [x: string]: unknown;
|
|
649
|
-
readonly content: string |
|
|
674
|
+
readonly content: string | readonly {
|
|
675
|
+
readonly type: "text";
|
|
676
|
+
readonly text: string;
|
|
677
|
+
readonly cache_control?: {
|
|
678
|
+
readonly type: "ephemeral";
|
|
679
|
+
readonly ttl?: string | undefined;
|
|
680
|
+
} | undefined;
|
|
681
|
+
}[] | null;
|
|
650
682
|
readonly role: "assistant";
|
|
651
683
|
readonly reasoning?: string | undefined;
|
|
652
684
|
readonly reasoning_content?: string | undefined;
|
|
653
685
|
readonly reasoning_text?: string | undefined;
|
|
654
|
-
readonly cache_control?: {
|
|
655
|
-
readonly type: "ephemeral";
|
|
656
|
-
readonly ttl?: string | undefined;
|
|
657
|
-
} | undefined;
|
|
658
686
|
readonly tool_calls?: readonly {
|
|
659
687
|
readonly function: {
|
|
660
688
|
readonly name: string;
|
|
@@ -670,13 +698,16 @@ export declare const protocol: Protocol<{
|
|
|
670
698
|
}[] | undefined;
|
|
671
699
|
readonly reasoning_details?: unknown;
|
|
672
700
|
} | {
|
|
673
|
-
readonly content: string;
|
|
674
701
|
readonly role: "tool";
|
|
675
702
|
readonly tool_call_id: string;
|
|
676
|
-
readonly
|
|
677
|
-
readonly type: "
|
|
678
|
-
readonly
|
|
679
|
-
|
|
703
|
+
readonly content: string | readonly {
|
|
704
|
+
readonly type: "text";
|
|
705
|
+
readonly text: string;
|
|
706
|
+
readonly cache_control?: {
|
|
707
|
+
readonly type: "ephemeral";
|
|
708
|
+
readonly ttl?: string | undefined;
|
|
709
|
+
} | undefined;
|
|
710
|
+
}[];
|
|
680
711
|
})[];
|
|
681
712
|
readonly stream: true;
|
|
682
713
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -831,15 +862,18 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
831
862
|
})[];
|
|
832
863
|
} | {
|
|
833
864
|
readonly [x: string]: unknown;
|
|
834
|
-
readonly content: string |
|
|
865
|
+
readonly content: string | readonly {
|
|
866
|
+
readonly type: "text";
|
|
867
|
+
readonly text: string;
|
|
868
|
+
readonly cache_control?: {
|
|
869
|
+
readonly type: "ephemeral";
|
|
870
|
+
readonly ttl?: string | undefined;
|
|
871
|
+
} | undefined;
|
|
872
|
+
}[] | null;
|
|
835
873
|
readonly role: "assistant";
|
|
836
874
|
readonly reasoning?: string | undefined;
|
|
837
875
|
readonly reasoning_content?: string | undefined;
|
|
838
876
|
readonly reasoning_text?: string | undefined;
|
|
839
|
-
readonly cache_control?: {
|
|
840
|
-
readonly type: "ephemeral";
|
|
841
|
-
readonly ttl?: string | undefined;
|
|
842
|
-
} | undefined;
|
|
843
877
|
readonly tool_calls?: readonly {
|
|
844
878
|
readonly function: {
|
|
845
879
|
readonly name: string;
|
|
@@ -855,13 +889,16 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
855
889
|
}[] | undefined;
|
|
856
890
|
readonly reasoning_details?: unknown;
|
|
857
891
|
} | {
|
|
858
|
-
readonly content: string;
|
|
859
892
|
readonly role: "tool";
|
|
860
893
|
readonly tool_call_id: string;
|
|
861
|
-
readonly
|
|
862
|
-
readonly type: "
|
|
863
|
-
readonly
|
|
864
|
-
|
|
894
|
+
readonly content: string | readonly {
|
|
895
|
+
readonly type: "text";
|
|
896
|
+
readonly text: string;
|
|
897
|
+
readonly cache_control?: {
|
|
898
|
+
readonly type: "ephemeral";
|
|
899
|
+
readonly ttl?: string | undefined;
|
|
900
|
+
} | undefined;
|
|
901
|
+
}[];
|
|
865
902
|
})[];
|
|
866
903
|
readonly stream: true;
|
|
867
904
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -947,15 +984,18 @@ export declare const route: Route<{
|
|
|
947
984
|
})[];
|
|
948
985
|
} | {
|
|
949
986
|
readonly [x: string]: unknown;
|
|
950
|
-
readonly content: string |
|
|
987
|
+
readonly content: string | readonly {
|
|
988
|
+
readonly type: "text";
|
|
989
|
+
readonly text: string;
|
|
990
|
+
readonly cache_control?: {
|
|
991
|
+
readonly type: "ephemeral";
|
|
992
|
+
readonly ttl?: string | undefined;
|
|
993
|
+
} | undefined;
|
|
994
|
+
}[] | null;
|
|
951
995
|
readonly role: "assistant";
|
|
952
996
|
readonly reasoning?: string | undefined;
|
|
953
997
|
readonly reasoning_content?: string | undefined;
|
|
954
998
|
readonly reasoning_text?: string | undefined;
|
|
955
|
-
readonly cache_control?: {
|
|
956
|
-
readonly type: "ephemeral";
|
|
957
|
-
readonly ttl?: string | undefined;
|
|
958
|
-
} | undefined;
|
|
959
999
|
readonly tool_calls?: readonly {
|
|
960
1000
|
readonly function: {
|
|
961
1001
|
readonly name: string;
|
|
@@ -971,13 +1011,16 @@ export declare const route: Route<{
|
|
|
971
1011
|
}[] | undefined;
|
|
972
1012
|
readonly reasoning_details?: unknown;
|
|
973
1013
|
} | {
|
|
974
|
-
readonly content: string;
|
|
975
1014
|
readonly role: "tool";
|
|
976
1015
|
readonly tool_call_id: string;
|
|
977
|
-
readonly
|
|
978
|
-
readonly type: "
|
|
979
|
-
readonly
|
|
980
|
-
|
|
1016
|
+
readonly content: string | readonly {
|
|
1017
|
+
readonly type: "text";
|
|
1018
|
+
readonly text: string;
|
|
1019
|
+
readonly cache_control?: {
|
|
1020
|
+
readonly type: "ephemeral";
|
|
1021
|
+
readonly ttl?: string | undefined;
|
|
1022
|
+
} | undefined;
|
|
1023
|
+
}[];
|
|
981
1024
|
})[];
|
|
982
1025
|
readonly stream: true;
|
|
983
1026
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -83,12 +83,13 @@ const ReasoningDetail = Schema.Union([
|
|
|
83
83
|
]);
|
|
84
84
|
const decodeReasoningDetail = Schema.decodeUnknownOption(ReasoningDetail);
|
|
85
85
|
const knownReasoningDetails = (details) => details.flatMap((detail) => Option.toArray(decodeReasoningDetail(detail)));
|
|
86
|
+
const OpenAIChatTextContent = Schema.Struct({
|
|
87
|
+
type: Schema.Literal("text"),
|
|
88
|
+
text: Schema.String,
|
|
89
|
+
cache_control: Schema.optional(OpenAIChatCacheControl),
|
|
90
|
+
});
|
|
86
91
|
const OpenAIChatUserContent = Schema.Union([
|
|
87
|
-
|
|
88
|
-
type: Schema.Literal("text"),
|
|
89
|
-
text: Schema.String,
|
|
90
|
-
cache_control: Schema.optional(OpenAIChatCacheControl),
|
|
91
|
-
}),
|
|
92
|
+
OpenAIChatTextContent,
|
|
92
93
|
Schema.Struct({
|
|
93
94
|
type: Schema.Literal("image_url"),
|
|
94
95
|
image_url: Schema.Struct({ url: Schema.String }),
|
|
@@ -109,19 +110,17 @@ const OpenAIChatMessage = Schema.Union([
|
|
|
109
110
|
}),
|
|
110
111
|
Schema.StructWithRest(Schema.Struct({
|
|
111
112
|
role: Schema.Literal("assistant"),
|
|
112
|
-
content: Schema.NullOr(Schema.String),
|
|
113
|
+
content: Schema.NullOr(Schema.Union([Schema.String, Schema.Array(OpenAIChatTextContent)])),
|
|
113
114
|
tool_calls: optionalArray(OpenAIChatAssistantToolCall),
|
|
114
115
|
reasoning_content: Schema.optional(Schema.String),
|
|
115
116
|
reasoning: Schema.optional(Schema.String),
|
|
116
117
|
reasoning_text: Schema.optional(Schema.String),
|
|
117
118
|
reasoning_details: Schema.optional(Schema.Unknown),
|
|
118
|
-
cache_control: Schema.optional(OpenAIChatCacheControl),
|
|
119
119
|
}), [Schema.Record(Schema.String, Schema.Unknown)]),
|
|
120
120
|
Schema.Struct({
|
|
121
121
|
role: Schema.Literal("tool"),
|
|
122
122
|
tool_call_id: Schema.String,
|
|
123
|
-
content: Schema.String,
|
|
124
|
-
cache_control: Schema.optional(OpenAIChatCacheControl),
|
|
123
|
+
content: Schema.Union([Schema.String, Schema.Array(OpenAIChatTextContent)]),
|
|
125
124
|
}),
|
|
126
125
|
]).pipe(Schema.toTaggedUnion("role"));
|
|
127
126
|
const OpenAIChatToolChoice = Schema.Union([
|
|
@@ -305,7 +304,7 @@ const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(func
|
|
|
305
304
|
if (!ProviderShared.supportsContent(part, ["text", "reasoning", "tool-call"]))
|
|
306
305
|
return yield* ProviderShared.unsupportedContent("OpenAI Chat", "assistant", ["text", "reasoning", "tool-call"]);
|
|
307
306
|
if (part.type === "text") {
|
|
308
|
-
content.push(part);
|
|
307
|
+
content.push({ type: "text", text: part.text, cache_control: options.cacheControl?.(part.cache) });
|
|
309
308
|
continue;
|
|
310
309
|
}
|
|
311
310
|
if (part.type === "reasoning") {
|
|
@@ -347,14 +346,17 @@ const lowerAssistantMessage = Effect.fn("OpenAIChat.lowerAssistantMessage")(func
|
|
|
347
346
|
return nativeReasoning ?? (requireReasoning ? "" : undefined);
|
|
348
347
|
return text;
|
|
349
348
|
})();
|
|
350
|
-
const cached = message.content.findLast((part) => "cache" in part && part.cache !== undefined);
|
|
351
|
-
const cacheControl = options.cacheControl?.(cached && "cache" in cached ? cached.cache : undefined);
|
|
352
349
|
const result = {
|
|
353
350
|
role: "assistant",
|
|
354
|
-
content:
|
|
351
|
+
content: (() => {
|
|
352
|
+
if (content.some((part) => part.cache_control !== undefined))
|
|
353
|
+
return content;
|
|
354
|
+
if (content.length === 0 && toolCalls.length > 0)
|
|
355
|
+
return null;
|
|
356
|
+
return content.map((part) => part.text).join("");
|
|
357
|
+
})(),
|
|
355
358
|
...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),
|
|
356
359
|
...(details !== undefined ? { reasoning_details: details } : {}),
|
|
357
|
-
...(cacheControl !== undefined ? { cache_control: cacheControl } : {}),
|
|
358
360
|
};
|
|
359
361
|
if (field === undefined || reasoningText === undefined)
|
|
360
362
|
return result;
|
|
@@ -367,27 +369,23 @@ const lowerToolMessages = Effect.fn("OpenAIChat.lowerToolMessages")(function* (m
|
|
|
367
369
|
if (!ProviderShared.supportsContent(part, ["tool-result"]))
|
|
368
370
|
return yield* ProviderShared.unsupportedContent("OpenAI Chat", "tool", ["tool-result"]);
|
|
369
371
|
if (part.result.type !== "content") {
|
|
370
|
-
messages.push(
|
|
371
|
-
role: "tool",
|
|
372
|
-
tool_call_id: options.toolCallID?.(part.id) ?? part.id,
|
|
373
|
-
content: ProviderShared.toolResultText(part),
|
|
374
|
-
cache_control: options.cacheControl?.(part.cache),
|
|
375
|
-
});
|
|
372
|
+
messages.push(toolMessage(options.toolCallID?.(part.id) ?? part.id, ProviderShared.toolResultText(part), options.cacheControl?.(part.cache)));
|
|
376
373
|
continue;
|
|
377
374
|
}
|
|
378
375
|
const content = part.result.value;
|
|
379
376
|
const text = content.filter((item) => item.type === "text").map((item) => item.text);
|
|
380
|
-
messages.push(
|
|
381
|
-
role: "tool",
|
|
382
|
-
tool_call_id: options.toolCallID?.(part.id) ?? part.id,
|
|
383
|
-
content: text.join("\n"),
|
|
384
|
-
cache_control: options.cacheControl?.(part.cache),
|
|
385
|
-
});
|
|
377
|
+
messages.push(toolMessage(options.toolCallID?.(part.id) ?? part.id, text.join("\n"), options.cacheControl?.(part.cache)));
|
|
386
378
|
const files = content.filter((item) => item.type === "file");
|
|
387
379
|
attachments.push(...(yield* Effect.forEach(files, (item) => lowerMedia(ProviderShared.toolFileMedia(item)))));
|
|
388
380
|
}
|
|
389
381
|
return { messages, attachments };
|
|
390
382
|
});
|
|
383
|
+
// Chat cache breakpoints belong on text content parts, not on the message itself.
|
|
384
|
+
const toolMessage = (toolCallID, text, cacheControl) => ({
|
|
385
|
+
role: "tool",
|
|
386
|
+
tool_call_id: toolCallID,
|
|
387
|
+
content: cacheControl === undefined ? text : [{ type: "text", text, cache_control: cacheControl }],
|
|
388
|
+
});
|
|
391
389
|
const lowerMessage = Effect.fn("OpenAIChat.lowerMessage")(function* (message, reasoningField, requireReasoning, options) {
|
|
392
390
|
if (message.role === "user")
|
|
393
391
|
return [yield* lowerUserMessage(message, options)];
|
|
@@ -452,24 +450,25 @@ const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request,
|
|
|
452
450
|
bridgeTools();
|
|
453
451
|
if (message.role === "system") {
|
|
454
452
|
const part = yield* ProviderShared.wrappedSystemUpdate("OpenAI Chat", message);
|
|
453
|
+
const cacheControl = options.cacheControl?.(part.cache);
|
|
455
454
|
if (pendingAttachments.length > 0) {
|
|
456
455
|
messages.push({
|
|
457
456
|
role: "user",
|
|
458
457
|
content: [
|
|
459
458
|
...pendingAttachments.splice(0),
|
|
460
|
-
{ type: "text", text: part.text, cache_control:
|
|
459
|
+
{ type: "text", text: part.text, cache_control: cacheControl },
|
|
461
460
|
],
|
|
462
461
|
});
|
|
463
462
|
continue;
|
|
464
463
|
}
|
|
465
464
|
const previous = messages.at(-1);
|
|
466
465
|
if (previous?.role === "user" && typeof previous.content === "string")
|
|
467
|
-
messages[messages.length - 1] =
|
|
466
|
+
messages[messages.length - 1] = cacheControl
|
|
468
467
|
? {
|
|
469
468
|
role: "user",
|
|
470
469
|
content: [
|
|
471
470
|
{ type: "text", text: previous.content },
|
|
472
|
-
{ type: "text", text: part.text, cache_control:
|
|
471
|
+
{ type: "text", text: part.text, cache_control: cacheControl },
|
|
473
472
|
],
|
|
474
473
|
}
|
|
475
474
|
: { role: "user", content: `${previous.content}\n${part.text}` };
|
|
@@ -478,14 +477,14 @@ const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request,
|
|
|
478
477
|
role: "user",
|
|
479
478
|
content: [
|
|
480
479
|
...previous.content,
|
|
481
|
-
{ type: "text", text: part.text, cache_control:
|
|
480
|
+
{ type: "text", text: part.text, cache_control: cacheControl },
|
|
482
481
|
],
|
|
483
482
|
};
|
|
484
483
|
else
|
|
485
|
-
messages.push(
|
|
484
|
+
messages.push(cacheControl
|
|
486
485
|
? {
|
|
487
486
|
role: "user",
|
|
488
|
-
content: [{ type: "text", text: part.text, cache_control:
|
|
487
|
+
content: [{ type: "text", text: part.text, cache_control: cacheControl }],
|
|
489
488
|
}
|
|
490
489
|
: { role: "user", content: part.text });
|
|
491
490
|
continue;
|
|
@@ -53,15 +53,18 @@ export declare const route: Route<{
|
|
|
53
53
|
})[];
|
|
54
54
|
} | {
|
|
55
55
|
readonly [x: string]: unknown;
|
|
56
|
-
readonly content: string |
|
|
56
|
+
readonly content: string | readonly {
|
|
57
|
+
readonly type: "text";
|
|
58
|
+
readonly text: string;
|
|
59
|
+
readonly cache_control?: {
|
|
60
|
+
readonly type: "ephemeral";
|
|
61
|
+
readonly ttl?: string | undefined;
|
|
62
|
+
} | undefined;
|
|
63
|
+
}[] | null;
|
|
57
64
|
readonly role: "assistant";
|
|
58
65
|
readonly reasoning?: string | undefined;
|
|
59
66
|
readonly reasoning_content?: string | undefined;
|
|
60
67
|
readonly reasoning_text?: string | undefined;
|
|
61
|
-
readonly cache_control?: {
|
|
62
|
-
readonly type: "ephemeral";
|
|
63
|
-
readonly ttl?: string | undefined;
|
|
64
|
-
} | undefined;
|
|
65
68
|
readonly tool_calls?: readonly {
|
|
66
69
|
readonly function: {
|
|
67
70
|
readonly name: string;
|
|
@@ -77,13 +80,16 @@ export declare const route: Route<{
|
|
|
77
80
|
}[] | undefined;
|
|
78
81
|
readonly reasoning_details?: unknown;
|
|
79
82
|
} | {
|
|
80
|
-
readonly content: string;
|
|
81
83
|
readonly role: "tool";
|
|
82
84
|
readonly tool_call_id: string;
|
|
83
|
-
readonly
|
|
84
|
-
readonly type: "
|
|
85
|
-
readonly
|
|
86
|
-
|
|
85
|
+
readonly content: string | readonly {
|
|
86
|
+
readonly type: "text";
|
|
87
|
+
readonly text: string;
|
|
88
|
+
readonly cache_control?: {
|
|
89
|
+
readonly type: "ephemeral";
|
|
90
|
+
readonly ttl?: string | undefined;
|
|
91
|
+
} | undefined;
|
|
92
|
+
}[];
|
|
87
93
|
})[];
|
|
88
94
|
readonly stream: true;
|
|
89
95
|
readonly max_completion_tokens?: number | undefined;
|
|
@@ -69,15 +69,18 @@ export declare const protocol: Protocol<{
|
|
|
69
69
|
})[];
|
|
70
70
|
} | {
|
|
71
71
|
readonly [x: string]: unknown;
|
|
72
|
-
readonly content: string |
|
|
72
|
+
readonly content: string | readonly {
|
|
73
|
+
readonly type: "text";
|
|
74
|
+
readonly text: string;
|
|
75
|
+
readonly cache_control?: {
|
|
76
|
+
readonly type: "ephemeral";
|
|
77
|
+
readonly ttl?: string | undefined;
|
|
78
|
+
} | undefined;
|
|
79
|
+
}[] | null;
|
|
73
80
|
readonly role: "assistant";
|
|
74
81
|
readonly reasoning?: string | undefined;
|
|
75
82
|
readonly reasoning_content?: string | undefined;
|
|
76
83
|
readonly reasoning_text?: string | undefined;
|
|
77
|
-
readonly cache_control?: {
|
|
78
|
-
readonly type: "ephemeral";
|
|
79
|
-
readonly ttl?: string | undefined;
|
|
80
|
-
} | undefined;
|
|
81
84
|
readonly tool_calls?: readonly {
|
|
82
85
|
readonly function: {
|
|
83
86
|
readonly name: string;
|
|
@@ -93,13 +96,16 @@ export declare const protocol: Protocol<{
|
|
|
93
96
|
}[] | undefined;
|
|
94
97
|
readonly reasoning_details?: unknown;
|
|
95
98
|
} | {
|
|
96
|
-
readonly content: string;
|
|
97
99
|
readonly role: "tool";
|
|
98
100
|
readonly tool_call_id: string;
|
|
99
|
-
readonly
|
|
100
|
-
readonly type: "
|
|
101
|
-
readonly
|
|
102
|
-
|
|
101
|
+
readonly content: string | readonly {
|
|
102
|
+
readonly type: "text";
|
|
103
|
+
readonly text: string;
|
|
104
|
+
readonly cache_control?: {
|
|
105
|
+
readonly type: "ephemeral";
|
|
106
|
+
readonly ttl?: string | undefined;
|
|
107
|
+
} | undefined;
|
|
108
|
+
}[];
|
|
103
109
|
})[];
|
|
104
110
|
readonly stream: true;
|
|
105
111
|
readonly max_completion_tokens?: number | undefined;
|
package/dist/provider-error.js
CHANGED
|
@@ -3,9 +3,13 @@ import { AuthenticationError, ContentPolicyError, InvalidRequestError, AIError,
|
|
|
3
3
|
const patterns = [
|
|
4
4
|
/prompt is too long/i,
|
|
5
5
|
/input is too long for requested model/i,
|
|
6
|
+
// Cloudflare Workers AI reports this as HTTP 413.
|
|
7
|
+
/exceeded this model context window limit/i,
|
|
6
8
|
/exceeds the context window/i,
|
|
7
9
|
/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
|
|
8
10
|
/input token count.*exceeds the maximum/i,
|
|
11
|
+
// Amazon Nova on Bedrock reports this as a mid-stream validationException.
|
|
12
|
+
/number of input tokens exceeds maximum length/i,
|
|
9
13
|
/tokens in request more than max tokens allowed/i,
|
|
10
14
|
/maximum prompt length is \d+/i,
|
|
11
15
|
/reduce the length of the messages/i,
|