@mariozechner/pi-ai 0.5.26 → 0.5.28
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 +355 -275
- package/dist/generate.d.ts +22 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +204 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -12
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +10 -71
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +3056 -2644
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +3063 -2648
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +17 -59
- package/dist/models.js.map +1 -1
- package/dist/providers/anthropic.d.ts +5 -18
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +249 -227
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/google.d.ts +3 -14
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +215 -220
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai-completions.d.ts +4 -14
- package/dist/providers/openai-completions.d.ts.map +1 -1
- package/dist/providers/openai-completions.js +247 -215
- package/dist/providers/openai-completions.js.map +1 -1
- package/dist/providers/openai-responses.d.ts +6 -13
- package/dist/providers/openai-responses.d.ts.map +1 -1
- package/dist/providers/openai-responses.js +242 -244
- package/dist/providers/openai-responses.js.map +1 -1
- package/dist/providers/utils.d.ts +2 -14
- package/dist/providers/utils.d.ts.map +1 -1
- package/dist/providers/utils.js +2 -15
- package/dist/providers/utils.js.map +1 -1
- package/dist/types.d.ts +39 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/providers/google.js
CHANGED
|
@@ -1,32 +1,16 @@
|
|
|
1
|
-
import { FunctionCallingConfigMode, GoogleGenAI, } from "@google/genai";
|
|
1
|
+
import { FinishReason, FunctionCallingConfigMode, GoogleGenAI, } from "@google/genai";
|
|
2
|
+
import { QueuedGenerateStream } from "../generate.js";
|
|
2
3
|
import { calculateCost } from "../models.js";
|
|
3
4
|
import { transformMessages } from "./utils.js";
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
constructor(model, apiKey) {
|
|
8
|
-
if (!apiKey) {
|
|
9
|
-
if (!process.env.GEMINI_API_KEY) {
|
|
10
|
-
throw new Error("Gemini API key is required. Set GEMINI_API_KEY environment variable or pass it as an argument.");
|
|
11
|
-
}
|
|
12
|
-
apiKey = process.env.GEMINI_API_KEY;
|
|
13
|
-
}
|
|
14
|
-
this.client = new GoogleGenAI({ apiKey });
|
|
15
|
-
this.modelInfo = model;
|
|
16
|
-
}
|
|
17
|
-
getModel() {
|
|
18
|
-
return this.modelInfo;
|
|
19
|
-
}
|
|
20
|
-
getApi() {
|
|
21
|
-
return "google-generative-ai";
|
|
22
|
-
}
|
|
23
|
-
async generate(context, options) {
|
|
5
|
+
export const streamGoogle = (model, context, options) => {
|
|
6
|
+
const stream = new QueuedGenerateStream();
|
|
7
|
+
(async () => {
|
|
24
8
|
const output = {
|
|
25
9
|
role: "assistant",
|
|
26
10
|
content: [],
|
|
27
|
-
api:
|
|
28
|
-
provider:
|
|
29
|
-
model:
|
|
11
|
+
api: "google-generative-ai",
|
|
12
|
+
provider: model.provider,
|
|
13
|
+
model: model.id,
|
|
30
14
|
usage: {
|
|
31
15
|
input: 0,
|
|
32
16
|
output: 0,
|
|
@@ -37,109 +21,78 @@ export class GoogleLLM {
|
|
|
37
21
|
stopReason: "stop",
|
|
38
22
|
};
|
|
39
23
|
try {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
generationConfig.temperature = options.temperature;
|
|
45
|
-
}
|
|
46
|
-
if (options?.maxTokens !== undefined) {
|
|
47
|
-
generationConfig.maxOutputTokens = options.maxTokens;
|
|
48
|
-
}
|
|
49
|
-
// Build the config object
|
|
50
|
-
const config = {
|
|
51
|
-
...(Object.keys(generationConfig).length > 0 && generationConfig),
|
|
52
|
-
...(context.systemPrompt && { systemInstruction: context.systemPrompt }),
|
|
53
|
-
...(context.tools && { tools: this.convertTools(context.tools) }),
|
|
54
|
-
};
|
|
55
|
-
// Add tool config if needed
|
|
56
|
-
if (context.tools && options?.toolChoice) {
|
|
57
|
-
config.toolConfig = {
|
|
58
|
-
functionCallingConfig: {
|
|
59
|
-
mode: this.mapToolChoice(options.toolChoice),
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
// Add thinking config if enabled and model supports it
|
|
64
|
-
if (options?.thinking?.enabled && this.modelInfo.reasoning) {
|
|
65
|
-
config.thinkingConfig = {
|
|
66
|
-
includeThoughts: true,
|
|
67
|
-
...(options.thinking.budgetTokens !== undefined && { thinkingBudget: options.thinking.budgetTokens }),
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
// Abort signal
|
|
71
|
-
if (options?.signal) {
|
|
72
|
-
if (options.signal.aborted) {
|
|
73
|
-
throw new Error("Request aborted");
|
|
74
|
-
}
|
|
75
|
-
config.abortSignal = options.signal;
|
|
76
|
-
}
|
|
77
|
-
// Build the request parameters
|
|
78
|
-
const params = {
|
|
79
|
-
model: this.modelInfo.id,
|
|
80
|
-
contents,
|
|
81
|
-
config,
|
|
82
|
-
};
|
|
83
|
-
const stream = await this.client.models.generateContentStream(params);
|
|
84
|
-
options?.onEvent?.({ type: "start", model: this.modelInfo.id, provider: this.modelInfo.provider });
|
|
24
|
+
const client = createClient(options?.apiKey);
|
|
25
|
+
const params = buildParams(model, context, options);
|
|
26
|
+
const googleStream = await client.models.generateContentStream(params);
|
|
27
|
+
stream.push({ type: "start", partial: output });
|
|
85
28
|
let currentBlock = null;
|
|
86
|
-
for await (const chunk of
|
|
87
|
-
// Extract parts from the chunk
|
|
29
|
+
for await (const chunk of googleStream) {
|
|
88
30
|
const candidate = chunk.candidates?.[0];
|
|
89
31
|
if (candidate?.content?.parts) {
|
|
90
32
|
for (const part of candidate.content.parts) {
|
|
91
33
|
if (part.text !== undefined) {
|
|
92
34
|
const isThinking = part.thought === true;
|
|
93
|
-
// Check if we need to switch blocks
|
|
94
35
|
if (!currentBlock ||
|
|
95
36
|
(isThinking && currentBlock.type !== "thinking") ||
|
|
96
37
|
(!isThinking && currentBlock.type !== "text")) {
|
|
97
38
|
if (currentBlock) {
|
|
98
39
|
if (currentBlock.type === "text") {
|
|
99
|
-
|
|
40
|
+
stream.push({
|
|
41
|
+
type: "text_end",
|
|
42
|
+
content: currentBlock.text,
|
|
43
|
+
partial: output,
|
|
44
|
+
});
|
|
100
45
|
}
|
|
101
46
|
else {
|
|
102
|
-
|
|
47
|
+
stream.push({
|
|
48
|
+
type: "thinking_end",
|
|
49
|
+
content: currentBlock.thinking,
|
|
50
|
+
partial: output,
|
|
51
|
+
});
|
|
103
52
|
}
|
|
104
53
|
}
|
|
105
|
-
// Start new block
|
|
106
54
|
if (isThinking) {
|
|
107
55
|
currentBlock = { type: "thinking", thinking: "", thinkingSignature: undefined };
|
|
108
|
-
|
|
56
|
+
stream.push({ type: "thinking_start", partial: output });
|
|
109
57
|
}
|
|
110
58
|
else {
|
|
111
59
|
currentBlock = { type: "text", text: "" };
|
|
112
|
-
|
|
60
|
+
stream.push({ type: "text_start", partial: output });
|
|
113
61
|
}
|
|
114
62
|
output.content.push(currentBlock);
|
|
115
63
|
}
|
|
116
|
-
// Append content to current block
|
|
117
64
|
if (currentBlock.type === "thinking") {
|
|
118
65
|
currentBlock.thinking += part.text;
|
|
119
66
|
currentBlock.thinkingSignature = part.thoughtSignature;
|
|
120
|
-
|
|
67
|
+
stream.push({
|
|
121
68
|
type: "thinking_delta",
|
|
122
|
-
content: currentBlock.thinking,
|
|
123
69
|
delta: part.text,
|
|
70
|
+
partial: output,
|
|
124
71
|
});
|
|
125
72
|
}
|
|
126
73
|
else {
|
|
127
74
|
currentBlock.text += part.text;
|
|
128
|
-
|
|
75
|
+
stream.push({ type: "text_delta", delta: part.text, partial: output });
|
|
129
76
|
}
|
|
130
77
|
}
|
|
131
|
-
// Handle function calls
|
|
132
78
|
if (part.functionCall) {
|
|
133
79
|
if (currentBlock) {
|
|
134
80
|
if (currentBlock.type === "text") {
|
|
135
|
-
|
|
81
|
+
stream.push({
|
|
82
|
+
type: "text_end",
|
|
83
|
+
content: currentBlock.text,
|
|
84
|
+
partial: output,
|
|
85
|
+
});
|
|
136
86
|
}
|
|
137
87
|
else {
|
|
138
|
-
|
|
88
|
+
stream.push({
|
|
89
|
+
type: "thinking_end",
|
|
90
|
+
content: currentBlock.thinking,
|
|
91
|
+
partial: output,
|
|
92
|
+
});
|
|
139
93
|
}
|
|
140
94
|
currentBlock = null;
|
|
141
95
|
}
|
|
142
|
-
// Add tool call
|
|
143
96
|
const toolCallId = part.functionCall.id || `${part.functionCall.name}_${Date.now()}`;
|
|
144
97
|
const toolCall = {
|
|
145
98
|
type: "toolCall",
|
|
@@ -148,19 +101,16 @@ export class GoogleLLM {
|
|
|
148
101
|
arguments: part.functionCall.args,
|
|
149
102
|
};
|
|
150
103
|
output.content.push(toolCall);
|
|
151
|
-
|
|
104
|
+
stream.push({ type: "toolCall", toolCall, partial: output });
|
|
152
105
|
}
|
|
153
106
|
}
|
|
154
107
|
}
|
|
155
|
-
// Map finish reason
|
|
156
108
|
if (candidate?.finishReason) {
|
|
157
|
-
output.stopReason =
|
|
158
|
-
// Check if we have tool calls in blocks
|
|
109
|
+
output.stopReason = mapStopReason(candidate.finishReason);
|
|
159
110
|
if (output.content.some((b) => b.type === "toolCall")) {
|
|
160
111
|
output.stopReason = "toolUse";
|
|
161
112
|
}
|
|
162
113
|
}
|
|
163
|
-
// Capture usage metadata if available
|
|
164
114
|
if (chunk.usageMetadata) {
|
|
165
115
|
output.usage = {
|
|
166
116
|
input: chunk.usageMetadata.promptTokenCount || 0,
|
|
@@ -175,163 +125,208 @@ export class GoogleLLM {
|
|
|
175
125
|
total: 0,
|
|
176
126
|
},
|
|
177
127
|
};
|
|
178
|
-
calculateCost(
|
|
128
|
+
calculateCost(model, output.usage);
|
|
179
129
|
}
|
|
180
130
|
}
|
|
181
|
-
// Finalize last block
|
|
182
131
|
if (currentBlock) {
|
|
183
132
|
if (currentBlock.type === "text") {
|
|
184
|
-
|
|
133
|
+
stream.push({ type: "text_end", content: currentBlock.text, partial: output });
|
|
185
134
|
}
|
|
186
135
|
else {
|
|
187
|
-
|
|
136
|
+
stream.push({ type: "thinking_end", content: currentBlock.thinking, partial: output });
|
|
188
137
|
}
|
|
189
138
|
}
|
|
190
|
-
|
|
191
|
-
|
|
139
|
+
stream.push({ type: "done", reason: output.stopReason, message: output });
|
|
140
|
+
stream.end();
|
|
192
141
|
}
|
|
193
142
|
catch (error) {
|
|
194
143
|
output.stopReason = "error";
|
|
195
144
|
output.error = error instanceof Error ? error.message : JSON.stringify(error);
|
|
196
|
-
|
|
197
|
-
|
|
145
|
+
stream.push({ type: "error", error: output.error, partial: output });
|
|
146
|
+
stream.end();
|
|
198
147
|
}
|
|
148
|
+
})();
|
|
149
|
+
return stream;
|
|
150
|
+
};
|
|
151
|
+
function createClient(apiKey) {
|
|
152
|
+
if (!apiKey) {
|
|
153
|
+
if (!process.env.GEMINI_API_KEY) {
|
|
154
|
+
throw new Error("Gemini API key is required. Set GEMINI_API_KEY environment variable or pass it as an argument.");
|
|
155
|
+
}
|
|
156
|
+
apiKey = process.env.GEMINI_API_KEY;
|
|
199
157
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
158
|
+
return new GoogleGenAI({ apiKey });
|
|
159
|
+
}
|
|
160
|
+
function buildParams(model, context, options = {}) {
|
|
161
|
+
const contents = convertMessages(model, context);
|
|
162
|
+
const generationConfig = {};
|
|
163
|
+
if (options.temperature !== undefined) {
|
|
164
|
+
generationConfig.temperature = options.temperature;
|
|
165
|
+
}
|
|
166
|
+
if (options.maxTokens !== undefined) {
|
|
167
|
+
generationConfig.maxOutputTokens = options.maxTokens;
|
|
168
|
+
}
|
|
169
|
+
const config = {
|
|
170
|
+
...(Object.keys(generationConfig).length > 0 && generationConfig),
|
|
171
|
+
...(context.systemPrompt && { systemInstruction: context.systemPrompt }),
|
|
172
|
+
...(context.tools && { tools: convertTools(context.tools) }),
|
|
173
|
+
};
|
|
174
|
+
if (context.tools && options.toolChoice) {
|
|
175
|
+
config.toolConfig = {
|
|
176
|
+
functionCallingConfig: {
|
|
177
|
+
mode: mapToolChoice(options.toolChoice),
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (options.thinking?.enabled && model.reasoning) {
|
|
182
|
+
config.thinkingConfig = {
|
|
183
|
+
includeThoughts: true,
|
|
184
|
+
...(options.thinking.budgetTokens !== undefined && { thinkingBudget: options.thinking.budgetTokens }),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (options.signal) {
|
|
188
|
+
if (options.signal.aborted) {
|
|
189
|
+
throw new Error("Request aborted");
|
|
190
|
+
}
|
|
191
|
+
config.abortSignal = options.signal;
|
|
192
|
+
}
|
|
193
|
+
const params = {
|
|
194
|
+
model: model.id,
|
|
195
|
+
contents,
|
|
196
|
+
config,
|
|
197
|
+
};
|
|
198
|
+
return params;
|
|
199
|
+
}
|
|
200
|
+
function convertMessages(model, context) {
|
|
201
|
+
const contents = [];
|
|
202
|
+
const transformedMessages = transformMessages(context.messages, model);
|
|
203
|
+
for (const msg of transformedMessages) {
|
|
204
|
+
if (msg.role === "user") {
|
|
205
|
+
if (typeof msg.content === "string") {
|
|
206
|
+
contents.push({
|
|
207
|
+
role: "user",
|
|
208
|
+
parts: [{ text: msg.content }],
|
|
209
|
+
});
|
|
237
210
|
}
|
|
238
|
-
else
|
|
239
|
-
const parts =
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (block.type === "text") {
|
|
243
|
-
parts.push({ text: block.text });
|
|
244
|
-
}
|
|
245
|
-
else if (block.type === "thinking") {
|
|
246
|
-
const thinkingPart = {
|
|
247
|
-
thought: true,
|
|
248
|
-
thoughtSignature: block.thinkingSignature,
|
|
249
|
-
text: block.thinking,
|
|
250
|
-
};
|
|
251
|
-
parts.push(thinkingPart);
|
|
211
|
+
else {
|
|
212
|
+
const parts = msg.content.map((item) => {
|
|
213
|
+
if (item.type === "text") {
|
|
214
|
+
return { text: item.text };
|
|
252
215
|
}
|
|
253
|
-
else
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
args: block.arguments,
|
|
216
|
+
else {
|
|
217
|
+
return {
|
|
218
|
+
inlineData: {
|
|
219
|
+
mimeType: item.mimeType,
|
|
220
|
+
data: item.data,
|
|
259
221
|
},
|
|
260
|
-
}
|
|
222
|
+
};
|
|
261
223
|
}
|
|
224
|
+
});
|
|
225
|
+
const filteredParts = !model.input.includes("image") ? parts.filter((p) => p.text !== undefined) : parts;
|
|
226
|
+
if (filteredParts.length === 0)
|
|
227
|
+
continue;
|
|
228
|
+
contents.push({
|
|
229
|
+
role: "user",
|
|
230
|
+
parts: filteredParts,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if (msg.role === "assistant") {
|
|
235
|
+
const parts = [];
|
|
236
|
+
for (const block of msg.content) {
|
|
237
|
+
if (block.type === "text") {
|
|
238
|
+
parts.push({ text: block.text });
|
|
262
239
|
}
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
240
|
+
else if (block.type === "thinking") {
|
|
241
|
+
const thinkingPart = {
|
|
242
|
+
thought: true,
|
|
243
|
+
thoughtSignature: block.thinkingSignature,
|
|
244
|
+
text: block.thinking,
|
|
245
|
+
};
|
|
246
|
+
parts.push(thinkingPart);
|
|
247
|
+
}
|
|
248
|
+
else if (block.type === "toolCall") {
|
|
249
|
+
parts.push({
|
|
250
|
+
functionCall: {
|
|
251
|
+
id: block.id,
|
|
252
|
+
name: block.name,
|
|
253
|
+
args: block.arguments,
|
|
254
|
+
},
|
|
267
255
|
});
|
|
268
256
|
}
|
|
269
257
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
258
|
+
if (parts.length === 0)
|
|
259
|
+
continue;
|
|
260
|
+
contents.push({
|
|
261
|
+
role: "model",
|
|
262
|
+
parts,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
else if (msg.role === "toolResult") {
|
|
266
|
+
contents.push({
|
|
267
|
+
role: "user",
|
|
268
|
+
parts: [
|
|
269
|
+
{
|
|
270
|
+
functionResponse: {
|
|
271
|
+
id: msg.toolCallId,
|
|
272
|
+
name: msg.toolName,
|
|
273
|
+
response: {
|
|
274
|
+
result: msg.content,
|
|
275
|
+
isError: msg.isError,
|
|
282
276
|
},
|
|
283
277
|
},
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
});
|
|
287
281
|
}
|
|
288
|
-
return contents;
|
|
289
|
-
}
|
|
290
|
-
convertTools(tools) {
|
|
291
|
-
return [
|
|
292
|
-
{
|
|
293
|
-
functionDeclarations: tools.map((tool) => ({
|
|
294
|
-
name: tool.name,
|
|
295
|
-
description: tool.description,
|
|
296
|
-
parameters: tool.parameters,
|
|
297
|
-
})),
|
|
298
|
-
},
|
|
299
|
-
];
|
|
300
282
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
283
|
+
return contents;
|
|
284
|
+
}
|
|
285
|
+
function convertTools(tools) {
|
|
286
|
+
return [
|
|
287
|
+
{
|
|
288
|
+
functionDeclarations: tools.map((tool) => ({
|
|
289
|
+
name: tool.name,
|
|
290
|
+
description: tool.description,
|
|
291
|
+
parameters: tool.parameters,
|
|
292
|
+
})),
|
|
293
|
+
},
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
function mapToolChoice(choice) {
|
|
297
|
+
switch (choice) {
|
|
298
|
+
case "auto":
|
|
299
|
+
return FunctionCallingConfigMode.AUTO;
|
|
300
|
+
case "none":
|
|
301
|
+
return FunctionCallingConfigMode.NONE;
|
|
302
|
+
case "any":
|
|
303
|
+
return FunctionCallingConfigMode.ANY;
|
|
304
|
+
default:
|
|
305
|
+
return FunctionCallingConfigMode.AUTO;
|
|
312
306
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
307
|
+
}
|
|
308
|
+
function mapStopReason(reason) {
|
|
309
|
+
switch (reason) {
|
|
310
|
+
case FinishReason.STOP:
|
|
311
|
+
return "stop";
|
|
312
|
+
case FinishReason.MAX_TOKENS:
|
|
313
|
+
return "length";
|
|
314
|
+
case FinishReason.BLOCKLIST:
|
|
315
|
+
case FinishReason.PROHIBITED_CONTENT:
|
|
316
|
+
case FinishReason.SPII:
|
|
317
|
+
case FinishReason.SAFETY:
|
|
318
|
+
case FinishReason.IMAGE_SAFETY:
|
|
319
|
+
case FinishReason.RECITATION:
|
|
320
|
+
return "safety";
|
|
321
|
+
case FinishReason.FINISH_REASON_UNSPECIFIED:
|
|
322
|
+
case FinishReason.OTHER:
|
|
323
|
+
case FinishReason.LANGUAGE:
|
|
324
|
+
case FinishReason.MALFORMED_FUNCTION_CALL:
|
|
325
|
+
case FinishReason.UNEXPECTED_TOOL_CALL:
|
|
326
|
+
return "error";
|
|
327
|
+
default: {
|
|
328
|
+
const _exhaustive = reason;
|
|
329
|
+
throw new Error(`Unhandled stop reason: ${_exhaustive}`);
|
|
335
330
|
}
|
|
336
331
|
}
|
|
337
332
|
}
|