@ljoukov/llm 2.1.0 → 3.0.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 +92 -49
- package/dist/index.cjs +1259 -257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -36
- package/dist/index.d.ts +92 -36
- package/dist/index.js +1246 -256
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
34
|
+
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION: () => CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
35
|
+
CODEX_APPLY_PATCH_LARK_GRAMMAR: () => CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
36
|
+
FIREWORKS_DEFAULT_GLM_MODEL: () => FIREWORKS_DEFAULT_GLM_MODEL,
|
|
37
|
+
FIREWORKS_DEFAULT_KIMI_MODEL: () => FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
38
|
+
FIREWORKS_DEFAULT_MINIMAX_MODEL: () => FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
39
|
+
FIREWORKS_MODEL_IDS: () => FIREWORKS_MODEL_IDS,
|
|
33
40
|
InMemoryAgentFilesystem: () => InMemoryAgentFilesystem,
|
|
34
41
|
LlmJsonCallError: () => LlmJsonCallError,
|
|
35
42
|
appendMarkdownSourcesSection: () => appendMarkdownSourcesSection,
|
|
@@ -42,6 +49,7 @@ __export(index_exports, {
|
|
|
42
49
|
createCodexReadFileTool: () => createCodexReadFileTool,
|
|
43
50
|
createFilesystemToolSetForModel: () => createFilesystemToolSetForModel,
|
|
44
51
|
createGeminiFilesystemToolSet: () => createGeminiFilesystemToolSet,
|
|
52
|
+
createGeminiReadFileTool: () => createGeminiReadFileTool,
|
|
45
53
|
createGlobTool: () => createGlobTool,
|
|
46
54
|
createGrepFilesTool: () => createGrepFilesTool,
|
|
47
55
|
createGrepSearchTool: () => createGrepSearchTool,
|
|
@@ -50,9 +58,11 @@ __export(index_exports, {
|
|
|
50
58
|
createListDirectoryTool: () => createListDirectoryTool,
|
|
51
59
|
createModelAgnosticFilesystemToolSet: () => createModelAgnosticFilesystemToolSet,
|
|
52
60
|
createNodeAgentFilesystem: () => createNodeAgentFilesystem,
|
|
53
|
-
|
|
61
|
+
createReadFilesTool: () => createReadFilesTool,
|
|
54
62
|
createReplaceTool: () => createReplaceTool,
|
|
63
|
+
createRgSearchTool: () => createRgSearchTool,
|
|
55
64
|
createWriteFileTool: () => createWriteFileTool,
|
|
65
|
+
customTool: () => customTool,
|
|
56
66
|
encodeChatGptAuthJson: () => encodeChatGptAuthJson,
|
|
57
67
|
encodeChatGptAuthJsonB64: () => encodeChatGptAuthJsonB64,
|
|
58
68
|
estimateCallCostUsd: () => estimateCallCostUsd,
|
|
@@ -63,12 +73,14 @@ __export(index_exports, {
|
|
|
63
73
|
generateText: () => generateText,
|
|
64
74
|
getChatGptAuthProfile: () => getChatGptAuthProfile,
|
|
65
75
|
getCurrentToolCallContext: () => getCurrentToolCallContext,
|
|
76
|
+
isFireworksModelId: () => isFireworksModelId,
|
|
66
77
|
isGeminiModelId: () => isGeminiModelId,
|
|
67
78
|
loadEnvFromFile: () => loadEnvFromFile,
|
|
68
79
|
loadLocalEnv: () => loadLocalEnv,
|
|
69
80
|
parseJsonFromLlmText: () => parseJsonFromLlmText,
|
|
70
81
|
refreshChatGptOauthToken: () => refreshChatGptOauthToken,
|
|
71
82
|
resolveFilesystemToolProfile: () => resolveFilesystemToolProfile,
|
|
83
|
+
resolveFireworksModelId: () => resolveFireworksModelId,
|
|
72
84
|
runAgentLoop: () => runAgentLoop,
|
|
73
85
|
runToolLoop: () => runToolLoop,
|
|
74
86
|
sanitisePartForLogging: () => sanitisePartForLogging,
|
|
@@ -152,6 +164,35 @@ function createAsyncQueue() {
|
|
|
152
164
|
return { push, close, fail, iterable: iterator() };
|
|
153
165
|
}
|
|
154
166
|
|
|
167
|
+
// src/fireworks/pricing.ts
|
|
168
|
+
var FIREWORKS_KIMI_K25_PRICING = {
|
|
169
|
+
inputRate: 0.6 / 1e6,
|
|
170
|
+
cachedRate: 0.1 / 1e6,
|
|
171
|
+
outputRate: 3 / 1e6
|
|
172
|
+
};
|
|
173
|
+
var FIREWORKS_GLM_5_PRICING = {
|
|
174
|
+
inputRate: 1 / 1e6,
|
|
175
|
+
cachedRate: 0.2 / 1e6,
|
|
176
|
+
outputRate: 3.2 / 1e6
|
|
177
|
+
};
|
|
178
|
+
var FIREWORKS_MINIMAX_M21_PRICING = {
|
|
179
|
+
inputRate: 0.3 / 1e6,
|
|
180
|
+
cachedRate: 0.15 / 1e6,
|
|
181
|
+
outputRate: 1.2 / 1e6
|
|
182
|
+
};
|
|
183
|
+
function getFireworksPricing(modelId) {
|
|
184
|
+
if (modelId.includes("kimi-k2.5") || modelId.includes("kimi-k2p5")) {
|
|
185
|
+
return FIREWORKS_KIMI_K25_PRICING;
|
|
186
|
+
}
|
|
187
|
+
if (modelId.includes("glm-5")) {
|
|
188
|
+
return FIREWORKS_GLM_5_PRICING;
|
|
189
|
+
}
|
|
190
|
+
if (modelId.includes("minimax-m2.1") || modelId.includes("minimax-m2p1")) {
|
|
191
|
+
return FIREWORKS_MINIMAX_M21_PRICING;
|
|
192
|
+
}
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
155
196
|
// src/google/pricing.ts
|
|
156
197
|
var GEMINI_3_PRO_PREVIEW_PRICING = {
|
|
157
198
|
threshold: 2e5,
|
|
@@ -209,12 +250,15 @@ var OPENAI_GPT_53_CODEX_PRICING = {
|
|
|
209
250
|
cachedRate: 0.125 / 1e6,
|
|
210
251
|
outputRate: 10 / 1e6
|
|
211
252
|
};
|
|
212
|
-
var
|
|
253
|
+
var OPENAI_GPT_5_MINI_PRICING = {
|
|
213
254
|
inputRate: 0.25 / 1e6,
|
|
214
255
|
cachedRate: 0.025 / 1e6,
|
|
215
256
|
outputRate: 2 / 1e6
|
|
216
257
|
};
|
|
217
258
|
function getOpenAiPricing(modelId) {
|
|
259
|
+
if (modelId.includes("gpt-5.3-codex-spark")) {
|
|
260
|
+
return OPENAI_GPT_5_MINI_PRICING;
|
|
261
|
+
}
|
|
218
262
|
if (modelId.includes("gpt-5.3-codex")) {
|
|
219
263
|
return OPENAI_GPT_53_CODEX_PRICING;
|
|
220
264
|
}
|
|
@@ -224,8 +268,11 @@ function getOpenAiPricing(modelId) {
|
|
|
224
268
|
if (modelId.includes("gpt-5.2")) {
|
|
225
269
|
return OPENAI_GPT_52_PRICING;
|
|
226
270
|
}
|
|
271
|
+
if (modelId.includes("gpt-5-mini")) {
|
|
272
|
+
return OPENAI_GPT_5_MINI_PRICING;
|
|
273
|
+
}
|
|
227
274
|
if (modelId.includes("gpt-5.1-codex-mini")) {
|
|
228
|
-
return
|
|
275
|
+
return OPENAI_GPT_5_MINI_PRICING;
|
|
229
276
|
}
|
|
230
277
|
return void 0;
|
|
231
278
|
}
|
|
@@ -286,6 +333,14 @@ function estimateCallCostUsd({
|
|
|
286
333
|
const outputCost = outputTokens * outputRate;
|
|
287
334
|
return inputCost + cachedCost + outputCost;
|
|
288
335
|
}
|
|
336
|
+
const fireworksPricing = getFireworksPricing(modelId);
|
|
337
|
+
if (fireworksPricing) {
|
|
338
|
+
const inputCost = nonCachedPrompt * fireworksPricing.inputRate;
|
|
339
|
+
const cachedCost = cachedTokens * fireworksPricing.cachedRate;
|
|
340
|
+
const outputTokens = responseTokens + thinkingTokens;
|
|
341
|
+
const outputCost = outputTokens * fireworksPricing.outputRate;
|
|
342
|
+
return inputCost + cachedCost + outputCost;
|
|
343
|
+
}
|
|
289
344
|
const openAiPricing = getOpenAiPricing(modelId);
|
|
290
345
|
if (openAiPricing) {
|
|
291
346
|
const inputCost = nonCachedPrompt * openAiPricing.inputRate;
|
|
@@ -298,11 +353,14 @@ function estimateCallCostUsd({
|
|
|
298
353
|
}
|
|
299
354
|
|
|
300
355
|
// src/openai/chatgpt-codex.ts
|
|
301
|
-
var
|
|
356
|
+
var import_node_os2 = __toESM(require("os"), 1);
|
|
302
357
|
var import_node_util = require("util");
|
|
303
358
|
|
|
304
359
|
// src/openai/chatgpt-auth.ts
|
|
305
360
|
var import_node_buffer = require("buffer");
|
|
361
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
362
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
363
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
306
364
|
var import_zod = require("zod");
|
|
307
365
|
|
|
308
366
|
// src/utils/env.ts
|
|
@@ -367,34 +425,30 @@ function parseEnvLine(line) {
|
|
|
367
425
|
}
|
|
368
426
|
|
|
369
427
|
// src/openai/chatgpt-auth.ts
|
|
370
|
-
var
|
|
371
|
-
var
|
|
372
|
-
var
|
|
373
|
-
var
|
|
374
|
-
var
|
|
375
|
-
var
|
|
376
|
-
var CHATGPT_ID_TOKEN_ENV = "CHATGPT_ID_TOKEN";
|
|
377
|
-
var CHATGPT_ACCESS_TOKEN_ENV = "CHATGPT_ACCESS_TOKEN";
|
|
378
|
-
var CHATGPT_REFRESH_TOKEN_ENV = "CHATGPT_REFRESH_TOKEN";
|
|
379
|
-
var CHATGPT_EXPIRES_AT_ENV = "CHATGPT_EXPIRES_AT";
|
|
428
|
+
var CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_URL";
|
|
429
|
+
var CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_STORE";
|
|
430
|
+
var CHATGPT_AUTH_SERVER_URL_ENV = "CHATGPT_AUTH_SERVER_URL";
|
|
431
|
+
var CHATGPT_AUTH_SERVER_STORE_ENV = "CHATGPT_AUTH_SERVER_STORE";
|
|
432
|
+
var CHATGPT_AUTH_API_KEY_ENV = "CHATGPT_AUTH_API_KEY";
|
|
433
|
+
var CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV = "CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY";
|
|
380
434
|
var CHATGPT_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
381
435
|
var CHATGPT_OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
382
436
|
var CHATGPT_OAUTH_REDIRECT_URI = "http://localhost:1455/auth/callback";
|
|
383
437
|
var TOKEN_EXPIRY_BUFFER_MS = 3e4;
|
|
384
|
-
var
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
438
|
+
var CodexAuthFileSchema = import_zod.z.object({
|
|
439
|
+
OPENAI_API_KEY: import_zod.z.string().nullable().optional(),
|
|
440
|
+
last_refresh: import_zod.z.string().optional(),
|
|
441
|
+
tokens: import_zod.z.object({
|
|
442
|
+
access_token: import_zod.z.string().min(1).optional(),
|
|
443
|
+
refresh_token: import_zod.z.string().min(1).optional(),
|
|
444
|
+
id_token: import_zod.z.string().min(1).optional(),
|
|
445
|
+
account_id: import_zod.z.string().min(1).optional(),
|
|
446
|
+
// Allow a bit of flexibility if the file format changes.
|
|
447
|
+
accessToken: import_zod.z.string().min(1).optional(),
|
|
448
|
+
refreshToken: import_zod.z.string().min(1).optional(),
|
|
449
|
+
idToken: import_zod.z.string().min(1).optional(),
|
|
450
|
+
accountId: import_zod.z.string().min(1).optional()
|
|
451
|
+
}).optional()
|
|
398
452
|
}).loose();
|
|
399
453
|
var RefreshResponseSchema = import_zod.z.object({
|
|
400
454
|
access_token: import_zod.z.string().min(1),
|
|
@@ -409,6 +463,44 @@ var ExchangeResponseSchema = import_zod.z.object({
|
|
|
409
463
|
});
|
|
410
464
|
var cachedProfile = null;
|
|
411
465
|
var refreshPromise = null;
|
|
466
|
+
async function fetchChatGptAuthProfileFromTokenProvider(options) {
|
|
467
|
+
const base = options.baseUrl.replace(/\/+$/u, "");
|
|
468
|
+
const store = options.store?.trim() ? options.store.trim() : "kv";
|
|
469
|
+
const url = new URL(`${base}/v1/token`);
|
|
470
|
+
url.searchParams.set("store", store);
|
|
471
|
+
const response = await fetch(url.toString(), {
|
|
472
|
+
method: "GET",
|
|
473
|
+
headers: {
|
|
474
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
475
|
+
"x-chatgpt-auth": options.apiKey,
|
|
476
|
+
Accept: "application/json"
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
if (!response.ok) {
|
|
480
|
+
const body = await response.text();
|
|
481
|
+
throw new Error(`ChatGPT token provider request failed (${response.status}): ${body}`);
|
|
482
|
+
}
|
|
483
|
+
const payload = await response.json();
|
|
484
|
+
if (!payload || typeof payload !== "object") {
|
|
485
|
+
throw new Error("ChatGPT token provider returned invalid JSON.");
|
|
486
|
+
}
|
|
487
|
+
const accessToken = payload.accessToken ?? payload.access_token;
|
|
488
|
+
const accountId = payload.accountId ?? payload.account_id;
|
|
489
|
+
const expiresAt = payload.expiresAt ?? payload.expires_at;
|
|
490
|
+
if (typeof accessToken !== "string" || accessToken.trim().length === 0) {
|
|
491
|
+
throw new Error("ChatGPT token provider response missing accessToken.");
|
|
492
|
+
}
|
|
493
|
+
if (typeof accountId !== "string" || accountId.trim().length === 0) {
|
|
494
|
+
throw new Error("ChatGPT token provider response missing accountId.");
|
|
495
|
+
}
|
|
496
|
+
const expires = normalizeEpochMillis(expiresAt) ?? Date.now() + 5 * 6e4;
|
|
497
|
+
return {
|
|
498
|
+
access: accessToken,
|
|
499
|
+
refresh: "token_provider",
|
|
500
|
+
expires,
|
|
501
|
+
accountId
|
|
502
|
+
};
|
|
503
|
+
}
|
|
412
504
|
function encodeChatGptAuthJson(profile) {
|
|
413
505
|
const payload = {
|
|
414
506
|
access: profile.access,
|
|
@@ -447,7 +539,7 @@ async function exchangeChatGptOauthCode({
|
|
|
447
539
|
const payload = ExchangeResponseSchema.parse(await response.json());
|
|
448
540
|
return profileFromTokenResponse(payload);
|
|
449
541
|
}
|
|
450
|
-
async function refreshChatGptOauthToken(refreshToken) {
|
|
542
|
+
async function refreshChatGptOauthToken(refreshToken, fallback) {
|
|
451
543
|
const params = new URLSearchParams();
|
|
452
544
|
params.set("grant_type", "refresh_token");
|
|
453
545
|
params.set("client_id", CHATGPT_OAUTH_CLIENT_ID);
|
|
@@ -464,9 +556,35 @@ async function refreshChatGptOauthToken(refreshToken) {
|
|
|
464
556
|
throw new Error(`ChatGPT OAuth refresh failed (${response.status}): ${body}`);
|
|
465
557
|
}
|
|
466
558
|
const payload = RefreshResponseSchema.parse(await response.json());
|
|
467
|
-
return profileFromTokenResponse(payload);
|
|
559
|
+
return profileFromTokenResponse(payload, fallback);
|
|
468
560
|
}
|
|
469
561
|
async function getChatGptAuthProfile() {
|
|
562
|
+
loadLocalEnv();
|
|
563
|
+
const tokenProviderUrl = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV] ?? process.env[CHATGPT_AUTH_SERVER_URL_ENV];
|
|
564
|
+
const tokenProviderKey = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_API_KEY_ENV] ?? process.env[CHATGPT_AUTH_API_KEY_ENV];
|
|
565
|
+
if (tokenProviderUrl && tokenProviderUrl.trim().length > 0 && tokenProviderKey && tokenProviderKey.trim().length > 0) {
|
|
566
|
+
if (cachedProfile && !isExpired(cachedProfile)) {
|
|
567
|
+
return cachedProfile;
|
|
568
|
+
}
|
|
569
|
+
if (refreshPromise) {
|
|
570
|
+
return refreshPromise;
|
|
571
|
+
}
|
|
572
|
+
refreshPromise = (async () => {
|
|
573
|
+
try {
|
|
574
|
+
const store = process.env[CHATGPT_AUTH_TOKEN_PROVIDER_STORE_ENV] ?? process.env[CHATGPT_AUTH_SERVER_STORE_ENV];
|
|
575
|
+
const profile = await fetchChatGptAuthProfileFromTokenProvider({
|
|
576
|
+
baseUrl: tokenProviderUrl,
|
|
577
|
+
apiKey: tokenProviderKey,
|
|
578
|
+
store: store ?? void 0
|
|
579
|
+
});
|
|
580
|
+
cachedProfile = profile;
|
|
581
|
+
return profile;
|
|
582
|
+
} finally {
|
|
583
|
+
refreshPromise = null;
|
|
584
|
+
}
|
|
585
|
+
})();
|
|
586
|
+
return refreshPromise;
|
|
587
|
+
}
|
|
470
588
|
if (cachedProfile && !isExpired(cachedProfile)) {
|
|
471
589
|
return cachedProfile;
|
|
472
590
|
}
|
|
@@ -475,8 +593,8 @@ async function getChatGptAuthProfile() {
|
|
|
475
593
|
}
|
|
476
594
|
refreshPromise = (async () => {
|
|
477
595
|
try {
|
|
478
|
-
const baseProfile = cachedProfile ??
|
|
479
|
-
const profile = isExpired(baseProfile) ? await
|
|
596
|
+
const baseProfile = cachedProfile ?? loadAuthProfileFromCodexStore();
|
|
597
|
+
const profile = isExpired(baseProfile) ? await refreshAndPersistCodexProfile(baseProfile) : baseProfile;
|
|
480
598
|
cachedProfile = profile;
|
|
481
599
|
return profile;
|
|
482
600
|
} finally {
|
|
@@ -485,39 +603,111 @@ async function getChatGptAuthProfile() {
|
|
|
485
603
|
})();
|
|
486
604
|
return refreshPromise;
|
|
487
605
|
}
|
|
488
|
-
function
|
|
489
|
-
const
|
|
490
|
-
|
|
606
|
+
function resolveCodexHome() {
|
|
607
|
+
const codexHome = process.env.CODEX_HOME;
|
|
608
|
+
if (codexHome && codexHome.trim().length > 0) {
|
|
609
|
+
return codexHome.trim();
|
|
610
|
+
}
|
|
611
|
+
return import_node_path2.default.join(import_node_os.default.homedir(), ".codex");
|
|
612
|
+
}
|
|
613
|
+
function resolveCodexAuthJsonPath() {
|
|
614
|
+
return import_node_path2.default.join(resolveCodexHome(), "auth.json");
|
|
615
|
+
}
|
|
616
|
+
function loadAuthProfileFromCodexStore() {
|
|
617
|
+
const authPath = resolveCodexAuthJsonPath();
|
|
618
|
+
let raw;
|
|
619
|
+
try {
|
|
620
|
+
raw = import_node_fs2.default.readFileSync(authPath, "utf8");
|
|
621
|
+
} catch {
|
|
622
|
+
throw new Error(
|
|
623
|
+
`ChatGPT auth not configured. Set ${CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV}+${CHATGPT_AUTH_API_KEY_ENV} or login via Codex to create ${authPath}.`
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
let parsed;
|
|
627
|
+
try {
|
|
628
|
+
parsed = CodexAuthFileSchema.parse(JSON.parse(raw));
|
|
629
|
+
} catch (e) {
|
|
630
|
+
throw new Error(
|
|
631
|
+
`Failed to parse Codex auth store at ${authPath}. (${e?.message ?? e})`
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
const tokens = parsed.tokens;
|
|
635
|
+
if (!tokens) {
|
|
636
|
+
throw new Error(
|
|
637
|
+
`Codex auth store at ${authPath} is missing tokens. Re-login via Codex, or configure ${CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV}.`
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
const access = tokens.access_token ?? tokens.accessToken ?? void 0;
|
|
641
|
+
const refresh = tokens.refresh_token ?? tokens.refreshToken ?? void 0;
|
|
642
|
+
const idToken = tokens.id_token ?? tokens.idToken ?? void 0;
|
|
643
|
+
if (!access || !refresh) {
|
|
644
|
+
throw new Error(
|
|
645
|
+
`Codex auth store at ${authPath} is missing access_token/refresh_token. Re-login via Codex, or configure ${CHATGPT_AUTH_TOKEN_PROVIDER_URL_ENV}.`
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
const expires = extractJwtExpiry(access) ?? extractJwtExpiry(idToken ?? "") ?? Date.now() + 5 * 6e4;
|
|
649
|
+
const accountId = tokens.account_id ?? tokens.accountId ?? extractChatGptAccountId(idToken ?? "") ?? extractChatGptAccountId(access);
|
|
491
650
|
if (!accountId) {
|
|
492
|
-
throw new Error(
|
|
651
|
+
throw new Error(`Codex auth store at ${authPath} is missing chatgpt_account_id/account_id.`);
|
|
493
652
|
}
|
|
494
653
|
return {
|
|
495
|
-
access
|
|
496
|
-
refresh
|
|
654
|
+
access,
|
|
655
|
+
refresh,
|
|
497
656
|
expires,
|
|
498
657
|
accountId,
|
|
499
|
-
idToken:
|
|
658
|
+
idToken: idToken ?? void 0
|
|
500
659
|
};
|
|
501
660
|
}
|
|
502
|
-
function
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
661
|
+
async function refreshAndPersistCodexProfile(baseProfile) {
|
|
662
|
+
const refreshed = await refreshChatGptOauthToken(baseProfile.refresh, {
|
|
663
|
+
accountId: baseProfile.accountId,
|
|
664
|
+
idToken: baseProfile.idToken
|
|
665
|
+
});
|
|
666
|
+
persistCodexTokens(refreshed);
|
|
667
|
+
return refreshed;
|
|
668
|
+
}
|
|
669
|
+
function persistCodexTokens(profile) {
|
|
670
|
+
const authPath = resolveCodexAuthJsonPath();
|
|
671
|
+
const codexHome = import_node_path2.default.dirname(authPath);
|
|
672
|
+
let doc = {};
|
|
673
|
+
try {
|
|
674
|
+
doc = JSON.parse(import_node_fs2.default.readFileSync(authPath, "utf8"));
|
|
675
|
+
} catch {
|
|
676
|
+
doc = {};
|
|
677
|
+
}
|
|
678
|
+
if (!doc || typeof doc !== "object") {
|
|
679
|
+
doc = {};
|
|
507
680
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
681
|
+
if (!doc.tokens || typeof doc.tokens !== "object") {
|
|
682
|
+
doc.tokens = {};
|
|
683
|
+
}
|
|
684
|
+
doc.tokens.access_token = profile.access;
|
|
685
|
+
doc.tokens.refresh_token = profile.refresh;
|
|
686
|
+
doc.tokens.account_id = profile.accountId;
|
|
687
|
+
if (profile.idToken) {
|
|
688
|
+
doc.tokens.id_token = profile.idToken;
|
|
689
|
+
}
|
|
690
|
+
doc.last_refresh = (/* @__PURE__ */ new Date()).toISOString();
|
|
691
|
+
import_node_fs2.default.mkdirSync(codexHome, { recursive: true, mode: 448 });
|
|
692
|
+
const tmpPath = `${authPath}.tmp.${process.pid}.${Math.random().toString(16).slice(2)}`;
|
|
693
|
+
import_node_fs2.default.writeFileSync(tmpPath, `${JSON.stringify(doc, null, 2)}
|
|
694
|
+
`, { mode: 384 });
|
|
695
|
+
import_node_fs2.default.renameSync(tmpPath, authPath);
|
|
696
|
+
}
|
|
697
|
+
function profileFromTokenResponse(payload, fallback) {
|
|
698
|
+
const expires = Date.now() + normalizeNumber(payload.expires_in) * 1e3;
|
|
699
|
+
const fallbackAccountId = fallback?.accountId;
|
|
700
|
+
const fallbackIdToken = fallback?.idToken;
|
|
701
|
+
const accountId = extractChatGptAccountId(payload.id_token ?? "") ?? extractChatGptAccountId(payload.access_token) ?? fallbackAccountId;
|
|
512
702
|
if (!accountId) {
|
|
513
|
-
throw new Error("
|
|
703
|
+
throw new Error("Failed to extract chatgpt_account_id from access token.");
|
|
514
704
|
}
|
|
515
705
|
return {
|
|
516
|
-
access,
|
|
517
|
-
refresh,
|
|
706
|
+
access: payload.access_token,
|
|
707
|
+
refresh: payload.refresh_token,
|
|
518
708
|
expires,
|
|
519
709
|
accountId,
|
|
520
|
-
idToken:
|
|
710
|
+
idToken: payload.id_token ?? fallbackIdToken
|
|
521
711
|
};
|
|
522
712
|
}
|
|
523
713
|
function normalizeEpochMillis(value) {
|
|
@@ -546,31 +736,6 @@ function isExpired(profile) {
|
|
|
546
736
|
}
|
|
547
737
|
return Date.now() + TOKEN_EXPIRY_BUFFER_MS >= expires;
|
|
548
738
|
}
|
|
549
|
-
function loadAuthProfileFromEnv() {
|
|
550
|
-
loadLocalEnv();
|
|
551
|
-
const rawJson = process.env[CHATGPT_AUTH_JSON_ENV];
|
|
552
|
-
if (rawJson && rawJson.trim().length > 0) {
|
|
553
|
-
return normalizeAuthProfile(AuthInputSchema.parse(JSON.parse(rawJson)));
|
|
554
|
-
}
|
|
555
|
-
const rawB64 = process.env[CHATGPT_AUTH_JSON_B64_ENV];
|
|
556
|
-
if (rawB64 && rawB64.trim().length > 0) {
|
|
557
|
-
const decoded = import_node_buffer.Buffer.from(rawB64.trim(), "base64url").toString("utf8");
|
|
558
|
-
return normalizeAuthProfile(AuthInputSchema.parse(JSON.parse(decoded)));
|
|
559
|
-
}
|
|
560
|
-
const access = process.env[CHATGPT_ACCESS_ENV] ?? process.env[CHATGPT_ACCESS_TOKEN_ENV] ?? void 0;
|
|
561
|
-
const refresh = process.env[CHATGPT_REFRESH_ENV] ?? process.env[CHATGPT_REFRESH_TOKEN_ENV] ?? void 0;
|
|
562
|
-
const expires = process.env[CHATGPT_EXPIRES_ENV] ?? process.env[CHATGPT_EXPIRES_AT_ENV] ?? void 0;
|
|
563
|
-
const accountId = process.env[CHATGPT_ACCOUNT_ID_ENV] ?? void 0;
|
|
564
|
-
const idToken = process.env[CHATGPT_ID_TOKEN_ENV] ?? void 0;
|
|
565
|
-
const parsed = AuthInputSchema.parse({
|
|
566
|
-
access,
|
|
567
|
-
refresh,
|
|
568
|
-
expires,
|
|
569
|
-
accountId,
|
|
570
|
-
idToken
|
|
571
|
-
});
|
|
572
|
-
return normalizeAuthProfile(parsed);
|
|
573
|
-
}
|
|
574
739
|
function decodeJwtPayload(token) {
|
|
575
740
|
const segments = token.split(".");
|
|
576
741
|
if (segments.length < 2) {
|
|
@@ -601,8 +766,12 @@ function extractChatGptAccountId(token) {
|
|
|
601
766
|
if (!payload || typeof payload !== "object") {
|
|
602
767
|
return void 0;
|
|
603
768
|
}
|
|
604
|
-
const
|
|
605
|
-
|
|
769
|
+
const direct = payload.chatgpt_account_id;
|
|
770
|
+
if (typeof direct === "string" && direct.length > 0) {
|
|
771
|
+
return direct;
|
|
772
|
+
}
|
|
773
|
+
const namespaced = payload["https://api.openai.com/auth"]?.chatgpt_account_id;
|
|
774
|
+
return typeof namespaced === "string" && namespaced.length > 0 ? namespaced : void 0;
|
|
606
775
|
}
|
|
607
776
|
|
|
608
777
|
// src/openai/chatgpt-codex.ts
|
|
@@ -638,7 +807,19 @@ async function streamChatGptCodexResponse(options) {
|
|
|
638
807
|
return parseEventStream(body);
|
|
639
808
|
}
|
|
640
809
|
async function collectChatGptCodexResponse(options) {
|
|
641
|
-
|
|
810
|
+
let stream;
|
|
811
|
+
try {
|
|
812
|
+
stream = await streamChatGptCodexResponse(options);
|
|
813
|
+
} catch (error) {
|
|
814
|
+
if (shouldRetryWithoutReasoningSummary(options.request, error)) {
|
|
815
|
+
stream = await streamChatGptCodexResponse({
|
|
816
|
+
...options,
|
|
817
|
+
request: removeReasoningSummary(options.request)
|
|
818
|
+
});
|
|
819
|
+
} else {
|
|
820
|
+
throw error;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
642
823
|
const toolCalls = /* @__PURE__ */ new Map();
|
|
643
824
|
const toolCallOrder = [];
|
|
644
825
|
const webSearchCalls = /* @__PURE__ */ new Map();
|
|
@@ -647,6 +828,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
647
828
|
const reasoningText = "";
|
|
648
829
|
let reasoningSummaryText = "";
|
|
649
830
|
let usage;
|
|
831
|
+
let responseId;
|
|
650
832
|
let model;
|
|
651
833
|
let status;
|
|
652
834
|
let blocked = false;
|
|
@@ -687,7 +869,18 @@ async function collectChatGptCodexResponse(options) {
|
|
|
687
869
|
if (!toolCalls.has(callId)) {
|
|
688
870
|
toolCallOrder.push(callId);
|
|
689
871
|
}
|
|
690
|
-
toolCalls.set(callId, { id, callId, name, arguments: args });
|
|
872
|
+
toolCalls.set(callId, { kind: "function", id, callId, name, arguments: args });
|
|
873
|
+
}
|
|
874
|
+
} else if (item.type === "custom_tool_call") {
|
|
875
|
+
const id = typeof item.id === "string" ? item.id : "";
|
|
876
|
+
const callId = typeof item.call_id === "string" ? item.call_id : id;
|
|
877
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
878
|
+
const input = typeof item.input === "string" ? item.input : "";
|
|
879
|
+
if (callId) {
|
|
880
|
+
if (!toolCalls.has(callId)) {
|
|
881
|
+
toolCallOrder.push(callId);
|
|
882
|
+
}
|
|
883
|
+
toolCalls.set(callId, { kind: "custom", id, callId, name, input });
|
|
691
884
|
}
|
|
692
885
|
} else if (item.type === "web_search_call") {
|
|
693
886
|
const id = typeof item.id === "string" ? item.id : "";
|
|
@@ -709,6 +902,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
709
902
|
const response = event.response;
|
|
710
903
|
if (response) {
|
|
711
904
|
usage = response.usage;
|
|
905
|
+
responseId = typeof response.id === "string" ? response.id : responseId;
|
|
712
906
|
model = typeof response.model === "string" ? response.model : void 0;
|
|
713
907
|
status = typeof response.status === "string" ? response.status : void 0;
|
|
714
908
|
}
|
|
@@ -718,6 +912,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
718
912
|
const response = event.response;
|
|
719
913
|
if (response) {
|
|
720
914
|
usage = response.usage;
|
|
915
|
+
responseId = typeof response.id === "string" ? response.id : responseId;
|
|
721
916
|
model = typeof response.model === "string" ? response.model : void 0;
|
|
722
917
|
status = typeof response.status === "string" ? response.status : void 0;
|
|
723
918
|
}
|
|
@@ -727,6 +922,7 @@ async function collectChatGptCodexResponse(options) {
|
|
|
727
922
|
const response = event.response;
|
|
728
923
|
if (response) {
|
|
729
924
|
usage = response.usage;
|
|
925
|
+
responseId = typeof response.id === "string" ? response.id : responseId;
|
|
730
926
|
model = typeof response.model === "string" ? response.model : void 0;
|
|
731
927
|
status = typeof response.status === "string" ? response.status : void 0;
|
|
732
928
|
}
|
|
@@ -744,15 +940,38 @@ async function collectChatGptCodexResponse(options) {
|
|
|
744
940
|
toolCalls: orderedToolCalls,
|
|
745
941
|
webSearchCalls: orderedWebSearchCalls,
|
|
746
942
|
usage,
|
|
943
|
+
id: responseId,
|
|
747
944
|
model,
|
|
748
945
|
status,
|
|
749
946
|
blocked
|
|
750
947
|
};
|
|
751
948
|
}
|
|
949
|
+
function shouldRetryWithoutReasoningSummary(request, error) {
|
|
950
|
+
if (!request.reasoning?.summary) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
if (!(error instanceof Error)) {
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
const message = error.message.toLowerCase();
|
|
957
|
+
return message.includes("unsupported parameter") && message.includes("reasoning.summary");
|
|
958
|
+
}
|
|
959
|
+
function removeReasoningSummary(request) {
|
|
960
|
+
const reasoning = request.reasoning;
|
|
961
|
+
if (!reasoning?.summary) {
|
|
962
|
+
return request;
|
|
963
|
+
}
|
|
964
|
+
return {
|
|
965
|
+
...request,
|
|
966
|
+
reasoning: {
|
|
967
|
+
effort: reasoning.effort
|
|
968
|
+
}
|
|
969
|
+
};
|
|
970
|
+
}
|
|
752
971
|
function buildUserAgent() {
|
|
753
972
|
const node = process.version;
|
|
754
|
-
const platform =
|
|
755
|
-
const release =
|
|
973
|
+
const platform = import_node_os2.default.platform();
|
|
974
|
+
const release = import_node_os2.default.release();
|
|
756
975
|
return `@ljoukov/llm (node ${node}; ${platform} ${release})`;
|
|
757
976
|
}
|
|
758
977
|
async function* parseEventStream(stream) {
|
|
@@ -900,6 +1119,110 @@ function createCallScheduler(options = {}) {
|
|
|
900
1119
|
return { run };
|
|
901
1120
|
}
|
|
902
1121
|
|
|
1122
|
+
// src/fireworks/client.ts
|
|
1123
|
+
var import_openai = __toESM(require("openai"), 1);
|
|
1124
|
+
var import_undici = require("undici");
|
|
1125
|
+
var DEFAULT_FIREWORKS_BASE_URL = "https://api.fireworks.ai/inference/v1";
|
|
1126
|
+
var DEFAULT_FIREWORKS_TIMEOUT_MS = 15 * 6e4;
|
|
1127
|
+
var cachedClient = null;
|
|
1128
|
+
var cachedFetch = null;
|
|
1129
|
+
var cachedBaseUrl = null;
|
|
1130
|
+
var cachedApiKey = null;
|
|
1131
|
+
var cachedTimeoutMs = null;
|
|
1132
|
+
function resolveTimeoutMs() {
|
|
1133
|
+
if (cachedTimeoutMs !== null) {
|
|
1134
|
+
return cachedTimeoutMs;
|
|
1135
|
+
}
|
|
1136
|
+
const raw = process.env.FIREWORKS_TIMEOUT_MS;
|
|
1137
|
+
const parsed = raw ? Number(raw) : Number.NaN;
|
|
1138
|
+
cachedTimeoutMs = Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_FIREWORKS_TIMEOUT_MS;
|
|
1139
|
+
return cachedTimeoutMs;
|
|
1140
|
+
}
|
|
1141
|
+
function resolveBaseUrl() {
|
|
1142
|
+
if (cachedBaseUrl !== null) {
|
|
1143
|
+
return cachedBaseUrl;
|
|
1144
|
+
}
|
|
1145
|
+
loadLocalEnv();
|
|
1146
|
+
const raw = process.env.FIREWORKS_BASE_URL?.trim();
|
|
1147
|
+
cachedBaseUrl = raw && raw.length > 0 ? raw : DEFAULT_FIREWORKS_BASE_URL;
|
|
1148
|
+
return cachedBaseUrl;
|
|
1149
|
+
}
|
|
1150
|
+
function resolveApiKey() {
|
|
1151
|
+
if (cachedApiKey !== null) {
|
|
1152
|
+
return cachedApiKey;
|
|
1153
|
+
}
|
|
1154
|
+
loadLocalEnv();
|
|
1155
|
+
const raw = process.env.FIREWORKS_TOKEN ?? process.env.FIREWORKS_API_KEY;
|
|
1156
|
+
const token = raw?.trim();
|
|
1157
|
+
if (!token) {
|
|
1158
|
+
throw new Error(
|
|
1159
|
+
"FIREWORKS_TOKEN (or FIREWORKS_API_KEY) must be provided to access Fireworks APIs."
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
cachedApiKey = token;
|
|
1163
|
+
return cachedApiKey;
|
|
1164
|
+
}
|
|
1165
|
+
function getFireworksFetch() {
|
|
1166
|
+
if (cachedFetch) {
|
|
1167
|
+
return cachedFetch;
|
|
1168
|
+
}
|
|
1169
|
+
const timeoutMs = resolveTimeoutMs();
|
|
1170
|
+
const dispatcher = new import_undici.Agent({
|
|
1171
|
+
bodyTimeout: timeoutMs,
|
|
1172
|
+
headersTimeout: timeoutMs
|
|
1173
|
+
});
|
|
1174
|
+
cachedFetch = ((input, init) => {
|
|
1175
|
+
return (0, import_undici.fetch)(input, {
|
|
1176
|
+
...init ?? {},
|
|
1177
|
+
dispatcher
|
|
1178
|
+
});
|
|
1179
|
+
});
|
|
1180
|
+
return cachedFetch;
|
|
1181
|
+
}
|
|
1182
|
+
function getFireworksClient() {
|
|
1183
|
+
if (cachedClient) {
|
|
1184
|
+
return cachedClient;
|
|
1185
|
+
}
|
|
1186
|
+
cachedClient = new import_openai.default({
|
|
1187
|
+
apiKey: resolveApiKey(),
|
|
1188
|
+
baseURL: resolveBaseUrl(),
|
|
1189
|
+
timeout: resolveTimeoutMs(),
|
|
1190
|
+
fetch: getFireworksFetch()
|
|
1191
|
+
});
|
|
1192
|
+
return cachedClient;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// src/fireworks/calls.ts
|
|
1196
|
+
var scheduler = createCallScheduler({
|
|
1197
|
+
maxParallelRequests: 3,
|
|
1198
|
+
minIntervalBetweenStartMs: 200,
|
|
1199
|
+
startJitterMs: 200
|
|
1200
|
+
});
|
|
1201
|
+
async function runFireworksCall(fn) {
|
|
1202
|
+
return scheduler.run(async () => fn(getFireworksClient()));
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// src/fireworks/models.ts
|
|
1206
|
+
var FIREWORKS_MODEL_IDS = ["kimi-k2.5", "glm-5", "minimax-m2.1"];
|
|
1207
|
+
var FIREWORKS_DEFAULT_KIMI_MODEL = "kimi-k2.5";
|
|
1208
|
+
var FIREWORKS_DEFAULT_GLM_MODEL = "glm-5";
|
|
1209
|
+
var FIREWORKS_DEFAULT_MINIMAX_MODEL = "minimax-m2.1";
|
|
1210
|
+
var FIREWORKS_CANONICAL_MODEL_IDS = {
|
|
1211
|
+
"kimi-k2.5": "accounts/fireworks/models/kimi-k2p5",
|
|
1212
|
+
"glm-5": "accounts/fireworks/models/glm-5",
|
|
1213
|
+
"minimax-m2.1": "accounts/fireworks/models/minimax-m2p1"
|
|
1214
|
+
};
|
|
1215
|
+
function isFireworksModelId(value) {
|
|
1216
|
+
return FIREWORKS_MODEL_IDS.includes(value.trim());
|
|
1217
|
+
}
|
|
1218
|
+
function resolveFireworksModelId(model) {
|
|
1219
|
+
const trimmed = model.trim();
|
|
1220
|
+
if (!isFireworksModelId(trimmed)) {
|
|
1221
|
+
return void 0;
|
|
1222
|
+
}
|
|
1223
|
+
return FIREWORKS_CANONICAL_MODEL_IDS[trimmed];
|
|
1224
|
+
}
|
|
1225
|
+
|
|
903
1226
|
// src/google/client.ts
|
|
904
1227
|
var import_genai = require("@google/genai");
|
|
905
1228
|
|
|
@@ -968,6 +1291,7 @@ function getGoogleAuthOptions(scopes) {
|
|
|
968
1291
|
// src/google/client.ts
|
|
969
1292
|
var GEMINI_MODEL_IDS = [
|
|
970
1293
|
"gemini-3-pro-preview",
|
|
1294
|
+
"gemini-3-flash-preview",
|
|
971
1295
|
"gemini-2.5-pro",
|
|
972
1296
|
"gemini-flash-latest",
|
|
973
1297
|
"gemini-flash-lite-latest"
|
|
@@ -1207,7 +1531,7 @@ function retryDelayMs(attempt) {
|
|
|
1207
1531
|
const jitter = Math.floor(Math.random() * 200);
|
|
1208
1532
|
return base + jitter;
|
|
1209
1533
|
}
|
|
1210
|
-
var
|
|
1534
|
+
var scheduler2 = createCallScheduler({
|
|
1211
1535
|
maxParallelRequests: 3,
|
|
1212
1536
|
minIntervalBetweenStartMs: 200,
|
|
1213
1537
|
startJitterMs: 200,
|
|
@@ -1223,46 +1547,46 @@ var scheduler = createCallScheduler({
|
|
|
1223
1547
|
}
|
|
1224
1548
|
});
|
|
1225
1549
|
async function runGeminiCall(fn) {
|
|
1226
|
-
return
|
|
1550
|
+
return scheduler2.run(async () => fn(await getGeminiClient()));
|
|
1227
1551
|
}
|
|
1228
1552
|
|
|
1229
1553
|
// src/openai/client.ts
|
|
1230
|
-
var
|
|
1231
|
-
var
|
|
1232
|
-
var
|
|
1233
|
-
var
|
|
1234
|
-
var
|
|
1235
|
-
var
|
|
1554
|
+
var import_openai2 = __toESM(require("openai"), 1);
|
|
1555
|
+
var import_undici2 = require("undici");
|
|
1556
|
+
var cachedApiKey2 = null;
|
|
1557
|
+
var cachedClient2 = null;
|
|
1558
|
+
var cachedFetch2 = null;
|
|
1559
|
+
var cachedTimeoutMs2 = null;
|
|
1236
1560
|
var DEFAULT_OPENAI_TIMEOUT_MS = 15 * 6e4;
|
|
1237
1561
|
function resolveOpenAiTimeoutMs() {
|
|
1238
|
-
if (
|
|
1239
|
-
return
|
|
1562
|
+
if (cachedTimeoutMs2 !== null) {
|
|
1563
|
+
return cachedTimeoutMs2;
|
|
1240
1564
|
}
|
|
1241
1565
|
const raw = process.env.OPENAI_STREAM_TIMEOUT_MS ?? process.env.OPENAI_TIMEOUT_MS;
|
|
1242
1566
|
const parsed = raw ? Number(raw) : Number.NaN;
|
|
1243
|
-
|
|
1244
|
-
return
|
|
1567
|
+
cachedTimeoutMs2 = Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_OPENAI_TIMEOUT_MS;
|
|
1568
|
+
return cachedTimeoutMs2;
|
|
1245
1569
|
}
|
|
1246
1570
|
function getOpenAiFetch() {
|
|
1247
|
-
if (
|
|
1248
|
-
return
|
|
1571
|
+
if (cachedFetch2) {
|
|
1572
|
+
return cachedFetch2;
|
|
1249
1573
|
}
|
|
1250
1574
|
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
1251
|
-
const dispatcher = new
|
|
1575
|
+
const dispatcher = new import_undici2.Agent({
|
|
1252
1576
|
bodyTimeout: timeoutMs,
|
|
1253
1577
|
headersTimeout: timeoutMs
|
|
1254
1578
|
});
|
|
1255
|
-
|
|
1256
|
-
return (0,
|
|
1579
|
+
cachedFetch2 = ((input, init) => {
|
|
1580
|
+
return (0, import_undici2.fetch)(input, {
|
|
1257
1581
|
...init ?? {},
|
|
1258
1582
|
dispatcher
|
|
1259
1583
|
});
|
|
1260
1584
|
});
|
|
1261
|
-
return
|
|
1585
|
+
return cachedFetch2;
|
|
1262
1586
|
}
|
|
1263
1587
|
function getOpenAiApiKey() {
|
|
1264
|
-
if (
|
|
1265
|
-
return
|
|
1588
|
+
if (cachedApiKey2 !== null) {
|
|
1589
|
+
return cachedApiKey2;
|
|
1266
1590
|
}
|
|
1267
1591
|
loadLocalEnv();
|
|
1268
1592
|
const raw = process.env.OPENAI_API_KEY;
|
|
@@ -1270,32 +1594,32 @@ function getOpenAiApiKey() {
|
|
|
1270
1594
|
if (!value) {
|
|
1271
1595
|
throw new Error("OPENAI_API_KEY must be provided to access OpenAI APIs.");
|
|
1272
1596
|
}
|
|
1273
|
-
|
|
1274
|
-
return
|
|
1597
|
+
cachedApiKey2 = value;
|
|
1598
|
+
return cachedApiKey2;
|
|
1275
1599
|
}
|
|
1276
1600
|
function getOpenAiClient() {
|
|
1277
|
-
if (
|
|
1278
|
-
return
|
|
1601
|
+
if (cachedClient2) {
|
|
1602
|
+
return cachedClient2;
|
|
1279
1603
|
}
|
|
1280
1604
|
const apiKey = getOpenAiApiKey();
|
|
1281
1605
|
const timeoutMs = resolveOpenAiTimeoutMs();
|
|
1282
|
-
|
|
1606
|
+
cachedClient2 = new import_openai2.default({
|
|
1283
1607
|
apiKey,
|
|
1284
1608
|
fetch: getOpenAiFetch(),
|
|
1285
1609
|
timeout: timeoutMs
|
|
1286
1610
|
});
|
|
1287
|
-
return
|
|
1611
|
+
return cachedClient2;
|
|
1288
1612
|
}
|
|
1289
1613
|
|
|
1290
1614
|
// src/openai/calls.ts
|
|
1291
1615
|
var DEFAULT_OPENAI_REASONING_EFFORT = "medium";
|
|
1292
|
-
var
|
|
1616
|
+
var scheduler3 = createCallScheduler({
|
|
1293
1617
|
maxParallelRequests: 3,
|
|
1294
1618
|
minIntervalBetweenStartMs: 200,
|
|
1295
1619
|
startJitterMs: 200
|
|
1296
1620
|
});
|
|
1297
1621
|
async function runOpenAiCall(fn) {
|
|
1298
|
-
return
|
|
1622
|
+
return scheduler3.run(async () => fn(getOpenAiClient()));
|
|
1299
1623
|
}
|
|
1300
1624
|
|
|
1301
1625
|
// src/llm.ts
|
|
@@ -1311,7 +1635,16 @@ var LlmJsonCallError = class extends Error {
|
|
|
1311
1635
|
}
|
|
1312
1636
|
};
|
|
1313
1637
|
function tool(options) {
|
|
1314
|
-
return
|
|
1638
|
+
return {
|
|
1639
|
+
type: "function",
|
|
1640
|
+
...options
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
function customTool(options) {
|
|
1644
|
+
return {
|
|
1645
|
+
type: "custom",
|
|
1646
|
+
...options
|
|
1647
|
+
};
|
|
1315
1648
|
}
|
|
1316
1649
|
function isPlainRecord(value) {
|
|
1317
1650
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1657,6 +1990,10 @@ function resolveProvider(model) {
|
|
|
1657
1990
|
if (model.startsWith("gemini-")) {
|
|
1658
1991
|
return { provider: "gemini", model };
|
|
1659
1992
|
}
|
|
1993
|
+
const fireworksModel = resolveFireworksModelId(model);
|
|
1994
|
+
if (fireworksModel) {
|
|
1995
|
+
return { provider: "fireworks", model: fireworksModel };
|
|
1996
|
+
}
|
|
1660
1997
|
return { provider: "openai", model };
|
|
1661
1998
|
}
|
|
1662
1999
|
function isOpenAiCodexModel(modelId) {
|
|
@@ -1686,6 +2023,27 @@ function toOpenAiReasoningEffort(effort) {
|
|
|
1686
2023
|
function resolveOpenAiVerbosity(modelId) {
|
|
1687
2024
|
return isOpenAiCodexModel(modelId) ? "medium" : "high";
|
|
1688
2025
|
}
|
|
2026
|
+
function isRetryableChatGptTransportError(error) {
|
|
2027
|
+
if (!(error instanceof Error)) {
|
|
2028
|
+
return false;
|
|
2029
|
+
}
|
|
2030
|
+
const message = error.message.toLowerCase();
|
|
2031
|
+
return message === "terminated" || message.includes("socket hang up") || message.includes("fetch failed") || message.includes("network");
|
|
2032
|
+
}
|
|
2033
|
+
async function collectChatGptCodexResponseWithRetry(options, maxAttempts = 2) {
|
|
2034
|
+
let attempt = 1;
|
|
2035
|
+
while (true) {
|
|
2036
|
+
try {
|
|
2037
|
+
return await collectChatGptCodexResponse(options);
|
|
2038
|
+
} catch (error) {
|
|
2039
|
+
if (attempt >= maxAttempts || !isRetryableChatGptTransportError(error)) {
|
|
2040
|
+
throw error;
|
|
2041
|
+
}
|
|
2042
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * attempt));
|
|
2043
|
+
attempt += 1;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
1689
2047
|
function isInlineImageMime(mimeType) {
|
|
1690
2048
|
if (!mimeType) {
|
|
1691
2049
|
return false;
|
|
@@ -2268,6 +2626,53 @@ function toChatGptInput(contents) {
|
|
|
2268
2626
|
input
|
|
2269
2627
|
};
|
|
2270
2628
|
}
|
|
2629
|
+
function toFireworksMessages(contents, options) {
|
|
2630
|
+
const systemMessages = [];
|
|
2631
|
+
const messages = [];
|
|
2632
|
+
if (options?.responseMimeType === "application/json") {
|
|
2633
|
+
systemMessages.push("Return valid JSON only. Do not include markdown or prose outside JSON.");
|
|
2634
|
+
}
|
|
2635
|
+
if (options?.responseJsonSchema) {
|
|
2636
|
+
systemMessages.push(`Target JSON schema:
|
|
2637
|
+
${JSON.stringify(options.responseJsonSchema)}`);
|
|
2638
|
+
}
|
|
2639
|
+
for (const content of contents) {
|
|
2640
|
+
const text = content.parts.map((part) => {
|
|
2641
|
+
if (part.type === "text") {
|
|
2642
|
+
return part.text;
|
|
2643
|
+
}
|
|
2644
|
+
const mimeType = part.mimeType ?? "application/octet-stream";
|
|
2645
|
+
if (isInlineImageMime(mimeType)) {
|
|
2646
|
+
return `[image:${mimeType}]`;
|
|
2647
|
+
}
|
|
2648
|
+
return `[file:${mimeType}]`;
|
|
2649
|
+
}).join("\n").trim();
|
|
2650
|
+
if (content.role === "system" || content.role === "developer") {
|
|
2651
|
+
if (text.length > 0) {
|
|
2652
|
+
systemMessages.push(text);
|
|
2653
|
+
}
|
|
2654
|
+
continue;
|
|
2655
|
+
}
|
|
2656
|
+
if (content.role === "tool" || content.role === "assistant") {
|
|
2657
|
+
messages.push({
|
|
2658
|
+
role: "assistant",
|
|
2659
|
+
content: text.length > 0 ? text : "(empty content)"
|
|
2660
|
+
});
|
|
2661
|
+
continue;
|
|
2662
|
+
}
|
|
2663
|
+
messages.push({
|
|
2664
|
+
role: "user",
|
|
2665
|
+
content: text.length > 0 ? text : "(empty content)"
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
if (systemMessages.length > 0) {
|
|
2669
|
+
messages.unshift({
|
|
2670
|
+
role: "system",
|
|
2671
|
+
content: systemMessages.join("\n\n")
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
return messages;
|
|
2675
|
+
}
|
|
2271
2676
|
function toGeminiTools(tools) {
|
|
2272
2677
|
if (!tools || tools.length === 0) {
|
|
2273
2678
|
return void 0;
|
|
@@ -2441,6 +2846,41 @@ function extractChatGptUsageTokens(usage) {
|
|
|
2441
2846
|
totalTokens
|
|
2442
2847
|
};
|
|
2443
2848
|
}
|
|
2849
|
+
function extractFireworksUsageTokens(usage) {
|
|
2850
|
+
if (!usage || typeof usage !== "object") {
|
|
2851
|
+
return void 0;
|
|
2852
|
+
}
|
|
2853
|
+
const promptTokens = toMaybeNumber(
|
|
2854
|
+
usage.prompt_tokens ?? usage.input_tokens
|
|
2855
|
+
);
|
|
2856
|
+
const cachedTokens = toMaybeNumber(
|
|
2857
|
+
usage.prompt_tokens_details?.cached_tokens ?? usage.input_tokens_details?.cached_tokens
|
|
2858
|
+
);
|
|
2859
|
+
const outputTokensRaw = toMaybeNumber(
|
|
2860
|
+
usage.completion_tokens ?? usage.output_tokens
|
|
2861
|
+
);
|
|
2862
|
+
const reasoningTokens = toMaybeNumber(
|
|
2863
|
+
usage.completion_tokens_details?.reasoning_tokens ?? usage.output_tokens_details?.reasoning_tokens
|
|
2864
|
+
);
|
|
2865
|
+
const totalTokens = toMaybeNumber(
|
|
2866
|
+
usage.total_tokens ?? usage.totalTokenCount
|
|
2867
|
+
);
|
|
2868
|
+
let responseTokens;
|
|
2869
|
+
if (outputTokensRaw !== void 0) {
|
|
2870
|
+
const adjusted = outputTokensRaw - (reasoningTokens ?? 0);
|
|
2871
|
+
responseTokens = adjusted >= 0 ? adjusted : 0;
|
|
2872
|
+
}
|
|
2873
|
+
if (promptTokens === void 0 && cachedTokens === void 0 && responseTokens === void 0 && reasoningTokens === void 0 && totalTokens === void 0) {
|
|
2874
|
+
return void 0;
|
|
2875
|
+
}
|
|
2876
|
+
return {
|
|
2877
|
+
promptTokens,
|
|
2878
|
+
cachedTokens,
|
|
2879
|
+
responseTokens,
|
|
2880
|
+
thinkingTokens: reasoningTokens,
|
|
2881
|
+
totalTokens
|
|
2882
|
+
};
|
|
2883
|
+
}
|
|
2444
2884
|
var MODERATION_FINISH_REASONS = /* @__PURE__ */ new Set([
|
|
2445
2885
|
import_genai2.FinishReason.SAFETY,
|
|
2446
2886
|
import_genai2.FinishReason.BLOCKLIST,
|
|
@@ -2479,8 +2919,8 @@ function parseOpenAiToolArguments(raw) {
|
|
|
2479
2919
|
function formatZodIssues(issues) {
|
|
2480
2920
|
const messages = [];
|
|
2481
2921
|
for (const issue of issues) {
|
|
2482
|
-
const
|
|
2483
|
-
messages.push(`${
|
|
2922
|
+
const path6 = issue.path.length > 0 ? issue.path.map(String).join(".") : "input";
|
|
2923
|
+
messages.push(`${path6}: ${issue.message}`);
|
|
2484
2924
|
}
|
|
2485
2925
|
return messages.join("; ");
|
|
2486
2926
|
}
|
|
@@ -2496,7 +2936,7 @@ function buildToolErrorOutput(message, issues) {
|
|
|
2496
2936
|
return output;
|
|
2497
2937
|
}
|
|
2498
2938
|
async function executeToolCall(params) {
|
|
2499
|
-
const { toolName, tool: tool2, rawInput, parseError } = params;
|
|
2939
|
+
const { callKind, toolName, tool: tool2, rawInput, parseError } = params;
|
|
2500
2940
|
if (!tool2) {
|
|
2501
2941
|
const message = `Unknown tool: ${toolName}`;
|
|
2502
2942
|
return {
|
|
@@ -2504,6 +2944,39 @@ async function executeToolCall(params) {
|
|
|
2504
2944
|
outputPayload: buildToolErrorOutput(message)
|
|
2505
2945
|
};
|
|
2506
2946
|
}
|
|
2947
|
+
if (callKind === "custom") {
|
|
2948
|
+
if (!isCustomTool(tool2)) {
|
|
2949
|
+
const message = `Tool ${toolName} was called as custom_tool_call but is declared as function.`;
|
|
2950
|
+
const outputPayload = buildToolErrorOutput(message);
|
|
2951
|
+
return {
|
|
2952
|
+
result: { toolName, input: rawInput, output: outputPayload, error: message },
|
|
2953
|
+
outputPayload
|
|
2954
|
+
};
|
|
2955
|
+
}
|
|
2956
|
+
const input = typeof rawInput === "string" ? rawInput : String(rawInput ?? "");
|
|
2957
|
+
try {
|
|
2958
|
+
const output = await tool2.execute(input);
|
|
2959
|
+
return {
|
|
2960
|
+
result: { toolName, input, output },
|
|
2961
|
+
outputPayload: output
|
|
2962
|
+
};
|
|
2963
|
+
} catch (error) {
|
|
2964
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2965
|
+
const outputPayload = buildToolErrorOutput(`Tool ${toolName} failed: ${message}`);
|
|
2966
|
+
return {
|
|
2967
|
+
result: { toolName, input, output: outputPayload, error: message },
|
|
2968
|
+
outputPayload
|
|
2969
|
+
};
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
if (isCustomTool(tool2)) {
|
|
2973
|
+
const message = `Tool ${toolName} was called as function_call but is declared as custom.`;
|
|
2974
|
+
const outputPayload = buildToolErrorOutput(message);
|
|
2975
|
+
return {
|
|
2976
|
+
result: { toolName, input: rawInput, output: outputPayload, error: message },
|
|
2977
|
+
outputPayload
|
|
2978
|
+
};
|
|
2979
|
+
}
|
|
2507
2980
|
if (parseError) {
|
|
2508
2981
|
const message = `Invalid JSON for tool ${toolName}: ${parseError}`;
|
|
2509
2982
|
return {
|
|
@@ -2560,8 +3033,12 @@ function normalizeChatGptToolIds(params) {
|
|
|
2560
3033
|
rawItemId = nextItemId ?? rawItemId;
|
|
2561
3034
|
}
|
|
2562
3035
|
const callValue = sanitizeChatGptToolId(rawCallId || rawItemId || (0, import_node_crypto.randomBytes)(8).toString("hex"));
|
|
2563
|
-
let itemValue = sanitizeChatGptToolId(rawItemId ||
|
|
2564
|
-
if (
|
|
3036
|
+
let itemValue = sanitizeChatGptToolId(rawItemId || callValue);
|
|
3037
|
+
if (params.callKind === "custom") {
|
|
3038
|
+
if (!itemValue.startsWith("ctc")) {
|
|
3039
|
+
itemValue = `ctc_${itemValue}`;
|
|
3040
|
+
}
|
|
3041
|
+
} else if (!itemValue.startsWith("fc")) {
|
|
2565
3042
|
itemValue = `fc-${itemValue}`;
|
|
2566
3043
|
}
|
|
2567
3044
|
return { callId: callValue, itemId: itemValue };
|
|
@@ -2626,7 +3103,7 @@ function extractOpenAiResponseParts(response) {
|
|
|
2626
3103
|
}
|
|
2627
3104
|
return { parts, blocked };
|
|
2628
3105
|
}
|
|
2629
|
-
function
|
|
3106
|
+
function extractOpenAiToolCalls(output) {
|
|
2630
3107
|
const calls = [];
|
|
2631
3108
|
if (!Array.isArray(output)) {
|
|
2632
3109
|
return calls;
|
|
@@ -2635,22 +3112,78 @@ function extractOpenAiFunctionCalls(output) {
|
|
|
2635
3112
|
if (!item || typeof item !== "object") {
|
|
2636
3113
|
continue;
|
|
2637
3114
|
}
|
|
2638
|
-
|
|
3115
|
+
const itemType = item.type;
|
|
3116
|
+
if (itemType === "function_call") {
|
|
2639
3117
|
const name = typeof item.name === "string" ? item.name : "";
|
|
2640
3118
|
const args = typeof item.arguments === "string" ? item.arguments : "";
|
|
2641
3119
|
const call_id = typeof item.call_id === "string" ? item.call_id : "";
|
|
2642
3120
|
const id = typeof item.id === "string" ? item.id : void 0;
|
|
2643
3121
|
if (name && call_id) {
|
|
2644
|
-
calls.push({ name, arguments: args, call_id, id });
|
|
3122
|
+
calls.push({ kind: "function", name, arguments: args, call_id, id });
|
|
3123
|
+
}
|
|
3124
|
+
continue;
|
|
3125
|
+
}
|
|
3126
|
+
if (itemType === "custom_tool_call") {
|
|
3127
|
+
const name = typeof item.name === "string" ? item.name : "";
|
|
3128
|
+
const input = typeof item.input === "string" ? item.input : "";
|
|
3129
|
+
const call_id = typeof item.call_id === "string" ? item.call_id : "";
|
|
3130
|
+
const id = typeof item.id === "string" ? item.id : void 0;
|
|
3131
|
+
if (name && call_id) {
|
|
3132
|
+
calls.push({ kind: "custom", name, input, call_id, id });
|
|
2645
3133
|
}
|
|
2646
3134
|
}
|
|
2647
3135
|
}
|
|
2648
3136
|
return calls;
|
|
2649
3137
|
}
|
|
3138
|
+
function extractFireworksMessageText(message) {
|
|
3139
|
+
if (!message || typeof message !== "object") {
|
|
3140
|
+
return "";
|
|
3141
|
+
}
|
|
3142
|
+
const content = message.content;
|
|
3143
|
+
if (typeof content === "string") {
|
|
3144
|
+
return content;
|
|
3145
|
+
}
|
|
3146
|
+
if (!Array.isArray(content)) {
|
|
3147
|
+
return "";
|
|
3148
|
+
}
|
|
3149
|
+
let text = "";
|
|
3150
|
+
for (const part of content) {
|
|
3151
|
+
const textPart = part.text;
|
|
3152
|
+
if (typeof textPart === "string") {
|
|
3153
|
+
text += textPart;
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
return text;
|
|
3157
|
+
}
|
|
3158
|
+
function extractFireworksToolCalls(message) {
|
|
3159
|
+
if (!message || typeof message !== "object") {
|
|
3160
|
+
return [];
|
|
3161
|
+
}
|
|
3162
|
+
const toolCalls = message.tool_calls;
|
|
3163
|
+
if (!Array.isArray(toolCalls)) {
|
|
3164
|
+
return [];
|
|
3165
|
+
}
|
|
3166
|
+
const calls = [];
|
|
3167
|
+
for (const call of toolCalls) {
|
|
3168
|
+
if (!call || typeof call !== "object") {
|
|
3169
|
+
continue;
|
|
3170
|
+
}
|
|
3171
|
+
const id = typeof call.id === "string" ? call.id : "";
|
|
3172
|
+
const fn = call.function;
|
|
3173
|
+
const name = fn && typeof fn === "object" && typeof fn.name === "string" ? fn.name ?? "" : "";
|
|
3174
|
+
const args = fn && typeof fn === "object" && typeof fn.arguments === "string" ? fn.arguments ?? "" : "";
|
|
3175
|
+
if (id && name) {
|
|
3176
|
+
calls.push({ id, name, arguments: args });
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
return calls;
|
|
3180
|
+
}
|
|
2650
3181
|
function resolveGeminiThinkingConfig(modelId) {
|
|
2651
3182
|
switch (modelId) {
|
|
2652
3183
|
case "gemini-3-pro-preview":
|
|
2653
3184
|
return { includeThoughts: true };
|
|
3185
|
+
case "gemini-3-flash-preview":
|
|
3186
|
+
return { includeThoughts: true, thinkingBudget: 16384 };
|
|
2654
3187
|
case "gemini-2.5-pro":
|
|
2655
3188
|
return { includeThoughts: true, thinkingBudget: 32768 };
|
|
2656
3189
|
case "gemini-flash-latest":
|
|
@@ -2826,7 +3359,7 @@ async function runTextCall(params) {
|
|
|
2826
3359
|
};
|
|
2827
3360
|
let sawResponseDelta = false;
|
|
2828
3361
|
let sawThoughtDelta = false;
|
|
2829
|
-
const result = await
|
|
3362
|
+
const result = await collectChatGptCodexResponseWithRetry({
|
|
2830
3363
|
request: requestPayload,
|
|
2831
3364
|
signal,
|
|
2832
3365
|
onDelta: (delta) => {
|
|
@@ -2857,6 +3390,47 @@ async function runTextCall(params) {
|
|
|
2857
3390
|
if (!sawResponseDelta && fallbackText.length > 0) {
|
|
2858
3391
|
pushDelta("response", fallbackText);
|
|
2859
3392
|
}
|
|
3393
|
+
} else if (provider === "fireworks") {
|
|
3394
|
+
if (request.tools && request.tools.length > 0) {
|
|
3395
|
+
throw new Error(
|
|
3396
|
+
"Fireworks provider does not support provider-native tools in generateText; use runToolLoop for function tools."
|
|
3397
|
+
);
|
|
3398
|
+
}
|
|
3399
|
+
const fireworksMessages = toFireworksMessages(contents, {
|
|
3400
|
+
responseMimeType: request.responseMimeType,
|
|
3401
|
+
responseJsonSchema: request.responseJsonSchema
|
|
3402
|
+
});
|
|
3403
|
+
await runFireworksCall(async (client) => {
|
|
3404
|
+
const responseFormat = request.responseJsonSchema ? {
|
|
3405
|
+
type: "json_schema",
|
|
3406
|
+
json_schema: {
|
|
3407
|
+
name: "llm-response",
|
|
3408
|
+
schema: request.responseJsonSchema
|
|
3409
|
+
}
|
|
3410
|
+
} : request.responseMimeType === "application/json" ? { type: "json_object" } : void 0;
|
|
3411
|
+
const response = await client.chat.completions.create(
|
|
3412
|
+
{
|
|
3413
|
+
model: modelForProvider,
|
|
3414
|
+
messages: fireworksMessages,
|
|
3415
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
3416
|
+
},
|
|
3417
|
+
{ signal }
|
|
3418
|
+
);
|
|
3419
|
+
modelVersion = typeof response.model === "string" ? response.model : request.model;
|
|
3420
|
+
queue.push({ type: "model", modelVersion });
|
|
3421
|
+
const choice = Array.isArray(response.choices) ? response.choices[0] : void 0;
|
|
3422
|
+
if (choice?.finish_reason === "content_filter") {
|
|
3423
|
+
blocked = true;
|
|
3424
|
+
queue.push({ type: "blocked" });
|
|
3425
|
+
}
|
|
3426
|
+
const textOutput = extractFireworksMessageText(
|
|
3427
|
+
choice?.message
|
|
3428
|
+
);
|
|
3429
|
+
if (textOutput.length > 0) {
|
|
3430
|
+
pushDelta("response", textOutput);
|
|
3431
|
+
}
|
|
3432
|
+
latestUsage = extractFireworksUsageTokens(response.usage);
|
|
3433
|
+
});
|
|
2860
3434
|
} else {
|
|
2861
3435
|
const geminiContents = contents.map(convertLlmContentToGeminiContent);
|
|
2862
3436
|
const config = {
|
|
@@ -2981,11 +3555,12 @@ function buildJsonSchemaConfig(request) {
|
|
|
2981
3555
|
const schemaName = (request.openAiSchemaName ?? "llm-response").trim() || "llm-response";
|
|
2982
3556
|
const providerInfo = resolveProvider(request.model);
|
|
2983
3557
|
const isOpenAiVariant = providerInfo.provider === "openai" || providerInfo.provider === "chatgpt";
|
|
3558
|
+
const isGeminiVariant = providerInfo.provider === "gemini";
|
|
2984
3559
|
const baseJsonSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(request.schema, {
|
|
2985
3560
|
name: schemaName,
|
|
2986
3561
|
target: isOpenAiVariant ? "openAi" : "jsonSchema7"
|
|
2987
3562
|
});
|
|
2988
|
-
const responseJsonSchema = isOpenAiVariant ? resolveOpenAiSchemaRoot(baseJsonSchema) : addGeminiPropertyOrdering(baseJsonSchema);
|
|
3563
|
+
const responseJsonSchema = isOpenAiVariant ? resolveOpenAiSchemaRoot(baseJsonSchema) : isGeminiVariant ? addGeminiPropertyOrdering(baseJsonSchema) : resolveOpenAiSchemaRoot(baseJsonSchema);
|
|
2989
3564
|
if (isOpenAiVariant && !isJsonSchemaObject(responseJsonSchema)) {
|
|
2990
3565
|
throw new Error("OpenAI structured outputs require a JSON object schema at the root.");
|
|
2991
3566
|
}
|
|
@@ -3152,15 +3727,46 @@ var DEFAULT_TOOL_LOOP_MAX_STEPS = 8;
|
|
|
3152
3727
|
function resolveToolLoopContents(input) {
|
|
3153
3728
|
return resolveTextContents(input);
|
|
3154
3729
|
}
|
|
3155
|
-
function
|
|
3730
|
+
function isCustomTool(toolDef) {
|
|
3731
|
+
return toolDef.type === "custom";
|
|
3732
|
+
}
|
|
3733
|
+
function buildOpenAiToolsFromToolSet(tools) {
|
|
3156
3734
|
const toolEntries = Object.entries(tools);
|
|
3157
|
-
return toolEntries.map(([name, toolDef]) =>
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3735
|
+
return toolEntries.map(([name, toolDef]) => {
|
|
3736
|
+
if (isCustomTool(toolDef)) {
|
|
3737
|
+
return {
|
|
3738
|
+
type: "custom",
|
|
3739
|
+
name,
|
|
3740
|
+
description: toolDef.description ?? void 0,
|
|
3741
|
+
...toolDef.format ? { format: toolDef.format } : {}
|
|
3742
|
+
};
|
|
3743
|
+
}
|
|
3744
|
+
return {
|
|
3745
|
+
type: "function",
|
|
3746
|
+
name,
|
|
3747
|
+
description: toolDef.description ?? void 0,
|
|
3748
|
+
parameters: buildOpenAiToolSchema(toolDef.inputSchema, name),
|
|
3749
|
+
strict: true
|
|
3750
|
+
};
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
function buildFireworksToolsFromToolSet(tools) {
|
|
3754
|
+
const toolEntries = Object.entries(tools);
|
|
3755
|
+
return toolEntries.map(([name, toolDef]) => {
|
|
3756
|
+
if (isCustomTool(toolDef)) {
|
|
3757
|
+
throw new Error(
|
|
3758
|
+
`Fireworks provider does not support custom/freeform tools (${name}). Use JSON function tools instead.`
|
|
3759
|
+
);
|
|
3760
|
+
}
|
|
3761
|
+
return {
|
|
3762
|
+
type: "function",
|
|
3763
|
+
function: {
|
|
3764
|
+
name,
|
|
3765
|
+
description: toolDef.description ?? void 0,
|
|
3766
|
+
parameters: buildOpenAiToolSchema(toolDef.inputSchema, name)
|
|
3767
|
+
}
|
|
3768
|
+
};
|
|
3769
|
+
});
|
|
3164
3770
|
}
|
|
3165
3771
|
function buildOpenAiToolSchema(schema, name) {
|
|
3166
3772
|
const rawSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(schema, { name, target: "openAi" });
|
|
@@ -3172,11 +3778,18 @@ function buildOpenAiToolSchema(schema, name) {
|
|
|
3172
3778
|
}
|
|
3173
3779
|
function buildGeminiFunctionDeclarations(tools) {
|
|
3174
3780
|
const toolEntries = Object.entries(tools);
|
|
3175
|
-
const functionDeclarations = toolEntries.map(([name, toolDef]) =>
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3781
|
+
const functionDeclarations = toolEntries.map(([name, toolDef]) => {
|
|
3782
|
+
if (isCustomTool(toolDef)) {
|
|
3783
|
+
throw new Error(
|
|
3784
|
+
`Gemini provider does not support custom/freeform tools (${name}). Use JSON function tools instead.`
|
|
3785
|
+
);
|
|
3786
|
+
}
|
|
3787
|
+
return {
|
|
3788
|
+
name,
|
|
3789
|
+
description: toolDef.description ?? "",
|
|
3790
|
+
parametersJsonSchema: buildGeminiToolSchema(toolDef.inputSchema, name)
|
|
3791
|
+
};
|
|
3792
|
+
});
|
|
3180
3793
|
return [{ functionDeclarations }];
|
|
3181
3794
|
}
|
|
3182
3795
|
function buildGeminiToolSchema(schema, name) {
|
|
@@ -3237,9 +3850,9 @@ async function runToolLoop(request) {
|
|
|
3237
3850
|
let finalText = "";
|
|
3238
3851
|
let finalThoughts = "";
|
|
3239
3852
|
if (providerInfo.provider === "openai") {
|
|
3240
|
-
const
|
|
3853
|
+
const openAiAgentTools = buildOpenAiToolsFromToolSet(request.tools);
|
|
3241
3854
|
const openAiNativeTools = toOpenAiTools(request.modelTools);
|
|
3242
|
-
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...
|
|
3855
|
+
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...openAiAgentTools] : [...openAiAgentTools];
|
|
3243
3856
|
const reasoningEffort = resolveOpenAiReasoningEffort(
|
|
3244
3857
|
providerInfo.model,
|
|
3245
3858
|
request.openAiReasoningEffort
|
|
@@ -3331,9 +3944,9 @@ async function runToolLoop(request) {
|
|
|
3331
3944
|
if (usageTokens) {
|
|
3332
3945
|
emitEvent({ type: "usage", usage: usageTokens, costUsd: stepCostUsd, modelVersion });
|
|
3333
3946
|
}
|
|
3334
|
-
const
|
|
3947
|
+
const responseToolCalls = extractOpenAiToolCalls(finalResponse.output);
|
|
3335
3948
|
const stepToolCalls = [];
|
|
3336
|
-
if (
|
|
3949
|
+
if (responseToolCalls.length === 0) {
|
|
3337
3950
|
finalText = responseText;
|
|
3338
3951
|
finalThoughts = reasoningSummary;
|
|
3339
3952
|
steps.push({
|
|
@@ -3347,10 +3960,21 @@ async function runToolLoop(request) {
|
|
|
3347
3960
|
});
|
|
3348
3961
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
3349
3962
|
}
|
|
3350
|
-
const callInputs =
|
|
3963
|
+
const callInputs = responseToolCalls.map((call, index) => {
|
|
3351
3964
|
const toolIndex = index + 1;
|
|
3352
3965
|
const toolId = buildToolLogId(turn, toolIndex);
|
|
3353
3966
|
const toolName = call.name;
|
|
3967
|
+
if (call.kind === "custom") {
|
|
3968
|
+
return {
|
|
3969
|
+
call,
|
|
3970
|
+
toolName,
|
|
3971
|
+
value: call.input,
|
|
3972
|
+
parseError: void 0,
|
|
3973
|
+
toolId,
|
|
3974
|
+
turn,
|
|
3975
|
+
toolIndex
|
|
3976
|
+
};
|
|
3977
|
+
}
|
|
3354
3978
|
const { value, error: parseError } = parseOpenAiToolArguments(call.arguments);
|
|
3355
3979
|
return { call, toolName, value, parseError, toolId, turn, toolIndex };
|
|
3356
3980
|
});
|
|
@@ -3365,6 +3989,7 @@ async function runToolLoop(request) {
|
|
|
3365
3989
|
},
|
|
3366
3990
|
async () => {
|
|
3367
3991
|
const { result, outputPayload } = await executeToolCall({
|
|
3992
|
+
callKind: entry.call.kind,
|
|
3368
3993
|
toolName: entry.toolName,
|
|
3369
3994
|
tool: request.tools[entry.toolName],
|
|
3370
3995
|
rawInput: entry.value,
|
|
@@ -3378,11 +4003,19 @@ async function runToolLoop(request) {
|
|
|
3378
4003
|
const toolOutputs = [];
|
|
3379
4004
|
for (const { entry, result, outputPayload } of callResults) {
|
|
3380
4005
|
stepToolCalls.push({ ...result, callId: entry.call.call_id });
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
4006
|
+
if (entry.call.kind === "custom") {
|
|
4007
|
+
toolOutputs.push({
|
|
4008
|
+
type: "custom_tool_call_output",
|
|
4009
|
+
call_id: entry.call.call_id,
|
|
4010
|
+
output: mergeToolOutput(outputPayload)
|
|
4011
|
+
});
|
|
4012
|
+
} else {
|
|
4013
|
+
toolOutputs.push({
|
|
4014
|
+
type: "function_call_output",
|
|
4015
|
+
call_id: entry.call.call_id,
|
|
4016
|
+
output: mergeToolOutput(outputPayload)
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
3386
4019
|
}
|
|
3387
4020
|
steps.push({
|
|
3388
4021
|
step: steps.length + 1,
|
|
@@ -3399,24 +4032,28 @@ async function runToolLoop(request) {
|
|
|
3399
4032
|
throw new Error(`Tool loop exceeded max steps (${maxSteps}) without final response.`);
|
|
3400
4033
|
}
|
|
3401
4034
|
if (providerInfo.provider === "chatgpt") {
|
|
3402
|
-
const
|
|
4035
|
+
const openAiAgentTools = buildOpenAiToolsFromToolSet(request.tools);
|
|
3403
4036
|
const openAiNativeTools = toOpenAiTools(request.modelTools);
|
|
3404
|
-
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...
|
|
4037
|
+
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...openAiAgentTools] : [...openAiAgentTools];
|
|
3405
4038
|
const reasoningEffort = resolveOpenAiReasoningEffort(
|
|
3406
4039
|
request.model,
|
|
3407
4040
|
request.openAiReasoningEffort
|
|
3408
4041
|
);
|
|
3409
4042
|
const toolLoopInput = toChatGptInput(contents);
|
|
4043
|
+
const conversationId = `tool-loop-${(0, import_node_crypto.randomBytes)(8).toString("hex")}`;
|
|
4044
|
+
const promptCacheKey = conversationId;
|
|
3410
4045
|
let input = [...toolLoopInput.input];
|
|
3411
4046
|
for (let stepIndex = 0; stepIndex < maxSteps; stepIndex += 1) {
|
|
3412
4047
|
const turn = stepIndex + 1;
|
|
3413
|
-
const response = await
|
|
4048
|
+
const response = await collectChatGptCodexResponseWithRetry({
|
|
4049
|
+
sessionId: conversationId,
|
|
3414
4050
|
request: {
|
|
3415
4051
|
model: providerInfo.model,
|
|
3416
4052
|
store: false,
|
|
3417
4053
|
stream: true,
|
|
3418
4054
|
instructions: toolLoopInput.instructions ?? "You are a helpful assistant.",
|
|
3419
4055
|
input,
|
|
4056
|
+
prompt_cache_key: promptCacheKey,
|
|
3420
4057
|
include: ["reasoning.encrypted_content"],
|
|
3421
4058
|
tools: openAiTools,
|
|
3422
4059
|
tool_choice: "auto",
|
|
@@ -3447,8 +4084,8 @@ async function runToolLoop(request) {
|
|
|
3447
4084
|
totalCostUsd += stepCostUsd;
|
|
3448
4085
|
const responseText = (response.text ?? "").trim();
|
|
3449
4086
|
const reasoningSummaryText = (response.reasoningSummaryText ?? "").trim();
|
|
3450
|
-
const
|
|
3451
|
-
if (
|
|
4087
|
+
const responseToolCalls = response.toolCalls ?? [];
|
|
4088
|
+
if (responseToolCalls.length === 0) {
|
|
3452
4089
|
finalText = responseText;
|
|
3453
4090
|
finalThoughts = reasoningSummaryText;
|
|
3454
4091
|
steps.push({
|
|
@@ -3464,12 +4101,16 @@ async function runToolLoop(request) {
|
|
|
3464
4101
|
}
|
|
3465
4102
|
const toolCalls = [];
|
|
3466
4103
|
const toolOutputs = [];
|
|
3467
|
-
const callInputs =
|
|
4104
|
+
const callInputs = responseToolCalls.map((call, index) => {
|
|
3468
4105
|
const toolIndex = index + 1;
|
|
3469
4106
|
const toolId = buildToolLogId(turn, toolIndex);
|
|
3470
4107
|
const toolName = call.name;
|
|
3471
|
-
const { value, error: parseError } = parseOpenAiToolArguments(call.arguments);
|
|
3472
|
-
const ids = normalizeChatGptToolIds({
|
|
4108
|
+
const { value, error: parseError } = call.kind === "custom" ? { value: call.input, error: void 0 } : parseOpenAiToolArguments(call.arguments);
|
|
4109
|
+
const ids = normalizeChatGptToolIds({
|
|
4110
|
+
callKind: call.kind,
|
|
4111
|
+
callId: call.callId,
|
|
4112
|
+
itemId: call.id
|
|
4113
|
+
});
|
|
3473
4114
|
return { call, toolName, value, parseError, ids, toolId, turn, toolIndex };
|
|
3474
4115
|
});
|
|
3475
4116
|
const callResults = await Promise.all(
|
|
@@ -3483,6 +4124,7 @@ async function runToolLoop(request) {
|
|
|
3483
4124
|
},
|
|
3484
4125
|
async () => {
|
|
3485
4126
|
const { result, outputPayload } = await executeToolCall({
|
|
4127
|
+
callKind: entry.call.kind,
|
|
3486
4128
|
toolName: entry.toolName,
|
|
3487
4129
|
tool: request.tools[entry.toolName],
|
|
3488
4130
|
rawInput: entry.value,
|
|
@@ -3495,19 +4137,35 @@ async function runToolLoop(request) {
|
|
|
3495
4137
|
);
|
|
3496
4138
|
for (const { entry, result, outputPayload } of callResults) {
|
|
3497
4139
|
toolCalls.push({ ...result, callId: entry.ids.callId });
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
4140
|
+
if (entry.call.kind === "custom") {
|
|
4141
|
+
toolOutputs.push({
|
|
4142
|
+
type: "custom_tool_call",
|
|
4143
|
+
id: entry.ids.itemId,
|
|
4144
|
+
call_id: entry.ids.callId,
|
|
4145
|
+
name: entry.toolName,
|
|
4146
|
+
input: entry.call.input,
|
|
4147
|
+
status: "completed"
|
|
4148
|
+
});
|
|
4149
|
+
toolOutputs.push({
|
|
4150
|
+
type: "custom_tool_call_output",
|
|
4151
|
+
call_id: entry.ids.callId,
|
|
4152
|
+
output: mergeToolOutput(outputPayload)
|
|
4153
|
+
});
|
|
4154
|
+
} else {
|
|
4155
|
+
toolOutputs.push({
|
|
4156
|
+
type: "function_call",
|
|
4157
|
+
id: entry.ids.itemId,
|
|
4158
|
+
call_id: entry.ids.callId,
|
|
4159
|
+
name: entry.toolName,
|
|
4160
|
+
arguments: entry.call.arguments,
|
|
4161
|
+
status: "completed"
|
|
4162
|
+
});
|
|
4163
|
+
toolOutputs.push({
|
|
4164
|
+
type: "function_call_output",
|
|
4165
|
+
call_id: entry.ids.callId,
|
|
4166
|
+
output: mergeToolOutput(outputPayload)
|
|
4167
|
+
});
|
|
4168
|
+
}
|
|
3511
4169
|
}
|
|
3512
4170
|
steps.push({
|
|
3513
4171
|
step: steps.length + 1,
|
|
@@ -3522,6 +4180,134 @@ async function runToolLoop(request) {
|
|
|
3522
4180
|
}
|
|
3523
4181
|
throw new Error(`Tool loop exceeded max steps (${maxSteps}) without final response.`);
|
|
3524
4182
|
}
|
|
4183
|
+
if (providerInfo.provider === "fireworks") {
|
|
4184
|
+
if (request.modelTools && request.modelTools.length > 0) {
|
|
4185
|
+
throw new Error(
|
|
4186
|
+
"Fireworks provider does not support provider-native modelTools in runToolLoop."
|
|
4187
|
+
);
|
|
4188
|
+
}
|
|
4189
|
+
const fireworksTools = buildFireworksToolsFromToolSet(request.tools);
|
|
4190
|
+
const messages = toFireworksMessages(contents);
|
|
4191
|
+
for (let stepIndex = 0; stepIndex < maxSteps; stepIndex += 1) {
|
|
4192
|
+
const turn = stepIndex + 1;
|
|
4193
|
+
const response = await runFireworksCall(async (client) => {
|
|
4194
|
+
return await client.chat.completions.create(
|
|
4195
|
+
{
|
|
4196
|
+
model: providerInfo.model,
|
|
4197
|
+
messages,
|
|
4198
|
+
tools: fireworksTools,
|
|
4199
|
+
tool_choice: "auto",
|
|
4200
|
+
parallel_tool_calls: true
|
|
4201
|
+
},
|
|
4202
|
+
{ signal: request.signal }
|
|
4203
|
+
);
|
|
4204
|
+
});
|
|
4205
|
+
const modelVersion = typeof response.model === "string" ? response.model : request.model;
|
|
4206
|
+
request.onEvent?.({ type: "model", modelVersion });
|
|
4207
|
+
const choice = Array.isArray(response.choices) ? response.choices[0] : void 0;
|
|
4208
|
+
if (choice?.finish_reason === "content_filter") {
|
|
4209
|
+
request.onEvent?.({ type: "blocked" });
|
|
4210
|
+
}
|
|
4211
|
+
const message = choice?.message;
|
|
4212
|
+
const responseText = extractFireworksMessageText(message).trim();
|
|
4213
|
+
if (responseText.length > 0) {
|
|
4214
|
+
request.onEvent?.({ type: "delta", channel: "response", text: responseText });
|
|
4215
|
+
}
|
|
4216
|
+
const usageTokens = extractFireworksUsageTokens(response.usage);
|
|
4217
|
+
const stepCostUsd = estimateCallCostUsd({
|
|
4218
|
+
modelId: modelVersion,
|
|
4219
|
+
tokens: usageTokens,
|
|
4220
|
+
responseImages: 0
|
|
4221
|
+
});
|
|
4222
|
+
totalCostUsd += stepCostUsd;
|
|
4223
|
+
if (usageTokens) {
|
|
4224
|
+
request.onEvent?.({
|
|
4225
|
+
type: "usage",
|
|
4226
|
+
usage: usageTokens,
|
|
4227
|
+
costUsd: stepCostUsd,
|
|
4228
|
+
modelVersion
|
|
4229
|
+
});
|
|
4230
|
+
}
|
|
4231
|
+
const responseToolCalls = extractFireworksToolCalls(message);
|
|
4232
|
+
if (responseToolCalls.length === 0) {
|
|
4233
|
+
finalText = responseText;
|
|
4234
|
+
finalThoughts = "";
|
|
4235
|
+
steps.push({
|
|
4236
|
+
step: steps.length + 1,
|
|
4237
|
+
modelVersion,
|
|
4238
|
+
text: responseText || void 0,
|
|
4239
|
+
thoughts: void 0,
|
|
4240
|
+
toolCalls: [],
|
|
4241
|
+
usage: usageTokens,
|
|
4242
|
+
costUsd: stepCostUsd
|
|
4243
|
+
});
|
|
4244
|
+
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
4245
|
+
}
|
|
4246
|
+
const stepToolCalls = [];
|
|
4247
|
+
const callInputs = responseToolCalls.map((call, index) => {
|
|
4248
|
+
const toolIndex = index + 1;
|
|
4249
|
+
const toolId = buildToolLogId(turn, toolIndex);
|
|
4250
|
+
const { value, error: parseError } = parseOpenAiToolArguments(call.arguments);
|
|
4251
|
+
return { call, toolName: call.name, value, parseError, toolId, turn, toolIndex };
|
|
4252
|
+
});
|
|
4253
|
+
const callResults = await Promise.all(
|
|
4254
|
+
callInputs.map(async (entry) => {
|
|
4255
|
+
return await toolCallContextStorage.run(
|
|
4256
|
+
{
|
|
4257
|
+
toolName: entry.toolName,
|
|
4258
|
+
toolId: entry.toolId,
|
|
4259
|
+
turn: entry.turn,
|
|
4260
|
+
toolIndex: entry.toolIndex
|
|
4261
|
+
},
|
|
4262
|
+
async () => {
|
|
4263
|
+
const { result, outputPayload } = await executeToolCall({
|
|
4264
|
+
callKind: "function",
|
|
4265
|
+
toolName: entry.toolName,
|
|
4266
|
+
tool: request.tools[entry.toolName],
|
|
4267
|
+
rawInput: entry.value,
|
|
4268
|
+
parseError: entry.parseError
|
|
4269
|
+
});
|
|
4270
|
+
return { entry, result, outputPayload };
|
|
4271
|
+
}
|
|
4272
|
+
);
|
|
4273
|
+
})
|
|
4274
|
+
);
|
|
4275
|
+
const assistantToolCalls = [];
|
|
4276
|
+
const toolMessages = [];
|
|
4277
|
+
for (const { entry, result, outputPayload } of callResults) {
|
|
4278
|
+
stepToolCalls.push({ ...result, callId: entry.call.id });
|
|
4279
|
+
assistantToolCalls.push({
|
|
4280
|
+
id: entry.call.id,
|
|
4281
|
+
type: "function",
|
|
4282
|
+
function: {
|
|
4283
|
+
name: entry.toolName,
|
|
4284
|
+
arguments: entry.call.arguments
|
|
4285
|
+
}
|
|
4286
|
+
});
|
|
4287
|
+
toolMessages.push({
|
|
4288
|
+
role: "tool",
|
|
4289
|
+
tool_call_id: entry.call.id,
|
|
4290
|
+
content: mergeToolOutput(outputPayload)
|
|
4291
|
+
});
|
|
4292
|
+
}
|
|
4293
|
+
steps.push({
|
|
4294
|
+
step: steps.length + 1,
|
|
4295
|
+
modelVersion,
|
|
4296
|
+
text: responseText || void 0,
|
|
4297
|
+
thoughts: void 0,
|
|
4298
|
+
toolCalls: stepToolCalls,
|
|
4299
|
+
usage: usageTokens,
|
|
4300
|
+
costUsd: stepCostUsd
|
|
4301
|
+
});
|
|
4302
|
+
messages.push({
|
|
4303
|
+
role: "assistant",
|
|
4304
|
+
...responseText.length > 0 ? { content: responseText } : {},
|
|
4305
|
+
tool_calls: assistantToolCalls
|
|
4306
|
+
});
|
|
4307
|
+
messages.push(...toolMessages);
|
|
4308
|
+
}
|
|
4309
|
+
throw new Error(`Tool loop exceeded max steps (${maxSteps}) without final response.`);
|
|
4310
|
+
}
|
|
3525
4311
|
const geminiFunctionTools = buildGeminiFunctionDeclarations(request.tools);
|
|
3526
4312
|
const geminiNativeTools = toGeminiTools(request.modelTools);
|
|
3527
4313
|
const geminiTools = geminiNativeTools ? geminiNativeTools.concat(geminiFunctionTools) : geminiFunctionTools;
|
|
@@ -3671,6 +4457,7 @@ async function runToolLoop(request) {
|
|
|
3671
4457
|
},
|
|
3672
4458
|
async () => {
|
|
3673
4459
|
const { result, outputPayload } = await executeToolCall({
|
|
4460
|
+
callKind: "function",
|
|
3674
4461
|
toolName: entry.toolName,
|
|
3675
4462
|
tool: request.tools[entry.toolName],
|
|
3676
4463
|
rawInput: entry.rawInput
|
|
@@ -3950,26 +4737,26 @@ ${lines}`;
|
|
|
3950
4737
|
}
|
|
3951
4738
|
|
|
3952
4739
|
// src/tools/filesystemTools.ts
|
|
3953
|
-
var
|
|
4740
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
3954
4741
|
var import_zod5 = require("zod");
|
|
3955
4742
|
|
|
3956
4743
|
// src/tools/applyPatch.ts
|
|
3957
|
-
var
|
|
4744
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
3958
4745
|
var import_zod4 = require("zod");
|
|
3959
4746
|
|
|
3960
4747
|
// src/tools/filesystem.ts
|
|
3961
|
-
var
|
|
3962
|
-
var
|
|
4748
|
+
var import_node_fs3 = require("fs");
|
|
4749
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
3963
4750
|
var InMemoryAgentFilesystem = class {
|
|
3964
4751
|
#files = /* @__PURE__ */ new Map();
|
|
3965
4752
|
#dirs = /* @__PURE__ */ new Map();
|
|
3966
4753
|
#clock = 0;
|
|
3967
4754
|
constructor(initialFiles = {}) {
|
|
3968
|
-
const root =
|
|
4755
|
+
const root = import_node_path3.default.resolve("/");
|
|
3969
4756
|
this.#dirs.set(root, { mtimeMs: this.#nextMtime() });
|
|
3970
4757
|
for (const [filePath, content] of Object.entries(initialFiles)) {
|
|
3971
|
-
const absolutePath =
|
|
3972
|
-
this.#ensureDirSync(
|
|
4758
|
+
const absolutePath = import_node_path3.default.resolve(filePath);
|
|
4759
|
+
this.#ensureDirSync(import_node_path3.default.dirname(absolutePath));
|
|
3973
4760
|
this.#files.set(absolutePath, {
|
|
3974
4761
|
content,
|
|
3975
4762
|
mtimeMs: this.#nextMtime()
|
|
@@ -3977,7 +4764,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
3977
4764
|
}
|
|
3978
4765
|
}
|
|
3979
4766
|
async readTextFile(filePath) {
|
|
3980
|
-
const absolutePath =
|
|
4767
|
+
const absolutePath = import_node_path3.default.resolve(filePath);
|
|
3981
4768
|
const file = this.#files.get(absolutePath);
|
|
3982
4769
|
if (!file) {
|
|
3983
4770
|
throw createNoSuchFileError("open", absolutePath);
|
|
@@ -3985,24 +4772,24 @@ var InMemoryAgentFilesystem = class {
|
|
|
3985
4772
|
return file.content;
|
|
3986
4773
|
}
|
|
3987
4774
|
async writeTextFile(filePath, content) {
|
|
3988
|
-
const absolutePath =
|
|
3989
|
-
const parentPath =
|
|
4775
|
+
const absolutePath = import_node_path3.default.resolve(filePath);
|
|
4776
|
+
const parentPath = import_node_path3.default.dirname(absolutePath);
|
|
3990
4777
|
if (!this.#dirs.has(parentPath)) {
|
|
3991
4778
|
throw createNoSuchFileError("open", parentPath);
|
|
3992
4779
|
}
|
|
3993
4780
|
this.#files.set(absolutePath, { content, mtimeMs: this.#nextMtime() });
|
|
3994
4781
|
}
|
|
3995
4782
|
async deleteFile(filePath) {
|
|
3996
|
-
const absolutePath =
|
|
4783
|
+
const absolutePath = import_node_path3.default.resolve(filePath);
|
|
3997
4784
|
if (!this.#files.delete(absolutePath)) {
|
|
3998
4785
|
throw createNoSuchFileError("unlink", absolutePath);
|
|
3999
4786
|
}
|
|
4000
4787
|
}
|
|
4001
4788
|
async ensureDir(directoryPath) {
|
|
4002
|
-
this.#ensureDirSync(
|
|
4789
|
+
this.#ensureDirSync(import_node_path3.default.resolve(directoryPath));
|
|
4003
4790
|
}
|
|
4004
4791
|
async readDir(directoryPath) {
|
|
4005
|
-
const absolutePath =
|
|
4792
|
+
const absolutePath = import_node_path3.default.resolve(directoryPath);
|
|
4006
4793
|
const directory = this.#dirs.get(absolutePath);
|
|
4007
4794
|
if (!directory) {
|
|
4008
4795
|
throw createNoSuchFileError("scandir", absolutePath);
|
|
@@ -4013,10 +4800,10 @@ var InMemoryAgentFilesystem = class {
|
|
|
4013
4800
|
if (dirPath === absolutePath) {
|
|
4014
4801
|
continue;
|
|
4015
4802
|
}
|
|
4016
|
-
if (
|
|
4803
|
+
if (import_node_path3.default.dirname(dirPath) !== absolutePath) {
|
|
4017
4804
|
continue;
|
|
4018
4805
|
}
|
|
4019
|
-
const name =
|
|
4806
|
+
const name = import_node_path3.default.basename(dirPath);
|
|
4020
4807
|
if (seenNames.has(name)) {
|
|
4021
4808
|
continue;
|
|
4022
4809
|
}
|
|
@@ -4029,10 +4816,10 @@ var InMemoryAgentFilesystem = class {
|
|
|
4029
4816
|
});
|
|
4030
4817
|
}
|
|
4031
4818
|
for (const [filePath, fileRecord] of this.#files.entries()) {
|
|
4032
|
-
if (
|
|
4819
|
+
if (import_node_path3.default.dirname(filePath) !== absolutePath) {
|
|
4033
4820
|
continue;
|
|
4034
4821
|
}
|
|
4035
|
-
const name =
|
|
4822
|
+
const name = import_node_path3.default.basename(filePath);
|
|
4036
4823
|
if (seenNames.has(name)) {
|
|
4037
4824
|
continue;
|
|
4038
4825
|
}
|
|
@@ -4048,7 +4835,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
4048
4835
|
return entries;
|
|
4049
4836
|
}
|
|
4050
4837
|
async stat(entryPath) {
|
|
4051
|
-
const absolutePath =
|
|
4838
|
+
const absolutePath = import_node_path3.default.resolve(entryPath);
|
|
4052
4839
|
const file = this.#files.get(absolutePath);
|
|
4053
4840
|
if (file) {
|
|
4054
4841
|
return { kind: "file", mtimeMs: file.mtimeMs };
|
|
@@ -4064,7 +4851,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
4064
4851
|
return Object.fromEntries(entries.map(([filePath, record]) => [filePath, record.content]));
|
|
4065
4852
|
}
|
|
4066
4853
|
#ensureDirSync(directoryPath) {
|
|
4067
|
-
const absolutePath =
|
|
4854
|
+
const absolutePath = import_node_path3.default.resolve(directoryPath);
|
|
4068
4855
|
const parts = [];
|
|
4069
4856
|
let cursor = absolutePath;
|
|
4070
4857
|
for (; ; ) {
|
|
@@ -4072,7 +4859,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
4072
4859
|
break;
|
|
4073
4860
|
}
|
|
4074
4861
|
parts.push(cursor);
|
|
4075
|
-
const parent =
|
|
4862
|
+
const parent = import_node_path3.default.dirname(cursor);
|
|
4076
4863
|
if (parent === cursor) {
|
|
4077
4864
|
break;
|
|
4078
4865
|
}
|
|
@@ -4095,18 +4882,18 @@ var InMemoryAgentFilesystem = class {
|
|
|
4095
4882
|
};
|
|
4096
4883
|
function createNodeAgentFilesystem() {
|
|
4097
4884
|
return {
|
|
4098
|
-
readTextFile: async (filePath) =>
|
|
4099
|
-
writeTextFile: async (filePath, content) =>
|
|
4100
|
-
deleteFile: async (filePath) =>
|
|
4885
|
+
readTextFile: async (filePath) => import_node_fs3.promises.readFile(filePath, "utf8"),
|
|
4886
|
+
writeTextFile: async (filePath, content) => import_node_fs3.promises.writeFile(filePath, content, "utf8"),
|
|
4887
|
+
deleteFile: async (filePath) => import_node_fs3.promises.unlink(filePath),
|
|
4101
4888
|
ensureDir: async (directoryPath) => {
|
|
4102
|
-
await
|
|
4889
|
+
await import_node_fs3.promises.mkdir(directoryPath, { recursive: true });
|
|
4103
4890
|
},
|
|
4104
4891
|
readDir: async (directoryPath) => {
|
|
4105
|
-
const entries = await
|
|
4892
|
+
const entries = await import_node_fs3.promises.readdir(directoryPath, { withFileTypes: true });
|
|
4106
4893
|
const result = [];
|
|
4107
4894
|
for (const entry of entries) {
|
|
4108
|
-
const entryPath =
|
|
4109
|
-
const stats = await
|
|
4895
|
+
const entryPath = import_node_path3.default.resolve(directoryPath, entry.name);
|
|
4896
|
+
const stats = await import_node_fs3.promises.lstat(entryPath);
|
|
4110
4897
|
result.push({
|
|
4111
4898
|
name: entry.name,
|
|
4112
4899
|
path: entryPath,
|
|
@@ -4117,7 +4904,7 @@ function createNodeAgentFilesystem() {
|
|
|
4117
4904
|
return result;
|
|
4118
4905
|
},
|
|
4119
4906
|
stat: async (entryPath) => {
|
|
4120
|
-
const stats = await
|
|
4907
|
+
const stats = await import_node_fs3.promises.lstat(entryPath);
|
|
4121
4908
|
return {
|
|
4122
4909
|
kind: statsToKind(stats),
|
|
4123
4910
|
mtimeMs: stats.mtimeMs
|
|
@@ -4159,12 +4946,104 @@ var UPDATE_FILE_PREFIX = "*** Update File: ";
|
|
|
4159
4946
|
var MOVE_TO_PREFIX = "*** Move to: ";
|
|
4160
4947
|
var END_OF_FILE_LINE = "*** End of File";
|
|
4161
4948
|
var DEFAULT_MAX_PATCH_BYTES = 1024 * 1024;
|
|
4949
|
+
var CODEX_APPLY_PATCH_INPUT_DESCRIPTION = "The entire contents of the apply_patch command";
|
|
4950
|
+
var CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION = "Use the `apply_patch` tool to edit files. This is a FREEFORM tool, so do not wrap the patch in JSON.";
|
|
4951
|
+
var CODEX_APPLY_PATCH_LARK_GRAMMAR = [
|
|
4952
|
+
"start: begin_patch hunk+ end_patch",
|
|
4953
|
+
'begin_patch: "*** Begin Patch" LF',
|
|
4954
|
+
'end_patch: "*** End Patch" LF?',
|
|
4955
|
+
"",
|
|
4956
|
+
"hunk: add_hunk | delete_hunk | update_hunk",
|
|
4957
|
+
'add_hunk: "*** Add File: " filename LF add_line+',
|
|
4958
|
+
'delete_hunk: "*** Delete File: " filename LF',
|
|
4959
|
+
'update_hunk: "*** Update File: " filename LF change_move? change?',
|
|
4960
|
+
"",
|
|
4961
|
+
"filename: /(.+)/",
|
|
4962
|
+
'add_line: "+" /(.*)/ LF -> line',
|
|
4963
|
+
"",
|
|
4964
|
+
'change_move: "*** Move to: " filename LF',
|
|
4965
|
+
"change: (change_context | change_line)+ eof_line?",
|
|
4966
|
+
'change_context: ("@@" | "@@ " /(.+)/) LF',
|
|
4967
|
+
'change_line: ("+" | "-" | " ") /(.*)/ LF',
|
|
4968
|
+
'eof_line: "*** End of File" LF',
|
|
4969
|
+
"",
|
|
4970
|
+
"%import common.LF"
|
|
4971
|
+
].join("\n");
|
|
4972
|
+
var CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION = [
|
|
4973
|
+
"Use the `apply_patch` tool to edit files.",
|
|
4974
|
+
"Your patch language is a stripped\u2011down, file\u2011oriented diff format designed to be easy to parse and safe to apply. You can think of it as a high\u2011level envelope:",
|
|
4975
|
+
"",
|
|
4976
|
+
"*** Begin Patch",
|
|
4977
|
+
"[ one or more file sections ]",
|
|
4978
|
+
"*** End Patch",
|
|
4979
|
+
"",
|
|
4980
|
+
"Within that envelope, you get a sequence of file operations.",
|
|
4981
|
+
"You MUST include a header to specify the action you are taking.",
|
|
4982
|
+
"Each operation starts with one of three headers:",
|
|
4983
|
+
"",
|
|
4984
|
+
"*** Add File: <path> - create a new file. Every following line is a + line (the initial contents).",
|
|
4985
|
+
"*** Delete File: <path> - remove an existing file. Nothing follows.",
|
|
4986
|
+
"*** Update File: <path> - patch an existing file in place (optionally with a rename).",
|
|
4987
|
+
"",
|
|
4988
|
+
"May be immediately followed by *** Move to: <new path> if you want to rename the file.",
|
|
4989
|
+
"Then one or more \u201Chunks\u201D, each introduced by @@ (optionally followed by a hunk header).",
|
|
4990
|
+
"Within a hunk each line starts with:",
|
|
4991
|
+
"",
|
|
4992
|
+
"For instructions on [context_before] and [context_after]:",
|
|
4993
|
+
"- By default, show 3 lines of code immediately above and 3 lines immediately below each change. If a change is within 3 lines of a previous change, do NOT duplicate the first change\u2019s [context_after] lines in the second change\u2019s [context_before] lines.",
|
|
4994
|
+
"- If 3 lines of context is insufficient to uniquely identify the snippet of code within the file, use the @@ operator to indicate the class or function to which the snippet belongs. For instance, we might have:",
|
|
4995
|
+
"@@ class BaseClass",
|
|
4996
|
+
"[3 lines of pre-context]",
|
|
4997
|
+
"- [old_code]",
|
|
4998
|
+
"+ [new_code]",
|
|
4999
|
+
"[3 lines of post-context]",
|
|
5000
|
+
"",
|
|
5001
|
+
"- If a code block is repeated so many times in a class or function such that even a single `@@` statement and 3 lines of context cannot uniquely identify the snippet of code, you can use multiple `@@` statements to jump to the right context. For instance:",
|
|
5002
|
+
"",
|
|
5003
|
+
"@@ class BaseClass",
|
|
5004
|
+
"@@ def method():",
|
|
5005
|
+
"[3 lines of pre-context]",
|
|
5006
|
+
"- [old_code]",
|
|
5007
|
+
"+ [new_code]",
|
|
5008
|
+
"[3 lines of post-context]",
|
|
5009
|
+
"",
|
|
5010
|
+
"The full grammar definition is below:",
|
|
5011
|
+
"Patch := Begin { FileOp } End",
|
|
5012
|
+
'Begin := "*** Begin Patch" NEWLINE',
|
|
5013
|
+
'End := "*** End Patch" NEWLINE',
|
|
5014
|
+
"FileOp := AddFile | DeleteFile | UpdateFile",
|
|
5015
|
+
'AddFile := "*** Add File: " path NEWLINE { "+" line NEWLINE }',
|
|
5016
|
+
'DeleteFile := "*** Delete File: " path NEWLINE',
|
|
5017
|
+
'UpdateFile := "*** Update File: " path NEWLINE [ MoveTo ] { Hunk }',
|
|
5018
|
+
'MoveTo := "*** Move to: " newPath NEWLINE',
|
|
5019
|
+
'Hunk := "@@" [ header ] NEWLINE { HunkLine } [ "*** End of File" NEWLINE ]',
|
|
5020
|
+
'HunkLine := (" " | "-" | "+") text NEWLINE',
|
|
5021
|
+
"",
|
|
5022
|
+
"A full patch can combine several operations:",
|
|
5023
|
+
"",
|
|
5024
|
+
"*** Begin Patch",
|
|
5025
|
+
"*** Add File: hello.txt",
|
|
5026
|
+
"+Hello world",
|
|
5027
|
+
"*** Update File: src/app.py",
|
|
5028
|
+
"*** Move to: src/main.py",
|
|
5029
|
+
"@@ def greet():",
|
|
5030
|
+
'-print("Hi")',
|
|
5031
|
+
'+print("Hello, world!")',
|
|
5032
|
+
"*** Delete File: obsolete.txt",
|
|
5033
|
+
"*** End Patch",
|
|
5034
|
+
"",
|
|
5035
|
+
"It is important to remember:",
|
|
5036
|
+
"",
|
|
5037
|
+
"- You must include a header with your intended action (Add/Delete/Update)",
|
|
5038
|
+
"- You must prefix new lines with `+` even when creating a new file",
|
|
5039
|
+
"- File references can only be relative, NEVER ABSOLUTE."
|
|
5040
|
+
].join("\n");
|
|
4162
5041
|
var applyPatchToolInputSchema = import_zod4.z.object({
|
|
4163
|
-
input: import_zod4.z.string().min(1).describe(
|
|
5042
|
+
input: import_zod4.z.string().min(1).describe(CODEX_APPLY_PATCH_INPUT_DESCRIPTION)
|
|
4164
5043
|
});
|
|
4165
5044
|
function createApplyPatchTool(options = {}) {
|
|
4166
5045
|
return tool({
|
|
4167
|
-
description: options.description ??
|
|
5046
|
+
description: options.description ?? CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
4168
5047
|
inputSchema: applyPatchToolInputSchema,
|
|
4169
5048
|
execute: async ({ input }) => applyPatch({
|
|
4170
5049
|
patch: input,
|
|
@@ -4177,7 +5056,7 @@ function createApplyPatchTool(options = {}) {
|
|
|
4177
5056
|
});
|
|
4178
5057
|
}
|
|
4179
5058
|
async function applyPatch(request) {
|
|
4180
|
-
const cwd =
|
|
5059
|
+
const cwd = import_node_path4.default.resolve(request.cwd ?? process.cwd());
|
|
4181
5060
|
const adapter = request.fs ?? createNodeAgentFilesystem();
|
|
4182
5061
|
const allowOutsideCwd = request.allowOutsideCwd === true;
|
|
4183
5062
|
const patchBytes = Buffer.byteLength(request.patch, "utf8");
|
|
@@ -4199,7 +5078,7 @@ async function applyPatch(request) {
|
|
|
4199
5078
|
kind: "add",
|
|
4200
5079
|
path: absolutePath2
|
|
4201
5080
|
});
|
|
4202
|
-
await adapter.ensureDir(
|
|
5081
|
+
await adapter.ensureDir(import_node_path4.default.dirname(absolutePath2));
|
|
4203
5082
|
await adapter.writeTextFile(absolutePath2, operation.content);
|
|
4204
5083
|
added.push(toDisplayPath(absolutePath2, cwd));
|
|
4205
5084
|
continue;
|
|
@@ -4233,7 +5112,7 @@ async function applyPatch(request) {
|
|
|
4233
5112
|
fromPath: absolutePath,
|
|
4234
5113
|
toPath: destinationPath
|
|
4235
5114
|
});
|
|
4236
|
-
await adapter.ensureDir(
|
|
5115
|
+
await adapter.ensureDir(import_node_path4.default.dirname(destinationPath));
|
|
4237
5116
|
await adapter.writeTextFile(destinationPath, next);
|
|
4238
5117
|
await adapter.deleteFile(absolutePath);
|
|
4239
5118
|
modified.push(toDisplayPath(destinationPath, cwd));
|
|
@@ -4264,22 +5143,22 @@ function resolvePatchPath(rawPath, cwd, allowOutsideCwd) {
|
|
|
4264
5143
|
if (trimmed.length === 0) {
|
|
4265
5144
|
throw new Error("apply_patch failed: empty file path");
|
|
4266
5145
|
}
|
|
4267
|
-
const absolutePath =
|
|
5146
|
+
const absolutePath = import_node_path4.default.isAbsolute(trimmed) ? import_node_path4.default.resolve(trimmed) : import_node_path4.default.resolve(cwd, trimmed);
|
|
4268
5147
|
if (!allowOutsideCwd && !isPathInsideCwd(absolutePath, cwd)) {
|
|
4269
5148
|
throw new Error(`apply_patch failed: path "${trimmed}" resolves outside cwd "${cwd}"`);
|
|
4270
5149
|
}
|
|
4271
5150
|
return absolutePath;
|
|
4272
5151
|
}
|
|
4273
5152
|
function isPathInsideCwd(candidatePath, cwd) {
|
|
4274
|
-
const relative =
|
|
4275
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
5153
|
+
const relative = import_node_path4.default.relative(cwd, candidatePath);
|
|
5154
|
+
return relative === "" || !relative.startsWith("..") && !import_node_path4.default.isAbsolute(relative);
|
|
4276
5155
|
}
|
|
4277
5156
|
function toDisplayPath(absolutePath, cwd) {
|
|
4278
|
-
const relative =
|
|
5157
|
+
const relative = import_node_path4.default.relative(cwd, absolutePath);
|
|
4279
5158
|
if (relative === "") {
|
|
4280
5159
|
return ".";
|
|
4281
5160
|
}
|
|
4282
|
-
if (!relative.startsWith("..") && !
|
|
5161
|
+
if (!relative.startsWith("..") && !import_node_path4.default.isAbsolute(relative)) {
|
|
4283
5162
|
return relative;
|
|
4284
5163
|
}
|
|
4285
5164
|
return absolutePath;
|
|
@@ -4559,6 +5438,8 @@ function formatSummary(added, modified, deleted) {
|
|
|
4559
5438
|
|
|
4560
5439
|
// src/tools/filesystemTools.ts
|
|
4561
5440
|
var DEFAULT_READ_FILE_LINE_LIMIT = 2e3;
|
|
5441
|
+
var DEFAULT_READ_FILES_LINE_LIMIT = 200;
|
|
5442
|
+
var DEFAULT_READ_FILES_CHAR_LIMIT = 4e3;
|
|
4562
5443
|
var DEFAULT_LIST_DIR_LIMIT = 25;
|
|
4563
5444
|
var DEFAULT_LIST_DIR_DEPTH = 2;
|
|
4564
5445
|
var DEFAULT_GREP_LIMIT = 100;
|
|
@@ -4592,12 +5473,29 @@ var codexGrepFilesInputSchema = import_zod5.z.object({
|
|
|
4592
5473
|
limit: import_zod5.z.number().int().min(1).optional().describe("Maximum number of file paths to return (defaults to 100).")
|
|
4593
5474
|
});
|
|
4594
5475
|
var applyPatchInputSchema = import_zod5.z.object({
|
|
4595
|
-
input: import_zod5.z.string().min(1)
|
|
5476
|
+
input: import_zod5.z.string().min(1).describe(CODEX_APPLY_PATCH_INPUT_DESCRIPTION)
|
|
4596
5477
|
});
|
|
4597
5478
|
var geminiReadFileInputSchema = import_zod5.z.object({
|
|
4598
5479
|
file_path: import_zod5.z.string().min(1),
|
|
4599
|
-
offset: import_zod5.z.number().int().min(0).
|
|
4600
|
-
limit: import_zod5.z.number().int().min(1).
|
|
5480
|
+
offset: import_zod5.z.number().int().min(0).nullish(),
|
|
5481
|
+
limit: import_zod5.z.number().int().min(1).nullish()
|
|
5482
|
+
});
|
|
5483
|
+
var geminiReadFilesInputSchema = import_zod5.z.object({
|
|
5484
|
+
paths: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
|
|
5485
|
+
line_offset: import_zod5.z.number().int().min(0).nullish(),
|
|
5486
|
+
line_limit: import_zod5.z.number().int().min(1).nullish(),
|
|
5487
|
+
char_offset: import_zod5.z.number().int().min(0).nullish(),
|
|
5488
|
+
char_limit: import_zod5.z.number().int().min(1).nullish(),
|
|
5489
|
+
include_line_numbers: import_zod5.z.boolean().nullish()
|
|
5490
|
+
}).superRefine((value, context) => {
|
|
5491
|
+
const hasLineWindow = value.line_offset !== void 0 || value.line_limit !== void 0;
|
|
5492
|
+
const hasCharWindow = value.char_offset !== void 0 || value.char_limit !== void 0;
|
|
5493
|
+
if (hasLineWindow && hasCharWindow) {
|
|
5494
|
+
context.addIssue({
|
|
5495
|
+
code: import_zod5.z.ZodIssueCode.custom,
|
|
5496
|
+
message: "Use either line_* or char_* window arguments, not both."
|
|
5497
|
+
});
|
|
5498
|
+
}
|
|
4601
5499
|
});
|
|
4602
5500
|
var geminiWriteFileInputSchema = import_zod5.z.object({
|
|
4603
5501
|
file_path: import_zod5.z.string().min(1),
|
|
@@ -4608,31 +5506,41 @@ var geminiReplaceInputSchema = import_zod5.z.object({
|
|
|
4608
5506
|
instruction: import_zod5.z.string().min(1),
|
|
4609
5507
|
old_string: import_zod5.z.string(),
|
|
4610
5508
|
new_string: import_zod5.z.string(),
|
|
4611
|
-
expected_replacements: import_zod5.z.number().int().min(1).
|
|
5509
|
+
expected_replacements: import_zod5.z.number().int().min(1).nullish()
|
|
4612
5510
|
});
|
|
4613
5511
|
var geminiListDirectoryInputSchema = import_zod5.z.object({
|
|
4614
5512
|
dir_path: import_zod5.z.string().min(1),
|
|
4615
|
-
ignore: import_zod5.z.array(import_zod5.z.string()).
|
|
5513
|
+
ignore: import_zod5.z.array(import_zod5.z.string()).nullish(),
|
|
4616
5514
|
file_filtering_options: import_zod5.z.object({
|
|
4617
|
-
respect_git_ignore: import_zod5.z.boolean().
|
|
4618
|
-
respect_gemini_ignore: import_zod5.z.boolean().
|
|
4619
|
-
}).
|
|
5515
|
+
respect_git_ignore: import_zod5.z.boolean().nullish(),
|
|
5516
|
+
respect_gemini_ignore: import_zod5.z.boolean().nullish()
|
|
5517
|
+
}).nullish()
|
|
5518
|
+
});
|
|
5519
|
+
var geminiRgSearchInputSchema = import_zod5.z.object({
|
|
5520
|
+
pattern: import_zod5.z.string().min(1),
|
|
5521
|
+
path: import_zod5.z.string().nullish(),
|
|
5522
|
+
glob: import_zod5.z.string().nullish(),
|
|
5523
|
+
case_sensitive: import_zod5.z.boolean().nullish(),
|
|
5524
|
+
exclude_pattern: import_zod5.z.string().nullish(),
|
|
5525
|
+
names_only: import_zod5.z.boolean().nullish(),
|
|
5526
|
+
max_matches_per_file: import_zod5.z.number().int().min(1).nullish(),
|
|
5527
|
+
max_results: import_zod5.z.number().int().min(1).nullish()
|
|
4620
5528
|
});
|
|
4621
5529
|
var geminiGrepSearchInputSchema = import_zod5.z.object({
|
|
4622
5530
|
pattern: import_zod5.z.string().min(1),
|
|
4623
|
-
dir_path: import_zod5.z.string().
|
|
4624
|
-
include: import_zod5.z.string().
|
|
4625
|
-
exclude_pattern: import_zod5.z.string().
|
|
4626
|
-
names_only: import_zod5.z.boolean().
|
|
4627
|
-
max_matches_per_file: import_zod5.z.number().int().min(1).
|
|
4628
|
-
total_max_matches: import_zod5.z.number().int().min(1).
|
|
5531
|
+
dir_path: import_zod5.z.string().nullish(),
|
|
5532
|
+
include: import_zod5.z.string().nullish(),
|
|
5533
|
+
exclude_pattern: import_zod5.z.string().nullish(),
|
|
5534
|
+
names_only: import_zod5.z.boolean().nullish(),
|
|
5535
|
+
max_matches_per_file: import_zod5.z.number().int().min(1).nullish(),
|
|
5536
|
+
total_max_matches: import_zod5.z.number().int().min(1).nullish()
|
|
4629
5537
|
});
|
|
4630
5538
|
var geminiGlobInputSchema = import_zod5.z.object({
|
|
4631
5539
|
pattern: import_zod5.z.string().min(1),
|
|
4632
|
-
dir_path: import_zod5.z.string().
|
|
4633
|
-
case_sensitive: import_zod5.z.boolean().
|
|
4634
|
-
respect_git_ignore: import_zod5.z.boolean().
|
|
4635
|
-
respect_gemini_ignore: import_zod5.z.boolean().
|
|
5540
|
+
dir_path: import_zod5.z.string().nullish(),
|
|
5541
|
+
case_sensitive: import_zod5.z.boolean().nullish(),
|
|
5542
|
+
respect_git_ignore: import_zod5.z.boolean().nullish(),
|
|
5543
|
+
respect_gemini_ignore: import_zod5.z.boolean().nullish()
|
|
4636
5544
|
});
|
|
4637
5545
|
function resolveFilesystemToolProfile(model, profile = "auto") {
|
|
4638
5546
|
if (profile !== "auto") {
|
|
@@ -4676,7 +5584,7 @@ function createCodexFilesystemToolSet(options = {}) {
|
|
|
4676
5584
|
}
|
|
4677
5585
|
function createGeminiFilesystemToolSet(options = {}) {
|
|
4678
5586
|
return {
|
|
4679
|
-
read_file:
|
|
5587
|
+
read_file: createGeminiReadFileTool(options),
|
|
4680
5588
|
write_file: createWriteFileTool(options),
|
|
4681
5589
|
replace: createReplaceTool(options),
|
|
4682
5590
|
list_directory: createListDirectoryTool(options),
|
|
@@ -4688,10 +5596,14 @@ function createModelAgnosticFilesystemToolSet(options = {}) {
|
|
|
4688
5596
|
return createGeminiFilesystemToolSet(options);
|
|
4689
5597
|
}
|
|
4690
5598
|
function createCodexApplyPatchTool(options = {}) {
|
|
4691
|
-
return
|
|
4692
|
-
description:
|
|
4693
|
-
|
|
4694
|
-
|
|
5599
|
+
return customTool({
|
|
5600
|
+
description: CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
5601
|
+
format: {
|
|
5602
|
+
type: "grammar",
|
|
5603
|
+
syntax: "lark",
|
|
5604
|
+
definition: CODEX_APPLY_PATCH_LARK_GRAMMAR
|
|
5605
|
+
},
|
|
5606
|
+
execute: async (input) => {
|
|
4695
5607
|
const runtime = resolveRuntime(options);
|
|
4696
5608
|
const result = await applyPatch({
|
|
4697
5609
|
patch: input,
|
|
@@ -4735,13 +5647,20 @@ function createGrepFilesTool(options = {}) {
|
|
|
4735
5647
|
execute: async (input) => grepFilesCodex(input, options)
|
|
4736
5648
|
});
|
|
4737
5649
|
}
|
|
4738
|
-
function
|
|
5650
|
+
function createGeminiReadFileTool(options = {}) {
|
|
4739
5651
|
return tool({
|
|
4740
|
-
description: "Reads and returns content of a specified file.",
|
|
5652
|
+
description: "Reads and returns the content of a specified file. Supports optional 0-based line offset and line limit.",
|
|
4741
5653
|
inputSchema: geminiReadFileInputSchema,
|
|
4742
5654
|
execute: async (input) => readFileGemini(input, options)
|
|
4743
5655
|
});
|
|
4744
5656
|
}
|
|
5657
|
+
function createReadFilesTool(options = {}) {
|
|
5658
|
+
return tool({
|
|
5659
|
+
description: "Reads one or more files with optional line-based or character-based slicing, similar to a controlled head/tail view.",
|
|
5660
|
+
inputSchema: geminiReadFilesInputSchema,
|
|
5661
|
+
execute: async (input) => readFilesGemini(input, options)
|
|
5662
|
+
});
|
|
5663
|
+
}
|
|
4745
5664
|
function createWriteFileTool(options = {}) {
|
|
4746
5665
|
return tool({
|
|
4747
5666
|
description: "Writes content to a specified file in the local filesystem.",
|
|
@@ -4770,6 +5689,13 @@ function createGrepSearchTool(options = {}) {
|
|
|
4770
5689
|
execute: async (input) => grepSearchGemini(input, options)
|
|
4771
5690
|
});
|
|
4772
5691
|
}
|
|
5692
|
+
function createRgSearchTool(options = {}) {
|
|
5693
|
+
return tool({
|
|
5694
|
+
description: "Searches for a regex pattern within file contents.",
|
|
5695
|
+
inputSchema: geminiRgSearchInputSchema,
|
|
5696
|
+
execute: async (input) => rgSearchGemini(input, options)
|
|
5697
|
+
});
|
|
5698
|
+
}
|
|
4773
5699
|
function createGlobTool(options = {}) {
|
|
4774
5700
|
return tool({
|
|
4775
5701
|
description: "Finds files matching glob patterns, sorted by modification time (newest first).",
|
|
@@ -4779,7 +5705,7 @@ function createGlobTool(options = {}) {
|
|
|
4779
5705
|
}
|
|
4780
5706
|
async function readFileCodex(input, options) {
|
|
4781
5707
|
const runtime = resolveRuntime(options);
|
|
4782
|
-
if (!
|
|
5708
|
+
if (!import_node_path5.default.isAbsolute(input.file_path)) {
|
|
4783
5709
|
throw new Error("file_path must be an absolute path");
|
|
4784
5710
|
}
|
|
4785
5711
|
const filePath = resolvePathWithPolicy(input.file_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -4830,7 +5756,7 @@ async function readFileCodex(input, options) {
|
|
|
4830
5756
|
}
|
|
4831
5757
|
async function listDirectoryCodex(input, options) {
|
|
4832
5758
|
const runtime = resolveRuntime(options);
|
|
4833
|
-
if (!
|
|
5759
|
+
if (!import_node_path5.default.isAbsolute(input.dir_path)) {
|
|
4834
5760
|
throw new Error("dir_path must be an absolute path");
|
|
4835
5761
|
}
|
|
4836
5762
|
const dirPath = resolvePathWithPolicy(input.dir_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -4927,9 +5853,6 @@ async function readFileGemini(input, options) {
|
|
|
4927
5853
|
path: filePath
|
|
4928
5854
|
});
|
|
4929
5855
|
const content = await runtime.filesystem.readTextFile(filePath);
|
|
4930
|
-
if (input.offset === void 0 && input.limit === void 0) {
|
|
4931
|
-
return content;
|
|
4932
|
-
}
|
|
4933
5856
|
const lines = splitLines(content);
|
|
4934
5857
|
const offset = Math.max(0, input.offset ?? 0);
|
|
4935
5858
|
const limit = input.limit ?? DEFAULT_READ_FILE_LINE_LIMIT;
|
|
@@ -4937,7 +5860,59 @@ async function readFileGemini(input, options) {
|
|
|
4937
5860
|
return "";
|
|
4938
5861
|
}
|
|
4939
5862
|
const end = Math.min(lines.length, offset + limit);
|
|
4940
|
-
return lines.slice(offset, end).
|
|
5863
|
+
return lines.slice(offset, end).map(
|
|
5864
|
+
(line, index) => `L${offset + index + 1}: ${truncateAtCodePointBoundary(line ?? "", runtime.maxLineLength)}`
|
|
5865
|
+
).join("\n");
|
|
5866
|
+
}
|
|
5867
|
+
async function readFilesGemini(input, options) {
|
|
5868
|
+
const runtime = resolveRuntime(options);
|
|
5869
|
+
const useCharWindow = input.char_offset !== void 0 || input.char_limit !== void 0;
|
|
5870
|
+
const lineOffset = Math.max(0, input.line_offset ?? 0);
|
|
5871
|
+
const lineLimit = input.line_limit ?? DEFAULT_READ_FILES_LINE_LIMIT;
|
|
5872
|
+
const charOffset = Math.max(0, input.char_offset ?? 0);
|
|
5873
|
+
const charLimit = input.char_limit ?? DEFAULT_READ_FILES_CHAR_LIMIT;
|
|
5874
|
+
const includeLineNumbers = input.include_line_numbers !== false;
|
|
5875
|
+
const sections = [];
|
|
5876
|
+
for (const rawPath of input.paths) {
|
|
5877
|
+
const filePath = resolvePathWithPolicy(rawPath, runtime.cwd, runtime.allowOutsideCwd);
|
|
5878
|
+
await runAccessHook2(runtime, {
|
|
5879
|
+
cwd: runtime.cwd,
|
|
5880
|
+
tool: "read_files",
|
|
5881
|
+
action: "read",
|
|
5882
|
+
path: filePath
|
|
5883
|
+
});
|
|
5884
|
+
const content = await runtime.filesystem.readTextFile(filePath);
|
|
5885
|
+
const displayPath = normalizeSlashes(toDisplayPath2(filePath, runtime.cwd));
|
|
5886
|
+
sections.push(`==> ${displayPath} <==`);
|
|
5887
|
+
if (useCharWindow) {
|
|
5888
|
+
if (charOffset >= content.length) {
|
|
5889
|
+
sections.push("");
|
|
5890
|
+
continue;
|
|
5891
|
+
}
|
|
5892
|
+
const end2 = Math.min(content.length, charOffset + charLimit);
|
|
5893
|
+
sections.push(content.slice(charOffset, end2));
|
|
5894
|
+
continue;
|
|
5895
|
+
}
|
|
5896
|
+
const lines = splitLines(content);
|
|
5897
|
+
if (lineOffset >= lines.length) {
|
|
5898
|
+
sections.push("");
|
|
5899
|
+
continue;
|
|
5900
|
+
}
|
|
5901
|
+
const end = Math.min(lines.length, lineOffset + lineLimit);
|
|
5902
|
+
const selected = lines.slice(lineOffset, end);
|
|
5903
|
+
if (includeLineNumbers) {
|
|
5904
|
+
for (let index = 0; index < selected.length; index += 1) {
|
|
5905
|
+
const lineNumber = lineOffset + index + 1;
|
|
5906
|
+
const line = selected[index] ?? "";
|
|
5907
|
+
sections.push(
|
|
5908
|
+
`L${lineNumber}: ${truncateAtCodePointBoundary(line, runtime.maxLineLength)}`
|
|
5909
|
+
);
|
|
5910
|
+
}
|
|
5911
|
+
continue;
|
|
5912
|
+
}
|
|
5913
|
+
sections.push(selected.join("\n"));
|
|
5914
|
+
}
|
|
5915
|
+
return sections.join("\n");
|
|
4941
5916
|
}
|
|
4942
5917
|
async function writeFileGemini(input, options) {
|
|
4943
5918
|
const runtime = resolveRuntime(options);
|
|
@@ -4948,7 +5923,7 @@ async function writeFileGemini(input, options) {
|
|
|
4948
5923
|
action: "write",
|
|
4949
5924
|
path: filePath
|
|
4950
5925
|
});
|
|
4951
|
-
await runtime.filesystem.ensureDir(
|
|
5926
|
+
await runtime.filesystem.ensureDir(import_node_path5.default.dirname(filePath));
|
|
4952
5927
|
await runtime.filesystem.writeTextFile(filePath, input.content);
|
|
4953
5928
|
return `Successfully wrote file: ${toDisplayPath2(filePath, runtime.cwd)}`;
|
|
4954
5929
|
}
|
|
@@ -4969,7 +5944,7 @@ async function replaceFileContentGemini(input, options) {
|
|
|
4969
5944
|
originalContent = await runtime.filesystem.readTextFile(filePath);
|
|
4970
5945
|
} catch (error) {
|
|
4971
5946
|
if (isNoEntError(error) && oldValue.length === 0) {
|
|
4972
|
-
await runtime.filesystem.ensureDir(
|
|
5947
|
+
await runtime.filesystem.ensureDir(import_node_path5.default.dirname(filePath));
|
|
4973
5948
|
await runtime.filesystem.writeTextFile(filePath, newValue);
|
|
4974
5949
|
return `Successfully wrote new file: ${toDisplayPath2(filePath, runtime.cwd)}`;
|
|
4975
5950
|
}
|
|
@@ -5020,25 +5995,25 @@ async function listDirectoryGemini(input, options) {
|
|
|
5020
5995
|
return label;
|
|
5021
5996
|
}).join("\n");
|
|
5022
5997
|
}
|
|
5023
|
-
async function
|
|
5998
|
+
async function rgSearchGemini(input, options, toolName = "rg_search") {
|
|
5024
5999
|
const runtime = resolveRuntime(options);
|
|
5025
6000
|
const pattern = input.pattern.trim();
|
|
5026
6001
|
if (pattern.length === 0) {
|
|
5027
6002
|
throw new Error("pattern must not be empty");
|
|
5028
6003
|
}
|
|
5029
|
-
const
|
|
6004
|
+
const glob = input.glob?.trim();
|
|
5030
6005
|
const searchPath = resolvePathWithPolicy(
|
|
5031
|
-
input.
|
|
6006
|
+
input.path ?? runtime.cwd,
|
|
5032
6007
|
runtime.cwd,
|
|
5033
6008
|
runtime.allowOutsideCwd
|
|
5034
6009
|
);
|
|
5035
6010
|
await runAccessHook2(runtime, {
|
|
5036
6011
|
cwd: runtime.cwd,
|
|
5037
|
-
tool:
|
|
6012
|
+
tool: toolName,
|
|
5038
6013
|
action: "search",
|
|
5039
6014
|
path: searchPath,
|
|
5040
6015
|
pattern,
|
|
5041
|
-
include
|
|
6016
|
+
include: glob
|
|
5042
6017
|
});
|
|
5043
6018
|
const searchPathInfo = await runtime.filesystem.stat(searchPath);
|
|
5044
6019
|
const filesToScan = await collectSearchFiles({
|
|
@@ -5047,10 +6022,10 @@ async function grepSearchGemini(input, options) {
|
|
|
5047
6022
|
rootKind: searchPathInfo.kind,
|
|
5048
6023
|
maxScannedFiles: runtime.grepMaxScannedFiles
|
|
5049
6024
|
});
|
|
5050
|
-
const matcher =
|
|
5051
|
-
const patternRegex = compileRegex(pattern);
|
|
6025
|
+
const matcher = glob ? createGlobMatcher(glob) : null;
|
|
6026
|
+
const patternRegex = compileRegex(pattern, input.case_sensitive === true ? "m" : "im");
|
|
5052
6027
|
const excludeRegex = input.exclude_pattern ? compileRegex(input.exclude_pattern) : null;
|
|
5053
|
-
const totalMaxMatches = input.
|
|
6028
|
+
const totalMaxMatches = input.max_results ?? DEFAULT_GREP_LIMIT;
|
|
5054
6029
|
const perFileMaxMatches = input.max_matches_per_file ?? Number.POSITIVE_INFINITY;
|
|
5055
6030
|
const matches = [];
|
|
5056
6031
|
const fileMatches = /* @__PURE__ */ new Set();
|
|
@@ -5105,6 +6080,21 @@ async function grepSearchGemini(input, options) {
|
|
|
5105
6080
|
}
|
|
5106
6081
|
return matches.slice(0, totalMaxMatches).map((match) => `${match.filePath}:${match.lineNumber}:${match.line ?? ""}`).join("\n");
|
|
5107
6082
|
}
|
|
6083
|
+
async function grepSearchGemini(input, options) {
|
|
6084
|
+
return rgSearchGemini(
|
|
6085
|
+
{
|
|
6086
|
+
pattern: input.pattern,
|
|
6087
|
+
path: input.dir_path,
|
|
6088
|
+
glob: input.include,
|
|
6089
|
+
exclude_pattern: input.exclude_pattern,
|
|
6090
|
+
names_only: input.names_only,
|
|
6091
|
+
max_matches_per_file: input.max_matches_per_file,
|
|
6092
|
+
max_results: input.total_max_matches
|
|
6093
|
+
},
|
|
6094
|
+
options,
|
|
6095
|
+
"grep_search"
|
|
6096
|
+
);
|
|
6097
|
+
}
|
|
5108
6098
|
async function globFilesGemini(input, options) {
|
|
5109
6099
|
const runtime = resolveRuntime(options);
|
|
5110
6100
|
const dirPath = resolvePathWithPolicy(
|
|
@@ -5132,7 +6122,7 @@ async function globFilesGemini(input, options) {
|
|
|
5132
6122
|
});
|
|
5133
6123
|
const matched = [];
|
|
5134
6124
|
for (const filePath of files) {
|
|
5135
|
-
const relativePath = normalizeSlashes(
|
|
6125
|
+
const relativePath = normalizeSlashes(import_node_path5.default.relative(dirPath, filePath));
|
|
5136
6126
|
if (!matcher(relativePath)) {
|
|
5137
6127
|
continue;
|
|
5138
6128
|
}
|
|
@@ -5146,11 +6136,11 @@ async function globFilesGemini(input, options) {
|
|
|
5146
6136
|
return "No files found.";
|
|
5147
6137
|
}
|
|
5148
6138
|
matched.sort((left, right) => right.mtimeMs - left.mtimeMs);
|
|
5149
|
-
return matched.map((entry) => normalizeSlashes(
|
|
6139
|
+
return matched.map((entry) => normalizeSlashes(toDisplayPath2(entry.filePath, runtime.cwd))).join("\n");
|
|
5150
6140
|
}
|
|
5151
6141
|
function resolveRuntime(options) {
|
|
5152
6142
|
return {
|
|
5153
|
-
cwd:
|
|
6143
|
+
cwd: import_node_path5.default.resolve(options.cwd ?? process.cwd()),
|
|
5154
6144
|
filesystem: options.fs ?? createNodeAgentFilesystem(),
|
|
5155
6145
|
allowOutsideCwd: options.allowOutsideCwd === true,
|
|
5156
6146
|
checkAccess: options.checkAccess,
|
|
@@ -5181,22 +6171,22 @@ function mapApplyPatchAction(action) {
|
|
|
5181
6171
|
return "move";
|
|
5182
6172
|
}
|
|
5183
6173
|
function resolvePathWithPolicy(inputPath, cwd, allowOutsideCwd) {
|
|
5184
|
-
const absolutePath =
|
|
6174
|
+
const absolutePath = import_node_path5.default.isAbsolute(inputPath) ? import_node_path5.default.resolve(inputPath) : import_node_path5.default.resolve(cwd, inputPath);
|
|
5185
6175
|
if (!allowOutsideCwd && !isPathInsideCwd2(absolutePath, cwd)) {
|
|
5186
6176
|
throw new Error(`path "${inputPath}" resolves outside cwd "${cwd}"`);
|
|
5187
6177
|
}
|
|
5188
6178
|
return absolutePath;
|
|
5189
6179
|
}
|
|
5190
6180
|
function isPathInsideCwd2(candidatePath, cwd) {
|
|
5191
|
-
const relative =
|
|
5192
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
6181
|
+
const relative = import_node_path5.default.relative(cwd, candidatePath);
|
|
6182
|
+
return relative === "" || !relative.startsWith("..") && !import_node_path5.default.isAbsolute(relative);
|
|
5193
6183
|
}
|
|
5194
6184
|
function toDisplayPath2(absolutePath, cwd) {
|
|
5195
|
-
const relative =
|
|
6185
|
+
const relative = import_node_path5.default.relative(cwd, absolutePath);
|
|
5196
6186
|
if (relative === "") {
|
|
5197
6187
|
return ".";
|
|
5198
6188
|
}
|
|
5199
|
-
if (!relative.startsWith("..") && !
|
|
6189
|
+
if (!relative.startsWith("..") && !import_node_path5.default.isAbsolute(relative)) {
|
|
5200
6190
|
return relative;
|
|
5201
6191
|
}
|
|
5202
6192
|
return absolutePath;
|
|
@@ -5406,9 +6396,9 @@ async function collectSearchFiles(params) {
|
|
|
5406
6396
|
}
|
|
5407
6397
|
return files;
|
|
5408
6398
|
}
|
|
5409
|
-
function compileRegex(pattern) {
|
|
6399
|
+
function compileRegex(pattern, flags = "m") {
|
|
5410
6400
|
try {
|
|
5411
|
-
return new RegExp(pattern,
|
|
6401
|
+
return new RegExp(pattern, flags);
|
|
5412
6402
|
} catch (error) {
|
|
5413
6403
|
const message = error instanceof Error ? error.message : String(error);
|
|
5414
6404
|
throw new Error(`invalid regex pattern: ${message}`);
|
|
@@ -5423,7 +6413,7 @@ function createGlobMatcher(pattern, caseSensitive = false) {
|
|
|
5423
6413
|
}));
|
|
5424
6414
|
return (candidatePath) => {
|
|
5425
6415
|
const normalizedPath = normalizeSlashes(candidatePath);
|
|
5426
|
-
const basename =
|
|
6416
|
+
const basename = import_node_path5.default.posix.basename(normalizedPath);
|
|
5427
6417
|
return compiled.some(
|
|
5428
6418
|
(entry) => entry.regex.test(entry.applyToBasename ? basename : normalizedPath)
|
|
5429
6419
|
);
|
|
@@ -5587,6 +6577,13 @@ function mergeToolSets(base, extra) {
|
|
|
5587
6577
|
}
|
|
5588
6578
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5589
6579
|
0 && (module.exports = {
|
|
6580
|
+
CODEX_APPLY_PATCH_FREEFORM_TOOL_DESCRIPTION,
|
|
6581
|
+
CODEX_APPLY_PATCH_JSON_TOOL_DESCRIPTION,
|
|
6582
|
+
CODEX_APPLY_PATCH_LARK_GRAMMAR,
|
|
6583
|
+
FIREWORKS_DEFAULT_GLM_MODEL,
|
|
6584
|
+
FIREWORKS_DEFAULT_KIMI_MODEL,
|
|
6585
|
+
FIREWORKS_DEFAULT_MINIMAX_MODEL,
|
|
6586
|
+
FIREWORKS_MODEL_IDS,
|
|
5590
6587
|
InMemoryAgentFilesystem,
|
|
5591
6588
|
LlmJsonCallError,
|
|
5592
6589
|
appendMarkdownSourcesSection,
|
|
@@ -5599,6 +6596,7 @@ function mergeToolSets(base, extra) {
|
|
|
5599
6596
|
createCodexReadFileTool,
|
|
5600
6597
|
createFilesystemToolSetForModel,
|
|
5601
6598
|
createGeminiFilesystemToolSet,
|
|
6599
|
+
createGeminiReadFileTool,
|
|
5602
6600
|
createGlobTool,
|
|
5603
6601
|
createGrepFilesTool,
|
|
5604
6602
|
createGrepSearchTool,
|
|
@@ -5607,9 +6605,11 @@ function mergeToolSets(base, extra) {
|
|
|
5607
6605
|
createListDirectoryTool,
|
|
5608
6606
|
createModelAgnosticFilesystemToolSet,
|
|
5609
6607
|
createNodeAgentFilesystem,
|
|
5610
|
-
|
|
6608
|
+
createReadFilesTool,
|
|
5611
6609
|
createReplaceTool,
|
|
6610
|
+
createRgSearchTool,
|
|
5612
6611
|
createWriteFileTool,
|
|
6612
|
+
customTool,
|
|
5613
6613
|
encodeChatGptAuthJson,
|
|
5614
6614
|
encodeChatGptAuthJsonB64,
|
|
5615
6615
|
estimateCallCostUsd,
|
|
@@ -5620,12 +6620,14 @@ function mergeToolSets(base, extra) {
|
|
|
5620
6620
|
generateText,
|
|
5621
6621
|
getChatGptAuthProfile,
|
|
5622
6622
|
getCurrentToolCallContext,
|
|
6623
|
+
isFireworksModelId,
|
|
5623
6624
|
isGeminiModelId,
|
|
5624
6625
|
loadEnvFromFile,
|
|
5625
6626
|
loadLocalEnv,
|
|
5626
6627
|
parseJsonFromLlmText,
|
|
5627
6628
|
refreshChatGptOauthToken,
|
|
5628
6629
|
resolveFilesystemToolProfile,
|
|
6630
|
+
resolveFireworksModelId,
|
|
5629
6631
|
runAgentLoop,
|
|
5630
6632
|
runToolLoop,
|
|
5631
6633
|
sanitisePartForLogging,
|