@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.
- package/README.md +61 -1
- package/dist/cache-policy.js +13 -9
- package/dist/protocols/alibaba-chat.d.ts +3 -3
- package/dist/protocols/alibaba-messages.d.ts +3 -0
- package/dist/protocols/alibaba-responses.d.ts +19 -12
- package/dist/protocols/alibaba-responses.js +3 -5
- package/dist/protocols/anthropic-messages.d.ts +3 -0
- package/dist/protocols/anthropic-messages.js +53 -48
- package/dist/protocols/bedrock-converse.js +3 -3
- package/dist/protocols/cartesia-speech.js +3 -3
- package/dist/protocols/cohere-chat.d.ts +178 -0
- package/dist/protocols/cohere-chat.js +299 -0
- package/dist/protocols/elevenlabs-speech.js +3 -3
- package/dist/protocols/gemini.d.ts +2 -2
- package/dist/protocols/gemini.js +3 -3
- package/dist/protocols/google-interactions.d.ts +236 -0
- package/dist/protocols/google-interactions.js +478 -0
- package/dist/protocols/google-speech.js +1 -1
- package/dist/protocols/google-transcription.js +1 -1
- package/dist/protocols/index.d.ts +2 -0
- package/dist/protocols/index.js +2 -0
- package/dist/protocols/meta-messages.d.ts +3 -0
- package/dist/protocols/meta-responses.d.ts +34 -58
- package/dist/protocols/meta-responses.js +8 -27
- package/dist/protocols/mistral-chat.d.ts +24 -9
- package/dist/protocols/mistral-chat.js +22 -10
- package/dist/protocols/open-responses.d.ts +424 -103
- package/dist/protocols/open-responses.js +30 -20
- package/dist/protocols/openai-chat.d.ts +401 -5
- package/dist/protocols/openai-chat.js +18 -21
- package/dist/protocols/openai-compatible-chat.d.ts +1 -1
- package/dist/protocols/openai-compatible-responses.d.ts +16 -4
- package/dist/protocols/openai-images.js +2 -2
- package/dist/protocols/openai-responses.d.ts +90 -223
- package/dist/protocols/openai-responses.js +6 -13
- package/dist/protocols/openai-speech.js +1 -1
- package/dist/protocols/openai-transcription.js +1 -1
- package/dist/protocols/shared.js +2 -2
- package/dist/protocols/stability-images.js +1 -1
- package/dist/protocols/utils/bedrock-media.js +2 -2
- package/dist/protocols/utils/gateway-protocol.d.ts +17 -0
- package/dist/protocols/utils/gateway-protocol.js +57 -0
- package/dist/protocols/utils/responses-checkpoint.js +2 -2
- package/dist/protocols/utils/responses-hosted-tools.js +1 -1
- package/dist/protocols/utils/tool-stream.js +15 -7
- package/dist/protocols/venice-chat.d.ts +280 -0
- package/dist/protocols/venice-chat.js +283 -0
- package/dist/protocols/xai-responses.d.ts +21 -21
- package/dist/protocols/xai-responses.js +2 -8
- package/dist/protocols/zai-chat.d.ts +3 -3
- package/dist/protocols/zai-messages.d.ts +3 -0
- package/dist/provider-error.js +7 -1
- package/dist/providers/alibaba.d.ts +17 -13
- package/dist/providers/amazon-bedrock/mantle/messages.d.ts +2 -0
- package/dist/providers/amazon-bedrock/mantle/messages.js +1 -0
- package/dist/providers/amazon-bedrock-mantle.d.ts +301 -9
- package/dist/providers/amazon-bedrock-mantle.js +28 -3
- package/dist/providers/azure.d.ts +13 -61
- package/dist/providers/baseten.d.ts +2 -2
- package/dist/providers/cerebras.d.ts +2 -2
- package/dist/providers/cloudflare-ai-gateway.d.ts +14 -62
- package/dist/providers/cloudflare-workers-ai.d.ts +2 -2
- package/dist/providers/cohere/chat.d.ts +4 -0
- package/dist/providers/cohere/chat.js +8 -0
- package/dist/providers/cohere.d.ts +395 -0
- package/dist/providers/cohere.js +48 -0
- package/dist/providers/deepinfra.d.ts +2 -2
- package/dist/providers/deepseek.d.ts +2 -2
- package/dist/providers/digitalocean.d.ts +5 -5
- package/dist/providers/fireworks.d.ts +2 -2
- package/dist/providers/google/interactions.d.ts +7 -0
- package/dist/providers/google/interactions.js +8 -0
- package/dist/providers/google-vertex-chat.d.ts +1 -1
- package/dist/providers/google-vertex-messages.js +1 -0
- package/dist/providers/google-vertex-responses.d.ts +16 -4
- package/dist/providers/google-vertex.d.ts +1 -1
- package/dist/providers/google.d.ts +95 -4
- package/dist/providers/google.js +8 -1
- package/dist/providers/groq.d.ts +4 -4
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/meta.d.ts +15 -28
- package/dist/providers/minimax.d.ts +17 -5
- package/dist/providers/mistral.d.ts +10 -4
- package/dist/providers/moonshot.d.ts +17 -5
- package/dist/providers/openai-compatible-responses.d.ts +16 -4
- package/dist/providers/openai-compatible.d.ts +1 -1
- package/dist/providers/openai-options.d.ts +1 -1
- package/dist/providers/openai.d.ts +7 -31
- package/dist/providers/openrouter.d.ts +5 -5
- package/dist/providers/togetherai.d.ts +2 -2
- package/dist/providers/venice.d.ts +183 -0
- package/dist/providers/venice.js +38 -0
- package/dist/providers/vercel-ai-gateway/chat.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/chat.js +1 -0
- package/dist/providers/vercel-ai-gateway/messages.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/messages.js +1 -0
- package/dist/providers/vercel-ai-gateway/responses.d.ts +2 -0
- package/dist/providers/vercel-ai-gateway/responses.js +1 -0
- package/dist/providers/vercel-ai-gateway.d.ts +91 -9
- package/dist/providers/vercel-ai-gateway.js +161 -21
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/zai-coding-plan.d.ts +17 -5
- package/dist/providers/zai.d.ts +1 -1
- package/dist/route/client.js +2 -5
- package/dist/route/framing.js +23 -23
- 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.
|
|
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.
|
|
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.
|
|
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: "
|
|
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: "
|
|
275
|
+
readonly mode: "NONE" | "AUTO" | "ANY";
|
|
276
276
|
readonly allowedFunctionNames?: readonly string[] | undefined;
|
|
277
277
|
};
|
|
278
278
|
} | undefined;
|
package/dist/protocols/gemini.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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:
|
|
385
|
+
systemInstruction: request.system.length === 0 ? undefined : { parts: request.system.map((part) => ({ text: part.text })) },
|
|
386
386
|
tools: hasTools
|
|
387
387
|
? [
|
|
388
388
|
{
|