@vibedev-si/dsh-vibedev 0.2.1
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/LICENSE +21 -0
- package/README.md +155 -0
- package/THIRD-PARTY-NOTICES.txt +566 -0
- package/client/client.js +1368 -0
- package/cordis.patch.yml +5 -0
- package/icon.svg +7 -0
- package/lib/account/index.d.ts +118 -0
- package/lib/anthropic-messages-KOS0z8Fy.js +13472 -0
- package/lib/auth/credentials.d.ts +47 -0
- package/lib/auth/login.d.ts +154 -0
- package/lib/gateway/assets.d.ts +61 -0
- package/lib/gateway/catalog.d.ts +126 -0
- package/lib/gateway/errors.d.ts +76 -0
- package/lib/gateway/http.d.ts +94 -0
- package/lib/index.d.ts +105 -0
- package/lib/index.js +7301 -0
- package/lib/llm/adapter.d.ts +129 -0
- package/lib/llm/catalog.d.ts +75 -0
- package/lib/llm/context.d.ts +54 -0
- package/lib/llm/index.d.ts +69 -0
- package/lib/llm/limits.d.ts +19 -0
- package/lib/llm/models.d.ts +67 -0
- package/lib/llm/replay.d.ts +66 -0
- package/lib/llm/stream.d.ts +46 -0
- package/lib/media/chat.d.ts +49 -0
- package/lib/media/sources.d.ts +46 -0
- package/lib/models-CAcLevEN.js +1045 -0
- package/lib/node-Cujw_a4_.js +2403 -0
- package/lib/node-vkDR3GtK.js +25 -0
- package/lib/openai-completions-DqTCiqpS.js +983 -0
- package/lib/openai-prompt-cache-kzRZVokq.js +9567 -0
- package/lib/openai-responses-DygWnsye.js +832 -0
- package/lib/pricing.d.ts +49 -0
- package/lib/runtime.d.ts +150 -0
- package/lib/search/provider.d.ts +86 -0
- package/lib/service.d.ts +99 -0
- package/lib/tasks/remote.d.ts +47 -0
- package/lib/tasks/store.d.ts +132 -0
- package/lib/tasks/tracker.d.ts +127 -0
- package/lib/tools/account.d.ts +21 -0
- package/lib/tools/audio.d.ts +13 -0
- package/lib/tools/common.d.ts +77 -0
- package/lib/tools/image.d.ts +50 -0
- package/lib/tools/models.d.ts +13 -0
- package/lib/tools/tasks.d.ts +13 -0
- package/lib/tools/transcribe.d.ts +19 -0
- package/lib/tools/video.d.ts +48 -0
- package/lib/transform-messages-Csvf2ItW.js +1023 -0
- package/lib/util/files.d.ts +80 -0
- package/lib/video/plan.d.ts +96 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +127 -0
|
@@ -0,0 +1,1023 @@
|
|
|
1
|
+
import { u as getSystemMessageText } from "./models-CAcLevEN.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
//#region \0rolldown/runtime.js
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
6
|
+
var __exportAll = (all, no_symbols) => {
|
|
7
|
+
let target = {};
|
|
8
|
+
for (var name in all) __defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true
|
|
11
|
+
});
|
|
12
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
+
return target;
|
|
14
|
+
};
|
|
15
|
+
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region node_modules/partial-json/dist/options.js
|
|
18
|
+
var require_options = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
19
|
+
/**
|
|
20
|
+
* Sometimes you don't allow every type to be partially parsed.
|
|
21
|
+
* For example, you may not want a partial number because it may increase its size gradually before it's complete.
|
|
22
|
+
* In this case, you can use the `Allow` object to control what types you allow to be partially parsed.
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Allow = exports.ALL = exports.COLLECTION = exports.ATOM = exports.SPECIAL = exports.INF = exports._INFINITY = exports.INFINITY = exports.NAN = exports.BOOL = exports.NULL = exports.OBJ = exports.ARR = exports.NUM = exports.STR = void 0;
|
|
27
|
+
/**
|
|
28
|
+
* allow partial strings like `"hello \u12` to be parsed as `"hello "`
|
|
29
|
+
*/
|
|
30
|
+
exports.STR = 1;
|
|
31
|
+
/**
|
|
32
|
+
* allow partial numbers like `123.` to be parsed as `123`
|
|
33
|
+
*/
|
|
34
|
+
exports.NUM = 2;
|
|
35
|
+
/**
|
|
36
|
+
* allow partial arrays like `[1, 2,` to be parsed as `[1, 2]`
|
|
37
|
+
*/
|
|
38
|
+
exports.ARR = 4;
|
|
39
|
+
/**
|
|
40
|
+
* allow partial objects like `{"a": 1, "b":` to be parsed as `{"a": 1}`
|
|
41
|
+
*/
|
|
42
|
+
exports.OBJ = 8;
|
|
43
|
+
/**
|
|
44
|
+
* allow `nu` to be parsed as `null`
|
|
45
|
+
*/
|
|
46
|
+
exports.NULL = 16;
|
|
47
|
+
/**
|
|
48
|
+
* allow `tr` to be parsed as `true`, and `fa` to be parsed as `false`
|
|
49
|
+
*/
|
|
50
|
+
exports.BOOL = 32;
|
|
51
|
+
/**
|
|
52
|
+
* allow `Na` to be parsed as `NaN`
|
|
53
|
+
*/
|
|
54
|
+
exports.NAN = 64;
|
|
55
|
+
/**
|
|
56
|
+
* allow `Inf` to be parsed as `Infinity`
|
|
57
|
+
*/
|
|
58
|
+
exports.INFINITY = 128;
|
|
59
|
+
/**
|
|
60
|
+
* allow `-Inf` to be parsed as `-Infinity`
|
|
61
|
+
*/
|
|
62
|
+
exports._INFINITY = 256;
|
|
63
|
+
exports.INF = exports.INFINITY | exports._INFINITY;
|
|
64
|
+
exports.SPECIAL = exports.NULL | exports.BOOL | exports.INF | exports.NAN;
|
|
65
|
+
exports.ATOM = exports.STR | exports.NUM | exports.SPECIAL;
|
|
66
|
+
exports.COLLECTION = exports.ARR | exports.OBJ;
|
|
67
|
+
exports.ALL = exports.ATOM | exports.COLLECTION;
|
|
68
|
+
/**
|
|
69
|
+
* Control what types you allow to be partially parsed.
|
|
70
|
+
* The default is to allow all types to be partially parsed, which in most casees is the best option.
|
|
71
|
+
* @example
|
|
72
|
+
* If you don't want to allow partial objects, you can use the following code:
|
|
73
|
+
* ```ts
|
|
74
|
+
* import { Allow, parse } from "partial-json";
|
|
75
|
+
* parse(`[{"a": 1, "b": 2}, {"a": 3,`, Allow.ARR); // [ { a: 1, b: 2 } ]
|
|
76
|
+
* ```
|
|
77
|
+
* Or you can use `~` to disallow a type:
|
|
78
|
+
* ```ts
|
|
79
|
+
* parse(`[{"a": 1, "b": 2}, {"a": 3,`, ~Allow.OBJ); // [ { a: 1, b: 2 } ]
|
|
80
|
+
* ```
|
|
81
|
+
* @example
|
|
82
|
+
* If you don't want to allow partial strings, you can use the following code:
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { Allow, parse } from "partial-json";
|
|
85
|
+
* parse(`["complete string", "incompl`, ~Allow.STR); // [ 'complete string' ]
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
exports.Allow = {
|
|
89
|
+
STR: exports.STR,
|
|
90
|
+
NUM: exports.NUM,
|
|
91
|
+
ARR: exports.ARR,
|
|
92
|
+
OBJ: exports.OBJ,
|
|
93
|
+
NULL: exports.NULL,
|
|
94
|
+
BOOL: exports.BOOL,
|
|
95
|
+
NAN: exports.NAN,
|
|
96
|
+
INFINITY: exports.INFINITY,
|
|
97
|
+
_INFINITY: exports._INFINITY,
|
|
98
|
+
INF: exports.INF,
|
|
99
|
+
SPECIAL: exports.SPECIAL,
|
|
100
|
+
ATOM: exports.ATOM,
|
|
101
|
+
COLLECTION: exports.COLLECTION,
|
|
102
|
+
ALL: exports.ALL
|
|
103
|
+
};
|
|
104
|
+
exports.default = exports.Allow;
|
|
105
|
+
}));
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/json-parse.js
|
|
108
|
+
var import_dist = (/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
109
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
110
|
+
if (k2 === void 0) k2 = k;
|
|
111
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
112
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) desc = {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
get: function() {
|
|
115
|
+
return m[k];
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
Object.defineProperty(o, k2, desc);
|
|
119
|
+
}) : (function(o, m, k, k2) {
|
|
120
|
+
if (k2 === void 0) k2 = k;
|
|
121
|
+
o[k2] = m[k];
|
|
122
|
+
}));
|
|
123
|
+
var __exportStar = exports && exports.__exportStar || function(m, exports$1) {
|
|
124
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p);
|
|
125
|
+
};
|
|
126
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
127
|
+
exports.Allow = exports.MalformedJSON = exports.PartialJSON = exports.parseJSON = exports.parse = void 0;
|
|
128
|
+
const options_1 = require_options();
|
|
129
|
+
Object.defineProperty(exports, "Allow", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
get: function() {
|
|
132
|
+
return options_1.Allow;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
__exportStar(require_options(), exports);
|
|
136
|
+
var PartialJSON = class extends Error {};
|
|
137
|
+
exports.PartialJSON = PartialJSON;
|
|
138
|
+
var MalformedJSON = class extends Error {};
|
|
139
|
+
exports.MalformedJSON = MalformedJSON;
|
|
140
|
+
/**
|
|
141
|
+
* Parse incomplete JSON
|
|
142
|
+
* @param {string} jsonString Partial JSON to be parsed
|
|
143
|
+
* @param {number} allowPartial Specify what types are allowed to be partial, see {@link Allow} for details
|
|
144
|
+
* @returns The parsed JSON
|
|
145
|
+
* @throws {PartialJSON} If the JSON is incomplete (related to the `allow` parameter)
|
|
146
|
+
* @throws {MalformedJSON} If the JSON is malformed
|
|
147
|
+
*/
|
|
148
|
+
function parseJSON(jsonString, allowPartial = options_1.Allow.ALL) {
|
|
149
|
+
if (typeof jsonString !== "string") throw new TypeError(`expecting str, got ${typeof jsonString}`);
|
|
150
|
+
if (!jsonString.trim()) throw new Error(`${jsonString} is empty`);
|
|
151
|
+
return _parseJSON(jsonString.trim(), allowPartial);
|
|
152
|
+
}
|
|
153
|
+
exports.parseJSON = parseJSON;
|
|
154
|
+
const _parseJSON = (jsonString, allow) => {
|
|
155
|
+
const length = jsonString.length;
|
|
156
|
+
let index = 0;
|
|
157
|
+
const markPartialJSON = (msg) => {
|
|
158
|
+
throw new PartialJSON(`${msg} at position ${index}`);
|
|
159
|
+
};
|
|
160
|
+
const throwMalformedError = (msg) => {
|
|
161
|
+
throw new MalformedJSON(`${msg} at position ${index}`);
|
|
162
|
+
};
|
|
163
|
+
const parseAny = () => {
|
|
164
|
+
skipBlank();
|
|
165
|
+
if (index >= length) markPartialJSON("Unexpected end of input");
|
|
166
|
+
if (jsonString[index] === "\"") return parseStr();
|
|
167
|
+
if (jsonString[index] === "{") return parseObj();
|
|
168
|
+
if (jsonString[index] === "[") return parseArr();
|
|
169
|
+
if (jsonString.substring(index, index + 4) === "null" || options_1.Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index))) {
|
|
170
|
+
index += 4;
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
if (jsonString.substring(index, index + 4) === "true" || options_1.Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index))) {
|
|
174
|
+
index += 4;
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
if (jsonString.substring(index, index + 5) === "false" || options_1.Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index))) {
|
|
178
|
+
index += 5;
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (jsonString.substring(index, index + 8) === "Infinity" || options_1.Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index))) {
|
|
182
|
+
index += 8;
|
|
183
|
+
return Infinity;
|
|
184
|
+
}
|
|
185
|
+
if (jsonString.substring(index, index + 9) === "-Infinity" || options_1.Allow._INFINITY & allow && 1 < length - index && length - index < 9 && "-Infinity".startsWith(jsonString.substring(index))) {
|
|
186
|
+
index += 9;
|
|
187
|
+
return -Infinity;
|
|
188
|
+
}
|
|
189
|
+
if (jsonString.substring(index, index + 3) === "NaN" || options_1.Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index))) {
|
|
190
|
+
index += 3;
|
|
191
|
+
return NaN;
|
|
192
|
+
}
|
|
193
|
+
return parseNum();
|
|
194
|
+
};
|
|
195
|
+
const parseStr = () => {
|
|
196
|
+
const start = index;
|
|
197
|
+
let escape = false;
|
|
198
|
+
index++;
|
|
199
|
+
while (index < length && (jsonString[index] !== "\"" || escape && jsonString[index - 1] === "\\")) {
|
|
200
|
+
escape = jsonString[index] === "\\" ? !escape : false;
|
|
201
|
+
index++;
|
|
202
|
+
}
|
|
203
|
+
if (jsonString.charAt(index) == "\"") try {
|
|
204
|
+
return JSON.parse(jsonString.substring(start, ++index - Number(escape)));
|
|
205
|
+
} catch (e) {
|
|
206
|
+
throwMalformedError(String(e));
|
|
207
|
+
}
|
|
208
|
+
else if (options_1.Allow.STR & allow) try {
|
|
209
|
+
return JSON.parse(jsonString.substring(start, index - Number(escape)) + "\"");
|
|
210
|
+
} catch (e) {
|
|
211
|
+
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + "\"");
|
|
212
|
+
}
|
|
213
|
+
markPartialJSON("Unterminated string literal");
|
|
214
|
+
};
|
|
215
|
+
const parseObj = () => {
|
|
216
|
+
index++;
|
|
217
|
+
skipBlank();
|
|
218
|
+
const obj = {};
|
|
219
|
+
try {
|
|
220
|
+
while (jsonString[index] !== "}") {
|
|
221
|
+
skipBlank();
|
|
222
|
+
if (index >= length && options_1.Allow.OBJ & allow) return obj;
|
|
223
|
+
const key = parseStr();
|
|
224
|
+
skipBlank();
|
|
225
|
+
index++;
|
|
226
|
+
try {
|
|
227
|
+
obj[key] = parseAny();
|
|
228
|
+
} catch (e) {
|
|
229
|
+
if (options_1.Allow.OBJ & allow) return obj;
|
|
230
|
+
else throw e;
|
|
231
|
+
}
|
|
232
|
+
skipBlank();
|
|
233
|
+
if (jsonString[index] === ",") index++;
|
|
234
|
+
}
|
|
235
|
+
} catch (e) {
|
|
236
|
+
if (options_1.Allow.OBJ & allow) return obj;
|
|
237
|
+
else markPartialJSON("Expected '}' at end of object");
|
|
238
|
+
}
|
|
239
|
+
index++;
|
|
240
|
+
return obj;
|
|
241
|
+
};
|
|
242
|
+
const parseArr = () => {
|
|
243
|
+
index++;
|
|
244
|
+
const arr = [];
|
|
245
|
+
try {
|
|
246
|
+
while (jsonString[index] !== "]") {
|
|
247
|
+
arr.push(parseAny());
|
|
248
|
+
skipBlank();
|
|
249
|
+
if (jsonString[index] === ",") index++;
|
|
250
|
+
}
|
|
251
|
+
} catch (e) {
|
|
252
|
+
if (options_1.Allow.ARR & allow) return arr;
|
|
253
|
+
markPartialJSON("Expected ']' at end of array");
|
|
254
|
+
}
|
|
255
|
+
index++;
|
|
256
|
+
return arr;
|
|
257
|
+
};
|
|
258
|
+
const parseNum = () => {
|
|
259
|
+
if (index === 0) {
|
|
260
|
+
if (jsonString === "-") throwMalformedError("Not sure what '-' is");
|
|
261
|
+
try {
|
|
262
|
+
return JSON.parse(jsonString);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
if (options_1.Allow.NUM & allow) try {
|
|
265
|
+
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf("e")));
|
|
266
|
+
} catch (e) {}
|
|
267
|
+
throwMalformedError(String(e));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const start = index;
|
|
271
|
+
if (jsonString[index] === "-") index++;
|
|
272
|
+
while (jsonString[index] && ",]}".indexOf(jsonString[index]) === -1) index++;
|
|
273
|
+
if (index == length && !(options_1.Allow.NUM & allow)) markPartialJSON("Unterminated number literal");
|
|
274
|
+
try {
|
|
275
|
+
return JSON.parse(jsonString.substring(start, index));
|
|
276
|
+
} catch (e) {
|
|
277
|
+
if (jsonString.substring(start, index) === "-") markPartialJSON("Not sure what '-' is");
|
|
278
|
+
try {
|
|
279
|
+
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("e")));
|
|
280
|
+
} catch (e) {
|
|
281
|
+
throwMalformedError(String(e));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
const skipBlank = () => {
|
|
286
|
+
while (index < length && " \n\r ".includes(jsonString[index])) index++;
|
|
287
|
+
};
|
|
288
|
+
return parseAny();
|
|
289
|
+
};
|
|
290
|
+
exports.parse = parseJSON;
|
|
291
|
+
})))();
|
|
292
|
+
const VALID_JSON_ESCAPES = /* @__PURE__ */ new Set([
|
|
293
|
+
"\"",
|
|
294
|
+
"\\",
|
|
295
|
+
"/",
|
|
296
|
+
"b",
|
|
297
|
+
"f",
|
|
298
|
+
"n",
|
|
299
|
+
"r",
|
|
300
|
+
"t",
|
|
301
|
+
"u"
|
|
302
|
+
]);
|
|
303
|
+
function isControlCharacter(char) {
|
|
304
|
+
const codePoint = char.codePointAt(0);
|
|
305
|
+
return codePoint !== void 0 && codePoint >= 0 && codePoint <= 31;
|
|
306
|
+
}
|
|
307
|
+
function escapeControlCharacter(char) {
|
|
308
|
+
switch (char) {
|
|
309
|
+
case "\b": return "\\b";
|
|
310
|
+
case "\f": return "\\f";
|
|
311
|
+
case "\n": return "\\n";
|
|
312
|
+
case "\r": return "\\r";
|
|
313
|
+
case " ": return "\\t";
|
|
314
|
+
default: return `\\u${char.codePointAt(0)?.toString(16).padStart(4, "0") ?? "0000"}`;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Repairs malformed JSON string literals by:
|
|
319
|
+
* - escaping raw control characters inside strings
|
|
320
|
+
* - doubling backslashes before invalid escape characters
|
|
321
|
+
*/
|
|
322
|
+
function repairJson(json) {
|
|
323
|
+
let repaired = "";
|
|
324
|
+
let inString = false;
|
|
325
|
+
for (let index = 0; index < json.length; index++) {
|
|
326
|
+
const char = json[index];
|
|
327
|
+
if (!inString) {
|
|
328
|
+
repaired += char;
|
|
329
|
+
if (char === "\"") inString = true;
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (char === "\"") {
|
|
333
|
+
repaired += char;
|
|
334
|
+
inString = false;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (char === "\\") {
|
|
338
|
+
const nextChar = json[index + 1];
|
|
339
|
+
if (nextChar === void 0) {
|
|
340
|
+
repaired += "\\\\";
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (nextChar === "u") {
|
|
344
|
+
const unicodeDigits = json.slice(index + 2, index + 6);
|
|
345
|
+
if (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {
|
|
346
|
+
repaired += `\\u${unicodeDigits}`;
|
|
347
|
+
index += 5;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (VALID_JSON_ESCAPES.has(nextChar)) {
|
|
352
|
+
repaired += `\\${nextChar}`;
|
|
353
|
+
index += 1;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
repaired += "\\\\";
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
repaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;
|
|
360
|
+
}
|
|
361
|
+
return repaired;
|
|
362
|
+
}
|
|
363
|
+
function parseJsonWithRepair(json) {
|
|
364
|
+
try {
|
|
365
|
+
return JSON.parse(json);
|
|
366
|
+
} catch (error) {
|
|
367
|
+
const repairedJson = repairJson(json);
|
|
368
|
+
if (repairedJson !== json) return JSON.parse(repairedJson);
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Attempts to parse potentially incomplete JSON during streaming.
|
|
374
|
+
* Always returns a valid object, even if the JSON is incomplete.
|
|
375
|
+
*
|
|
376
|
+
* @param partialJson The partial JSON string from streaming
|
|
377
|
+
* @returns Parsed object or empty object if parsing fails
|
|
378
|
+
*/
|
|
379
|
+
function parseStreamingJson(partialJson) {
|
|
380
|
+
if (!partialJson || partialJson.trim() === "") return {};
|
|
381
|
+
try {
|
|
382
|
+
return parseJsonWithRepair(partialJson);
|
|
383
|
+
} catch {
|
|
384
|
+
try {
|
|
385
|
+
return (0, import_dist.parse)(partialJson) ?? {};
|
|
386
|
+
} catch {
|
|
387
|
+
try {
|
|
388
|
+
return (0, import_dist.parse)(repairJson(partialJson)) ?? {};
|
|
389
|
+
} catch {
|
|
390
|
+
return {};
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
396
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/headers.js
|
|
397
|
+
function headersToRecord(headers) {
|
|
398
|
+
const result = {};
|
|
399
|
+
for (const [key, value] of headers.entries()) result[key] = value;
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/pi-user-agent.js
|
|
404
|
+
function loadNodeOs() {
|
|
405
|
+
if (typeof process === "undefined" || !(process.versions?.node || process.versions?.bun)) return null;
|
|
406
|
+
return process.getBuiltinModule?.("node:os") ?? null;
|
|
407
|
+
}
|
|
408
|
+
const nodeOs = loadNodeOs();
|
|
409
|
+
function getPiUserAgent() {
|
|
410
|
+
return nodeOs ? `pi (${nodeOs.platform()} ${nodeOs.release()}; ${nodeOs.arch()})` : "pi (browser)";
|
|
411
|
+
}
|
|
412
|
+
//#endregion
|
|
413
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/provider-env.js
|
|
414
|
+
let procEnvCache = null;
|
|
415
|
+
/**
|
|
416
|
+
* Fallback for https://github.com/oven-sh/bun/issues/27802.
|
|
417
|
+
* Bun compiled binaries can expose an empty process.env inside Linux sandboxes
|
|
418
|
+
* even though /proc/self/environ contains the environment.
|
|
419
|
+
*
|
|
420
|
+
* This intentionally duplicates restoreSandboxEnv() in
|
|
421
|
+
* packages/coding-agent/src/bun/restore-sandbox-env.ts. The ai package can be
|
|
422
|
+
* used directly, without going through that entrypoint, so provider env lookup
|
|
423
|
+
* must not depend on process.env having been patched.
|
|
424
|
+
*/
|
|
425
|
+
function getBunSandboxEnvValue(name) {
|
|
426
|
+
if (typeof process === "undefined" || !process.versions?.bun || Object.keys(process.env).length > 0) return;
|
|
427
|
+
if (procEnvCache === null) {
|
|
428
|
+
procEnvCache = /* @__PURE__ */ new Map();
|
|
429
|
+
try {
|
|
430
|
+
const { readFileSync } = __require("node:fs");
|
|
431
|
+
const data = readFileSync("/proc/self/environ", "utf-8");
|
|
432
|
+
for (const entry of data.split("\0")) {
|
|
433
|
+
const idx = entry.indexOf("=");
|
|
434
|
+
if (idx > 0) procEnvCache.set(entry.slice(0, idx), entry.slice(idx + 1));
|
|
435
|
+
}
|
|
436
|
+
} catch {}
|
|
437
|
+
}
|
|
438
|
+
return procEnvCache.get(name);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Resolve a provider env value from scoped overrides, normal process.env, then
|
|
442
|
+
* the duplicated Bun sandbox fallback for direct pi-ai consumers.
|
|
443
|
+
*/
|
|
444
|
+
function getProviderEnvValue(name, env) {
|
|
445
|
+
return env?.[name] || (typeof process !== "undefined" ? process.env[name] : void 0) || getBunSandboxEnvValue(name) || void 0;
|
|
446
|
+
}
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/provider-retry.js
|
|
449
|
+
const DEFAULT_MAX_RETRY_DELAY_MS = 6e4;
|
|
450
|
+
function isProviderError(error) {
|
|
451
|
+
if (!(error instanceof Error) || !("status" in error) || !("headers" in error)) return false;
|
|
452
|
+
return (error.status === void 0 || typeof error.status === "number") && (error.headers === void 0 || error.headers instanceof Headers);
|
|
453
|
+
}
|
|
454
|
+
/** Mirrors the pinned OpenAI/Anthropic SDK retry policy; review when either SDK is upgraded. */
|
|
455
|
+
function isRetryableProviderError(error) {
|
|
456
|
+
const shouldRetry = error.headers?.get("x-should-retry");
|
|
457
|
+
if (shouldRetry === "true") return true;
|
|
458
|
+
if (shouldRetry === "false") return false;
|
|
459
|
+
if (error.status === void 0) return true;
|
|
460
|
+
return error.status === 408 || error.status === 409 || error.status === 429 || typeof error.status === "number" && error.status >= 500;
|
|
461
|
+
}
|
|
462
|
+
function validateServerRetryDelayMs(delayMs, maxRetryDelayMs, providerErrorMessage) {
|
|
463
|
+
const maxDelayMs = maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
464
|
+
if (maxDelayMs > 0 && delayMs > maxDelayMs) throw new Error(`Server requested ${Math.ceil(delayMs / 1e3)}s retry delay (max: ${Math.ceil(maxDelayMs / 1e3)}s). ${providerErrorMessage}`);
|
|
465
|
+
return delayMs;
|
|
466
|
+
}
|
|
467
|
+
function getRetryDelayMs(error, retryIndex, maxRetryDelayMs) {
|
|
468
|
+
const retryAfterMs = error.headers?.get("retry-after-ms");
|
|
469
|
+
if (retryAfterMs) {
|
|
470
|
+
const value = Number.parseFloat(retryAfterMs);
|
|
471
|
+
if (!Number.isNaN(value)) return validateServerRetryDelayMs(value, maxRetryDelayMs, error.message);
|
|
472
|
+
}
|
|
473
|
+
const retryAfter = error.headers?.get("retry-after");
|
|
474
|
+
if (retryAfter) {
|
|
475
|
+
const seconds = Number.parseFloat(retryAfter);
|
|
476
|
+
return validateServerRetryDelayMs(Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1e3, maxRetryDelayMs, error.message);
|
|
477
|
+
}
|
|
478
|
+
return Math.min(.5 * 2 ** retryIndex, 8) * 1e3 * (1 - Math.random() * .25);
|
|
479
|
+
}
|
|
480
|
+
function createAbortError() {
|
|
481
|
+
const error = /* @__PURE__ */ new Error("Request aborted");
|
|
482
|
+
error.name = "AbortError";
|
|
483
|
+
return error;
|
|
484
|
+
}
|
|
485
|
+
function abortableSleep(ms, signal) {
|
|
486
|
+
return new Promise((resolve, reject) => {
|
|
487
|
+
if (signal?.aborted) {
|
|
488
|
+
reject(createAbortError());
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const onAbort = () => {
|
|
492
|
+
clearTimeout(timeout);
|
|
493
|
+
reject(createAbortError());
|
|
494
|
+
};
|
|
495
|
+
const timeout = setTimeout(() => {
|
|
496
|
+
signal?.removeEventListener("abort", onAbort);
|
|
497
|
+
resolve();
|
|
498
|
+
}, Math.max(0, ms));
|
|
499
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Reproduce the retry behavior used by the OpenAI and Anthropic SDKs while making
|
|
504
|
+
* their backoff sleep interruptible. Their built-in retry timers ignore the
|
|
505
|
+
* request AbortSignal, so callers must invoke the SDK with `maxRetries: 0` and
|
|
506
|
+
* wrap the request with this helper. Provider-requested delays above
|
|
507
|
+
* `maxRetryDelayMs` fail immediately (60 seconds by default); set it to zero to
|
|
508
|
+
* disable the limit.
|
|
509
|
+
*/
|
|
510
|
+
async function retryProviderRequest(request, options = {}) {
|
|
511
|
+
const maxRetries = options.maxRetries ?? 0;
|
|
512
|
+
let retriesRemaining = maxRetries;
|
|
513
|
+
for (;;) try {
|
|
514
|
+
return await request();
|
|
515
|
+
} catch (error) {
|
|
516
|
+
if (options.signal?.aborted) throw createAbortError();
|
|
517
|
+
if (retriesRemaining <= 0 || !isProviderError(error) || !isRetryableProviderError(error)) throw error;
|
|
518
|
+
const retryIndex = maxRetries - retriesRemaining;
|
|
519
|
+
retriesRemaining--;
|
|
520
|
+
await abortableSleep(getRetryDelayMs(error, retryIndex, options.maxRetryDelayMs), options.signal);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
//#endregion
|
|
524
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js
|
|
525
|
+
/**
|
|
526
|
+
* Removes unpaired Unicode surrogate characters from a string.
|
|
527
|
+
*
|
|
528
|
+
* Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
|
|
529
|
+
* or vice versa) cause JSON serialization errors in many API providers.
|
|
530
|
+
*
|
|
531
|
+
* Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
|
|
532
|
+
* surrogates and will NOT be affected by this function.
|
|
533
|
+
*
|
|
534
|
+
* @param text - The text to sanitize
|
|
535
|
+
* @returns The sanitized text with unpaired surrogates removed
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* // Valid emoji (properly paired surrogates) are preserved
|
|
539
|
+
* sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
|
|
540
|
+
*
|
|
541
|
+
* // Unpaired high surrogate is removed
|
|
542
|
+
* const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
|
|
543
|
+
* sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
|
|
544
|
+
*/
|
|
545
|
+
function sanitizeSurrogates(text) {
|
|
546
|
+
return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
|
|
547
|
+
}
|
|
548
|
+
//#endregion
|
|
549
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js
|
|
550
|
+
var UnsupportedStrictJsonSchemaError = class extends Error {};
|
|
551
|
+
const UNSUPPORTED_STRICT_SCHEMA_KEYS = [
|
|
552
|
+
"$ref",
|
|
553
|
+
"$defs",
|
|
554
|
+
"definitions",
|
|
555
|
+
"allOf",
|
|
556
|
+
"oneOf",
|
|
557
|
+
"patternProperties",
|
|
558
|
+
"dependentSchemas",
|
|
559
|
+
"dependencies",
|
|
560
|
+
"unevaluatedProperties",
|
|
561
|
+
"propertyNames",
|
|
562
|
+
"contains",
|
|
563
|
+
"prefixItems",
|
|
564
|
+
"not",
|
|
565
|
+
"if",
|
|
566
|
+
"then",
|
|
567
|
+
"else"
|
|
568
|
+
];
|
|
569
|
+
function isJsonSchemaObject(value) {
|
|
570
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
571
|
+
}
|
|
572
|
+
function isStructuredSchema(schema) {
|
|
573
|
+
if (!isJsonSchemaObject(schema)) return false;
|
|
574
|
+
const types = typeof schema.type === "string" ? [schema.type] : Array.isArray(schema.type) ? schema.type : [];
|
|
575
|
+
return types.includes("object") || types.includes("array") || schema.properties !== void 0 || schema.items !== void 0;
|
|
576
|
+
}
|
|
577
|
+
function schemaAllowsNull(schema) {
|
|
578
|
+
if (!isJsonSchemaObject(schema)) return false;
|
|
579
|
+
if (schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null")) return true;
|
|
580
|
+
if (schema.const === null || Array.isArray(schema.enum) && schema.enum.includes(null)) return true;
|
|
581
|
+
return Array.isArray(schema.anyOf) && schema.anyOf.some((variant) => schemaAllowsNull(variant));
|
|
582
|
+
}
|
|
583
|
+
function makeJsonSchemaNodeStrict(schema) {
|
|
584
|
+
if (!isJsonSchemaObject(schema)) throw new UnsupportedStrictJsonSchemaError("boolean schemas are unsupported");
|
|
585
|
+
for (const key of UNSUPPORTED_STRICT_SCHEMA_KEYS) if (schema[key] !== void 0) throw new UnsupportedStrictJsonSchemaError(`${key} schemas are unsupported`);
|
|
586
|
+
if (schema.anyOf !== void 0) {
|
|
587
|
+
if (!Array.isArray(schema.anyOf) || schema.anyOf.length === 0) throw new UnsupportedStrictJsonSchemaError("anyOf must contain at least one schema");
|
|
588
|
+
for (const variant of schema.anyOf) {
|
|
589
|
+
if (isStructuredSchema(variant)) throw new UnsupportedStrictJsonSchemaError("object and array unions are unsupported");
|
|
590
|
+
makeJsonSchemaNodeStrict(variant);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (schema.items !== void 0) {
|
|
594
|
+
if (Array.isArray(schema.items)) throw new UnsupportedStrictJsonSchemaError("tuple schemas are unsupported");
|
|
595
|
+
makeJsonSchemaNodeStrict(schema.items);
|
|
596
|
+
}
|
|
597
|
+
const isObjectSchema = schema.type === "object";
|
|
598
|
+
if (schema.properties !== void 0 && !isObjectSchema) throw new UnsupportedStrictJsonSchemaError("properties require type object");
|
|
599
|
+
if (!isObjectSchema) return;
|
|
600
|
+
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) throw new UnsupportedStrictJsonSchemaError("schema-valued or true additionalProperties is unsupported");
|
|
601
|
+
if (schema.properties !== void 0 && !isJsonSchemaObject(schema.properties)) throw new UnsupportedStrictJsonSchemaError("object properties must be a schema map");
|
|
602
|
+
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");
|
|
603
|
+
const properties = schema.properties ?? {};
|
|
604
|
+
const propertyNames = Object.keys(properties);
|
|
605
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
606
|
+
if ([...required].some((key) => !propertyNames.includes(key))) throw new UnsupportedStrictJsonSchemaError("required contains an unknown property");
|
|
607
|
+
for (const [key, property] of Object.entries(properties)) {
|
|
608
|
+
makeJsonSchemaNodeStrict(property);
|
|
609
|
+
if (!required.has(key) && !schemaAllowsNull(property)) properties[key] = { anyOf: [property, { type: "null" }] };
|
|
610
|
+
}
|
|
611
|
+
schema.required = propertyNames;
|
|
612
|
+
schema.additionalProperties = false;
|
|
613
|
+
}
|
|
614
|
+
/** Convert a tool schema to the strict subset expected by provider constrained sampling. */
|
|
615
|
+
function makeStrictJsonSchema(schema) {
|
|
616
|
+
const cloned = structuredClone(schema);
|
|
617
|
+
if (!isJsonSchemaObject(cloned)) throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
618
|
+
makeJsonSchemaNodeStrict(cloned);
|
|
619
|
+
if (cloned.type !== "object") throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
|
|
620
|
+
return cloned;
|
|
621
|
+
}
|
|
622
|
+
function getJsonSchemaToolParameters(tool, strict) {
|
|
623
|
+
return strict === true ? makeStrictJsonSchema(tool.parameters) : tool.parameters;
|
|
624
|
+
}
|
|
625
|
+
function getGrammarToolInput(toolName, arguments_, inputProperty) {
|
|
626
|
+
const input = arguments_[inputProperty];
|
|
627
|
+
if (typeof input !== "string") throw new Error(`Grammar tool call "${toolName}" requires argument "${inputProperty}" to be a string.`);
|
|
628
|
+
return input;
|
|
629
|
+
}
|
|
630
|
+
function appendGrammarToolInputJsonDelta(buffer, inputProperty, nextInput, close) {
|
|
631
|
+
if (buffer.closed) {
|
|
632
|
+
if (close && nextInput === buffer.input) return void 0;
|
|
633
|
+
throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
|
|
634
|
+
}
|
|
635
|
+
if (!nextInput.startsWith(buffer.input)) throw new Error(`grammar tool input for property "${inputProperty}" changed non-monotonically`);
|
|
636
|
+
const inputDelta = nextInput.slice(buffer.input.length);
|
|
637
|
+
if (!close && inputDelta.length === 0) return void 0;
|
|
638
|
+
let delta = "";
|
|
639
|
+
if (!buffer.started) {
|
|
640
|
+
delta += `{${JSON.stringify(inputProperty)}:"`;
|
|
641
|
+
buffer.started = true;
|
|
642
|
+
}
|
|
643
|
+
delta += JSON.stringify(inputDelta).slice(1, -1);
|
|
644
|
+
buffer.input = nextInput;
|
|
645
|
+
if (close) {
|
|
646
|
+
delta += "\"}";
|
|
647
|
+
buffer.closed = true;
|
|
648
|
+
}
|
|
649
|
+
return delta;
|
|
650
|
+
}
|
|
651
|
+
function inferGrammarInputProperty(tool) {
|
|
652
|
+
const schema = tool.parameters;
|
|
653
|
+
if (schema.type !== "object") throw new Error("grammar constrained sampling requires an object parameter schema");
|
|
654
|
+
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");
|
|
655
|
+
const inputProperty = schema.required[0];
|
|
656
|
+
if (!schema.properties?.[inputProperty]) throw new Error(`grammar constrained sampling requires a properties entry for ${inputProperty}`);
|
|
657
|
+
if (schema.properties[inputProperty]?.type !== "string") throw new Error(`grammar constrained sampling property ${inputProperty} must have type string`);
|
|
658
|
+
return inputProperty;
|
|
659
|
+
}
|
|
660
|
+
function resolveJsonSchemaStrictSampling(tool, supportsStrictMode) {
|
|
661
|
+
const config = tool.constrainedSampling;
|
|
662
|
+
if (!config || config.type !== "json_schema") return void 0;
|
|
663
|
+
if (supportsStrictMode) try {
|
|
664
|
+
makeStrictJsonSchema(tool.parameters);
|
|
665
|
+
return true;
|
|
666
|
+
} catch (error) {
|
|
667
|
+
if (!(error instanceof UnsupportedStrictJsonSchemaError)) throw error;
|
|
668
|
+
if (config.strict !== "require") return void 0;
|
|
669
|
+
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but ${error.message}.`);
|
|
670
|
+
}
|
|
671
|
+
if (config.strict === "require") throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but strict tools are unsupported.`);
|
|
672
|
+
}
|
|
673
|
+
function resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools) {
|
|
674
|
+
const config = tool.constrainedSampling;
|
|
675
|
+
if (!config || config.type !== "grammar") return;
|
|
676
|
+
if (!supportsOpenAIGrammarTools) return;
|
|
677
|
+
const larkDefinition = config.variants.openai_lark;
|
|
678
|
+
const regexDefinition = config.variants.openai_regex;
|
|
679
|
+
const hasLarkDefinition = typeof larkDefinition === "string" && larkDefinition.trim().length > 0;
|
|
680
|
+
const hasRegexDefinition = typeof regexDefinition === "string" && regexDefinition.trim().length > 0;
|
|
681
|
+
if (!hasLarkDefinition && !hasRegexDefinition) throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: no supported grammar variant was provided.`);
|
|
682
|
+
try {
|
|
683
|
+
return {
|
|
684
|
+
format: hasLarkDefinition ? "lark" : "regex",
|
|
685
|
+
definition: hasLarkDefinition ? larkDefinition : regexDefinition,
|
|
686
|
+
inputProperty: inferGrammarInputProperty(tool)
|
|
687
|
+
};
|
|
688
|
+
} catch (error) {
|
|
689
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
690
|
+
throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: ${message}.`);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function createGrammarToolInputProperties(tools, supportsOpenAIGrammarTools) {
|
|
694
|
+
const properties = /* @__PURE__ */ new Map();
|
|
695
|
+
for (const tool of tools ?? []) {
|
|
696
|
+
const grammar = resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools);
|
|
697
|
+
if (grammar) properties.set(tool.name, grammar.inputProperty);
|
|
698
|
+
}
|
|
699
|
+
return properties;
|
|
700
|
+
}
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js
|
|
703
|
+
function inferCopilotInitiator(messages) {
|
|
704
|
+
const last = messages[messages.length - 1];
|
|
705
|
+
return last && last.role !== "user" ? "agent" : "user";
|
|
706
|
+
}
|
|
707
|
+
function hasCopilotVisionInput(messages) {
|
|
708
|
+
return messages.some((msg) => {
|
|
709
|
+
if (msg.role === "user" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
|
|
710
|
+
if (msg.role === "toolResult" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
|
|
711
|
+
return false;
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
function buildCopilotDynamicHeaders(params) {
|
|
715
|
+
const headers = {
|
|
716
|
+
"X-Initiator": inferCopilotInitiator(params.messages),
|
|
717
|
+
"Openai-Intent": "conversation-edits"
|
|
718
|
+
};
|
|
719
|
+
if (params.hasImages) headers["Copilot-Vision-Request"] = "true";
|
|
720
|
+
return headers;
|
|
721
|
+
}
|
|
722
|
+
//#endregion
|
|
723
|
+
//#region node_modules/@earendil-works/pi-ai/dist/utils/estimate.js
|
|
724
|
+
const CHARS_PER_TOKEN = 4;
|
|
725
|
+
const ESTIMATED_IMAGE_CHARS = 4800;
|
|
726
|
+
function calculateContextTokens(usage) {
|
|
727
|
+
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
728
|
+
}
|
|
729
|
+
function safeJsonStringify(value) {
|
|
730
|
+
try {
|
|
731
|
+
return JSON.stringify(value) ?? "undefined";
|
|
732
|
+
} catch {
|
|
733
|
+
return "[unserializable]";
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
function estimateTextAndImageContentChars(content) {
|
|
737
|
+
if (typeof content === "string") return content.length;
|
|
738
|
+
let chars = 0;
|
|
739
|
+
for (const block of content) chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
|
|
740
|
+
return chars;
|
|
741
|
+
}
|
|
742
|
+
function estimateTextTokens(text) {
|
|
743
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
744
|
+
}
|
|
745
|
+
function estimateTextAndImageContentTokens(content) {
|
|
746
|
+
return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
|
|
747
|
+
}
|
|
748
|
+
function estimateMessageTokens(message) {
|
|
749
|
+
let chars = 0;
|
|
750
|
+
if (message.role === "system") return estimateTextTokens(getSystemMessageText(message)) + estimateToolsTokens(message.toolsAdded) + estimateToolsTokens(message.toolsRemoved);
|
|
751
|
+
if (message.role === "user") return estimateTextAndImageContentTokens(message.content);
|
|
752
|
+
if (message.role === "toolResult") return estimateTextAndImageContentTokens(message.content);
|
|
753
|
+
for (const block of message.content) if (block.type === "text") chars += block.text.length;
|
|
754
|
+
else if (block.type === "thinking") chars += block.thinking.length;
|
|
755
|
+
else chars += block.name.length + safeJsonStringify(block.arguments).length;
|
|
756
|
+
return Math.ceil(chars / CHARS_PER_TOKEN);
|
|
757
|
+
}
|
|
758
|
+
function getLastAssistantUsageInfo(messages) {
|
|
759
|
+
let latestPrefixTimestamp = Number.NEGATIVE_INFINITY;
|
|
760
|
+
let usageInfo;
|
|
761
|
+
for (let i = 0; i < messages.length; i++) {
|
|
762
|
+
const message = messages[i];
|
|
763
|
+
if (message.role === "assistant") {
|
|
764
|
+
const assistant = message;
|
|
765
|
+
if (assistant.timestamp >= latestPrefixTimestamp && assistant.stopReason !== "aborted" && assistant.stopReason !== "error" && calculateContextTokens(assistant.usage) > 0) usageInfo = {
|
|
766
|
+
usage: assistant.usage,
|
|
767
|
+
index: i
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
|
|
771
|
+
}
|
|
772
|
+
return usageInfo;
|
|
773
|
+
}
|
|
774
|
+
function estimateContextTokens(context) {
|
|
775
|
+
const messages = "messages" in context ? context.messages : context;
|
|
776
|
+
const usageInfo = getLastAssistantUsageInfo(messages);
|
|
777
|
+
if (usageInfo) {
|
|
778
|
+
const usageTokens = calculateContextTokens(usageInfo.usage);
|
|
779
|
+
let trailingTokens = 0;
|
|
780
|
+
for (let i = usageInfo.index + 1; i < messages.length; i++) trailingTokens += estimateMessageTokens(messages[i]);
|
|
781
|
+
return {
|
|
782
|
+
tokens: usageTokens + trailingTokens,
|
|
783
|
+
usageTokens,
|
|
784
|
+
trailingTokens,
|
|
785
|
+
lastUsageIndex: usageInfo.index
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
let tokens = 0;
|
|
789
|
+
for (const message of messages) tokens += estimateMessageTokens(message);
|
|
790
|
+
return {
|
|
791
|
+
tokens,
|
|
792
|
+
usageTokens: 0,
|
|
793
|
+
trailingTokens: tokens,
|
|
794
|
+
lastUsageIndex: null
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function estimateToolsTokens(tools) {
|
|
798
|
+
if (!tools || tools.length === 0) return 0;
|
|
799
|
+
return estimateTextTokens(safeJsonStringify(tools));
|
|
800
|
+
}
|
|
801
|
+
//#endregion
|
|
802
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/simple-options.js
|
|
803
|
+
const CONTEXT_SAFETY_TOKENS = 4096;
|
|
804
|
+
const MIN_MAX_TOKENS = 1;
|
|
805
|
+
function clampMaxTokensToContext(model, context, maxTokens) {
|
|
806
|
+
if (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);
|
|
807
|
+
const available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;
|
|
808
|
+
return Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));
|
|
809
|
+
}
|
|
810
|
+
function buildBaseOptions(model, context, options, apiKey) {
|
|
811
|
+
const samplingParams = model.samplingParams || options?.samplingParams ? {
|
|
812
|
+
...model.samplingParams,
|
|
813
|
+
...options?.samplingParams
|
|
814
|
+
} : void 0;
|
|
815
|
+
return {
|
|
816
|
+
temperature: options?.temperature,
|
|
817
|
+
samplingParams,
|
|
818
|
+
maxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),
|
|
819
|
+
signal: options?.signal,
|
|
820
|
+
telemetryContext: options?.telemetryContext,
|
|
821
|
+
apiKey: apiKey || options?.apiKey,
|
|
822
|
+
fetch: options?.fetch,
|
|
823
|
+
transport: options?.transport,
|
|
824
|
+
cacheRetention: options?.cacheRetention,
|
|
825
|
+
sessionId: options?.sessionId,
|
|
826
|
+
headers: options?.headers,
|
|
827
|
+
onPayload: options?.onPayload,
|
|
828
|
+
onResponse: options?.onResponse,
|
|
829
|
+
timeoutMs: options?.timeoutMs,
|
|
830
|
+
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
|
|
831
|
+
maxRetries: options?.maxRetries,
|
|
832
|
+
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
833
|
+
metadata: options?.metadata,
|
|
834
|
+
env: options?.env
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
/** Tokens always left for the answer when a thinking budget shares the response ceiling. */
|
|
838
|
+
const MIN_ANSWER_TOKENS = 1024;
|
|
839
|
+
const DEFAULT_THINKING_BUDGETS = {
|
|
840
|
+
minimal: 1024,
|
|
841
|
+
low: 2048,
|
|
842
|
+
medium: 8192,
|
|
843
|
+
high: 16384
|
|
844
|
+
};
|
|
845
|
+
function clampReasoning(effort) {
|
|
846
|
+
return effort === "xhigh" || effort === "max" ? "high" : effort;
|
|
847
|
+
}
|
|
848
|
+
function thinkingBudgetForLevel(reasoningLevel, customBudgets) {
|
|
849
|
+
return {
|
|
850
|
+
...DEFAULT_THINKING_BUDGETS,
|
|
851
|
+
...customBudgets
|
|
852
|
+
}[clampReasoning(reasoningLevel)];
|
|
853
|
+
}
|
|
854
|
+
/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */
|
|
855
|
+
function clampThinkingBudgetToAnswerRoom(thinkingBudget, ceiling) {
|
|
856
|
+
return Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));
|
|
857
|
+
}
|
|
858
|
+
function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
|
|
859
|
+
let thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);
|
|
860
|
+
const maxTokens = baseMaxTokens === void 0 ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
|
|
861
|
+
if (maxTokens <= thinkingBudget) thinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);
|
|
862
|
+
return {
|
|
863
|
+
maxTokens,
|
|
864
|
+
thinkingBudget
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
//#endregion
|
|
868
|
+
//#region node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js
|
|
869
|
+
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
870
|
+
const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
|
|
871
|
+
function replaceImagesWithPlaceholder(content, placeholder) {
|
|
872
|
+
const result = [];
|
|
873
|
+
let previousWasPlaceholder = false;
|
|
874
|
+
for (const block of content) {
|
|
875
|
+
if (block.type === "image") {
|
|
876
|
+
if (!previousWasPlaceholder) result.push({
|
|
877
|
+
type: "text",
|
|
878
|
+
text: placeholder
|
|
879
|
+
});
|
|
880
|
+
previousWasPlaceholder = true;
|
|
881
|
+
continue;
|
|
882
|
+
}
|
|
883
|
+
result.push(block);
|
|
884
|
+
previousWasPlaceholder = block.text === placeholder;
|
|
885
|
+
}
|
|
886
|
+
return result;
|
|
887
|
+
}
|
|
888
|
+
function downgradeUnsupportedImages(messages, model) {
|
|
889
|
+
if (model.input.includes("image")) return messages;
|
|
890
|
+
return messages.map((msg) => {
|
|
891
|
+
if (msg.role === "user" && Array.isArray(msg.content)) return {
|
|
892
|
+
...msg,
|
|
893
|
+
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
|
|
894
|
+
};
|
|
895
|
+
if (msg.role === "toolResult") return {
|
|
896
|
+
...msg,
|
|
897
|
+
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
|
|
898
|
+
};
|
|
899
|
+
return msg;
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Normalize tool call ID for cross-provider compatibility.
|
|
904
|
+
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
|
905
|
+
* Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
|
|
906
|
+
*/
|
|
907
|
+
function transformMessages(messages, model, normalizeToolCallId) {
|
|
908
|
+
const toolCallIdMap = /* @__PURE__ */ new Map();
|
|
909
|
+
const transformed = downgradeUnsupportedImages(messages.map((msg) => msg.content == null ? {
|
|
910
|
+
...msg,
|
|
911
|
+
content: []
|
|
912
|
+
} : msg), model).map((msg) => {
|
|
913
|
+
if (msg.role === "system" || msg.role === "user") return msg;
|
|
914
|
+
if (msg.role === "toolResult") {
|
|
915
|
+
const normalizedId = toolCallIdMap.get(msg.toolCallId);
|
|
916
|
+
if (normalizedId && normalizedId !== msg.toolCallId) return {
|
|
917
|
+
...msg,
|
|
918
|
+
toolCallId: normalizedId
|
|
919
|
+
};
|
|
920
|
+
return msg;
|
|
921
|
+
}
|
|
922
|
+
if (msg.role === "assistant") {
|
|
923
|
+
const assistantMsg = msg;
|
|
924
|
+
const isSameModel = assistantMsg.provider === model.provider && assistantMsg.api === model.api && assistantMsg.model === model.id;
|
|
925
|
+
const transformedContent = assistantMsg.content.flatMap((block) => {
|
|
926
|
+
if (block.type === "thinking") {
|
|
927
|
+
if (block.redacted) return isSameModel ? block : [];
|
|
928
|
+
if (isSameModel && block.thinkingSignature) return block;
|
|
929
|
+
if (!block.thinking || block.thinking.trim() === "") return [];
|
|
930
|
+
if (isSameModel) return block;
|
|
931
|
+
return {
|
|
932
|
+
type: "text",
|
|
933
|
+
text: block.thinking
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
if (block.type === "text") {
|
|
937
|
+
if (isSameModel) return block;
|
|
938
|
+
return {
|
|
939
|
+
type: "text",
|
|
940
|
+
text: block.text
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
if (block.type === "toolCall") {
|
|
944
|
+
const toolCall = block;
|
|
945
|
+
let normalizedToolCall = toolCall;
|
|
946
|
+
if (!isSameModel && toolCall.thoughtSignature) {
|
|
947
|
+
normalizedToolCall = { ...toolCall };
|
|
948
|
+
delete normalizedToolCall.thoughtSignature;
|
|
949
|
+
}
|
|
950
|
+
if (!isSameModel && normalizeToolCallId) {
|
|
951
|
+
const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
|
|
952
|
+
if (normalizedId !== toolCall.id) {
|
|
953
|
+
toolCallIdMap.set(toolCall.id, normalizedId);
|
|
954
|
+
normalizedToolCall = {
|
|
955
|
+
...normalizedToolCall,
|
|
956
|
+
id: normalizedId
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
return normalizedToolCall;
|
|
961
|
+
}
|
|
962
|
+
return block;
|
|
963
|
+
});
|
|
964
|
+
return {
|
|
965
|
+
...assistantMsg,
|
|
966
|
+
content: transformedContent
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
return msg;
|
|
970
|
+
});
|
|
971
|
+
const result = [];
|
|
972
|
+
let pendingToolCalls = [];
|
|
973
|
+
let existingToolResultIds = /* @__PURE__ */ new Set();
|
|
974
|
+
const heldSystemMessages = [];
|
|
975
|
+
const closePendingToolCalls = () => {
|
|
976
|
+
if (pendingToolCalls.length > 0) {
|
|
977
|
+
for (const tc of pendingToolCalls) if (!existingToolResultIds.has(tc.id)) result.push({
|
|
978
|
+
role: "toolResult",
|
|
979
|
+
toolCallId: tc.id,
|
|
980
|
+
toolName: tc.name,
|
|
981
|
+
content: [{
|
|
982
|
+
type: "text",
|
|
983
|
+
text: "No result provided"
|
|
984
|
+
}],
|
|
985
|
+
isError: true,
|
|
986
|
+
timestamp: Date.now()
|
|
987
|
+
});
|
|
988
|
+
pendingToolCalls = [];
|
|
989
|
+
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
990
|
+
}
|
|
991
|
+
result.push(...heldSystemMessages);
|
|
992
|
+
heldSystemMessages.length = 0;
|
|
993
|
+
};
|
|
994
|
+
for (let i = 0; i < transformed.length; i++) {
|
|
995
|
+
const msg = transformed[i];
|
|
996
|
+
if (msg.role === "assistant") {
|
|
997
|
+
closePendingToolCalls();
|
|
998
|
+
const assistantMsg = msg;
|
|
999
|
+
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") continue;
|
|
1000
|
+
const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
|
|
1001
|
+
if (toolCalls.length > 0) {
|
|
1002
|
+
pendingToolCalls = toolCalls;
|
|
1003
|
+
existingToolResultIds = /* @__PURE__ */ new Set();
|
|
1004
|
+
}
|
|
1005
|
+
result.push(msg);
|
|
1006
|
+
} else if (msg.role === "toolResult") {
|
|
1007
|
+
existingToolResultIds.add(msg.toolCallId);
|
|
1008
|
+
result.push(msg);
|
|
1009
|
+
} else if (msg.role === "system") {
|
|
1010
|
+
if (pendingToolCalls.length > 0) heldSystemMessages.push(msg);
|
|
1011
|
+
else result.push(msg);
|
|
1012
|
+
} else if (msg.role === "user") {
|
|
1013
|
+
closePendingToolCalls();
|
|
1014
|
+
result.push(msg);
|
|
1015
|
+
} else result.push(msg);
|
|
1016
|
+
}
|
|
1017
|
+
closePendingToolCalls();
|
|
1018
|
+
return result;
|
|
1019
|
+
}
|
|
1020
|
+
//#endregion
|
|
1021
|
+
export { __exportAll as C, __commonJSMin as S, getProviderEnvValue as _, clampThinkingBudgetToAnswerRoom as a, parseJsonWithRepair as b, hasCopilotVisionInput as c, getGrammarToolInput as d, getJsonSchemaToolParameters as f, retryProviderRequest as g, sanitizeSurrogates as h, clampMaxTokensToContext as i, appendGrammarToolInputJsonDelta as l, resolveJsonSchemaStrictSampling as m, adjustMaxTokensForThinking as n, thinkingBudgetForLevel as o, resolveGrammarConstrainedSampling as p, buildBaseOptions as r, buildCopilotDynamicHeaders as s, transformMessages as t, createGrammarToolInputProperties as u, getPiUserAgent as v, parseStreamingJson as x, headersToRecord as y };
|
|
1022
|
+
|
|
1023
|
+
//# sourceMappingURL=transform-messages-Csvf2ItW.js.map
|