@ljoukov/llm 3.0.11 → 3.0.12
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/dist/index.cjs +173 -241
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -31
- package/dist/index.d.ts +31 -31
- package/dist/index.js +172 -240
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -68,10 +68,10 @@ __export(index_exports, {
|
|
|
68
68
|
createListDirectoryTool: () => createListDirectoryTool,
|
|
69
69
|
createModelAgnosticFilesystemToolSet: () => createModelAgnosticFilesystemToolSet,
|
|
70
70
|
createNodeAgentFilesystem: () => createNodeAgentFilesystem,
|
|
71
|
-
createReadFilesTool: () => createReadFilesTool,
|
|
72
71
|
createReplaceTool: () => createReplaceTool,
|
|
73
72
|
createRgSearchTool: () => createRgSearchTool,
|
|
74
73
|
createToolLoopSteeringChannel: () => createToolLoopSteeringChannel,
|
|
74
|
+
createViewImageTool: () => createViewImageTool,
|
|
75
75
|
createWriteFileTool: () => createWriteFileTool,
|
|
76
76
|
customTool: () => customTool,
|
|
77
77
|
encodeChatGptAuthJson: () => encodeChatGptAuthJson,
|
|
@@ -2218,7 +2218,6 @@ function getGoogleAuthOptions(scopes) {
|
|
|
2218
2218
|
|
|
2219
2219
|
// src/google/client.ts
|
|
2220
2220
|
var GEMINI_TEXT_MODEL_IDS = [
|
|
2221
|
-
"gemini-3-pro-preview",
|
|
2222
2221
|
"gemini-3.1-pro-preview",
|
|
2223
2222
|
"gemini-3-flash-preview",
|
|
2224
2223
|
"gemini-2.5-pro",
|
|
@@ -4022,6 +4021,38 @@ function mergeToolOutput(value) {
|
|
|
4022
4021
|
return JSON.stringify({ error: "Failed to serialize tool output", detail: message });
|
|
4023
4022
|
}
|
|
4024
4023
|
}
|
|
4024
|
+
function isLlmToolOutputContentItem(value) {
|
|
4025
|
+
if (!isPlainRecord(value)) {
|
|
4026
|
+
return false;
|
|
4027
|
+
}
|
|
4028
|
+
const itemType = typeof value.type === "string" ? value.type : "";
|
|
4029
|
+
if (itemType === "input_text") {
|
|
4030
|
+
return typeof value.text === "string";
|
|
4031
|
+
}
|
|
4032
|
+
if (itemType === "input_image") {
|
|
4033
|
+
return typeof value.image_url === "string";
|
|
4034
|
+
}
|
|
4035
|
+
if (itemType === "input_file") {
|
|
4036
|
+
const keys = ["file_data", "file_id", "file_url", "filename"];
|
|
4037
|
+
for (const key of keys) {
|
|
4038
|
+
const part = value[key];
|
|
4039
|
+
if (part !== void 0 && part !== null && typeof part !== "string") {
|
|
4040
|
+
return false;
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
return true;
|
|
4044
|
+
}
|
|
4045
|
+
return false;
|
|
4046
|
+
}
|
|
4047
|
+
function toOpenAiToolOutput(value) {
|
|
4048
|
+
if (isLlmToolOutputContentItem(value)) {
|
|
4049
|
+
return [value];
|
|
4050
|
+
}
|
|
4051
|
+
if (Array.isArray(value) && value.every((item) => isLlmToolOutputContentItem(item))) {
|
|
4052
|
+
return value;
|
|
4053
|
+
}
|
|
4054
|
+
return mergeToolOutput(value);
|
|
4055
|
+
}
|
|
4025
4056
|
function parseOpenAiToolArguments(raw) {
|
|
4026
4057
|
const trimmed = raw.trim();
|
|
4027
4058
|
if (trimmed.length === 0) {
|
|
@@ -4377,7 +4408,6 @@ function resolveGeminiThinkingConfig(modelId) {
|
|
|
4377
4408
|
return void 0;
|
|
4378
4409
|
}
|
|
4379
4410
|
switch (modelId) {
|
|
4380
|
-
case "gemini-3-pro-preview":
|
|
4381
4411
|
case "gemini-3.1-pro-preview":
|
|
4382
4412
|
return { includeThoughts: true };
|
|
4383
4413
|
case "gemini-3-flash-preview":
|
|
@@ -5379,13 +5409,13 @@ async function runToolLoop(request) {
|
|
|
5379
5409
|
toolOutputs.push({
|
|
5380
5410
|
type: "custom_tool_call_output",
|
|
5381
5411
|
call_id: entry.call.call_id,
|
|
5382
|
-
output:
|
|
5412
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5383
5413
|
});
|
|
5384
5414
|
} else {
|
|
5385
5415
|
toolOutputs.push({
|
|
5386
5416
|
type: "function_call_output",
|
|
5387
5417
|
call_id: entry.call.call_id,
|
|
5388
|
-
output:
|
|
5418
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5389
5419
|
});
|
|
5390
5420
|
}
|
|
5391
5421
|
}
|
|
@@ -5600,7 +5630,7 @@ async function runToolLoop(request) {
|
|
|
5600
5630
|
toolOutputs.push({
|
|
5601
5631
|
type: "custom_tool_call_output",
|
|
5602
5632
|
call_id: entry.ids.callId,
|
|
5603
|
-
output:
|
|
5633
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5604
5634
|
});
|
|
5605
5635
|
} else {
|
|
5606
5636
|
toolOutputs.push({
|
|
@@ -5614,7 +5644,7 @@ async function runToolLoop(request) {
|
|
|
5614
5644
|
toolOutputs.push({
|
|
5615
5645
|
type: "function_call_output",
|
|
5616
5646
|
call_id: entry.ids.callId,
|
|
5617
|
-
output:
|
|
5647
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5618
5648
|
});
|
|
5619
5649
|
}
|
|
5620
5650
|
}
|
|
@@ -7245,6 +7275,7 @@ function sleep2(ms) {
|
|
|
7245
7275
|
|
|
7246
7276
|
// src/tools/filesystemTools.ts
|
|
7247
7277
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
7278
|
+
var import_node_buffer3 = require("buffer");
|
|
7248
7279
|
var import_zod6 = require("zod");
|
|
7249
7280
|
|
|
7250
7281
|
// src/tools/applyPatch.ts
|
|
@@ -7278,6 +7309,10 @@ var InMemoryAgentFilesystem = class {
|
|
|
7278
7309
|
}
|
|
7279
7310
|
return file.content;
|
|
7280
7311
|
}
|
|
7312
|
+
async readBinaryFile(filePath) {
|
|
7313
|
+
const content = await this.readTextFile(filePath);
|
|
7314
|
+
return Buffer.from(content, "utf8");
|
|
7315
|
+
}
|
|
7281
7316
|
async writeTextFile(filePath, content) {
|
|
7282
7317
|
const absolutePath = import_node_path3.default.resolve(filePath);
|
|
7283
7318
|
const parentPath = import_node_path3.default.dirname(absolutePath);
|
|
@@ -7390,6 +7425,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
7390
7425
|
function createNodeAgentFilesystem() {
|
|
7391
7426
|
return {
|
|
7392
7427
|
readTextFile: async (filePath) => import_node_fs3.promises.readFile(filePath, "utf8"),
|
|
7428
|
+
readBinaryFile: async (filePath) => import_node_fs3.promises.readFile(filePath),
|
|
7393
7429
|
writeTextFile: async (filePath, content) => import_node_fs3.promises.writeFile(filePath, content, "utf8"),
|
|
7394
7430
|
deleteFile: async (filePath) => import_node_fs3.promises.unlink(filePath),
|
|
7395
7431
|
ensureDir: async (directoryPath) => {
|
|
@@ -7945,30 +7981,28 @@ function formatSummary(added, modified, deleted) {
|
|
|
7945
7981
|
|
|
7946
7982
|
// src/tools/filesystemTools.ts
|
|
7947
7983
|
var DEFAULT_READ_FILE_LINE_LIMIT = 2e3;
|
|
7948
|
-
var DEFAULT_READ_FILES_LINE_LIMIT = 200;
|
|
7949
|
-
var DEFAULT_READ_FILES_CHAR_LIMIT = 4e3;
|
|
7950
7984
|
var DEFAULT_LIST_DIR_LIMIT = 25;
|
|
7951
7985
|
var DEFAULT_LIST_DIR_DEPTH = 2;
|
|
7952
7986
|
var DEFAULT_GREP_LIMIT = 100;
|
|
7953
7987
|
var MAX_GREP_LIMIT = 2e3;
|
|
7988
|
+
var MAX_VIEW_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
7954
7989
|
var DEFAULT_MAX_LINE_LENGTH = 500;
|
|
7955
7990
|
var DEFAULT_GREP_MAX_SCANNED_FILES = 2e4;
|
|
7956
|
-
var
|
|
7991
|
+
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
7992
|
+
var IMAGE_MIME_BY_EXTENSION = {
|
|
7993
|
+
".png": "image/png",
|
|
7994
|
+
".jpg": "image/jpeg",
|
|
7995
|
+
".jpeg": "image/jpeg",
|
|
7996
|
+
".webp": "image/webp",
|
|
7997
|
+
".gif": "image/gif"
|
|
7998
|
+
};
|
|
7957
7999
|
var codexReadFileInputSchema = import_zod6.z.object({
|
|
7958
8000
|
file_path: import_zod6.z.string().min(1).describe(
|
|
7959
8001
|
"Path to the file (relative to cwd, or absolute. In sandbox mode, / maps to the sandbox root)."
|
|
7960
8002
|
),
|
|
7961
8003
|
offset: import_zod6.z.number().int().min(1).nullish().describe("The line number to start reading from. Must be 1 or greater."),
|
|
7962
|
-
limit: import_zod6.z.number().int().min(1).nullish().describe("The maximum number of lines to return.")
|
|
7963
|
-
|
|
7964
|
-
indentation: import_zod6.z.object({
|
|
7965
|
-
anchor_line: import_zod6.z.number().int().min(1).nullish(),
|
|
7966
|
-
max_levels: import_zod6.z.number().int().min(0).nullish(),
|
|
7967
|
-
include_siblings: import_zod6.z.boolean().nullish(),
|
|
7968
|
-
include_header: import_zod6.z.boolean().nullish(),
|
|
7969
|
-
max_lines: import_zod6.z.number().int().min(1).nullish()
|
|
7970
|
-
}).nullish()
|
|
7971
|
-
});
|
|
8004
|
+
limit: import_zod6.z.number().int().min(1).nullish().describe("The maximum number of lines to return.")
|
|
8005
|
+
}).strict();
|
|
7972
8006
|
var codexListDirInputSchema = import_zod6.z.object({
|
|
7973
8007
|
dir_path: import_zod6.z.string().min(1).describe(
|
|
7974
8008
|
"Path to the directory to list (relative to cwd, or absolute. In sandbox mode, / maps to the sandbox root)."
|
|
@@ -7983,6 +8017,9 @@ var codexGrepFilesInputSchema = import_zod6.z.object({
|
|
|
7983
8017
|
path: import_zod6.z.string().nullish().describe("Directory or file path to search. Defaults to cwd."),
|
|
7984
8018
|
limit: import_zod6.z.number().int().min(1).nullish().describe("Maximum number of file paths to return (defaults to 100).")
|
|
7985
8019
|
});
|
|
8020
|
+
var codexViewImageInputSchema = import_zod6.z.object({
|
|
8021
|
+
path: import_zod6.z.string().min(1).describe("Local filesystem path to an image file")
|
|
8022
|
+
});
|
|
7986
8023
|
var applyPatchInputSchema = import_zod6.z.object({
|
|
7987
8024
|
input: import_zod6.z.string().min(1).describe(CODEX_APPLY_PATCH_INPUT_DESCRIPTION)
|
|
7988
8025
|
});
|
|
@@ -7990,24 +8027,7 @@ var geminiReadFileInputSchema = import_zod6.z.object({
|
|
|
7990
8027
|
file_path: import_zod6.z.string().min(1),
|
|
7991
8028
|
offset: import_zod6.z.number().int().min(0).nullish(),
|
|
7992
8029
|
limit: import_zod6.z.number().int().min(1).nullish()
|
|
7993
|
-
});
|
|
7994
|
-
var geminiReadFilesInputSchema = import_zod6.z.object({
|
|
7995
|
-
paths: import_zod6.z.array(import_zod6.z.string().min(1)).min(1),
|
|
7996
|
-
line_offset: import_zod6.z.number().int().min(0).nullish(),
|
|
7997
|
-
line_limit: import_zod6.z.number().int().min(1).nullish(),
|
|
7998
|
-
char_offset: import_zod6.z.number().int().min(0).nullish(),
|
|
7999
|
-
char_limit: import_zod6.z.number().int().min(1).nullish(),
|
|
8000
|
-
include_line_numbers: import_zod6.z.boolean().nullish()
|
|
8001
|
-
}).superRefine((value, context) => {
|
|
8002
|
-
const hasLineWindow = value.line_offset !== void 0 || value.line_limit !== void 0;
|
|
8003
|
-
const hasCharWindow = value.char_offset !== void 0 || value.char_limit !== void 0;
|
|
8004
|
-
if (hasLineWindow && hasCharWindow) {
|
|
8005
|
-
context.addIssue({
|
|
8006
|
-
code: import_zod6.z.ZodIssueCode.custom,
|
|
8007
|
-
message: "Use either line_* or char_* window arguments, not both."
|
|
8008
|
-
});
|
|
8009
|
-
}
|
|
8010
|
-
});
|
|
8030
|
+
}).strict();
|
|
8011
8031
|
var geminiWriteFileInputSchema = import_zod6.z.object({
|
|
8012
8032
|
file_path: import_zod6.z.string().min(1),
|
|
8013
8033
|
content: import_zod6.z.string()
|
|
@@ -8090,7 +8110,8 @@ function createCodexFilesystemToolSet(options = {}) {
|
|
|
8090
8110
|
apply_patch: createCodexApplyPatchTool(options),
|
|
8091
8111
|
read_file: createCodexReadFileTool(options),
|
|
8092
8112
|
list_dir: createListDirTool(options),
|
|
8093
|
-
grep_files: createGrepFilesTool(options)
|
|
8113
|
+
grep_files: createGrepFilesTool(options),
|
|
8114
|
+
view_image: createViewImageTool(options)
|
|
8094
8115
|
};
|
|
8095
8116
|
}
|
|
8096
8117
|
function createGeminiFilesystemToolSet(options = {}) {
|
|
@@ -8139,7 +8160,7 @@ function createCodexApplyPatchTool(options = {}) {
|
|
|
8139
8160
|
}
|
|
8140
8161
|
function createCodexReadFileTool(options = {}) {
|
|
8141
8162
|
return tool({
|
|
8142
|
-
description: "Reads a local file with 1-indexed line numbers
|
|
8163
|
+
description: "Reads a local UTF-8 text file with 1-indexed line numbers.",
|
|
8143
8164
|
inputSchema: codexReadFileInputSchema,
|
|
8144
8165
|
execute: async (input) => readFileCodex(input, options)
|
|
8145
8166
|
});
|
|
@@ -8158,6 +8179,13 @@ function createGrepFilesTool(options = {}) {
|
|
|
8158
8179
|
execute: async (input) => grepFilesCodex(input, options)
|
|
8159
8180
|
});
|
|
8160
8181
|
}
|
|
8182
|
+
function createViewImageTool(options = {}) {
|
|
8183
|
+
return tool({
|
|
8184
|
+
description: "View a local image from the filesystem (only use if given a full filepath by the user, and the image isn't already attached to the thread context within <image ...> tags).",
|
|
8185
|
+
inputSchema: codexViewImageInputSchema,
|
|
8186
|
+
execute: async (input) => viewImageCodex(input, options)
|
|
8187
|
+
});
|
|
8188
|
+
}
|
|
8161
8189
|
function createGeminiReadFileTool(options = {}) {
|
|
8162
8190
|
return tool({
|
|
8163
8191
|
description: "Reads and returns the content of a specified file. Supports optional 0-based line offset and line limit.",
|
|
@@ -8165,13 +8193,6 @@ function createGeminiReadFileTool(options = {}) {
|
|
|
8165
8193
|
execute: async (input) => readFileGemini(input, options)
|
|
8166
8194
|
});
|
|
8167
8195
|
}
|
|
8168
|
-
function createReadFilesTool(options = {}) {
|
|
8169
|
-
return tool({
|
|
8170
|
-
description: "Reads one or more files with optional line-based or character-based slicing, similar to a controlled head/tail view.",
|
|
8171
|
-
inputSchema: geminiReadFilesInputSchema,
|
|
8172
|
-
execute: async (input) => readFilesGemini(input, options)
|
|
8173
|
-
});
|
|
8174
|
-
}
|
|
8175
8196
|
function createWriteFileTool(options = {}) {
|
|
8176
8197
|
return tool({
|
|
8177
8198
|
description: "Writes content to a specified file in the local filesystem.",
|
|
@@ -8223,44 +8244,37 @@ async function readFileCodex(input, options) {
|
|
|
8223
8244
|
action: "read",
|
|
8224
8245
|
path: filePath
|
|
8225
8246
|
});
|
|
8226
|
-
const
|
|
8247
|
+
const fileBytes = await readBinaryFile(runtime.filesystem, filePath);
|
|
8248
|
+
const imageMimeType = detectImageMimeType(fileBytes, filePath);
|
|
8249
|
+
if (imageMimeType) {
|
|
8250
|
+
throw new Error(
|
|
8251
|
+
`read_file only supports text files; "${toDisplayPath2(filePath, runtime.cwd)}" is an image (${imageMimeType}). Use view_image instead.`
|
|
8252
|
+
);
|
|
8253
|
+
}
|
|
8254
|
+
if (isPdfFile(fileBytes, filePath)) {
|
|
8255
|
+
throw new Error(
|
|
8256
|
+
`read_file only supports text files; "${toDisplayPath2(filePath, runtime.cwd)}" is a PDF.`
|
|
8257
|
+
);
|
|
8258
|
+
}
|
|
8259
|
+
if (!isValidUtf8(fileBytes)) {
|
|
8260
|
+
throw new Error(
|
|
8261
|
+
`read_file only supports UTF-8 text files; "${toDisplayPath2(filePath, runtime.cwd)}" appears to be binary.`
|
|
8262
|
+
);
|
|
8263
|
+
}
|
|
8264
|
+
const content = fileBytes.toString("utf8");
|
|
8227
8265
|
const lines = splitLines(content);
|
|
8228
8266
|
const offset = input.offset ?? 1;
|
|
8229
8267
|
const limit = input.limit ?? DEFAULT_READ_FILE_LINE_LIMIT;
|
|
8230
|
-
const mode = input.mode ?? "slice";
|
|
8231
8268
|
if (offset > lines.length) {
|
|
8232
8269
|
throw new Error("offset exceeds file length");
|
|
8233
8270
|
}
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
return output.join("\n");
|
|
8242
|
-
}
|
|
8243
|
-
const indentation = input.indentation ?? {};
|
|
8244
|
-
const anchorLine = indentation.anchor_line ?? offset;
|
|
8245
|
-
if (anchorLine < 1 || anchorLine > lines.length) {
|
|
8246
|
-
throw new Error("anchor_line exceeds file length");
|
|
8247
|
-
}
|
|
8248
|
-
const records = lines.map((line, index) => ({
|
|
8249
|
-
number: index + 1,
|
|
8250
|
-
raw: line,
|
|
8251
|
-
display: truncateAtCodePointBoundary(line, runtime.maxLineLength),
|
|
8252
|
-
indent: measureIndent(line, DEFAULT_TAB_WIDTH)
|
|
8253
|
-
}));
|
|
8254
|
-
const selected = readWithIndentationMode({
|
|
8255
|
-
records,
|
|
8256
|
-
anchorLine,
|
|
8257
|
-
limit,
|
|
8258
|
-
maxLevels: indentation.max_levels ?? 0,
|
|
8259
|
-
includeSiblings: indentation.include_siblings ?? false,
|
|
8260
|
-
includeHeader: indentation.include_header ?? true,
|
|
8261
|
-
maxLines: indentation.max_lines ?? void 0
|
|
8262
|
-
});
|
|
8263
|
-
return selected.map((record) => `L${record.number}: ${record.display}`).join("\n");
|
|
8271
|
+
const output = [];
|
|
8272
|
+
const lastLine = Math.min(lines.length, offset + limit - 1);
|
|
8273
|
+
for (let lineNumber = offset; lineNumber <= lastLine; lineNumber += 1) {
|
|
8274
|
+
const line = lines[lineNumber - 1] ?? "";
|
|
8275
|
+
output.push(`L${lineNumber}: ${truncateAtCodePointBoundary(line, runtime.maxLineLength)}`);
|
|
8276
|
+
}
|
|
8277
|
+
return output.join("\n");
|
|
8264
8278
|
}
|
|
8265
8279
|
async function listDirectoryCodex(input, options) {
|
|
8266
8280
|
const runtime = resolveRuntime(options);
|
|
@@ -8348,6 +8362,85 @@ async function grepFilesCodex(input, options) {
|
|
|
8348
8362
|
const limit = Math.min(input.limit ?? DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
|
|
8349
8363
|
return matches.slice(0, limit).map((match) => match.filePath).join("\n");
|
|
8350
8364
|
}
|
|
8365
|
+
async function viewImageCodex(input, options) {
|
|
8366
|
+
const runtime = resolveRuntime(options);
|
|
8367
|
+
const imagePath = resolvePathWithPolicy(input.path, runtime.cwd, runtime.allowOutsideCwd);
|
|
8368
|
+
await runAccessHook2(runtime, {
|
|
8369
|
+
cwd: runtime.cwd,
|
|
8370
|
+
tool: "view_image",
|
|
8371
|
+
action: "read",
|
|
8372
|
+
path: imagePath
|
|
8373
|
+
});
|
|
8374
|
+
const stats = await runtime.filesystem.stat(imagePath);
|
|
8375
|
+
if (stats.kind !== "file") {
|
|
8376
|
+
throw new Error(`image path \`${toDisplayPath2(imagePath, runtime.cwd)}\` is not a file`);
|
|
8377
|
+
}
|
|
8378
|
+
const bytes = await readBinaryFile(runtime.filesystem, imagePath);
|
|
8379
|
+
if (bytes.byteLength > MAX_VIEW_IMAGE_BYTES) {
|
|
8380
|
+
return [
|
|
8381
|
+
{
|
|
8382
|
+
type: "input_text",
|
|
8383
|
+
text: `Codex cannot attach image at \`${toDisplayPath2(imagePath, runtime.cwd)}\`: image exceeds ${MAX_VIEW_IMAGE_BYTES} bytes.`
|
|
8384
|
+
}
|
|
8385
|
+
];
|
|
8386
|
+
}
|
|
8387
|
+
const mimeType = detectImageMimeType(bytes, imagePath);
|
|
8388
|
+
if (!mimeType) {
|
|
8389
|
+
return [
|
|
8390
|
+
{
|
|
8391
|
+
type: "input_text",
|
|
8392
|
+
text: `Codex cannot attach image at \`${toDisplayPath2(imagePath, runtime.cwd)}\`: unsupported image format.`
|
|
8393
|
+
}
|
|
8394
|
+
];
|
|
8395
|
+
}
|
|
8396
|
+
return [
|
|
8397
|
+
{
|
|
8398
|
+
type: "input_image",
|
|
8399
|
+
image_url: `data:${mimeType};base64,${bytes.toString("base64")}`
|
|
8400
|
+
}
|
|
8401
|
+
];
|
|
8402
|
+
}
|
|
8403
|
+
async function readBinaryFile(filesystem, filePath) {
|
|
8404
|
+
if (typeof filesystem.readBinaryFile === "function") {
|
|
8405
|
+
return await filesystem.readBinaryFile(filePath);
|
|
8406
|
+
}
|
|
8407
|
+
const text = await filesystem.readTextFile(filePath);
|
|
8408
|
+
return import_node_buffer3.Buffer.from(text, "utf8");
|
|
8409
|
+
}
|
|
8410
|
+
function detectImageMimeType(buffer, filePath) {
|
|
8411
|
+
if (buffer.length >= 8 && buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10) {
|
|
8412
|
+
return "image/png";
|
|
8413
|
+
}
|
|
8414
|
+
if (buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) {
|
|
8415
|
+
return "image/jpeg";
|
|
8416
|
+
}
|
|
8417
|
+
if (buffer.length >= 6) {
|
|
8418
|
+
const signature = buffer.subarray(0, 6).toString("ascii");
|
|
8419
|
+
if (signature === "GIF87a" || signature === "GIF89a") {
|
|
8420
|
+
return "image/gif";
|
|
8421
|
+
}
|
|
8422
|
+
}
|
|
8423
|
+
if (buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
8424
|
+
return "image/webp";
|
|
8425
|
+
}
|
|
8426
|
+
const fromExtension = IMAGE_MIME_BY_EXTENSION[import_node_path5.default.extname(filePath).toLowerCase()];
|
|
8427
|
+
if (fromExtension && SUPPORTED_IMAGE_MIME_TYPES.has(fromExtension)) {
|
|
8428
|
+
return fromExtension;
|
|
8429
|
+
}
|
|
8430
|
+
return void 0;
|
|
8431
|
+
}
|
|
8432
|
+
function isPdfFile(buffer, filePath) {
|
|
8433
|
+
if (buffer.length >= 5 && buffer.subarray(0, 5).toString("ascii") === "%PDF-") {
|
|
8434
|
+
return true;
|
|
8435
|
+
}
|
|
8436
|
+
return import_node_path5.default.extname(filePath).toLowerCase() === ".pdf";
|
|
8437
|
+
}
|
|
8438
|
+
function isValidUtf8(buffer) {
|
|
8439
|
+
if (buffer.length === 0) {
|
|
8440
|
+
return true;
|
|
8441
|
+
}
|
|
8442
|
+
return import_node_buffer3.Buffer.from(buffer.toString("utf8"), "utf8").equals(buffer);
|
|
8443
|
+
}
|
|
8351
8444
|
async function readFileGemini(input, options) {
|
|
8352
8445
|
const runtime = resolveRuntime(options);
|
|
8353
8446
|
const filePath = resolvePathWithPolicy(input.file_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -8369,56 +8462,6 @@ async function readFileGemini(input, options) {
|
|
|
8369
8462
|
(line, index) => `L${offset + index + 1}: ${truncateAtCodePointBoundary(line ?? "", runtime.maxLineLength)}`
|
|
8370
8463
|
).join("\n");
|
|
8371
8464
|
}
|
|
8372
|
-
async function readFilesGemini(input, options) {
|
|
8373
|
-
const runtime = resolveRuntime(options);
|
|
8374
|
-
const useCharWindow = input.char_offset !== void 0 || input.char_limit !== void 0;
|
|
8375
|
-
const lineOffset = Math.max(0, input.line_offset ?? 0);
|
|
8376
|
-
const lineLimit = input.line_limit ?? DEFAULT_READ_FILES_LINE_LIMIT;
|
|
8377
|
-
const charOffset = Math.max(0, input.char_offset ?? 0);
|
|
8378
|
-
const charLimit = input.char_limit ?? DEFAULT_READ_FILES_CHAR_LIMIT;
|
|
8379
|
-
const includeLineNumbers = input.include_line_numbers !== false;
|
|
8380
|
-
const sections = [];
|
|
8381
|
-
for (const rawPath of input.paths) {
|
|
8382
|
-
const filePath = resolvePathWithPolicy(rawPath, runtime.cwd, runtime.allowOutsideCwd);
|
|
8383
|
-
await runAccessHook2(runtime, {
|
|
8384
|
-
cwd: runtime.cwd,
|
|
8385
|
-
tool: "read_files",
|
|
8386
|
-
action: "read",
|
|
8387
|
-
path: filePath
|
|
8388
|
-
});
|
|
8389
|
-
const content = await runtime.filesystem.readTextFile(filePath);
|
|
8390
|
-
const displayPath = normalizeSlashes(toDisplayPath2(filePath, runtime.cwd));
|
|
8391
|
-
sections.push(`==> ${displayPath} <==`);
|
|
8392
|
-
if (useCharWindow) {
|
|
8393
|
-
if (charOffset >= content.length) {
|
|
8394
|
-
sections.push("");
|
|
8395
|
-
continue;
|
|
8396
|
-
}
|
|
8397
|
-
const end2 = Math.min(content.length, charOffset + charLimit);
|
|
8398
|
-
sections.push(content.slice(charOffset, end2));
|
|
8399
|
-
continue;
|
|
8400
|
-
}
|
|
8401
|
-
const lines = splitLines(content);
|
|
8402
|
-
if (lineOffset >= lines.length) {
|
|
8403
|
-
sections.push("");
|
|
8404
|
-
continue;
|
|
8405
|
-
}
|
|
8406
|
-
const end = Math.min(lines.length, lineOffset + lineLimit);
|
|
8407
|
-
const selected = lines.slice(lineOffset, end);
|
|
8408
|
-
if (includeLineNumbers) {
|
|
8409
|
-
for (let index = 0; index < selected.length; index += 1) {
|
|
8410
|
-
const lineNumber = lineOffset + index + 1;
|
|
8411
|
-
const line = selected[index] ?? "";
|
|
8412
|
-
sections.push(
|
|
8413
|
-
`L${lineNumber}: ${truncateAtCodePointBoundary(line, runtime.maxLineLength)}`
|
|
8414
|
-
);
|
|
8415
|
-
}
|
|
8416
|
-
continue;
|
|
8417
|
-
}
|
|
8418
|
-
sections.push(selected.join("\n"));
|
|
8419
|
-
}
|
|
8420
|
-
return sections.join("\n");
|
|
8421
|
-
}
|
|
8422
8465
|
async function writeFileGemini(input, options) {
|
|
8423
8466
|
const runtime = resolveRuntime(options);
|
|
8424
8467
|
const filePath = resolvePathWithPolicy(input.file_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -8727,117 +8770,6 @@ function truncateAtCodePointBoundary(value, maxLength) {
|
|
|
8727
8770
|
}
|
|
8728
8771
|
return Array.from(value).slice(0, maxLength).join("");
|
|
8729
8772
|
}
|
|
8730
|
-
function measureIndent(line, tabWidth) {
|
|
8731
|
-
let count = 0;
|
|
8732
|
-
for (const char of line) {
|
|
8733
|
-
if (char === " ") {
|
|
8734
|
-
count += 1;
|
|
8735
|
-
continue;
|
|
8736
|
-
}
|
|
8737
|
-
if (char === " ") {
|
|
8738
|
-
count += tabWidth;
|
|
8739
|
-
continue;
|
|
8740
|
-
}
|
|
8741
|
-
break;
|
|
8742
|
-
}
|
|
8743
|
-
return count;
|
|
8744
|
-
}
|
|
8745
|
-
function computeEffectiveIndents(records) {
|
|
8746
|
-
const effective = [];
|
|
8747
|
-
let previous = 0;
|
|
8748
|
-
for (const record of records) {
|
|
8749
|
-
if (record.raw.trim().length === 0) {
|
|
8750
|
-
effective.push(previous);
|
|
8751
|
-
} else {
|
|
8752
|
-
previous = record.indent;
|
|
8753
|
-
effective.push(previous);
|
|
8754
|
-
}
|
|
8755
|
-
}
|
|
8756
|
-
return effective;
|
|
8757
|
-
}
|
|
8758
|
-
function trimBoundaryBlankLines(records) {
|
|
8759
|
-
while (records.length > 0 && records[0]?.raw.trim().length === 0) {
|
|
8760
|
-
records.shift();
|
|
8761
|
-
}
|
|
8762
|
-
while (records.length > 0 && records[records.length - 1]?.raw.trim().length === 0) {
|
|
8763
|
-
records.pop();
|
|
8764
|
-
}
|
|
8765
|
-
}
|
|
8766
|
-
function isCommentLine(line) {
|
|
8767
|
-
const trimmed = line.trim();
|
|
8768
|
-
return trimmed.startsWith("#") || trimmed.startsWith("//") || trimmed.startsWith("--");
|
|
8769
|
-
}
|
|
8770
|
-
function readWithIndentationMode(params) {
|
|
8771
|
-
const { records, anchorLine, limit, maxLevels, includeSiblings, includeHeader, maxLines } = params;
|
|
8772
|
-
const anchorIndex = anchorLine - 1;
|
|
8773
|
-
const effectiveIndents = computeEffectiveIndents(records);
|
|
8774
|
-
const anchorIndent = effectiveIndents[anchorIndex] ?? 0;
|
|
8775
|
-
const minIndent = maxLevels === 0 ? 0 : Math.max(anchorIndent - maxLevels * DEFAULT_TAB_WIDTH, 0);
|
|
8776
|
-
const guardLimit = maxLines ?? limit;
|
|
8777
|
-
const finalLimit = Math.min(limit, guardLimit, records.length);
|
|
8778
|
-
if (finalLimit <= 1) {
|
|
8779
|
-
return [records[anchorIndex]].filter((entry) => Boolean(entry));
|
|
8780
|
-
}
|
|
8781
|
-
let upper = anchorIndex - 1;
|
|
8782
|
-
let lower = anchorIndex + 1;
|
|
8783
|
-
let upperMinIndentHits = 0;
|
|
8784
|
-
let lowerMinIndentHits = 0;
|
|
8785
|
-
const output = [records[anchorIndex]].filter(
|
|
8786
|
-
(entry) => Boolean(entry)
|
|
8787
|
-
);
|
|
8788
|
-
while (output.length < finalLimit) {
|
|
8789
|
-
let progressed = 0;
|
|
8790
|
-
if (upper >= 0) {
|
|
8791
|
-
const candidate = records[upper];
|
|
8792
|
-
const candidateIndent = effectiveIndents[upper] ?? 0;
|
|
8793
|
-
if (candidate && candidateIndent >= minIndent) {
|
|
8794
|
-
output.unshift(candidate);
|
|
8795
|
-
progressed += 1;
|
|
8796
|
-
upper -= 1;
|
|
8797
|
-
if (candidateIndent === minIndent && !includeSiblings) {
|
|
8798
|
-
const allowHeaderComment = includeHeader && isCommentLine(candidate.raw);
|
|
8799
|
-
const canTakeLine = allowHeaderComment || upperMinIndentHits === 0;
|
|
8800
|
-
if (canTakeLine) {
|
|
8801
|
-
upperMinIndentHits += 1;
|
|
8802
|
-
} else {
|
|
8803
|
-
output.shift();
|
|
8804
|
-
progressed -= 1;
|
|
8805
|
-
upper = -1;
|
|
8806
|
-
}
|
|
8807
|
-
}
|
|
8808
|
-
if (output.length >= finalLimit) {
|
|
8809
|
-
break;
|
|
8810
|
-
}
|
|
8811
|
-
} else {
|
|
8812
|
-
upper = -1;
|
|
8813
|
-
}
|
|
8814
|
-
}
|
|
8815
|
-
if (lower < records.length) {
|
|
8816
|
-
const candidate = records[lower];
|
|
8817
|
-
const candidateIndent = effectiveIndents[lower] ?? 0;
|
|
8818
|
-
if (candidate && candidateIndent >= minIndent) {
|
|
8819
|
-
output.push(candidate);
|
|
8820
|
-
progressed += 1;
|
|
8821
|
-
lower += 1;
|
|
8822
|
-
if (candidateIndent === minIndent && !includeSiblings) {
|
|
8823
|
-
if (lowerMinIndentHits > 0) {
|
|
8824
|
-
output.pop();
|
|
8825
|
-
progressed -= 1;
|
|
8826
|
-
lower = records.length;
|
|
8827
|
-
}
|
|
8828
|
-
lowerMinIndentHits += 1;
|
|
8829
|
-
}
|
|
8830
|
-
} else {
|
|
8831
|
-
lower = records.length;
|
|
8832
|
-
}
|
|
8833
|
-
}
|
|
8834
|
-
if (progressed === 0) {
|
|
8835
|
-
break;
|
|
8836
|
-
}
|
|
8837
|
-
}
|
|
8838
|
-
trimBoundaryBlankLines(output);
|
|
8839
|
-
return output;
|
|
8840
|
-
}
|
|
8841
8773
|
async function collectDirectoryEntries(filesystem, rootPath, depth, maxLineLength) {
|
|
8842
8774
|
const queue = [
|
|
8843
8775
|
{ path: rootPath, relativePrefix: "", remainingDepth: depth }
|
|
@@ -10156,10 +10088,10 @@ async function runCandidateEvolution(options) {
|
|
|
10156
10088
|
createListDirectoryTool,
|
|
10157
10089
|
createModelAgnosticFilesystemToolSet,
|
|
10158
10090
|
createNodeAgentFilesystem,
|
|
10159
|
-
createReadFilesTool,
|
|
10160
10091
|
createReplaceTool,
|
|
10161
10092
|
createRgSearchTool,
|
|
10162
10093
|
createToolLoopSteeringChannel,
|
|
10094
|
+
createViewImageTool,
|
|
10163
10095
|
createWriteFileTool,
|
|
10164
10096
|
customTool,
|
|
10165
10097
|
encodeChatGptAuthJson,
|