pagegraph 0.13.0 → 0.14.0

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 (80) hide show
  1. package/README.md +48 -41
  2. package/dist/anthropic-messages-TqKpKmfW.js +1067 -0
  3. package/dist/anthropic-messages-TqKpKmfW.js.map +1 -0
  4. package/dist/audit.d.ts +2 -0
  5. package/dist/audit.js +1 -1
  6. package/dist/audit.js.map +1 -1
  7. package/dist/azure-openai-responses-DJjBLwoI.js +231 -0
  8. package/dist/azure-openai-responses-DJjBLwoI.js.map +1 -0
  9. package/dist/cli.js +10487 -38044
  10. package/dist/cli.js.map +1 -1
  11. package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js +41 -0
  12. package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js.map +1 -0
  13. package/dist/config.d.ts +6 -6
  14. package/dist/config.js.map +1 -1
  15. package/dist/diagnostics-Wt5faNDM.js +108 -0
  16. package/dist/diagnostics-Wt5faNDM.js.map +1 -0
  17. package/dist/dist-B6zg_Z3Z.js +4794 -0
  18. package/dist/dist-B6zg_Z3Z.js.map +1 -0
  19. package/dist/env-api-keys-C-OA0yM-.js +124 -0
  20. package/dist/env-api-keys-C-OA0yM-.js.map +1 -0
  21. package/dist/error-body-CyiejW4b.js +103 -0
  22. package/dist/error-body-CyiejW4b.js.map +1 -0
  23. package/dist/github-copilot-headers-CEpMOpQF.js +24 -0
  24. package/dist/github-copilot-headers-CEpMOpQF.js.map +1 -0
  25. package/dist/google-generative-ai-BxABKIKO.js +330 -0
  26. package/dist/google-generative-ai-BxABKIKO.js.map +1 -0
  27. package/dist/google-shared-0gpM2jFi.js +19471 -0
  28. package/dist/google-shared-0gpM2jFi.js.map +1 -0
  29. package/dist/google-vertex-D8Eb5cbu.js +376 -0
  30. package/dist/google-vertex-D8Eb5cbu.js.map +1 -0
  31. package/dist/hash-Dp7EzZUo.js +18 -0
  32. package/dist/hash-Dp7EzZUo.js.map +1 -0
  33. package/dist/headers-BRNMVpzu.js +19 -0
  34. package/dist/headers-BRNMVpzu.js.map +1 -0
  35. package/dist/json-parse-C10znB7l.js +383 -0
  36. package/dist/json-parse-C10znB7l.js.map +1 -0
  37. package/dist/mistral-conversations-CvaqBWjR.js +690 -0
  38. package/dist/mistral-conversations-CvaqBWjR.js.map +1 -0
  39. package/dist/models-DcT5qOEL.js +1203 -0
  40. package/dist/models-DcT5qOEL.js.map +1 -0
  41. package/dist/node-Ccvru9GE.js +26 -0
  42. package/dist/node-Ccvru9GE.js.map +1 -0
  43. package/dist/node-MEosBOF2.js +2403 -0
  44. package/dist/node-MEosBOF2.js.map +1 -0
  45. package/dist/openai-BCBEd2eO.js +17350 -0
  46. package/dist/openai-BCBEd2eO.js.map +1 -0
  47. package/dist/openai-codex-responses-vJqxeeRC.js +1268 -0
  48. package/dist/openai-codex-responses-vJqxeeRC.js.map +1 -0
  49. package/dist/openai-completions-Cb_fRAbI.js +989 -0
  50. package/dist/openai-completions-Cb_fRAbI.js.map +1 -0
  51. package/dist/openai-prompt-cache-Bc6qNWt0.js +10 -0
  52. package/dist/openai-prompt-cache-Bc6qNWt0.js.map +1 -0
  53. package/dist/openai-responses-sDuh82G5.js +268 -0
  54. package/dist/openai-responses-sDuh82G5.js.map +1 -0
  55. package/dist/openai-responses-shared-mhuo1Jov.js +599 -0
  56. package/dist/openai-responses-shared-mhuo1Jov.js.map +1 -0
  57. package/dist/openrouter-images-CRmBkzpX.js +127 -0
  58. package/dist/openrouter-images-CRmBkzpX.js.map +1 -0
  59. package/dist/pi-Bvw6J0gh.js +56795 -0
  60. package/dist/pi-Bvw6J0gh.js.map +1 -0
  61. package/dist/pi-messages-CejiVYvO.js +308 -0
  62. package/dist/pi-messages-CejiVYvO.js.map +1 -0
  63. package/dist/provider-env-t38GK5FF.js +39 -0
  64. package/dist/provider-env-t38GK5FF.js.map +1 -0
  65. package/dist/provider-retry-DzKoh1X7.js +80 -0
  66. package/dist/provider-retry-DzKoh1X7.js.map +1 -0
  67. package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
  68. package/dist/sanitize-unicode-Ds14l9Om.js +28 -0
  69. package/dist/sanitize-unicode-Ds14l9Om.js.map +1 -0
  70. package/dist/sdk-C9_wiO6w.js +12503 -0
  71. package/dist/sdk-C9_wiO6w.js.map +1 -0
  72. package/dist/state-BuJP_3Lr.js +28102 -0
  73. package/dist/state-BuJP_3Lr.js.map +1 -0
  74. package/dist/system-one-shared-Dl10ZF7Z.js +167 -0
  75. package/dist/system-one-shared-Dl10ZF7Z.js.map +1 -0
  76. package/dist/transform-messages-BLJ8EfK6.js +468 -0
  77. package/dist/transform-messages-BLJ8EfK6.js.map +1 -0
  78. package/dist/typesafe-system-one-CwEWMV8P.js +25 -0
  79. package/dist/typesafe-system-one-CwEWMV8P.js.map +1 -0
  80. package/package.json +4 -8
@@ -0,0 +1,690 @@
1
+ import { a as AssistantMessageEventStream } from "./diagnostics-Wt5faNDM.js";
2
+ import { C as renderSystemMessageUpdate, S as getSystemMessageText, d as getCurrentTools, n as clampThinkingLevel, t as calculateCost, v as resolveTranscript } from "./models-DcT5qOEL.js";
3
+ import { t as headersToRecord } from "./headers-BRNMVpzu.js";
4
+ import { n as parseStreamingJson } from "./json-parse-C10znB7l.js";
5
+ import { f as resolveJsonSchemaStrictSampling, p as getPiUserAgent, r as buildBaseOptions, t as transformMessages, u as getJsonSchemaToolParameters } from "./transform-messages-BLJ8EfK6.js";
6
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-Ds14l9Om.js";
7
+ import { t as shortHash } from "./hash-Dp7EzZUo.js";
8
+ //#region node_modules/@earendil-works/pi-ai/dist/api/mistral-conversations.js
9
+ const MISTRAL_TOOL_CALL_ID_LENGTH = 9;
10
+ const MAX_MISTRAL_ERROR_BODY_CHARS = 4e3;
11
+ /**
12
+ * Stream responses from the native Mistral Chat Completions endpoint.
13
+ */
14
+ const stream = (model, context, options) => {
15
+ const stream = new AssistantMessageEventStream();
16
+ const normalizedContext = resolveTranscript(context, model.compat?.supportsMidConvoSystemMessages);
17
+ (async () => {
18
+ const output = createOutput(model);
19
+ try {
20
+ const apiKey = options?.apiKey;
21
+ if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
22
+ const normalizeMistralToolCallId = createMistralToolCallIdNormalizer();
23
+ const transformedMessages = transformMessages(normalizedContext.messages, model, (id) => normalizeMistralToolCallId(id));
24
+ let payload = buildChatPayload(model, normalizedContext, transformedMessages, options);
25
+ const nextPayload = await options?.onPayload?.(payload, model);
26
+ if (nextPayload !== void 0) payload = nextPayload;
27
+ const mistralStream = await requestMistralStream(model, payload, apiKey, options);
28
+ stream.push({
29
+ type: "start",
30
+ partial: output
31
+ });
32
+ await consumeChatStream(model, output, stream, mistralStream, options?.onProviderStreamEvent);
33
+ if (options?.signal?.aborted) throw new Error("Request was aborted");
34
+ if (output.stopReason === "pending") throw new Error("Mistral stream ended without a finish reason");
35
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage || "An unknown error occurred");
36
+ stream.push({
37
+ type: "done",
38
+ reason: output.stopReason,
39
+ message: output
40
+ });
41
+ stream.end();
42
+ } catch (error) {
43
+ for (const block of output.content) delete block.partialArgs;
44
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
45
+ output.errorMessage = formatMistralError(error);
46
+ stream.push({
47
+ type: "error",
48
+ reason: output.stopReason,
49
+ error: output
50
+ });
51
+ stream.end();
52
+ }
53
+ })();
54
+ return stream;
55
+ };
56
+ /**
57
+ * Maps provider-agnostic `SimpleStreamOptions` to Mistral options.
58
+ */
59
+ const streamSimple = (model, context, options) => {
60
+ const apiKey = options?.apiKey;
61
+ if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
62
+ const base = {
63
+ ...buildBaseOptions(model, context, options, apiKey),
64
+ toolChoice: options?.toolChoice
65
+ };
66
+ const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : void 0;
67
+ const reasoning = clampedReasoning === "off" ? void 0 : clampedReasoning;
68
+ const effortMap = model.reasoning ? model.thinkingLevelMap : void 0;
69
+ const reasoningEffort = effortMap ? reasoning ? effortMap[reasoning] ?? "high" : effortMap.off ?? void 0 : void 0;
70
+ return stream(model, context, {
71
+ ...base,
72
+ promptMode: model.reasoning && !effortMap && reasoning ? "reasoning" : void 0,
73
+ reasoningEffort
74
+ });
75
+ };
76
+ function createOutput(model) {
77
+ return {
78
+ role: "assistant",
79
+ content: [],
80
+ api: model.api,
81
+ provider: model.provider,
82
+ model: model.id,
83
+ usage: {
84
+ input: 0,
85
+ output: 0,
86
+ cacheRead: 0,
87
+ cacheWrite: 0,
88
+ totalTokens: 0,
89
+ cost: {
90
+ input: 0,
91
+ output: 0,
92
+ cacheRead: 0,
93
+ cacheWrite: 0,
94
+ total: 0
95
+ }
96
+ },
97
+ stopReason: "pending",
98
+ timestamp: Date.now()
99
+ };
100
+ }
101
+ function createMistralToolCallIdNormalizer() {
102
+ const idMap = /* @__PURE__ */ new Map();
103
+ const reverseMap = /* @__PURE__ */ new Map();
104
+ return (id) => {
105
+ const existing = idMap.get(id);
106
+ if (existing) return existing;
107
+ let attempt = 0;
108
+ while (true) {
109
+ const candidate = deriveMistralToolCallId(id, attempt);
110
+ const owner = reverseMap.get(candidate);
111
+ if (!owner || owner === id) {
112
+ idMap.set(id, candidate);
113
+ reverseMap.set(candidate, id);
114
+ return candidate;
115
+ }
116
+ attempt++;
117
+ }
118
+ };
119
+ }
120
+ function deriveMistralToolCallId(id, attempt) {
121
+ const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
122
+ if (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH) return normalized;
123
+ const seedBase = normalized || id;
124
+ const seed = attempt === 0 ? seedBase : `${seedBase}:${attempt}`;
125
+ return shortHash(seed).replace(/[^a-zA-Z0-9]/g, "").slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);
126
+ }
127
+ function formatMistralError(error) {
128
+ if (error instanceof Error) {
129
+ const httpError = error;
130
+ const statusCode = typeof httpError.statusCode === "number" ? httpError.statusCode : void 0;
131
+ const bodyText = typeof httpError.body === "string" ? httpError.body.trim() : void 0;
132
+ if (statusCode !== void 0 && bodyText) return `Mistral API error (${statusCode}): ${truncateErrorText(bodyText, MAX_MISTRAL_ERROR_BODY_CHARS)}`;
133
+ if (statusCode !== void 0) return `Mistral API error (${statusCode}): ${error.message}`;
134
+ return error.message;
135
+ }
136
+ return safeJsonStringify(error);
137
+ }
138
+ function truncateErrorText(text, maxChars) {
139
+ if (text.length <= maxChars) return text;
140
+ return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
141
+ }
142
+ function safeJsonStringify(value) {
143
+ try {
144
+ const serialized = JSON.stringify(value);
145
+ return serialized === void 0 ? String(value) : serialized;
146
+ } catch {
147
+ return String(value);
148
+ }
149
+ }
150
+ async function requestMistralStream(model, payload, apiKey, options) {
151
+ const baseUrl = new URL(model.baseUrl);
152
+ baseUrl.pathname = `${baseUrl.pathname.replace(/\/+$/u, "")}/`;
153
+ const url = new URL("v1/chat/completions", baseUrl);
154
+ const headers = buildMistralHeaders(model, apiKey, options);
155
+ const timeoutSignal = AbortSignal.timeout(options?.timeoutMs ?? 6e4);
156
+ const signal = options?.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
157
+ const response = await (options?.fetch ?? globalThis.fetch)(url, {
158
+ method: "POST",
159
+ headers,
160
+ body: JSON.stringify(toMistralWirePayload(payload)),
161
+ signal
162
+ });
163
+ await options?.onResponse?.({
164
+ status: response.status,
165
+ headers: headersToRecord(response.headers)
166
+ }, model);
167
+ if (!response.ok) {
168
+ const body = await response.text();
169
+ throw new MistralHttpError(response.status, body, response.statusText);
170
+ }
171
+ if (!response.body) throw new Error("Mistral response has no body");
172
+ return readMistralEvents(response.body, signal);
173
+ }
174
+ var MistralHttpError = class extends Error {
175
+ statusCode;
176
+ body;
177
+ constructor(statusCode, body, statusText) {
178
+ super(statusText || `Request failed with status ${statusCode}`);
179
+ this.name = "MistralHttpError";
180
+ this.statusCode = statusCode;
181
+ this.body = body;
182
+ }
183
+ };
184
+ function buildMistralHeaders(model, apiKey, options) {
185
+ const headers = new Headers({
186
+ "User-Agent": getPiUserAgent(),
187
+ accept: "text/event-stream",
188
+ authorization: `Bearer ${apiKey}`,
189
+ "content-type": "application/json"
190
+ });
191
+ applyMistralHeaderOverrides(headers, model.headers);
192
+ applyMistralHeaderOverrides(headers, options?.headers);
193
+ const hasExplicitAffinity = hasMistralHeaderOverride(model.headers, "x-affinity") || hasMistralHeaderOverride(options?.headers, "x-affinity");
194
+ if (shouldUsePromptCaching(options) && !hasExplicitAffinity) headers.set("x-affinity", options.sessionId);
195
+ return headers;
196
+ }
197
+ function applyMistralHeaderOverrides(headers, overrides) {
198
+ if (!overrides) return;
199
+ for (const [name, value] of Object.entries(overrides)) if (value === null) headers.delete(name);
200
+ else headers.set(name, value);
201
+ }
202
+ function hasMistralHeaderOverride(overrides, target) {
203
+ return !!overrides && Object.keys(overrides).some((name) => name.toLowerCase() === target);
204
+ }
205
+ function toMistralWirePayload(payload) {
206
+ const wirePayload = { ...payload };
207
+ for (const [source, target] of [
208
+ ["topP", "top_p"],
209
+ ["maxTokens", "max_tokens"],
210
+ ["randomSeed", "random_seed"],
211
+ ["responseFormat", "response_format"],
212
+ ["toolChoice", "tool_choice"],
213
+ ["presencePenalty", "presence_penalty"],
214
+ ["frequencyPenalty", "frequency_penalty"],
215
+ ["parallelToolCalls", "parallel_tool_calls"],
216
+ ["reasoningEffort", "reasoning_effort"],
217
+ ["promptMode", "prompt_mode"],
218
+ ["promptCacheKey", "prompt_cache_key"],
219
+ ["safePrompt", "safe_prompt"]
220
+ ]) remapMistralProperty(wirePayload, source, target);
221
+ wirePayload.messages = payload.messages.map((message) => toMistralWireMessage(message));
222
+ const responseFormat = wirePayload.response_format;
223
+ if (isMistralRecord(responseFormat)) {
224
+ const wireResponseFormat = { ...responseFormat };
225
+ remapMistralProperty(wireResponseFormat, "jsonSchema", "json_schema");
226
+ const jsonSchema = wireResponseFormat.json_schema;
227
+ if (isMistralRecord(jsonSchema)) {
228
+ const wireJsonSchema = { ...jsonSchema };
229
+ remapMistralProperty(wireJsonSchema, "schemaDefinition", "schema");
230
+ wireResponseFormat.json_schema = wireJsonSchema;
231
+ }
232
+ wirePayload.response_format = wireResponseFormat;
233
+ }
234
+ return wirePayload;
235
+ }
236
+ function toMistralWireMessage(message) {
237
+ const wireMessage = { ...message };
238
+ remapMistralProperty(wireMessage, "toolCalls", "tool_calls");
239
+ remapMistralProperty(wireMessage, "toolCallId", "tool_call_id");
240
+ if (Array.isArray(message.content)) wireMessage.content = message.content.map((chunk) => toMistralWireContentChunk(chunk));
241
+ return wireMessage;
242
+ }
243
+ function toMistralWireContentChunk(chunk) {
244
+ const wireChunk = { ...chunk };
245
+ for (const [source, target] of [
246
+ ["imageUrl", "image_url"],
247
+ ["documentUrl", "document_url"],
248
+ ["documentName", "document_name"],
249
+ ["fileId", "file_id"],
250
+ ["referenceIds", "reference_ids"],
251
+ ["inputAudio", "input_audio"]
252
+ ]) remapMistralProperty(wireChunk, source, target);
253
+ return wireChunk;
254
+ }
255
+ function remapMistralProperty(record, source, target) {
256
+ if (!(source in record)) return;
257
+ record[target] = record[source];
258
+ delete record[source];
259
+ }
260
+ function isMistralRecord(value) {
261
+ return typeof value === "object" && value !== null && !Array.isArray(value);
262
+ }
263
+ const MISTRAL_STREAM_DONE = Symbol("mistral-stream-done");
264
+ async function* readMistralEvents(body, signal) {
265
+ const reader = body.getReader();
266
+ const decoder = new TextDecoder();
267
+ let buffer = "";
268
+ const onAbort = () => {
269
+ reader.cancel().catch(() => {});
270
+ };
271
+ signal.addEventListener("abort", onAbort, { once: true });
272
+ try {
273
+ while (true) {
274
+ if (signal.aborted) throw signal.reason;
275
+ const { done, value } = await reader.read();
276
+ if (signal.aborted) throw signal.reason;
277
+ buffer += done ? decoder.decode() : decoder.decode(value, { stream: true });
278
+ let boundary = findMistralEventBoundary(buffer);
279
+ while (boundary) {
280
+ const event = parseMistralEvent(buffer.slice(0, boundary.index));
281
+ buffer = buffer.slice(boundary.index + boundary.length);
282
+ if (event === MISTRAL_STREAM_DONE) return;
283
+ if (event) yield event;
284
+ boundary = findMistralEventBoundary(buffer);
285
+ }
286
+ if (done) break;
287
+ }
288
+ if (buffer.trim()) {
289
+ const event = parseMistralEvent(buffer);
290
+ if (event !== MISTRAL_STREAM_DONE && event) yield event;
291
+ }
292
+ } finally {
293
+ signal.removeEventListener("abort", onAbort);
294
+ try {
295
+ await reader.cancel();
296
+ } catch {}
297
+ try {
298
+ reader.releaseLock();
299
+ } catch {}
300
+ }
301
+ }
302
+ function findMistralEventBoundary(buffer) {
303
+ const match = /\r\n\r\n|\r\n\r|\r\n\n|\r\r\n|\n\r\n|\r\r|\n\r|\n\n/u.exec(buffer);
304
+ return match?.index === void 0 ? void 0 : {
305
+ index: match.index,
306
+ length: match[0].length
307
+ };
308
+ }
309
+ function parseMistralEvent(raw) {
310
+ const data = raw.split(/\r\n|\r|\n/u).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n").trim();
311
+ if (!data) return void 0;
312
+ if (data === "[DONE]") return MISTRAL_STREAM_DONE;
313
+ const parsed = JSON.parse(data);
314
+ if (!isMistralRecord(parsed) || !Array.isArray(parsed.choices)) throw new Error("Invalid Mistral streaming event");
315
+ return { data: parsed };
316
+ }
317
+ function buildChatPayload(model, context, messages, options) {
318
+ const payload = {
319
+ model: model.id,
320
+ stream: true,
321
+ messages: toChatMessages(messages, model.input.includes("image"))
322
+ };
323
+ const currentTools = getCurrentTools(context.messages);
324
+ if (currentTools.length > 0) payload.tools = toFunctionTools(currentTools);
325
+ if (options?.temperature !== void 0) payload.temperature = options.temperature;
326
+ if (options?.maxTokens !== void 0) payload.maxTokens = options.maxTokens;
327
+ if (options?.toolChoice) payload.toolChoice = mapToolChoice(options.toolChoice);
328
+ if (options?.promptMode) payload.promptMode = options.promptMode;
329
+ if (options?.reasoningEffort) payload.reasoningEffort = options.reasoningEffort;
330
+ if (shouldUsePromptCaching(options)) payload.promptCacheKey = options.sessionId;
331
+ return payload;
332
+ }
333
+ function shouldUsePromptCaching(options) {
334
+ return options?.cacheRetention !== "none" && !!options?.sessionId;
335
+ }
336
+ function getMistralCachedPromptTokens(usage, promptTokens) {
337
+ const rawUsage = usage;
338
+ const rawCachedTokens = rawUsage.promptTokensDetails?.cachedTokens ?? rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.promptTokenDetails?.cachedTokens ?? rawUsage.prompt_token_details?.cached_tokens ?? rawUsage.numCachedTokens ?? rawUsage.num_cached_tokens ?? 0;
339
+ return Math.min(promptTokens, Math.max(0, typeof rawCachedTokens === "number" && Number.isFinite(rawCachedTokens) ? rawCachedTokens : 0));
340
+ }
341
+ async function consumeChatStream(model, output, stream, mistralStream, onProviderStreamEvent) {
342
+ let currentBlock = null;
343
+ const blocks = output.content;
344
+ const blockIndex = () => blocks.length - 1;
345
+ const toolBlocksByKey = /* @__PURE__ */ new Map();
346
+ const finishCurrentBlock = (block) => {
347
+ if (!block) return;
348
+ if (block.type === "text") {
349
+ stream.push({
350
+ type: "text_end",
351
+ contentIndex: blockIndex(),
352
+ content: block.text,
353
+ partial: output
354
+ });
355
+ return;
356
+ }
357
+ if (block.type === "thinking") stream.push({
358
+ type: "thinking_end",
359
+ contentIndex: blockIndex(),
360
+ content: block.thinking,
361
+ partial: output
362
+ });
363
+ };
364
+ for await (const event of mistralStream) {
365
+ const chunk = event.data;
366
+ await onProviderStreamEvent?.(chunk, model);
367
+ output.responseId ||= chunk.id;
368
+ if (chunk.usage) {
369
+ const promptTokens = chunk.usage.prompt_tokens || 0;
370
+ const cachedPromptTokens = getMistralCachedPromptTokens(chunk.usage, promptTokens);
371
+ output.usage.input = Math.max(0, promptTokens - cachedPromptTokens);
372
+ output.usage.output = chunk.usage.completion_tokens || 0;
373
+ output.usage.cacheRead = cachedPromptTokens;
374
+ output.usage.cacheWrite = 0;
375
+ output.usage.totalTokens = chunk.usage.total_tokens || output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
376
+ calculateCost(model, output.usage);
377
+ }
378
+ const choice = chunk.choices[0];
379
+ if (!choice) continue;
380
+ if (choice.finish_reason) {
381
+ output.rawStopReason = choice.finish_reason;
382
+ const stopReasonResult = mapChatStopReason(choice.finish_reason);
383
+ output.stopReason = stopReasonResult.stopReason;
384
+ if (stopReasonResult.errorMessage) output.errorMessage = stopReasonResult.errorMessage;
385
+ }
386
+ const delta = choice.delta;
387
+ if (delta.content !== null && delta.content !== void 0) {
388
+ const contentItems = typeof delta.content === "string" ? [delta.content] : delta.content;
389
+ for (const item of contentItems) {
390
+ if (typeof item === "string") {
391
+ const textDelta = sanitizeSurrogates(item);
392
+ if (!textDelta) continue;
393
+ if (!currentBlock || currentBlock.type !== "text") {
394
+ finishCurrentBlock(currentBlock);
395
+ currentBlock = {
396
+ type: "text",
397
+ text: ""
398
+ };
399
+ output.content.push(currentBlock);
400
+ stream.push({
401
+ type: "text_start",
402
+ contentIndex: blockIndex(),
403
+ partial: output
404
+ });
405
+ }
406
+ currentBlock.text += textDelta;
407
+ stream.push({
408
+ type: "text_delta",
409
+ contentIndex: blockIndex(),
410
+ delta: textDelta,
411
+ partial: output
412
+ });
413
+ continue;
414
+ }
415
+ if (item.type === "thinking") {
416
+ const deltaText = (item.thinking ?? []).map((part) => part.text ?? "").filter((text) => text.length > 0).join("");
417
+ const thinkingDelta = sanitizeSurrogates(deltaText);
418
+ if (!thinkingDelta) continue;
419
+ if (!currentBlock || currentBlock.type !== "thinking") {
420
+ finishCurrentBlock(currentBlock);
421
+ currentBlock = {
422
+ type: "thinking",
423
+ thinking: ""
424
+ };
425
+ output.content.push(currentBlock);
426
+ stream.push({
427
+ type: "thinking_start",
428
+ contentIndex: blockIndex(),
429
+ partial: output
430
+ });
431
+ }
432
+ currentBlock.thinking += thinkingDelta;
433
+ stream.push({
434
+ type: "thinking_delta",
435
+ contentIndex: blockIndex(),
436
+ delta: thinkingDelta,
437
+ partial: output
438
+ });
439
+ continue;
440
+ }
441
+ if (item.type === "text") {
442
+ const textDelta = sanitizeSurrogates(item.text ?? "");
443
+ if (!textDelta) continue;
444
+ if (!currentBlock || currentBlock.type !== "text") {
445
+ finishCurrentBlock(currentBlock);
446
+ currentBlock = {
447
+ type: "text",
448
+ text: ""
449
+ };
450
+ output.content.push(currentBlock);
451
+ stream.push({
452
+ type: "text_start",
453
+ contentIndex: blockIndex(),
454
+ partial: output
455
+ });
456
+ }
457
+ currentBlock.text += textDelta;
458
+ stream.push({
459
+ type: "text_delta",
460
+ contentIndex: blockIndex(),
461
+ delta: textDelta,
462
+ partial: output
463
+ });
464
+ }
465
+ }
466
+ }
467
+ const toolCalls = delta.tool_calls || [];
468
+ for (const toolCall of toolCalls) {
469
+ if (currentBlock) {
470
+ finishCurrentBlock(currentBlock);
471
+ currentBlock = null;
472
+ }
473
+ const callId = toolCall.id && toolCall.id !== "null" ? toolCall.id : deriveMistralToolCallId(`toolcall:${toolCall.index ?? 0}`, 0);
474
+ const key = toolCall.index ?? callId;
475
+ const existingIndex = toolBlocksByKey.get(key);
476
+ let block;
477
+ if (existingIndex !== void 0) {
478
+ const existing = output.content[existingIndex];
479
+ if (existing?.type === "toolCall") block = existing;
480
+ }
481
+ if (!block) {
482
+ block = {
483
+ type: "toolCall",
484
+ id: callId,
485
+ name: toolCall.function.name,
486
+ arguments: {},
487
+ partialArgs: ""
488
+ };
489
+ output.content.push(block);
490
+ toolBlocksByKey.set(key, output.content.length - 1);
491
+ stream.push({
492
+ type: "toolcall_start",
493
+ contentIndex: output.content.length - 1,
494
+ partial: output
495
+ });
496
+ }
497
+ const argsDelta = typeof toolCall.function.arguments === "string" ? toolCall.function.arguments : JSON.stringify(toolCall.function.arguments || {});
498
+ block.partialArgs = (block.partialArgs || "") + argsDelta;
499
+ block.arguments = parseStreamingJson(block.partialArgs);
500
+ stream.push({
501
+ type: "toolcall_delta",
502
+ contentIndex: toolBlocksByKey.get(key),
503
+ delta: argsDelta,
504
+ partial: output
505
+ });
506
+ }
507
+ }
508
+ finishCurrentBlock(currentBlock);
509
+ for (const index of toolBlocksByKey.values()) {
510
+ const block = output.content[index];
511
+ if (block.type !== "toolCall") continue;
512
+ const toolBlock = block;
513
+ toolBlock.arguments = parseStreamingJson(toolBlock.partialArgs);
514
+ delete toolBlock.partialArgs;
515
+ stream.push({
516
+ type: "toolcall_end",
517
+ contentIndex: index,
518
+ toolCall: toolBlock,
519
+ partial: output
520
+ });
521
+ }
522
+ }
523
+ function toFunctionTools(tools) {
524
+ return tools.map((tool) => {
525
+ const strict = resolveJsonSchemaStrictSampling(tool, true);
526
+ return {
527
+ type: "function",
528
+ function: {
529
+ name: tool.name,
530
+ description: tool.description,
531
+ parameters: stripSymbolKeys(getJsonSchemaToolParameters(tool, strict)),
532
+ strict: strict ?? false
533
+ }
534
+ };
535
+ });
536
+ }
537
+ function stripSymbolKeys(value) {
538
+ if (Array.isArray(value)) return value.map((item) => stripSymbolKeys(item));
539
+ if (value && typeof value === "object") {
540
+ const result = {};
541
+ for (const [key, entry] of Object.entries(value)) result[key] = stripSymbolKeys(entry);
542
+ return result;
543
+ }
544
+ return value;
545
+ }
546
+ function toChatMessages(messages, supportsImages) {
547
+ const result = [];
548
+ for (const [index, msg] of messages.entries()) {
549
+ if (msg.role === "system") {
550
+ const text = index === 0 ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg);
551
+ if (text.length > 0) result.push({
552
+ role: "system",
553
+ content: sanitizeSurrogates(text)
554
+ });
555
+ continue;
556
+ }
557
+ if (msg.role === "user") {
558
+ if (typeof msg.content === "string") {
559
+ result.push({
560
+ role: "user",
561
+ content: sanitizeSurrogates(msg.content)
562
+ });
563
+ continue;
564
+ }
565
+ const hadImages = msg.content.some((item) => item.type === "image");
566
+ const content = msg.content.filter((item) => item.type === "text" || supportsImages).map((item) => {
567
+ if (item.type === "text") return {
568
+ type: "text",
569
+ text: sanitizeSurrogates(item.text)
570
+ };
571
+ return {
572
+ type: "image_url",
573
+ imageUrl: `data:${item.mimeType};base64,${item.data}`
574
+ };
575
+ });
576
+ if (content.length > 0) {
577
+ result.push({
578
+ role: "user",
579
+ content
580
+ });
581
+ continue;
582
+ }
583
+ if (hadImages && !supportsImages) result.push({
584
+ role: "user",
585
+ content: "(image omitted: model does not support images)"
586
+ });
587
+ continue;
588
+ }
589
+ if (msg.role === "assistant") {
590
+ const contentParts = [];
591
+ const toolCalls = [];
592
+ for (const block of msg.content) {
593
+ if (block.type === "text") {
594
+ if (block.text.trim().length > 0) contentParts.push({
595
+ type: "text",
596
+ text: sanitizeSurrogates(block.text)
597
+ });
598
+ continue;
599
+ }
600
+ if (block.type === "thinking") {
601
+ if (block.thinking.trim().length > 0) contentParts.push({
602
+ type: "thinking",
603
+ thinking: [{
604
+ type: "text",
605
+ text: sanitizeSurrogates(block.thinking)
606
+ }]
607
+ });
608
+ continue;
609
+ }
610
+ toolCalls.push({
611
+ id: block.id,
612
+ type: "function",
613
+ function: {
614
+ name: block.name,
615
+ arguments: JSON.stringify(block.arguments || {})
616
+ },
617
+ index: 0
618
+ });
619
+ }
620
+ const assistantMessage = {
621
+ role: "assistant",
622
+ prefix: false
623
+ };
624
+ if (contentParts.length > 0) assistantMessage.content = contentParts;
625
+ if (toolCalls.length > 0) assistantMessage.toolCalls = toolCalls;
626
+ if (contentParts.length > 0 || toolCalls.length > 0) result.push(assistantMessage);
627
+ continue;
628
+ }
629
+ const toolContent = [];
630
+ const toolText = buildToolResultText(msg.content.filter((part) => part.type === "text").map((part) => part.type === "text" ? sanitizeSurrogates(part.text) : "").join("\n"), msg.content.some((part) => part.type === "image"), supportsImages, msg.isError);
631
+ toolContent.push({
632
+ type: "text",
633
+ text: toolText
634
+ });
635
+ for (const part of msg.content) {
636
+ if (!supportsImages) continue;
637
+ if (part.type !== "image") continue;
638
+ toolContent.push({
639
+ type: "image_url",
640
+ imageUrl: `data:${part.mimeType};base64,${part.data}`
641
+ });
642
+ }
643
+ result.push({
644
+ role: "tool",
645
+ toolCallId: msg.toolCallId,
646
+ name: msg.toolName,
647
+ content: toolContent
648
+ });
649
+ }
650
+ return result;
651
+ }
652
+ function buildToolResultText(text, hasImages, supportsImages, isError) {
653
+ const trimmed = text.trim();
654
+ const errorPrefix = isError ? "[tool error] " : "";
655
+ if (trimmed.length > 0) return `${errorPrefix}${trimmed}${hasImages && !supportsImages ? "\n[tool image omitted: model does not support images]" : ""}`;
656
+ if (hasImages) {
657
+ if (supportsImages) return isError ? "[tool error] (see attached image)" : "(see attached image)";
658
+ return isError ? "[tool error] (image omitted: model does not support images)" : "(image omitted: model does not support images)";
659
+ }
660
+ return isError ? "[tool error] (no tool output)" : "(no tool output)";
661
+ }
662
+ function mapToolChoice(choice) {
663
+ if (!choice) return void 0;
664
+ if (choice === "auto" || choice === "none" || choice === "any" || choice === "required") return choice;
665
+ return {
666
+ type: "function",
667
+ function: { name: choice.function.name }
668
+ };
669
+ }
670
+ function mapChatStopReason(reason) {
671
+ if (reason === null) return { stopReason: "stop" };
672
+ switch (reason) {
673
+ case "stop": return { stopReason: "stop" };
674
+ case "length":
675
+ case "model_length": return { stopReason: "length" };
676
+ case "tool_calls": return { stopReason: "toolUse" };
677
+ case "error": return {
678
+ stopReason: "error",
679
+ errorMessage: "Provider stopped with: error"
680
+ };
681
+ default: return {
682
+ stopReason: "error",
683
+ errorMessage: `Provider stopped with: ${reason}`
684
+ };
685
+ }
686
+ }
687
+ //#endregion
688
+ export { stream, streamSimple };
689
+
690
+ //# sourceMappingURL=mistral-conversations-CvaqBWjR.js.map