@opencode/ai 2.0.22 → 2.0.24

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.
Files changed (107) hide show
  1. package/README.md +61 -1
  2. package/dist/cache-policy.js +13 -9
  3. package/dist/protocols/alibaba-chat.d.ts +3 -3
  4. package/dist/protocols/alibaba-messages.d.ts +3 -0
  5. package/dist/protocols/alibaba-responses.d.ts +19 -12
  6. package/dist/protocols/alibaba-responses.js +3 -5
  7. package/dist/protocols/anthropic-messages.d.ts +3 -0
  8. package/dist/protocols/anthropic-messages.js +53 -48
  9. package/dist/protocols/bedrock-converse.js +3 -3
  10. package/dist/protocols/cartesia-speech.js +3 -3
  11. package/dist/protocols/cohere-chat.d.ts +178 -0
  12. package/dist/protocols/cohere-chat.js +299 -0
  13. package/dist/protocols/elevenlabs-speech.js +3 -3
  14. package/dist/protocols/gemini.d.ts +2 -2
  15. package/dist/protocols/gemini.js +3 -3
  16. package/dist/protocols/google-interactions.d.ts +236 -0
  17. package/dist/protocols/google-interactions.js +478 -0
  18. package/dist/protocols/google-speech.js +1 -1
  19. package/dist/protocols/google-transcription.js +1 -1
  20. package/dist/protocols/index.d.ts +2 -0
  21. package/dist/protocols/index.js +2 -0
  22. package/dist/protocols/meta-messages.d.ts +3 -0
  23. package/dist/protocols/meta-responses.d.ts +34 -58
  24. package/dist/protocols/meta-responses.js +8 -27
  25. package/dist/protocols/mistral-chat.d.ts +24 -9
  26. package/dist/protocols/mistral-chat.js +22 -10
  27. package/dist/protocols/open-responses.d.ts +424 -103
  28. package/dist/protocols/open-responses.js +30 -20
  29. package/dist/protocols/openai-chat.d.ts +401 -5
  30. package/dist/protocols/openai-chat.js +18 -21
  31. package/dist/protocols/openai-compatible-chat.d.ts +1 -1
  32. package/dist/protocols/openai-compatible-responses.d.ts +16 -4
  33. package/dist/protocols/openai-images.js +2 -2
  34. package/dist/protocols/openai-responses.d.ts +90 -223
  35. package/dist/protocols/openai-responses.js +6 -13
  36. package/dist/protocols/openai-speech.js +1 -1
  37. package/dist/protocols/openai-transcription.js +1 -1
  38. package/dist/protocols/shared.js +2 -2
  39. package/dist/protocols/stability-images.js +1 -1
  40. package/dist/protocols/utils/bedrock-media.js +2 -2
  41. package/dist/protocols/utils/gateway-protocol.d.ts +17 -0
  42. package/dist/protocols/utils/gateway-protocol.js +57 -0
  43. package/dist/protocols/utils/responses-checkpoint.js +2 -2
  44. package/dist/protocols/utils/responses-hosted-tools.js +1 -1
  45. package/dist/protocols/utils/tool-stream.js +15 -7
  46. package/dist/protocols/venice-chat.d.ts +280 -0
  47. package/dist/protocols/venice-chat.js +283 -0
  48. package/dist/protocols/xai-responses.d.ts +21 -21
  49. package/dist/protocols/xai-responses.js +2 -8
  50. package/dist/protocols/zai-chat.d.ts +3 -3
  51. package/dist/protocols/zai-messages.d.ts +3 -0
  52. package/dist/provider-error.js +7 -1
  53. package/dist/providers/alibaba.d.ts +17 -13
  54. package/dist/providers/amazon-bedrock/mantle/messages.d.ts +2 -0
  55. package/dist/providers/amazon-bedrock/mantle/messages.js +1 -0
  56. package/dist/providers/amazon-bedrock-mantle.d.ts +301 -9
  57. package/dist/providers/amazon-bedrock-mantle.js +28 -3
  58. package/dist/providers/azure.d.ts +13 -61
  59. package/dist/providers/baseten.d.ts +2 -2
  60. package/dist/providers/cerebras.d.ts +2 -2
  61. package/dist/providers/cloudflare-ai-gateway.d.ts +14 -62
  62. package/dist/providers/cloudflare-workers-ai.d.ts +2 -2
  63. package/dist/providers/cohere/chat.d.ts +4 -0
  64. package/dist/providers/cohere/chat.js +8 -0
  65. package/dist/providers/cohere.d.ts +395 -0
  66. package/dist/providers/cohere.js +48 -0
  67. package/dist/providers/deepinfra.d.ts +2 -2
  68. package/dist/providers/deepseek.d.ts +2 -2
  69. package/dist/providers/digitalocean.d.ts +5 -5
  70. package/dist/providers/fireworks.d.ts +2 -2
  71. package/dist/providers/google/interactions.d.ts +7 -0
  72. package/dist/providers/google/interactions.js +8 -0
  73. package/dist/providers/google-vertex-chat.d.ts +1 -1
  74. package/dist/providers/google-vertex-messages.js +1 -0
  75. package/dist/providers/google-vertex-responses.d.ts +16 -4
  76. package/dist/providers/google-vertex.d.ts +1 -1
  77. package/dist/providers/google.d.ts +95 -4
  78. package/dist/providers/google.js +8 -1
  79. package/dist/providers/groq.d.ts +4 -4
  80. package/dist/providers/index.d.ts +2 -0
  81. package/dist/providers/index.js +2 -0
  82. package/dist/providers/meta.d.ts +15 -28
  83. package/dist/providers/minimax.d.ts +17 -5
  84. package/dist/providers/mistral.d.ts +10 -4
  85. package/dist/providers/moonshot.d.ts +17 -5
  86. package/dist/providers/openai-compatible-responses.d.ts +16 -4
  87. package/dist/providers/openai-compatible.d.ts +1 -1
  88. package/dist/providers/openai-options.d.ts +1 -1
  89. package/dist/providers/openai.d.ts +7 -31
  90. package/dist/providers/openrouter.d.ts +5 -5
  91. package/dist/providers/togetherai.d.ts +2 -2
  92. package/dist/providers/venice.d.ts +183 -0
  93. package/dist/providers/venice.js +38 -0
  94. package/dist/providers/vercel-ai-gateway/chat.d.ts +2 -0
  95. package/dist/providers/vercel-ai-gateway/chat.js +1 -0
  96. package/dist/providers/vercel-ai-gateway/messages.d.ts +2 -0
  97. package/dist/providers/vercel-ai-gateway/messages.js +1 -0
  98. package/dist/providers/vercel-ai-gateway/responses.d.ts +2 -0
  99. package/dist/providers/vercel-ai-gateway/responses.js +1 -0
  100. package/dist/providers/vercel-ai-gateway.d.ts +91 -9
  101. package/dist/providers/vercel-ai-gateway.js +161 -21
  102. package/dist/providers/xai.d.ts +1 -1
  103. package/dist/providers/zai-coding-plan.d.ts +17 -5
  104. package/dist/providers/zai.d.ts +1 -1
  105. package/dist/route/client.js +2 -5
  106. package/dist/route/framing.js +23 -23
  107. package/package.json +3 -3
@@ -0,0 +1,178 @@
1
+ import { Schema } from "effect";
2
+ import { Route } from "../route/client.js";
3
+ import { Protocol } from "../route/protocol.js";
4
+ import { Lifecycle } from "./utils/lifecycle.js";
5
+ import { ToolStream } from "./utils/tool-stream.js";
6
+ export declare const DEFAULT_BASE_URL = "https://api.cohere.com/v2";
7
+ declare const Options: Schema.Struct<{
8
+ readonly thinking: Schema.optional<Schema.Struct<{
9
+ readonly type: Schema.optional<Schema.Literals<readonly ["enabled", "disabled"]>>;
10
+ readonly tokenBudget: Schema.optional<Schema.Int>;
11
+ }>>;
12
+ }>;
13
+ export type ProviderOptionsInput = Schema.Schema.Type<typeof Options>;
14
+ export declare const protocol: Protocol<{
15
+ readonly model: string;
16
+ readonly messages: readonly {
17
+ readonly role: "tool" | "system" | "user" | "assistant";
18
+ readonly content?: string | readonly ({
19
+ readonly type: "text";
20
+ readonly text: string;
21
+ } | {
22
+ readonly type: "thinking";
23
+ readonly thinking: string;
24
+ } | {
25
+ readonly type: "image_url";
26
+ readonly image_url: {
27
+ readonly url: string;
28
+ };
29
+ })[] | undefined;
30
+ readonly tool_calls?: readonly {
31
+ readonly id: string;
32
+ readonly type: "function";
33
+ readonly function: {
34
+ readonly name: string;
35
+ readonly arguments: string;
36
+ };
37
+ }[] | undefined;
38
+ readonly tool_call_id?: string | undefined;
39
+ readonly tool_plan?: string | undefined;
40
+ }[];
41
+ readonly stream: true;
42
+ readonly max_tokens?: number | undefined;
43
+ readonly tools?: readonly {
44
+ readonly type: "function";
45
+ readonly function: {
46
+ readonly name: string;
47
+ readonly parameters: unknown;
48
+ readonly description?: string | undefined;
49
+ };
50
+ }[] | undefined;
51
+ readonly temperature?: number | undefined;
52
+ readonly seed?: number | undefined;
53
+ readonly thinking?: {
54
+ readonly type: string;
55
+ readonly token_budget?: number | undefined;
56
+ } | undefined;
57
+ readonly tool_choice?: "NONE" | "REQUIRED" | undefined;
58
+ readonly stop_sequences?: readonly string[] | undefined;
59
+ readonly p?: number | undefined;
60
+ readonly k?: number | undefined;
61
+ readonly frequency_penalty?: number | undefined;
62
+ readonly presence_penalty?: number | undefined;
63
+ }, string, {
64
+ readonly type: "message-start";
65
+ } | {
66
+ readonly type: "content-start" | "content-delta";
67
+ readonly index: number;
68
+ readonly delta: {
69
+ readonly message: {
70
+ readonly content: {
71
+ readonly text?: string | undefined;
72
+ readonly thinking?: string | undefined;
73
+ };
74
+ };
75
+ };
76
+ } | {
77
+ readonly type: "content-end";
78
+ readonly index: number;
79
+ } | {
80
+ readonly type: "tool-plan-delta";
81
+ readonly delta: {
82
+ readonly message: {
83
+ readonly tool_plan: string;
84
+ };
85
+ };
86
+ } | {
87
+ readonly type: "tool-call-start" | "tool-call-delta";
88
+ readonly index: number;
89
+ readonly delta: {
90
+ readonly message: {
91
+ readonly tool_calls: {
92
+ readonly function: {
93
+ readonly name?: string | undefined;
94
+ readonly arguments?: string | undefined;
95
+ };
96
+ readonly id?: string | undefined;
97
+ };
98
+ };
99
+ };
100
+ } | {
101
+ readonly type: "tool-call-end";
102
+ readonly index: number;
103
+ } | {
104
+ readonly type: "message-end";
105
+ readonly delta: {
106
+ readonly finish_reason: string;
107
+ readonly usage?: {
108
+ readonly tokens?: {
109
+ readonly input_tokens?: number | undefined;
110
+ readonly output_tokens?: number | undefined;
111
+ readonly reasoning_tokens?: number | undefined;
112
+ } | undefined;
113
+ readonly billed_units?: {
114
+ readonly input_tokens?: number | undefined;
115
+ readonly output_tokens?: number | undefined;
116
+ readonly reasoning_tokens?: number | undefined;
117
+ } | undefined;
118
+ readonly cached_tokens?: number | undefined;
119
+ } | undefined;
120
+ };
121
+ } | {
122
+ readonly type: "citation-start" | "citation-end";
123
+ }, {
124
+ readonly tools: Partial<Record<number, ToolStream.PendingTool>>;
125
+ readonly lifecycle: Lifecycle.State;
126
+ readonly finished: boolean;
127
+ }>;
128
+ export declare const route: Route<{
129
+ readonly model: string;
130
+ readonly messages: readonly {
131
+ readonly role: "tool" | "system" | "user" | "assistant";
132
+ readonly content?: string | readonly ({
133
+ readonly type: "text";
134
+ readonly text: string;
135
+ } | {
136
+ readonly type: "thinking";
137
+ readonly thinking: string;
138
+ } | {
139
+ readonly type: "image_url";
140
+ readonly image_url: {
141
+ readonly url: string;
142
+ };
143
+ })[] | undefined;
144
+ readonly tool_calls?: readonly {
145
+ readonly id: string;
146
+ readonly type: "function";
147
+ readonly function: {
148
+ readonly name: string;
149
+ readonly arguments: string;
150
+ };
151
+ }[] | undefined;
152
+ readonly tool_call_id?: string | undefined;
153
+ readonly tool_plan?: string | undefined;
154
+ }[];
155
+ readonly stream: true;
156
+ readonly max_tokens?: number | undefined;
157
+ readonly tools?: readonly {
158
+ readonly type: "function";
159
+ readonly function: {
160
+ readonly name: string;
161
+ readonly parameters: unknown;
162
+ readonly description?: string | undefined;
163
+ };
164
+ }[] | undefined;
165
+ readonly temperature?: number | undefined;
166
+ readonly seed?: number | undefined;
167
+ readonly thinking?: {
168
+ readonly type: string;
169
+ readonly token_budget?: number | undefined;
170
+ } | undefined;
171
+ readonly tool_choice?: "NONE" | "REQUIRED" | undefined;
172
+ readonly stop_sequences?: readonly string[] | undefined;
173
+ readonly p?: number | undefined;
174
+ readonly k?: number | undefined;
175
+ readonly frequency_penalty?: number | undefined;
176
+ readonly presence_penalty?: number | undefined;
177
+ }, import("../route/transport/http.js").HttpPrepared<string>, import("../route/client.js").CompactionOperations | undefined>;
178
+ export * as CohereChat from "./cohere-chat.js";
@@ -0,0 +1,299 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Route } from "../route/client.js";
3
+ import { Endpoint } from "../route/endpoint.js";
4
+ import { Framing } from "../route/framing.js";
5
+ import { Protocol } from "../route/protocol.js";
6
+ import { LLMEvent, Usage } from "../schema/index.js";
7
+ import { ProviderShared } from "./shared.js";
8
+ import { Lifecycle } from "./utils/lifecycle.js";
9
+ import { ToolStream } from "./utils/tool-stream.js";
10
+ const ADAPTER = "cohere-chat";
11
+ export const DEFAULT_BASE_URL = "https://api.cohere.com/v2";
12
+ const Options = Schema.Struct({
13
+ thinking: Schema.optional(Schema.Struct({
14
+ type: Schema.optional(Schema.Literals(["enabled", "disabled"])),
15
+ tokenBudget: Schema.optional(Schema.Int.check(Schema.isGreaterThan(0))),
16
+ })),
17
+ });
18
+ const Content = Schema.Union([
19
+ Schema.Struct({ type: Schema.Literal("text"), text: Schema.String }),
20
+ Schema.Struct({ type: Schema.Literal("thinking"), thinking: Schema.String }),
21
+ Schema.Struct({ type: Schema.Literal("image_url"), image_url: Schema.Struct({ url: Schema.String }) }),
22
+ ]);
23
+ const ToolCall = Schema.Struct({
24
+ id: Schema.String,
25
+ type: Schema.Literal("function"),
26
+ function: Schema.Struct({ name: Schema.String, arguments: Schema.String }),
27
+ });
28
+ const Message = Schema.Struct({
29
+ role: Schema.Literals(["system", "user", "assistant", "tool"]),
30
+ content: Schema.optional(Schema.Union([Schema.String, Schema.Array(Content)])),
31
+ tool_calls: Schema.optional(Schema.Array(ToolCall)),
32
+ tool_call_id: Schema.optional(Schema.String),
33
+ tool_plan: Schema.optional(Schema.String),
34
+ });
35
+ const Body = Schema.Struct({
36
+ model: Schema.String,
37
+ messages: Schema.Array(Message),
38
+ stream: Schema.Literal(true),
39
+ tools: Schema.optional(Schema.Array(Schema.Struct({
40
+ type: Schema.Literal("function"),
41
+ function: Schema.Struct({
42
+ name: Schema.String,
43
+ description: Schema.optional(Schema.String),
44
+ parameters: Schema.Unknown,
45
+ }),
46
+ }))),
47
+ tool_choice: Schema.optional(Schema.Literals(["NONE", "REQUIRED"])),
48
+ thinking: Schema.optional(Schema.Struct({ type: Schema.String, token_budget: Schema.optional(Schema.Number) })),
49
+ max_tokens: Schema.optional(Schema.Number),
50
+ temperature: Schema.optional(Schema.Number),
51
+ p: Schema.optional(Schema.Number),
52
+ k: Schema.optional(Schema.Number),
53
+ seed: Schema.optional(Schema.Number),
54
+ stop_sequences: Schema.optional(Schema.Array(Schema.String)),
55
+ frequency_penalty: Schema.optional(Schema.Number),
56
+ presence_penalty: Schema.optional(Schema.Number),
57
+ });
58
+ const TokenCounts = Schema.Struct({
59
+ input_tokens: Schema.optional(Schema.Number),
60
+ output_tokens: Schema.optional(Schema.Number),
61
+ reasoning_tokens: Schema.optional(Schema.Number),
62
+ });
63
+ const NativeUsage = Schema.Struct({
64
+ tokens: Schema.optional(TokenCounts),
65
+ billed_units: Schema.optional(TokenCounts),
66
+ cached_tokens: Schema.optional(Schema.Number),
67
+ });
68
+ const Event = Schema.Union([
69
+ Schema.Struct({ type: Schema.Literal("message-start") }),
70
+ Schema.Struct({
71
+ type: Schema.Literals(["content-start", "content-delta"]),
72
+ index: Schema.Number,
73
+ delta: Schema.Struct({
74
+ message: Schema.Struct({
75
+ content: Schema.Struct({ text: Schema.optional(Schema.String), thinking: Schema.optional(Schema.String) }),
76
+ }),
77
+ }),
78
+ }),
79
+ Schema.Struct({ type: Schema.Literal("content-end"), index: Schema.Number }),
80
+ Schema.Struct({
81
+ type: Schema.Literal("tool-plan-delta"),
82
+ delta: Schema.Struct({ message: Schema.Struct({ tool_plan: Schema.String }) }),
83
+ }),
84
+ Schema.Struct({
85
+ type: Schema.Literals(["tool-call-start", "tool-call-delta"]),
86
+ index: Schema.Number,
87
+ delta: Schema.Struct({
88
+ message: Schema.Struct({
89
+ tool_calls: Schema.Struct({
90
+ id: Schema.optional(Schema.String),
91
+ function: Schema.Struct({ name: Schema.optional(Schema.String), arguments: Schema.optional(Schema.String) }),
92
+ }),
93
+ }),
94
+ }),
95
+ }),
96
+ Schema.Struct({ type: Schema.Literal("tool-call-end"), index: Schema.Number }),
97
+ Schema.Struct({
98
+ type: Schema.Literal("message-end"),
99
+ delta: Schema.Struct({ finish_reason: Schema.String, usage: Schema.optional(NativeUsage) }),
100
+ }),
101
+ // Citation output is outside this basic chat surface.
102
+ Schema.Struct({ type: Schema.Literals(["citation-start", "citation-end"]) }),
103
+ ]);
104
+ const TOOL_CHOICE = { auto: undefined, none: "NONE", required: "REQUIRED", tool: "REQUIRED" };
105
+ const fromRequest = Effect.fn("CohereChat.fromRequest")(function* (request) {
106
+ const options = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(request.providerOptions ?? {});
107
+ const flattened = ProviderShared.flattenToolRequest(request);
108
+ const messages = request.system.length
109
+ ? [
110
+ {
111
+ role: "system",
112
+ content: request.system.length === 1
113
+ ? request.system[0].text
114
+ : request.system.map((part) => ({ type: "text", text: part.text })),
115
+ },
116
+ ]
117
+ : [];
118
+ for (const message of flattened.request.messages) {
119
+ if (message.role === "system") {
120
+ messages.push({ role: "user", content: (yield* ProviderShared.wrappedSystemUpdate("Cohere Chat", message)).text });
121
+ continue;
122
+ }
123
+ if (message.role === "tool") {
124
+ for (const part of message.content) {
125
+ if (part.type !== "tool-result")
126
+ return yield* ProviderShared.unsupportedContent("Cohere Chat", "tool", ["tool-result"]);
127
+ if (part.result.type === "content" && part.result.value.some((item) => item.type === "file"))
128
+ return yield* ProviderShared.invalidRequest("Cohere Chat does not support file content in tool results");
129
+ messages.push({ role: "tool", tool_call_id: part.id, content: ProviderShared.toolResultText(part) });
130
+ }
131
+ continue;
132
+ }
133
+ const content = [];
134
+ const calls = [];
135
+ const plans = [];
136
+ for (const part of message.content) {
137
+ if (part.type === "text") {
138
+ content.push({ type: "text", text: part.text });
139
+ continue;
140
+ }
141
+ if (message.role === "assistant" && part.type === "reasoning") {
142
+ if (part.providerMetadata?.cohere?.toolPlan === true)
143
+ plans.push(part.text);
144
+ else
145
+ content.push({ type: "thinking", thinking: part.text });
146
+ continue;
147
+ }
148
+ if (message.role === "assistant" && part.type === "tool-call") {
149
+ const args = ProviderShared.encodeJson(part.input);
150
+ calls.push({ id: part.id, type: "function", function: { name: part.name, arguments: args } });
151
+ continue;
152
+ }
153
+ if (message.role === "user" && part.type === "media" && part.media.mediaType.startsWith("image/")) {
154
+ const url = ProviderShared.mediaUrl(part.media) ??
155
+ (yield* ProviderShared.requireInlineMedia("Cohere Chat", part.media)).dataUrl;
156
+ content.push({ type: "image_url", image_url: { url } });
157
+ continue;
158
+ }
159
+ return yield* ProviderShared.unsupportedContent("Cohere Chat", message.role, message.role === "user" ? ["text", "media"] : ["text", "reasoning", "tool-call"]);
160
+ }
161
+ messages.push({
162
+ role: message.role,
163
+ content: content.length ? content : undefined,
164
+ tool_calls: calls.length ? calls : undefined,
165
+ tool_plan: plans.length ? plans.join("") : undefined,
166
+ });
167
+ }
168
+ const selected = request.toolChoice?.type === "tool" ? request.toolChoice.name : undefined;
169
+ const tools = selected === undefined ? flattened.tools : flattened.tools.filter((tool) => tool.name === selected);
170
+ if (selected !== undefined && tools.length === 0)
171
+ return yield* ProviderShared.invalidRequest("Cohere Chat tool choice must name an available tool");
172
+ if (tools.some((tool) => tool.native !== undefined))
173
+ return yield* ProviderShared.invalidRequest("Cohere Chat does not support provider-defined tools");
174
+ return {
175
+ model: request.model.id,
176
+ messages,
177
+ stream: true,
178
+ tools: tools.length
179
+ ? tools.map((tool) => ({
180
+ type: "function",
181
+ function: { name: tool.name, description: tool.description, parameters: tool.inputSchema },
182
+ }))
183
+ : undefined,
184
+ tool_choice: TOOL_CHOICE[request.toolChoice?.type ?? "auto"],
185
+ thinking: options.thinking && {
186
+ type: options.thinking.type ?? "enabled",
187
+ // Cohere rejects budgets above max_tokens; fitting also leaves room for the answer.
188
+ token_budget: options.thinking.tokenBudget === undefined
189
+ ? undefined
190
+ : ProviderShared.fitThinkingBudget(options.thinking.tokenBudget, request.generation?.maxTokens),
191
+ },
192
+ max_tokens: request.generation?.maxTokens,
193
+ temperature: request.generation?.temperature,
194
+ p: request.generation?.topP,
195
+ k: request.generation?.topK,
196
+ seed: request.generation?.seed,
197
+ stop_sequences: request.generation?.stop,
198
+ frequency_penalty: request.generation?.frequencyPenalty,
199
+ presence_penalty: request.generation?.presencePenalty,
200
+ };
201
+ });
202
+ const finishReason = (raw) => {
203
+ switch (raw) {
204
+ case "COMPLETE":
205
+ case "STOP_SEQUENCE":
206
+ return { normalized: "stop", raw };
207
+ case "MAX_TOKENS":
208
+ return { normalized: "length", raw };
209
+ case "TOOL_CALL":
210
+ return { normalized: "tool-calls", raw };
211
+ case "ERROR":
212
+ case "TIMEOUT":
213
+ return { normalized: "error", raw };
214
+ default:
215
+ return { normalized: "unknown", raw };
216
+ }
217
+ };
218
+ const mapUsage = (usage) => new Usage({
219
+ inputTokens: usage.tokens?.input_tokens,
220
+ outputTokens: usage.tokens?.output_tokens,
221
+ nonCachedInputTokens: ProviderShared.subtractTokens(usage.tokens?.input_tokens, usage.cached_tokens),
222
+ cacheReadInputTokens: usage.cached_tokens,
223
+ reasoningTokens: usage.tokens?.reasoning_tokens,
224
+ totalTokens: ProviderShared.totalTokens(usage.tokens?.input_tokens, usage.tokens?.output_tokens, undefined),
225
+ providerMetadata: { cohere: usage },
226
+ });
227
+ // Lifecycle deltas open blocks on demand and ends are no-ops for closed blocks, so content-start needs no handling.
228
+ const step = Effect.fnUntraced(function* (state, event) {
229
+ const events = [];
230
+ switch (event.type) {
231
+ case "message-start":
232
+ return [{ ...state, lifecycle: Lifecycle.stepStart(state.lifecycle, events) }, events];
233
+ case "content-delta": {
234
+ const id = String(event.index);
235
+ const content = event.delta.message.content;
236
+ const lifecycle = content.thinking !== undefined
237
+ ? Lifecycle.reasoningDelta(state.lifecycle, events, id, content.thinking)
238
+ : Lifecycle.textDelta(state.lifecycle, events, id, content.text ?? "");
239
+ return [{ ...state, lifecycle }, events];
240
+ }
241
+ case "content-end": {
242
+ const id = String(event.index);
243
+ const lifecycle = Lifecycle.textEnd(Lifecycle.reasoningEnd(state.lifecycle, events, id), events, id);
244
+ return [{ ...state, lifecycle }, events];
245
+ }
246
+ case "tool-plan-delta": {
247
+ const plan = event.delta.message.tool_plan;
248
+ const lifecycle = Lifecycle.reasoningDelta(state.lifecycle, events, "tool-plan", plan, {
249
+ cohere: { toolPlan: true },
250
+ });
251
+ return [{ ...state, lifecycle }, events];
252
+ }
253
+ case "tool-call-start":
254
+ case "tool-call-delta": {
255
+ const call = event.delta.message.tool_calls;
256
+ const result = ToolStream.appendOrStart(ADAPTER, state.tools, event.index, { id: call.id, name: call.function.name, text: call.function.arguments ?? "" }, "Cohere tool call is missing id or name");
257
+ if (ToolStream.isError(result))
258
+ return yield* result;
259
+ return [{ ...state, tools: result.tools }, result.events];
260
+ }
261
+ case "tool-call-end": {
262
+ const result = yield* ToolStream.finish(ADAPTER, state.tools, event.index);
263
+ return [{ ...state, tools: result.tools }, result.events ?? []];
264
+ }
265
+ case "message-end": {
266
+ const pending = yield* ToolStream.finishAll(ADAPTER, state.tools);
267
+ events.push(...pending.events);
268
+ const lifecycle = Lifecycle.finish(state.lifecycle, events, {
269
+ reason: finishReason(event.delta.finish_reason),
270
+ usage: event.delta.usage && mapUsage(event.delta.usage),
271
+ });
272
+ return [{ tools: pending.tools, lifecycle, finished: true }, events];
273
+ }
274
+ default:
275
+ return [state, events];
276
+ }
277
+ });
278
+ export const protocol = Protocol.make({
279
+ id: ADAPTER,
280
+ body: { schema: Body, from: fromRequest },
281
+ stream: {
282
+ event: Protocol.jsonEvent(Event),
283
+ initial: () => ({ lifecycle: Lifecycle.initial(), tools: ToolStream.empty(), finished: false }),
284
+ step,
285
+ terminal: (event) => event.type === "message-end",
286
+ onHalt: (state) => state.finished
287
+ ? Effect.succeed([])
288
+ : Effect.fail(ProviderShared.eventError(ADAPTER, "Cohere stream ended without message-end")),
289
+ },
290
+ });
291
+ export const route = Route.make({
292
+ id: ADAPTER,
293
+ provider: "cohere",
294
+ providerMetadataKey: "cohere",
295
+ protocol,
296
+ endpoint: Endpoint.path("/chat", { baseURL: DEFAULT_BASE_URL }),
297
+ framing: Framing.sse,
298
+ });
299
+ export * as CohereChat from "./cohere-chat.js";
@@ -32,7 +32,7 @@ const OUTPUT_FORMATS = {
32
32
  opus: "opus_48000_64",
33
33
  };
34
34
  /** WAV is served only by the non-streaming endpoints. */
35
- const outputFormat = Effect.fn("ElevenLabsSpeech.outputFormat")(function* (request) {
35
+ const outputFormat = Effect.fnUntraced(function* (request) {
36
36
  const format = request.providerOptions?.outputFormat ?? OUTPUT_FORMATS[request.format ?? "mp3"];
37
37
  if (format === undefined)
38
38
  return yield* route.unsupported("media.format", `${route.name} has no default output format for "${request.format}"; pass providerOptions.outputFormat`);
@@ -55,7 +55,7 @@ const path = (request) => `${PATH}/${encodeURIComponent(SpeechStream.voiceID(req
55
55
  // ---------------------------------------------------------------------------
56
56
  // 6. Stream parsing
57
57
  // ---------------------------------------------------------------------------
58
- const onRecord = Effect.fn("ElevenLabsSpeech.onRecord")(function* (state, frame) {
58
+ const onRecord = Effect.fnUntraced(function* (state, frame) {
59
59
  const record = yield* decodeRecord(frame);
60
60
  const [next, events] = SpeechStream.delta(state, record.audio_base64);
61
61
  const alignment = record.alignment;
@@ -80,7 +80,7 @@ const describeOutput = (format) => {
80
80
  const encoding = PCM_CODECS[codec];
81
81
  return encoding === undefined ? SpeechStream.container(codec, sampleRate) : SpeechStream.pcm(encoding, sampleRate);
82
82
  };
83
- const finish = Effect.fn("ElevenLabsSpeech.finish")(function* (state, context) {
83
+ const finish = Effect.fnUntraced(function* (state, context) {
84
84
  const requestID = context.http.headers["request-id"];
85
85
  return yield* SpeechStream.finish(route, state, {
86
86
  ...describeOutput(yield* outputFormat(context.request)),
@@ -158,7 +158,7 @@ export declare const protocol: Protocol<{
158
158
  readonly serviceTier?: string | undefined;
159
159
  readonly toolConfig?: {
160
160
  readonly functionCallingConfig: {
161
- readonly mode: "AUTO" | "NONE" | "ANY";
161
+ readonly mode: "NONE" | "AUTO" | "ANY";
162
162
  readonly allowedFunctionNames?: readonly string[] | undefined;
163
163
  };
164
164
  } | undefined;
@@ -272,7 +272,7 @@ export declare const route: Route<{
272
272
  readonly serviceTier?: string | undefined;
273
273
  readonly toolConfig?: {
274
274
  readonly functionCallingConfig: {
275
- readonly mode: "AUTO" | "NONE" | "ANY";
275
+ readonly mode: "NONE" | "AUTO" | "ANY";
276
276
  readonly allowedFunctionNames?: readonly string[] | undefined;
277
277
  };
278
278
  } | undefined;
@@ -201,7 +201,7 @@ const lowerToolConfig = (toolChoice) => ProviderShared.matchToolChoice("Gemini",
201
201
  required: () => ({ functionCallingConfig: { mode: "ANY" } }),
202
202
  tool: (name) => ({ functionCallingConfig: { mode: "ANY", allowedFunctionNames: [name] } }),
203
203
  });
204
- const lowerContentPart = Effect.fn("Gemini.lowerContentPart")(function* (part) {
204
+ const lowerContentPart = Effect.fnUntraced(function* (part) {
205
205
  if (part.type === "text")
206
206
  return { text: part.text };
207
207
  return yield* GeminiGenerateContent.mediaPart("Gemini", part.media);
@@ -217,7 +217,7 @@ const lowerToolCall = (part, omitIds, metadataKey) => ({
217
217
  functionCall: { ...(omitIds ? {} : { id: part.id }), name: part.name, args: part.input },
218
218
  thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey),
219
219
  });
220
- const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
220
+ const lowerMessages = Effect.fnUntraced(function* (request) {
221
221
  const contents = [];
222
222
  const metadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
223
223
  const omitCallIds = omitsFunctionCallIds(request.model.id);
@@ -382,7 +382,7 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request) {
382
382
  contents: yield* lowerMessages(flattened.request),
383
383
  safetySettings: options.safetySettings,
384
384
  serviceTier: options.serviceTier,
385
- systemInstruction: request.system.length === 0 ? undefined : { parts: [{ text: ProviderShared.joinText(request.system) }] },
385
+ systemInstruction: request.system.length === 0 ? undefined : { parts: request.system.map((part) => ({ text: part.text })) },
386
386
  tools: hasTools
387
387
  ? [
388
388
  {