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.
- package/README.md +48 -41
- package/dist/anthropic-messages-TqKpKmfW.js +1067 -0
- package/dist/anthropic-messages-TqKpKmfW.js.map +1 -0
- package/dist/audit.d.ts +2 -0
- package/dist/audit.js +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/azure-openai-responses-DJjBLwoI.js +231 -0
- package/dist/azure-openai-responses-DJjBLwoI.js.map +1 -0
- package/dist/cli.js +10487 -38044
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js +41 -0
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js.map +1 -0
- package/dist/config.d.ts +6 -6
- package/dist/config.js.map +1 -1
- package/dist/diagnostics-Wt5faNDM.js +108 -0
- package/dist/diagnostics-Wt5faNDM.js.map +1 -0
- package/dist/dist-B6zg_Z3Z.js +4794 -0
- package/dist/dist-B6zg_Z3Z.js.map +1 -0
- package/dist/env-api-keys-C-OA0yM-.js +124 -0
- package/dist/env-api-keys-C-OA0yM-.js.map +1 -0
- package/dist/error-body-CyiejW4b.js +103 -0
- package/dist/error-body-CyiejW4b.js.map +1 -0
- package/dist/github-copilot-headers-CEpMOpQF.js +24 -0
- package/dist/github-copilot-headers-CEpMOpQF.js.map +1 -0
- package/dist/google-generative-ai-BxABKIKO.js +330 -0
- package/dist/google-generative-ai-BxABKIKO.js.map +1 -0
- package/dist/google-shared-0gpM2jFi.js +19471 -0
- package/dist/google-shared-0gpM2jFi.js.map +1 -0
- package/dist/google-vertex-D8Eb5cbu.js +376 -0
- package/dist/google-vertex-D8Eb5cbu.js.map +1 -0
- package/dist/hash-Dp7EzZUo.js +18 -0
- package/dist/hash-Dp7EzZUo.js.map +1 -0
- package/dist/headers-BRNMVpzu.js +19 -0
- package/dist/headers-BRNMVpzu.js.map +1 -0
- package/dist/json-parse-C10znB7l.js +383 -0
- package/dist/json-parse-C10znB7l.js.map +1 -0
- package/dist/mistral-conversations-CvaqBWjR.js +690 -0
- package/dist/mistral-conversations-CvaqBWjR.js.map +1 -0
- package/dist/models-DcT5qOEL.js +1203 -0
- package/dist/models-DcT5qOEL.js.map +1 -0
- package/dist/node-Ccvru9GE.js +26 -0
- package/dist/node-Ccvru9GE.js.map +1 -0
- package/dist/node-MEosBOF2.js +2403 -0
- package/dist/node-MEosBOF2.js.map +1 -0
- package/dist/openai-BCBEd2eO.js +17350 -0
- package/dist/openai-BCBEd2eO.js.map +1 -0
- package/dist/openai-codex-responses-vJqxeeRC.js +1268 -0
- package/dist/openai-codex-responses-vJqxeeRC.js.map +1 -0
- package/dist/openai-completions-Cb_fRAbI.js +989 -0
- package/dist/openai-completions-Cb_fRAbI.js.map +1 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js +10 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js.map +1 -0
- package/dist/openai-responses-sDuh82G5.js +268 -0
- package/dist/openai-responses-sDuh82G5.js.map +1 -0
- package/dist/openai-responses-shared-mhuo1Jov.js +599 -0
- package/dist/openai-responses-shared-mhuo1Jov.js.map +1 -0
- package/dist/openrouter-images-CRmBkzpX.js +127 -0
- package/dist/openrouter-images-CRmBkzpX.js.map +1 -0
- package/dist/pi-Bvw6J0gh.js +56795 -0
- package/dist/pi-Bvw6J0gh.js.map +1 -0
- package/dist/pi-messages-CejiVYvO.js +308 -0
- package/dist/pi-messages-CejiVYvO.js.map +1 -0
- package/dist/provider-env-t38GK5FF.js +39 -0
- package/dist/provider-env-t38GK5FF.js.map +1 -0
- package/dist/provider-retry-DzKoh1X7.js +80 -0
- package/dist/provider-retry-DzKoh1X7.js.map +1 -0
- package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
- package/dist/sanitize-unicode-Ds14l9Om.js +28 -0
- package/dist/sanitize-unicode-Ds14l9Om.js.map +1 -0
- package/dist/sdk-C9_wiO6w.js +12503 -0
- package/dist/sdk-C9_wiO6w.js.map +1 -0
- package/dist/state-BuJP_3Lr.js +28102 -0
- package/dist/state-BuJP_3Lr.js.map +1 -0
- package/dist/system-one-shared-Dl10ZF7Z.js +167 -0
- package/dist/system-one-shared-Dl10ZF7Z.js.map +1 -0
- package/dist/transform-messages-BLJ8EfK6.js +468 -0
- package/dist/transform-messages-BLJ8EfK6.js.map +1 -0
- package/dist/typesafe-system-one-CwEWMV8P.js +25 -0
- package/dist/typesafe-system-one-CwEWMV8P.js.map +1 -0
- package/package.json +4 -8
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { t as calculateCost } from "./models-DcT5qOEL.js";
|
|
2
|
+
import { n as providerHeadersToRecord, t as headersToRecord } from "./headers-BRNMVpzu.js";
|
|
3
|
+
import { t as retryProviderRequest } from "./provider-retry-DzKoh1X7.js";
|
|
4
|
+
import { n as normalizeProviderError, t as formatProviderError } from "./error-body-CyiejW4b.js";
|
|
5
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/system-one-shared.js
|
|
6
|
+
function httpError(label, response, body) {
|
|
7
|
+
const error = /* @__PURE__ */ new Error(`${label} returned ${response.status}`);
|
|
8
|
+
error.status = response.status;
|
|
9
|
+
error.headers = response.headers;
|
|
10
|
+
error.body = body;
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
function timeoutError(timeoutMs) {
|
|
14
|
+
const error = /* @__PURE__ */ new Error(`Request timed out after ${timeoutMs}ms`);
|
|
15
|
+
error.name = "TimeoutError";
|
|
16
|
+
error.status = void 0;
|
|
17
|
+
error.headers = void 0;
|
|
18
|
+
error.body = "";
|
|
19
|
+
return error;
|
|
20
|
+
}
|
|
21
|
+
function isRecord(value) {
|
|
22
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
function requiredNumber(label, value, field) {
|
|
25
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${label} returned an invalid ${field}`);
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function probabilities(label, value, id) {
|
|
29
|
+
if (!isRecord(value)) throw new Error(`${label} returned invalid probabilities for ${id}`);
|
|
30
|
+
return Object.fromEntries(Object.entries(value).map(([key, probability]) => [key, requiredNumber(label, probability, `probability for ${id}.${key}`)]));
|
|
31
|
+
}
|
|
32
|
+
function parseAnswers(label, value, context) {
|
|
33
|
+
if (!isRecord(value)) throw new Error(`${label} returned an unexpected response`);
|
|
34
|
+
const answers = [];
|
|
35
|
+
for (const [id, question] of Object.entries(context.questions)) {
|
|
36
|
+
const answer = value[id];
|
|
37
|
+
if (!isRecord(answer)) throw new Error(`${label} did not return an answer for ${id}`);
|
|
38
|
+
if (question.type === "choice") {
|
|
39
|
+
if (answer.type !== "choice" || typeof answer.choice !== "string") throw new Error(`${label} did not return a choice answer for ${id}`);
|
|
40
|
+
answers.push([id, {
|
|
41
|
+
type: "choice",
|
|
42
|
+
choice: answer.choice,
|
|
43
|
+
probabilities: probabilities(label, answer.probabilities, id),
|
|
44
|
+
confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`)
|
|
45
|
+
}]);
|
|
46
|
+
} else if (question.type === "score") {
|
|
47
|
+
if (answer.type !== "score") throw new Error(`${label} did not return a score answer for ${id}`);
|
|
48
|
+
answers.push([id, {
|
|
49
|
+
type: "score",
|
|
50
|
+
score: requiredNumber(label, answer.score, `score for ${id}`),
|
|
51
|
+
confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`)
|
|
52
|
+
}]);
|
|
53
|
+
} else {
|
|
54
|
+
if (answer.type !== "noul") throw new Error(`${label} did not return a bool answer for ${id}`);
|
|
55
|
+
answers.push([id, {
|
|
56
|
+
type: "bool",
|
|
57
|
+
probability: requiredNumber(label, answer.noul, `probability for ${id}`)
|
|
58
|
+
}]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return Object.fromEntries(answers);
|
|
62
|
+
}
|
|
63
|
+
function tokenCount(value) {
|
|
64
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Usage from System One's `{ input_tokens, output_tokens }`, priced from the model catalog like chat
|
|
68
|
+
* usage. A missing or malformed usage object leaves the result without usage instead of failing it.
|
|
69
|
+
*/
|
|
70
|
+
function parseUsage(value, model) {
|
|
71
|
+
if (!isRecord(value) || value.input_tokens === void 0 && value.output_tokens === void 0) return void 0;
|
|
72
|
+
const input = tokenCount(value.input_tokens);
|
|
73
|
+
const output = tokenCount(value.output_tokens);
|
|
74
|
+
const usage = {
|
|
75
|
+
input,
|
|
76
|
+
output,
|
|
77
|
+
cacheRead: 0,
|
|
78
|
+
cacheWrite: 0,
|
|
79
|
+
totalTokens: input + output,
|
|
80
|
+
cost: {
|
|
81
|
+
input: 0,
|
|
82
|
+
output: 0,
|
|
83
|
+
cacheRead: 0,
|
|
84
|
+
cacheWrite: 0,
|
|
85
|
+
total: 0
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
calculateCost(model, usage);
|
|
89
|
+
return usage;
|
|
90
|
+
}
|
|
91
|
+
/** Maps public `bool` questions to TypeSafe's wire-level `noul` type. */
|
|
92
|
+
function wireRequest(context) {
|
|
93
|
+
return {
|
|
94
|
+
state: context.state,
|
|
95
|
+
questions: Object.fromEntries(Object.entries(context.questions).map(([id, question]) => [id, question.type === "bool" ? {
|
|
96
|
+
...question,
|
|
97
|
+
type: "noul"
|
|
98
|
+
} : question]))
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function requestHeaders(model, apiKey, optionsHeaders) {
|
|
102
|
+
return providerHeadersToRecord({
|
|
103
|
+
authorization: `Bearer ${apiKey}`,
|
|
104
|
+
"content-type": "application/json"
|
|
105
|
+
}, model.headers, optionsHeaders) ?? {};
|
|
106
|
+
}
|
|
107
|
+
/** Runs one System One classification over the given transport. */
|
|
108
|
+
async function classifySystemOne(transport, model, context, options) {
|
|
109
|
+
const output = {
|
|
110
|
+
api: model.api,
|
|
111
|
+
provider: model.provider,
|
|
112
|
+
model: model.id,
|
|
113
|
+
answers: {},
|
|
114
|
+
stopReason: "stop",
|
|
115
|
+
timestamp: Date.now()
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
if (model.api !== transport.api) throw new Error(`Unsupported classifier API: ${model.api}`);
|
|
119
|
+
if (!options?.apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
120
|
+
const apiKey = options.apiKey;
|
|
121
|
+
let payload = transport.payload(model, wireRequest(context));
|
|
122
|
+
const transformed = await options.onPayload?.(payload, model);
|
|
123
|
+
if (transformed !== void 0) payload = transformed;
|
|
124
|
+
const requestFetch = options.fetch ?? globalThis.fetch;
|
|
125
|
+
const { response, body } = await retryProviderRequest(async () => {
|
|
126
|
+
const timeoutSignal = options.timeoutMs !== void 0 ? AbortSignal.timeout(options.timeoutMs) : void 0;
|
|
127
|
+
const signal = options.signal && timeoutSignal ? AbortSignal.any([options.signal, timeoutSignal]) : options.signal ?? timeoutSignal;
|
|
128
|
+
try {
|
|
129
|
+
const next = await requestFetch(transport.url(model), {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: requestHeaders(model, apiKey, options.headers),
|
|
132
|
+
body: JSON.stringify(payload),
|
|
133
|
+
signal
|
|
134
|
+
});
|
|
135
|
+
if (!next.ok) throw httpError(transport.label, next, await next.text());
|
|
136
|
+
return {
|
|
137
|
+
response: next,
|
|
138
|
+
body: await next.json()
|
|
139
|
+
};
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (timeoutSignal?.aborted && !options.signal?.aborted) throw timeoutError(options.timeoutMs);
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}, {
|
|
145
|
+
maxRetries: options.maxRetries ?? 2,
|
|
146
|
+
maxRetryDelayMs: options.maxRetryDelayMs,
|
|
147
|
+
signal: options.signal
|
|
148
|
+
});
|
|
149
|
+
await options.onResponse?.({
|
|
150
|
+
status: response.status,
|
|
151
|
+
headers: headersToRecord(response.headers)
|
|
152
|
+
}, model);
|
|
153
|
+
const result = transport.output(body);
|
|
154
|
+
const usage = parseUsage(result.usage, model);
|
|
155
|
+
if (usage) output.usage = usage;
|
|
156
|
+
output.answers = parseAnswers(transport.label, result.answers, context);
|
|
157
|
+
return output;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
160
|
+
output.errorMessage = formatProviderError(normalizeProviderError(error), `${transport.label} error`);
|
|
161
|
+
return output;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
export { isRecord as n, classifySystemOne as t };
|
|
166
|
+
|
|
167
|
+
//# sourceMappingURL=system-one-shared-Dl10ZF7Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-one-shared-Dl10ZF7Z.js","names":[],"sources":["../node_modules/@earendil-works/pi-ai/dist/api/system-one-shared.js"],"sourcesContent":["import { calculateCost } from \"../models.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.js\";\nimport { retryProviderRequest } from \"../utils/provider-retry.js\";\nfunction httpError(label, response, body) {\n const error = new Error(`${label} returned ${response.status}`);\n error.status = response.status;\n error.headers = response.headers;\n error.body = body;\n return error;\n}\nfunction timeoutError(timeoutMs) {\n const error = new Error(`Request timed out after ${timeoutMs}ms`);\n error.name = \"TimeoutError\";\n error.status = undefined;\n error.headers = undefined;\n error.body = \"\";\n return error;\n}\nexport function isRecord(value) {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\nfunction requiredNumber(label, value, field) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`${label} returned an invalid ${field}`);\n }\n return value;\n}\nfunction probabilities(label, value, id) {\n if (!isRecord(value))\n throw new Error(`${label} returned invalid probabilities for ${id}`);\n return Object.fromEntries(Object.entries(value).map(([key, probability]) => [\n key,\n requiredNumber(label, probability, `probability for ${id}.${key}`),\n ]));\n}\nfunction parseAnswers(label, value, context) {\n if (!isRecord(value))\n throw new Error(`${label} returned an unexpected response`);\n const answers = [];\n for (const [id, question] of Object.entries(context.questions)) {\n const answer = value[id];\n if (!isRecord(answer))\n throw new Error(`${label} did not return an answer for ${id}`);\n if (question.type === \"choice\") {\n if (answer.type !== \"choice\" || typeof answer.choice !== \"string\") {\n throw new Error(`${label} did not return a choice answer for ${id}`);\n }\n answers.push([\n id,\n {\n type: \"choice\",\n choice: answer.choice,\n probabilities: probabilities(label, answer.probabilities, id),\n confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`),\n },\n ]);\n }\n else if (question.type === \"score\") {\n if (answer.type !== \"score\")\n throw new Error(`${label} did not return a score answer for ${id}`);\n answers.push([\n id,\n {\n type: \"score\",\n score: requiredNumber(label, answer.score, `score for ${id}`),\n confidence: requiredNumber(label, answer.confidence, `confidence for ${id}`),\n },\n ]);\n }\n else {\n if (answer.type !== \"noul\")\n throw new Error(`${label} did not return a bool answer for ${id}`);\n answers.push([\n id,\n {\n type: \"bool\",\n probability: requiredNumber(label, answer.noul, `probability for ${id}`),\n },\n ]);\n }\n }\n return Object.fromEntries(answers);\n}\nfunction tokenCount(value) {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : 0;\n}\n/**\n * Usage from System One's `{ input_tokens, output_tokens }`, priced from the model catalog like chat\n * usage. A missing or malformed usage object leaves the result without usage instead of failing it.\n */\nfunction parseUsage(value, model) {\n if (!isRecord(value) || (value.input_tokens === undefined && value.output_tokens === undefined))\n return undefined;\n const input = tokenCount(value.input_tokens);\n const output = tokenCount(value.output_tokens);\n const usage = {\n input,\n output,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: input + output,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n };\n calculateCost(model, usage);\n return usage;\n}\n/** Maps public `bool` questions to TypeSafe's wire-level `noul` type. */\nfunction wireRequest(context) {\n return {\n state: context.state,\n questions: Object.fromEntries(Object.entries(context.questions).map(([id, question]) => [\n id,\n question.type === \"bool\" ? { ...question, type: \"noul\" } : question,\n ])),\n };\n}\nfunction requestHeaders(model, apiKey, optionsHeaders) {\n return (providerHeadersToRecord({ authorization: `Bearer ${apiKey}`, \"content-type\": \"application/json\" }, model.headers, optionsHeaders) ?? {});\n}\n/** Runs one System One classification over the given transport. */\nexport async function classifySystemOne(transport, model, context, options) {\n const output = {\n api: model.api,\n provider: model.provider,\n model: model.id,\n answers: {},\n stopReason: \"stop\",\n timestamp: Date.now(),\n };\n try {\n if (model.api !== transport.api)\n throw new Error(`Unsupported classifier API: ${model.api}`);\n if (!options?.apiKey)\n throw new Error(`No API key for provider: ${model.provider}`);\n const apiKey = options.apiKey;\n let payload = transport.payload(model, wireRequest(context));\n const transformed = await options.onPayload?.(payload, model);\n if (transformed !== undefined)\n payload = transformed;\n const requestFetch = options.fetch ?? globalThis.fetch;\n const { response, body } = await retryProviderRequest(async () => {\n const timeoutSignal = options.timeoutMs !== undefined ? AbortSignal.timeout(options.timeoutMs) : undefined;\n const signal = options.signal && timeoutSignal\n ? AbortSignal.any([options.signal, timeoutSignal])\n : (options.signal ?? timeoutSignal);\n try {\n const next = await requestFetch(transport.url(model), {\n method: \"POST\",\n headers: requestHeaders(model, apiKey, options.headers),\n body: JSON.stringify(payload),\n signal,\n });\n if (!next.ok)\n throw httpError(transport.label, next, await next.text());\n return { response: next, body: (await next.json()) };\n }\n catch (error) {\n if (timeoutSignal?.aborted && !options.signal?.aborted)\n throw timeoutError(options.timeoutMs);\n throw error;\n }\n }, {\n maxRetries: options.maxRetries ?? 2,\n maxRetryDelayMs: options.maxRetryDelayMs,\n signal: options.signal,\n });\n await options.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n const result = transport.output(body);\n // Set before parsing answers: a request with malformed answers was still billed.\n const usage = parseUsage(result.usage, model);\n if (usage)\n output.usage = usage;\n output.answers = parseAnswers(transport.label, result.answers, context);\n return output;\n }\n catch (error) {\n output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n output.errorMessage = formatProviderError(normalizeProviderError(error), `${transport.label} error`);\n return output;\n }\n}\n//# sourceMappingURL=system-one-shared.js.map"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
import { S as getSystemMessageText } from "./models-DcT5qOEL.js";
|
|
2
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.js
|
|
3
|
+
function loadNodeOs() {
|
|
4
|
+
if (typeof process === "undefined" || !(process.versions?.node || process.versions?.bun)) return null;
|
|
5
|
+
return process.getBuiltinModule?.("node:os") ?? null;
|
|
6
|
+
}
|
|
7
|
+
const nodeOs = loadNodeOs();
|
|
8
|
+
function getPiUserAgent() {
|
|
9
|
+
return nodeOs ? `pi (${nodeOs.platform()} ${nodeOs.release()}; ${nodeOs.arch()})` : "pi (browser)";
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js
|
|
13
|
+
var UnsupportedStrictJsonSchemaError = class extends Error {};
|
|
14
|
+
const UNSUPPORTED_STRICT_SCHEMA_KEYS = [
|
|
15
|
+
"$ref",
|
|
16
|
+
"$defs",
|
|
17
|
+
"definitions",
|
|
18
|
+
"allOf",
|
|
19
|
+
"oneOf",
|
|
20
|
+
"patternProperties",
|
|
21
|
+
"dependentSchemas",
|
|
22
|
+
"dependencies",
|
|
23
|
+
"unevaluatedProperties",
|
|
24
|
+
"propertyNames",
|
|
25
|
+
"contains",
|
|
26
|
+
"prefixItems",
|
|
27
|
+
"not",
|
|
28
|
+
"if",
|
|
29
|
+
"then",
|
|
30
|
+
"else"
|
|
31
|
+
];
|
|
32
|
+
function isJsonSchemaObject(value) {
|
|
33
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34
|
+
}
|
|
35
|
+
function isStructuredSchema(schema) {
|
|
36
|
+
if (!isJsonSchemaObject(schema)) return false;
|
|
37
|
+
const types = typeof schema.type === "string" ? [schema.type] : Array.isArray(schema.type) ? schema.type : [];
|
|
38
|
+
return types.includes("object") || types.includes("array") || schema.properties !== void 0 || schema.items !== void 0;
|
|
39
|
+
}
|
|
40
|
+
function schemaAllowsNull(schema) {
|
|
41
|
+
if (!isJsonSchemaObject(schema)) return false;
|
|
42
|
+
if (schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null")) return true;
|
|
43
|
+
if (schema.const === null || Array.isArray(schema.enum) && schema.enum.includes(null)) return true;
|
|
44
|
+
return Array.isArray(schema.anyOf) && schema.anyOf.some((variant) => schemaAllowsNull(variant));
|
|
45
|
+
}
|
|
46
|
+
function makeJsonSchemaNodeStrict(schema, isUnsupportedKeyword) {
|
|
47
|
+
if (!isJsonSchemaObject(schema)) throw new UnsupportedStrictJsonSchemaError("boolean schemas are unsupported");
|
|
48
|
+
for (const key of UNSUPPORTED_STRICT_SCHEMA_KEYS) if (schema[key] !== void 0) throw new UnsupportedStrictJsonSchemaError(`${key} schemas are unsupported`);
|
|
49
|
+
if (isUnsupportedKeyword) {
|
|
50
|
+
for (const [key, value] of Object.entries(schema)) if (isUnsupportedKeyword(key, value)) throw new UnsupportedStrictJsonSchemaError(`${key}: ${JSON.stringify(value)} is unsupported`);
|
|
51
|
+
}
|
|
52
|
+
if (schema.anyOf !== void 0) {
|
|
53
|
+
if (!Array.isArray(schema.anyOf) || schema.anyOf.length === 0) throw new UnsupportedStrictJsonSchemaError("anyOf must contain at least one schema");
|
|
54
|
+
for (const variant of schema.anyOf) {
|
|
55
|
+
if (isStructuredSchema(variant)) throw new UnsupportedStrictJsonSchemaError("object and array unions are unsupported");
|
|
56
|
+
makeJsonSchemaNodeStrict(variant, isUnsupportedKeyword);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (schema.items !== void 0) {
|
|
60
|
+
if (Array.isArray(schema.items)) throw new UnsupportedStrictJsonSchemaError("tuple schemas are unsupported");
|
|
61
|
+
makeJsonSchemaNodeStrict(schema.items, isUnsupportedKeyword);
|
|
62
|
+
}
|
|
63
|
+
const isObjectSchema = schema.type === "object";
|
|
64
|
+
if (schema.properties !== void 0 && !isObjectSchema) throw new UnsupportedStrictJsonSchemaError("properties require type object");
|
|
65
|
+
if (!isObjectSchema) return;
|
|
66
|
+
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) throw new UnsupportedStrictJsonSchemaError("schema-valued or true additionalProperties is unsupported");
|
|
67
|
+
if (schema.properties !== void 0 && !isJsonSchemaObject(schema.properties)) throw new UnsupportedStrictJsonSchemaError("object properties must be a schema map");
|
|
68
|
+
if (schema.required !== void 0 && (!Array.isArray(schema.required) || schema.required.some((key) => typeof key !== "string"))) throw new UnsupportedStrictJsonSchemaError("object required must be a string array");
|
|
69
|
+
const properties = schema.properties ?? {};
|
|
70
|
+
const propertyNames = Object.keys(properties);
|
|
71
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
72
|
+
if ([...required].some((key) => !propertyNames.includes(key))) throw new UnsupportedStrictJsonSchemaError("required contains an unknown property");
|
|
73
|
+
for (const [key, property] of Object.entries(properties)) {
|
|
74
|
+
makeJsonSchemaNodeStrict(property, isUnsupportedKeyword);
|
|
75
|
+
if (!required.has(key) && !schemaAllowsNull(property)) properties[key] = { anyOf: [property, { type: "null" }] };
|
|
76
|
+
}
|
|
77
|
+
schema.required = propertyNames;
|
|
78
|
+
schema.additionalProperties = false;
|
|
79
|
+
}
|
|
80
|
+
/** Convert a tool schema to the strict subset expected by provider constrained sampling. */
|
|
81
|
+
function makeStrictJsonSchema(schema, isUnsupportedKeyword) {
|
|
82
|
+
const cloned = structuredClone(schema);
|
|
83
|
+
if (!isJsonSchemaObject(cloned)) throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
84
|
+
makeJsonSchemaNodeStrict(cloned, isUnsupportedKeyword);
|
|
85
|
+
if (cloned.type !== "object") throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
86
|
+
return cloned;
|
|
87
|
+
}
|
|
88
|
+
function getJsonSchemaToolParameters(tool, strict) {
|
|
89
|
+
return strict === true ? makeStrictJsonSchema(tool.parameters) : tool.parameters;
|
|
90
|
+
}
|
|
91
|
+
function getGrammarToolInput(toolName, arguments_, inputProperty) {
|
|
92
|
+
const input = arguments_[inputProperty];
|
|
93
|
+
if (typeof input !== "string") throw new Error(`Grammar tool call "${toolName}" requires argument "${inputProperty}" to be a string.`);
|
|
94
|
+
return input;
|
|
95
|
+
}
|
|
96
|
+
function appendGrammarToolInputJsonDelta(buffer, inputProperty, nextInput, close) {
|
|
97
|
+
if (buffer.closed) {
|
|
98
|
+
if (close && nextInput === buffer.input) return void 0;
|
|
99
|
+
throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
|
|
100
|
+
}
|
|
101
|
+
if (!nextInput.startsWith(buffer.input)) throw new Error(`grammar tool input for property "${inputProperty}" changed non-monotonically`);
|
|
102
|
+
const inputDelta = nextInput.slice(buffer.input.length);
|
|
103
|
+
if (!close && inputDelta.length === 0) return void 0;
|
|
104
|
+
let delta = "";
|
|
105
|
+
if (!buffer.started) {
|
|
106
|
+
delta += `{${JSON.stringify(inputProperty)}:"`;
|
|
107
|
+
buffer.started = true;
|
|
108
|
+
}
|
|
109
|
+
delta += JSON.stringify(inputDelta).slice(1, -1);
|
|
110
|
+
buffer.input = nextInput;
|
|
111
|
+
if (close) {
|
|
112
|
+
delta += "\"}";
|
|
113
|
+
buffer.closed = true;
|
|
114
|
+
}
|
|
115
|
+
return delta;
|
|
116
|
+
}
|
|
117
|
+
function inferGrammarInputProperty(tool) {
|
|
118
|
+
const schema = tool.parameters;
|
|
119
|
+
if (schema.type !== "object") throw new Error("grammar constrained sampling requires an object parameter schema");
|
|
120
|
+
if (!Array.isArray(schema.required) || schema.required.length !== 1 || typeof schema.required[0] !== "string") throw new Error("grammar constrained sampling requires exactly one required string property");
|
|
121
|
+
const inputProperty = schema.required[0];
|
|
122
|
+
if (!schema.properties?.[inputProperty]) throw new Error(`grammar constrained sampling requires a properties entry for ${inputProperty}`);
|
|
123
|
+
if (schema.properties[inputProperty]?.type !== "string") throw new Error(`grammar constrained sampling property ${inputProperty} must have type string`);
|
|
124
|
+
return inputProperty;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Decide whether a JSON-schema tool is sent in strict mode. `isUnsupportedKeyword` lets a provider
|
|
128
|
+
* reject extra keywords its strict mode does not accept, so "prefer" tools fall back to non-strict.
|
|
129
|
+
*/
|
|
130
|
+
function resolveJsonSchemaStrictSampling(tool, supportsStrictMode, isUnsupportedKeyword) {
|
|
131
|
+
const config = tool.constrainedSampling;
|
|
132
|
+
if (!config || config.type !== "json_schema") return void 0;
|
|
133
|
+
if (supportsStrictMode) try {
|
|
134
|
+
makeStrictJsonSchema(tool.parameters, isUnsupportedKeyword);
|
|
135
|
+
return true;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (!(error instanceof UnsupportedStrictJsonSchemaError)) throw error;
|
|
138
|
+
if (config.strict !== "require") return void 0;
|
|
139
|
+
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but ${error.message}.`);
|
|
140
|
+
}
|
|
141
|
+
if (config.strict === "require") throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but strict tools are unsupported.`);
|
|
142
|
+
}
|
|
143
|
+
function resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools) {
|
|
144
|
+
const config = tool.constrainedSampling;
|
|
145
|
+
if (!config || config.type !== "grammar") return;
|
|
146
|
+
if (!supportsOpenAIGrammarTools) return;
|
|
147
|
+
const larkDefinition = config.variants.openai_lark;
|
|
148
|
+
const regexDefinition = config.variants.openai_regex;
|
|
149
|
+
const hasLarkDefinition = typeof larkDefinition === "string" && larkDefinition.trim().length > 0;
|
|
150
|
+
const hasRegexDefinition = typeof regexDefinition === "string" && regexDefinition.trim().length > 0;
|
|
151
|
+
if (!hasLarkDefinition && !hasRegexDefinition) throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: no supported grammar variant was provided.`);
|
|
152
|
+
try {
|
|
153
|
+
return {
|
|
154
|
+
format: hasLarkDefinition ? "lark" : "regex",
|
|
155
|
+
definition: hasLarkDefinition ? larkDefinition : regexDefinition,
|
|
156
|
+
inputProperty: inferGrammarInputProperty(tool)
|
|
157
|
+
};
|
|
158
|
+
} catch (error) {
|
|
159
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
160
|
+
throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: ${message}.`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function createGrammarToolInputProperties(tools, supportsOpenAIGrammarTools) {
|
|
164
|
+
const properties = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const tool of tools ?? []) {
|
|
166
|
+
const grammar = resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools);
|
|
167
|
+
if (grammar) properties.set(tool.name, grammar.inputProperty);
|
|
168
|
+
}
|
|
169
|
+
return properties;
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/estimate.js
|
|
173
|
+
const CHARS_PER_TOKEN = 4;
|
|
174
|
+
const ESTIMATED_IMAGE_CHARS = 4800;
|
|
175
|
+
function calculateContextTokens(usage) {
|
|
176
|
+
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
177
|
+
}
|
|
178
|
+
function safeJsonStringify(value) {
|
|
179
|
+
try {
|
|
180
|
+
return JSON.stringify(value) ?? "undefined";
|
|
181
|
+
} catch {
|
|
182
|
+
return "[unserializable]";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function estimateTextAndImageContentChars(content) {
|
|
186
|
+
if (typeof content === "string") return content.length;
|
|
187
|
+
let chars = 0;
|
|
188
|
+
for (const block of content) chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
|
|
189
|
+
return chars;
|
|
190
|
+
}
|
|
191
|
+
function estimateTextTokens(text) {
|
|
192
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
193
|
+
}
|
|
194
|
+
function estimateTextAndImageContentTokens(content) {
|
|
195
|
+
return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
|
|
196
|
+
}
|
|
197
|
+
function estimateMessageTokens(message) {
|
|
198
|
+
let chars = 0;
|
|
199
|
+
if (message.role === "system") return estimateTextTokens(getSystemMessageText(message)) + estimateToolsTokens(message.toolsAdded) + estimateToolsTokens(message.toolsRemoved);
|
|
200
|
+
if (message.role === "user") return estimateTextAndImageContentTokens(message.content);
|
|
201
|
+
if (message.role === "toolResult") return estimateTextAndImageContentTokens(message.content);
|
|
202
|
+
for (const block of message.content) if (block.type === "text") chars += block.text.length;
|
|
203
|
+
else if (block.type === "thinking") chars += block.thinking.length;
|
|
204
|
+
else chars += block.name.length + safeJsonStringify(block.arguments).length;
|
|
205
|
+
return Math.ceil(chars / CHARS_PER_TOKEN);
|
|
206
|
+
}
|
|
207
|
+
function getLastAssistantUsageInfo(messages) {
|
|
208
|
+
let latestPrefixTimestamp = Number.NEGATIVE_INFINITY;
|
|
209
|
+
let usageInfo;
|
|
210
|
+
for (let i = 0; i < messages.length; i++) {
|
|
211
|
+
const message = messages[i];
|
|
212
|
+
if (message.role === "assistant") {
|
|
213
|
+
const assistant = message;
|
|
214
|
+
if (assistant.timestamp >= latestPrefixTimestamp && assistant.stopReason !== "aborted" && assistant.stopReason !== "error" && calculateContextTokens(assistant.usage) > 0) usageInfo = {
|
|
215
|
+
usage: assistant.usage,
|
|
216
|
+
index: i
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
|
|
220
|
+
}
|
|
221
|
+
return usageInfo;
|
|
222
|
+
}
|
|
223
|
+
function estimateContextTokens(context) {
|
|
224
|
+
const messages = "messages" in context ? context.messages : context;
|
|
225
|
+
const usageInfo = getLastAssistantUsageInfo(messages);
|
|
226
|
+
if (usageInfo) {
|
|
227
|
+
const usageTokens = calculateContextTokens(usageInfo.usage);
|
|
228
|
+
let trailingTokens = 0;
|
|
229
|
+
for (let i = usageInfo.index + 1; i < messages.length; i++) trailingTokens += estimateMessageTokens(messages[i]);
|
|
230
|
+
return {
|
|
231
|
+
tokens: usageTokens + trailingTokens,
|
|
232
|
+
usageTokens,
|
|
233
|
+
trailingTokens,
|
|
234
|
+
lastUsageIndex: usageInfo.index
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
let tokens = 0;
|
|
238
|
+
for (const message of messages) tokens += estimateMessageTokens(message);
|
|
239
|
+
return {
|
|
240
|
+
tokens,
|
|
241
|
+
usageTokens: 0,
|
|
242
|
+
trailingTokens: tokens,
|
|
243
|
+
lastUsageIndex: null
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function estimateToolsTokens(tools) {
|
|
247
|
+
if (!tools || tools.length === 0) return 0;
|
|
248
|
+
return estimateTextTokens(safeJsonStringify(tools));
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/simple-options.js
|
|
252
|
+
const CONTEXT_SAFETY_TOKENS = 4096;
|
|
253
|
+
const MIN_MAX_TOKENS = 1;
|
|
254
|
+
function clampMaxTokensToContext(model, context, maxTokens) {
|
|
255
|
+
if (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);
|
|
256
|
+
const available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;
|
|
257
|
+
return Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));
|
|
258
|
+
}
|
|
259
|
+
function buildBaseOptions(model, context, options, apiKey) {
|
|
260
|
+
return {
|
|
261
|
+
temperature: options?.temperature,
|
|
262
|
+
samplingParams: options?.samplingParams,
|
|
263
|
+
maxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),
|
|
264
|
+
signal: options?.signal,
|
|
265
|
+
telemetryContext: options?.telemetryContext,
|
|
266
|
+
apiKey: apiKey || options?.apiKey,
|
|
267
|
+
fetch: options?.fetch,
|
|
268
|
+
transport: options?.transport,
|
|
269
|
+
cacheRetention: options?.cacheRetention,
|
|
270
|
+
sessionId: options?.sessionId,
|
|
271
|
+
headers: options?.headers,
|
|
272
|
+
onPayload: options?.onPayload,
|
|
273
|
+
onResponse: options?.onResponse,
|
|
274
|
+
onProviderStreamEvent: options?.onProviderStreamEvent,
|
|
275
|
+
timeoutMs: options?.timeoutMs,
|
|
276
|
+
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
|
|
277
|
+
maxRetries: options?.maxRetries,
|
|
278
|
+
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
279
|
+
metadata: options?.metadata,
|
|
280
|
+
env: options?.env
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/** Tokens always left for the answer when a thinking budget shares the response ceiling. */
|
|
284
|
+
const MIN_ANSWER_TOKENS = 1024;
|
|
285
|
+
const DEFAULT_THINKING_BUDGETS = {
|
|
286
|
+
minimal: 1024,
|
|
287
|
+
low: 2048,
|
|
288
|
+
medium: 8192,
|
|
289
|
+
high: 16384
|
|
290
|
+
};
|
|
291
|
+
function clampReasoning(effort) {
|
|
292
|
+
return effort === "xhigh" || effort === "max" ? "high" : effort;
|
|
293
|
+
}
|
|
294
|
+
function thinkingBudgetForLevel(reasoningLevel, customBudgets) {
|
|
295
|
+
return {
|
|
296
|
+
...DEFAULT_THINKING_BUDGETS,
|
|
297
|
+
...customBudgets
|
|
298
|
+
}[clampReasoning(reasoningLevel)];
|
|
299
|
+
}
|
|
300
|
+
/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */
|
|
301
|
+
function clampThinkingBudgetToAnswerRoom(thinkingBudget, ceiling) {
|
|
302
|
+
return Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));
|
|
303
|
+
}
|
|
304
|
+
function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
|
|
305
|
+
let thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);
|
|
306
|
+
const maxTokens = baseMaxTokens === void 0 ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
|
|
307
|
+
if (maxTokens <= thinkingBudget) thinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);
|
|
308
|
+
return {
|
|
309
|
+
maxTokens,
|
|
310
|
+
thinkingBudget
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js
|
|
315
|
+
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
316
|
+
const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
317
|
+
function replaceImagesWithPlaceholder(content, placeholder) {
|
|
318
|
+
const result = [];
|
|
319
|
+
let previousWasPlaceholder = false;
|
|
320
|
+
for (const block of content) {
|
|
321
|
+
if (block.type === "image") {
|
|
322
|
+
if (!previousWasPlaceholder) result.push({
|
|
323
|
+
type: "text",
|
|
324
|
+
text: placeholder
|
|
325
|
+
});
|
|
326
|
+
previousWasPlaceholder = true;
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
result.push(block);
|
|
330
|
+
previousWasPlaceholder = block.text === placeholder;
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
function downgradeUnsupportedImages(messages, model) {
|
|
335
|
+
if (model.input.includes("image")) return messages;
|
|
336
|
+
return messages.map((msg) => {
|
|
337
|
+
if (msg.role === "user" && Array.isArray(msg.content)) return {
|
|
338
|
+
...msg,
|
|
339
|
+
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
|
|
340
|
+
};
|
|
341
|
+
if (msg.role === "toolResult") return {
|
|
342
|
+
...msg,
|
|
343
|
+
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
|
|
344
|
+
};
|
|
345
|
+
return msg;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Normalize tool call ID for cross-provider compatibility.
|
|
350
|
+
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
|
351
|
+
* Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
|
|
352
|
+
*/
|
|
353
|
+
function transformMessages(messages, model, normalizeToolCallId) {
|
|
354
|
+
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
355
|
+
const transformed = downgradeUnsupportedImages(messages.map((msg) => msg.content == null ? {
|
|
356
|
+
...msg,
|
|
357
|
+
content: []
|
|
358
|
+
} : msg), model).map((msg) => {
|
|
359
|
+
if (msg.role === "system" || msg.role === "user") return msg;
|
|
360
|
+
if (msg.role === "toolResult") {
|
|
361
|
+
const normalizedId = toolCallIdMap.get(msg.toolCallId);
|
|
362
|
+
if (normalizedId && normalizedId !== msg.toolCallId) return {
|
|
363
|
+
...msg,
|
|
364
|
+
toolCallId: normalizedId
|
|
365
|
+
};
|
|
366
|
+
return msg;
|
|
367
|
+
}
|
|
368
|
+
if (msg.role === "assistant") {
|
|
369
|
+
const assistantMsg = msg;
|
|
370
|
+
const isSameModel = assistantMsg.provider === model.provider && assistantMsg.api === model.api && assistantMsg.model === model.id;
|
|
371
|
+
const transformedContent = assistantMsg.content.flatMap((block) => {
|
|
372
|
+
if (block.type === "thinking") {
|
|
373
|
+
if (block.redacted) return isSameModel ? block : [];
|
|
374
|
+
if (isSameModel && block.thinkingSignature) return block;
|
|
375
|
+
if (!block.thinking || block.thinking.trim() === "") return [];
|
|
376
|
+
if (isSameModel) return block;
|
|
377
|
+
return {
|
|
378
|
+
type: "text",
|
|
379
|
+
text: block.thinking
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (block.type === "text") {
|
|
383
|
+
if (isSameModel) return block;
|
|
384
|
+
return {
|
|
385
|
+
type: "text",
|
|
386
|
+
text: block.text
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
if (block.type === "toolCall") {
|
|
390
|
+
const toolCall = block;
|
|
391
|
+
let normalizedToolCall = toolCall;
|
|
392
|
+
if (!isSameModel && toolCall.thoughtSignature) {
|
|
393
|
+
normalizedToolCall = { ...toolCall };
|
|
394
|
+
delete normalizedToolCall.thoughtSignature;
|
|
395
|
+
}
|
|
396
|
+
if (!isSameModel && normalizeToolCallId) {
|
|
397
|
+
const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
|
|
398
|
+
if (normalizedId !== toolCall.id) {
|
|
399
|
+
toolCallIdMap.set(toolCall.id, normalizedId);
|
|
400
|
+
normalizedToolCall = {
|
|
401
|
+
...normalizedToolCall,
|
|
402
|
+
id: normalizedId
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return normalizedToolCall;
|
|
407
|
+
}
|
|
408
|
+
return block;
|
|
409
|
+
});
|
|
410
|
+
return {
|
|
411
|
+
...assistantMsg,
|
|
412
|
+
content: transformedContent
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return msg;
|
|
416
|
+
});
|
|
417
|
+
const result = [];
|
|
418
|
+
let pendingToolCalls = [];
|
|
419
|
+
let existingToolResultIds = /* @__PURE__ */ new Set();
|
|
420
|
+
const heldSystemMessages = [];
|
|
421
|
+
const closePendingToolCalls = () => {
|
|
422
|
+
if (pendingToolCalls.length > 0) {
|
|
423
|
+
for (const tc of pendingToolCalls) if (!existingToolResultIds.has(tc.id)) result.push({
|
|
424
|
+
role: "toolResult",
|
|
425
|
+
toolCallId: tc.id,
|
|
426
|
+
toolName: tc.name,
|
|
427
|
+
content: [{
|
|
428
|
+
type: "text",
|
|
429
|
+
text: "No result provided"
|
|
430
|
+
}],
|
|
431
|
+
isError: true,
|
|
432
|
+
timestamp: Date.now()
|
|
433
|
+
});
|
|
434
|
+
pendingToolCalls = [];
|
|
435
|
+
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
436
|
+
}
|
|
437
|
+
result.push(...heldSystemMessages);
|
|
438
|
+
heldSystemMessages.length = 0;
|
|
439
|
+
};
|
|
440
|
+
for (let i = 0; i < transformed.length; i++) {
|
|
441
|
+
const msg = transformed[i];
|
|
442
|
+
if (msg.role === "assistant") {
|
|
443
|
+
closePendingToolCalls();
|
|
444
|
+
const assistantMsg = msg;
|
|
445
|
+
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") continue;
|
|
446
|
+
const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
|
|
447
|
+
if (toolCalls.length > 0) {
|
|
448
|
+
pendingToolCalls = toolCalls;
|
|
449
|
+
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
450
|
+
}
|
|
451
|
+
result.push(msg);
|
|
452
|
+
} else if (msg.role === "toolResult") {
|
|
453
|
+
existingToolResultIds.add(msg.toolCallId);
|
|
454
|
+
result.push(msg);
|
|
455
|
+
} else if (msg.role === "system") if (pendingToolCalls.length > 0) heldSystemMessages.push(msg);
|
|
456
|
+
else result.push(msg);
|
|
457
|
+
else if (msg.role === "user") {
|
|
458
|
+
closePendingToolCalls();
|
|
459
|
+
result.push(msg);
|
|
460
|
+
} else result.push(msg);
|
|
461
|
+
}
|
|
462
|
+
closePendingToolCalls();
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
//#endregion
|
|
466
|
+
export { clampThinkingBudgetToAnswerRoom as a, createGrammarToolInputProperties as c, resolveGrammarConstrainedSampling as d, resolveJsonSchemaStrictSampling as f, clampMaxTokensToContext as i, getGrammarToolInput as l, adjustMaxTokensForThinking as n, thinkingBudgetForLevel as o, getPiUserAgent as p, buildBaseOptions as r, appendGrammarToolInputJsonDelta as s, transformMessages as t, getJsonSchemaToolParameters as u };
|
|
467
|
+
|
|
468
|
+
//# sourceMappingURL=transform-messages-BLJ8EfK6.js.map
|