@ljoukov/llm 3.0.10 → 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 +185 -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 +184 -240
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -121,6 +121,15 @@ var GEMINI_2_5_PRO_PRICING = {
|
|
|
121
121
|
outputRateLow: 10 / 1e6,
|
|
122
122
|
outputRateHigh: 15 / 1e6
|
|
123
123
|
};
|
|
124
|
+
var GEMINI_2_5_FLASH_PRICING = {
|
|
125
|
+
threshold: 2e5,
|
|
126
|
+
inputRateLow: 0.3 / 1e6,
|
|
127
|
+
inputRateHigh: 0.3 / 1e6,
|
|
128
|
+
cachedRateLow: 0.03 / 1e6,
|
|
129
|
+
cachedRateHigh: 0.03 / 1e6,
|
|
130
|
+
outputRateLow: 2.5 / 1e6,
|
|
131
|
+
outputRateHigh: 2.5 / 1e6
|
|
132
|
+
};
|
|
124
133
|
var GEMINI_IMAGE_PREVIEW_PRICING = {
|
|
125
134
|
inputRate: 2 / 1e6,
|
|
126
135
|
cachedRate: 0.2 / 1e6,
|
|
@@ -136,6 +145,9 @@ function getGeminiProPricing(modelId) {
|
|
|
136
145
|
if (modelId.includes("gemini-2.5-pro")) {
|
|
137
146
|
return GEMINI_2_5_PRO_PRICING;
|
|
138
147
|
}
|
|
148
|
+
if (modelId.includes("gemini-2.5-flash") || modelId.includes("gemini-flash-latest")) {
|
|
149
|
+
return GEMINI_2_5_FLASH_PRICING;
|
|
150
|
+
}
|
|
139
151
|
if (modelId.includes("gemini-3-pro") || modelId.includes("gemini-3.1-pro")) {
|
|
140
152
|
return GEMINI_3_PRO_PREVIEW_PRICING;
|
|
141
153
|
}
|
|
@@ -2093,7 +2105,6 @@ function getGoogleAuthOptions(scopes) {
|
|
|
2093
2105
|
|
|
2094
2106
|
// src/google/client.ts
|
|
2095
2107
|
var GEMINI_TEXT_MODEL_IDS = [
|
|
2096
|
-
"gemini-3-pro-preview",
|
|
2097
2108
|
"gemini-3.1-pro-preview",
|
|
2098
2109
|
"gemini-3-flash-preview",
|
|
2099
2110
|
"gemini-2.5-pro",
|
|
@@ -3897,6 +3908,38 @@ function mergeToolOutput(value) {
|
|
|
3897
3908
|
return JSON.stringify({ error: "Failed to serialize tool output", detail: message });
|
|
3898
3909
|
}
|
|
3899
3910
|
}
|
|
3911
|
+
function isLlmToolOutputContentItem(value) {
|
|
3912
|
+
if (!isPlainRecord(value)) {
|
|
3913
|
+
return false;
|
|
3914
|
+
}
|
|
3915
|
+
const itemType = typeof value.type === "string" ? value.type : "";
|
|
3916
|
+
if (itemType === "input_text") {
|
|
3917
|
+
return typeof value.text === "string";
|
|
3918
|
+
}
|
|
3919
|
+
if (itemType === "input_image") {
|
|
3920
|
+
return typeof value.image_url === "string";
|
|
3921
|
+
}
|
|
3922
|
+
if (itemType === "input_file") {
|
|
3923
|
+
const keys = ["file_data", "file_id", "file_url", "filename"];
|
|
3924
|
+
for (const key of keys) {
|
|
3925
|
+
const part = value[key];
|
|
3926
|
+
if (part !== void 0 && part !== null && typeof part !== "string") {
|
|
3927
|
+
return false;
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
return true;
|
|
3931
|
+
}
|
|
3932
|
+
return false;
|
|
3933
|
+
}
|
|
3934
|
+
function toOpenAiToolOutput(value) {
|
|
3935
|
+
if (isLlmToolOutputContentItem(value)) {
|
|
3936
|
+
return [value];
|
|
3937
|
+
}
|
|
3938
|
+
if (Array.isArray(value) && value.every((item) => isLlmToolOutputContentItem(item))) {
|
|
3939
|
+
return value;
|
|
3940
|
+
}
|
|
3941
|
+
return mergeToolOutput(value);
|
|
3942
|
+
}
|
|
3900
3943
|
function parseOpenAiToolArguments(raw) {
|
|
3901
3944
|
const trimmed = raw.trim();
|
|
3902
3945
|
if (trimmed.length === 0) {
|
|
@@ -4252,7 +4295,6 @@ function resolveGeminiThinkingConfig(modelId) {
|
|
|
4252
4295
|
return void 0;
|
|
4253
4296
|
}
|
|
4254
4297
|
switch (modelId) {
|
|
4255
|
-
case "gemini-3-pro-preview":
|
|
4256
4298
|
case "gemini-3.1-pro-preview":
|
|
4257
4299
|
return { includeThoughts: true };
|
|
4258
4300
|
case "gemini-3-flash-preview":
|
|
@@ -5254,13 +5296,13 @@ async function runToolLoop(request) {
|
|
|
5254
5296
|
toolOutputs.push({
|
|
5255
5297
|
type: "custom_tool_call_output",
|
|
5256
5298
|
call_id: entry.call.call_id,
|
|
5257
|
-
output:
|
|
5299
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5258
5300
|
});
|
|
5259
5301
|
} else {
|
|
5260
5302
|
toolOutputs.push({
|
|
5261
5303
|
type: "function_call_output",
|
|
5262
5304
|
call_id: entry.call.call_id,
|
|
5263
|
-
output:
|
|
5305
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5264
5306
|
});
|
|
5265
5307
|
}
|
|
5266
5308
|
}
|
|
@@ -5475,7 +5517,7 @@ async function runToolLoop(request) {
|
|
|
5475
5517
|
toolOutputs.push({
|
|
5476
5518
|
type: "custom_tool_call_output",
|
|
5477
5519
|
call_id: entry.ids.callId,
|
|
5478
|
-
output:
|
|
5520
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5479
5521
|
});
|
|
5480
5522
|
} else {
|
|
5481
5523
|
toolOutputs.push({
|
|
@@ -5489,7 +5531,7 @@ async function runToolLoop(request) {
|
|
|
5489
5531
|
toolOutputs.push({
|
|
5490
5532
|
type: "function_call_output",
|
|
5491
5533
|
call_id: entry.ids.callId,
|
|
5492
|
-
output:
|
|
5534
|
+
output: toOpenAiToolOutput(outputPayload)
|
|
5493
5535
|
});
|
|
5494
5536
|
}
|
|
5495
5537
|
}
|
|
@@ -7120,6 +7162,7 @@ function sleep2(ms) {
|
|
|
7120
7162
|
|
|
7121
7163
|
// src/tools/filesystemTools.ts
|
|
7122
7164
|
import path5 from "path";
|
|
7165
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
7123
7166
|
import { z as z6 } from "zod";
|
|
7124
7167
|
|
|
7125
7168
|
// src/tools/applyPatch.ts
|
|
@@ -7153,6 +7196,10 @@ var InMemoryAgentFilesystem = class {
|
|
|
7153
7196
|
}
|
|
7154
7197
|
return file.content;
|
|
7155
7198
|
}
|
|
7199
|
+
async readBinaryFile(filePath) {
|
|
7200
|
+
const content = await this.readTextFile(filePath);
|
|
7201
|
+
return Buffer.from(content, "utf8");
|
|
7202
|
+
}
|
|
7156
7203
|
async writeTextFile(filePath, content) {
|
|
7157
7204
|
const absolutePath = path3.resolve(filePath);
|
|
7158
7205
|
const parentPath = path3.dirname(absolutePath);
|
|
@@ -7265,6 +7312,7 @@ var InMemoryAgentFilesystem = class {
|
|
|
7265
7312
|
function createNodeAgentFilesystem() {
|
|
7266
7313
|
return {
|
|
7267
7314
|
readTextFile: async (filePath) => fs3.readFile(filePath, "utf8"),
|
|
7315
|
+
readBinaryFile: async (filePath) => fs3.readFile(filePath),
|
|
7268
7316
|
writeTextFile: async (filePath, content) => fs3.writeFile(filePath, content, "utf8"),
|
|
7269
7317
|
deleteFile: async (filePath) => fs3.unlink(filePath),
|
|
7270
7318
|
ensureDir: async (directoryPath) => {
|
|
@@ -7820,30 +7868,28 @@ function formatSummary(added, modified, deleted) {
|
|
|
7820
7868
|
|
|
7821
7869
|
// src/tools/filesystemTools.ts
|
|
7822
7870
|
var DEFAULT_READ_FILE_LINE_LIMIT = 2e3;
|
|
7823
|
-
var DEFAULT_READ_FILES_LINE_LIMIT = 200;
|
|
7824
|
-
var DEFAULT_READ_FILES_CHAR_LIMIT = 4e3;
|
|
7825
7871
|
var DEFAULT_LIST_DIR_LIMIT = 25;
|
|
7826
7872
|
var DEFAULT_LIST_DIR_DEPTH = 2;
|
|
7827
7873
|
var DEFAULT_GREP_LIMIT = 100;
|
|
7828
7874
|
var MAX_GREP_LIMIT = 2e3;
|
|
7875
|
+
var MAX_VIEW_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
7829
7876
|
var DEFAULT_MAX_LINE_LENGTH = 500;
|
|
7830
7877
|
var DEFAULT_GREP_MAX_SCANNED_FILES = 2e4;
|
|
7831
|
-
var
|
|
7878
|
+
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
7879
|
+
var IMAGE_MIME_BY_EXTENSION = {
|
|
7880
|
+
".png": "image/png",
|
|
7881
|
+
".jpg": "image/jpeg",
|
|
7882
|
+
".jpeg": "image/jpeg",
|
|
7883
|
+
".webp": "image/webp",
|
|
7884
|
+
".gif": "image/gif"
|
|
7885
|
+
};
|
|
7832
7886
|
var codexReadFileInputSchema = z6.object({
|
|
7833
7887
|
file_path: z6.string().min(1).describe(
|
|
7834
7888
|
"Path to the file (relative to cwd, or absolute. In sandbox mode, / maps to the sandbox root)."
|
|
7835
7889
|
),
|
|
7836
7890
|
offset: z6.number().int().min(1).nullish().describe("The line number to start reading from. Must be 1 or greater."),
|
|
7837
|
-
limit: z6.number().int().min(1).nullish().describe("The maximum number of lines to return.")
|
|
7838
|
-
|
|
7839
|
-
indentation: z6.object({
|
|
7840
|
-
anchor_line: z6.number().int().min(1).nullish(),
|
|
7841
|
-
max_levels: z6.number().int().min(0).nullish(),
|
|
7842
|
-
include_siblings: z6.boolean().nullish(),
|
|
7843
|
-
include_header: z6.boolean().nullish(),
|
|
7844
|
-
max_lines: z6.number().int().min(1).nullish()
|
|
7845
|
-
}).nullish()
|
|
7846
|
-
});
|
|
7891
|
+
limit: z6.number().int().min(1).nullish().describe("The maximum number of lines to return.")
|
|
7892
|
+
}).strict();
|
|
7847
7893
|
var codexListDirInputSchema = z6.object({
|
|
7848
7894
|
dir_path: z6.string().min(1).describe(
|
|
7849
7895
|
"Path to the directory to list (relative to cwd, or absolute. In sandbox mode, / maps to the sandbox root)."
|
|
@@ -7858,6 +7904,9 @@ var codexGrepFilesInputSchema = z6.object({
|
|
|
7858
7904
|
path: z6.string().nullish().describe("Directory or file path to search. Defaults to cwd."),
|
|
7859
7905
|
limit: z6.number().int().min(1).nullish().describe("Maximum number of file paths to return (defaults to 100).")
|
|
7860
7906
|
});
|
|
7907
|
+
var codexViewImageInputSchema = z6.object({
|
|
7908
|
+
path: z6.string().min(1).describe("Local filesystem path to an image file")
|
|
7909
|
+
});
|
|
7861
7910
|
var applyPatchInputSchema = z6.object({
|
|
7862
7911
|
input: z6.string().min(1).describe(CODEX_APPLY_PATCH_INPUT_DESCRIPTION)
|
|
7863
7912
|
});
|
|
@@ -7865,24 +7914,7 @@ var geminiReadFileInputSchema = z6.object({
|
|
|
7865
7914
|
file_path: z6.string().min(1),
|
|
7866
7915
|
offset: z6.number().int().min(0).nullish(),
|
|
7867
7916
|
limit: z6.number().int().min(1).nullish()
|
|
7868
|
-
});
|
|
7869
|
-
var geminiReadFilesInputSchema = z6.object({
|
|
7870
|
-
paths: z6.array(z6.string().min(1)).min(1),
|
|
7871
|
-
line_offset: z6.number().int().min(0).nullish(),
|
|
7872
|
-
line_limit: z6.number().int().min(1).nullish(),
|
|
7873
|
-
char_offset: z6.number().int().min(0).nullish(),
|
|
7874
|
-
char_limit: z6.number().int().min(1).nullish(),
|
|
7875
|
-
include_line_numbers: z6.boolean().nullish()
|
|
7876
|
-
}).superRefine((value, context) => {
|
|
7877
|
-
const hasLineWindow = value.line_offset !== void 0 || value.line_limit !== void 0;
|
|
7878
|
-
const hasCharWindow = value.char_offset !== void 0 || value.char_limit !== void 0;
|
|
7879
|
-
if (hasLineWindow && hasCharWindow) {
|
|
7880
|
-
context.addIssue({
|
|
7881
|
-
code: z6.ZodIssueCode.custom,
|
|
7882
|
-
message: "Use either line_* or char_* window arguments, not both."
|
|
7883
|
-
});
|
|
7884
|
-
}
|
|
7885
|
-
});
|
|
7917
|
+
}).strict();
|
|
7886
7918
|
var geminiWriteFileInputSchema = z6.object({
|
|
7887
7919
|
file_path: z6.string().min(1),
|
|
7888
7920
|
content: z6.string()
|
|
@@ -7965,7 +7997,8 @@ function createCodexFilesystemToolSet(options = {}) {
|
|
|
7965
7997
|
apply_patch: createCodexApplyPatchTool(options),
|
|
7966
7998
|
read_file: createCodexReadFileTool(options),
|
|
7967
7999
|
list_dir: createListDirTool(options),
|
|
7968
|
-
grep_files: createGrepFilesTool(options)
|
|
8000
|
+
grep_files: createGrepFilesTool(options),
|
|
8001
|
+
view_image: createViewImageTool(options)
|
|
7969
8002
|
};
|
|
7970
8003
|
}
|
|
7971
8004
|
function createGeminiFilesystemToolSet(options = {}) {
|
|
@@ -8014,7 +8047,7 @@ function createCodexApplyPatchTool(options = {}) {
|
|
|
8014
8047
|
}
|
|
8015
8048
|
function createCodexReadFileTool(options = {}) {
|
|
8016
8049
|
return tool({
|
|
8017
|
-
description: "Reads a local file with 1-indexed line numbers
|
|
8050
|
+
description: "Reads a local UTF-8 text file with 1-indexed line numbers.",
|
|
8018
8051
|
inputSchema: codexReadFileInputSchema,
|
|
8019
8052
|
execute: async (input) => readFileCodex(input, options)
|
|
8020
8053
|
});
|
|
@@ -8033,6 +8066,13 @@ function createGrepFilesTool(options = {}) {
|
|
|
8033
8066
|
execute: async (input) => grepFilesCodex(input, options)
|
|
8034
8067
|
});
|
|
8035
8068
|
}
|
|
8069
|
+
function createViewImageTool(options = {}) {
|
|
8070
|
+
return tool({
|
|
8071
|
+
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).",
|
|
8072
|
+
inputSchema: codexViewImageInputSchema,
|
|
8073
|
+
execute: async (input) => viewImageCodex(input, options)
|
|
8074
|
+
});
|
|
8075
|
+
}
|
|
8036
8076
|
function createGeminiReadFileTool(options = {}) {
|
|
8037
8077
|
return tool({
|
|
8038
8078
|
description: "Reads and returns the content of a specified file. Supports optional 0-based line offset and line limit.",
|
|
@@ -8040,13 +8080,6 @@ function createGeminiReadFileTool(options = {}) {
|
|
|
8040
8080
|
execute: async (input) => readFileGemini(input, options)
|
|
8041
8081
|
});
|
|
8042
8082
|
}
|
|
8043
|
-
function createReadFilesTool(options = {}) {
|
|
8044
|
-
return tool({
|
|
8045
|
-
description: "Reads one or more files with optional line-based or character-based slicing, similar to a controlled head/tail view.",
|
|
8046
|
-
inputSchema: geminiReadFilesInputSchema,
|
|
8047
|
-
execute: async (input) => readFilesGemini(input, options)
|
|
8048
|
-
});
|
|
8049
|
-
}
|
|
8050
8083
|
function createWriteFileTool(options = {}) {
|
|
8051
8084
|
return tool({
|
|
8052
8085
|
description: "Writes content to a specified file in the local filesystem.",
|
|
@@ -8098,44 +8131,37 @@ async function readFileCodex(input, options) {
|
|
|
8098
8131
|
action: "read",
|
|
8099
8132
|
path: filePath
|
|
8100
8133
|
});
|
|
8101
|
-
const
|
|
8134
|
+
const fileBytes = await readBinaryFile(runtime.filesystem, filePath);
|
|
8135
|
+
const imageMimeType = detectImageMimeType(fileBytes, filePath);
|
|
8136
|
+
if (imageMimeType) {
|
|
8137
|
+
throw new Error(
|
|
8138
|
+
`read_file only supports text files; "${toDisplayPath2(filePath, runtime.cwd)}" is an image (${imageMimeType}). Use view_image instead.`
|
|
8139
|
+
);
|
|
8140
|
+
}
|
|
8141
|
+
if (isPdfFile(fileBytes, filePath)) {
|
|
8142
|
+
throw new Error(
|
|
8143
|
+
`read_file only supports text files; "${toDisplayPath2(filePath, runtime.cwd)}" is a PDF.`
|
|
8144
|
+
);
|
|
8145
|
+
}
|
|
8146
|
+
if (!isValidUtf8(fileBytes)) {
|
|
8147
|
+
throw new Error(
|
|
8148
|
+
`read_file only supports UTF-8 text files; "${toDisplayPath2(filePath, runtime.cwd)}" appears to be binary.`
|
|
8149
|
+
);
|
|
8150
|
+
}
|
|
8151
|
+
const content = fileBytes.toString("utf8");
|
|
8102
8152
|
const lines = splitLines(content);
|
|
8103
8153
|
const offset = input.offset ?? 1;
|
|
8104
8154
|
const limit = input.limit ?? DEFAULT_READ_FILE_LINE_LIMIT;
|
|
8105
|
-
const mode = input.mode ?? "slice";
|
|
8106
8155
|
if (offset > lines.length) {
|
|
8107
8156
|
throw new Error("offset exceeds file length");
|
|
8108
8157
|
}
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
return output.join("\n");
|
|
8117
|
-
}
|
|
8118
|
-
const indentation = input.indentation ?? {};
|
|
8119
|
-
const anchorLine = indentation.anchor_line ?? offset;
|
|
8120
|
-
if (anchorLine < 1 || anchorLine > lines.length) {
|
|
8121
|
-
throw new Error("anchor_line exceeds file length");
|
|
8122
|
-
}
|
|
8123
|
-
const records = lines.map((line, index) => ({
|
|
8124
|
-
number: index + 1,
|
|
8125
|
-
raw: line,
|
|
8126
|
-
display: truncateAtCodePointBoundary(line, runtime.maxLineLength),
|
|
8127
|
-
indent: measureIndent(line, DEFAULT_TAB_WIDTH)
|
|
8128
|
-
}));
|
|
8129
|
-
const selected = readWithIndentationMode({
|
|
8130
|
-
records,
|
|
8131
|
-
anchorLine,
|
|
8132
|
-
limit,
|
|
8133
|
-
maxLevels: indentation.max_levels ?? 0,
|
|
8134
|
-
includeSiblings: indentation.include_siblings ?? false,
|
|
8135
|
-
includeHeader: indentation.include_header ?? true,
|
|
8136
|
-
maxLines: indentation.max_lines ?? void 0
|
|
8137
|
-
});
|
|
8138
|
-
return selected.map((record) => `L${record.number}: ${record.display}`).join("\n");
|
|
8158
|
+
const output = [];
|
|
8159
|
+
const lastLine = Math.min(lines.length, offset + limit - 1);
|
|
8160
|
+
for (let lineNumber = offset; lineNumber <= lastLine; lineNumber += 1) {
|
|
8161
|
+
const line = lines[lineNumber - 1] ?? "";
|
|
8162
|
+
output.push(`L${lineNumber}: ${truncateAtCodePointBoundary(line, runtime.maxLineLength)}`);
|
|
8163
|
+
}
|
|
8164
|
+
return output.join("\n");
|
|
8139
8165
|
}
|
|
8140
8166
|
async function listDirectoryCodex(input, options) {
|
|
8141
8167
|
const runtime = resolveRuntime(options);
|
|
@@ -8223,6 +8249,85 @@ async function grepFilesCodex(input, options) {
|
|
|
8223
8249
|
const limit = Math.min(input.limit ?? DEFAULT_GREP_LIMIT, MAX_GREP_LIMIT);
|
|
8224
8250
|
return matches.slice(0, limit).map((match) => match.filePath).join("\n");
|
|
8225
8251
|
}
|
|
8252
|
+
async function viewImageCodex(input, options) {
|
|
8253
|
+
const runtime = resolveRuntime(options);
|
|
8254
|
+
const imagePath = resolvePathWithPolicy(input.path, runtime.cwd, runtime.allowOutsideCwd);
|
|
8255
|
+
await runAccessHook2(runtime, {
|
|
8256
|
+
cwd: runtime.cwd,
|
|
8257
|
+
tool: "view_image",
|
|
8258
|
+
action: "read",
|
|
8259
|
+
path: imagePath
|
|
8260
|
+
});
|
|
8261
|
+
const stats = await runtime.filesystem.stat(imagePath);
|
|
8262
|
+
if (stats.kind !== "file") {
|
|
8263
|
+
throw new Error(`image path \`${toDisplayPath2(imagePath, runtime.cwd)}\` is not a file`);
|
|
8264
|
+
}
|
|
8265
|
+
const bytes = await readBinaryFile(runtime.filesystem, imagePath);
|
|
8266
|
+
if (bytes.byteLength > MAX_VIEW_IMAGE_BYTES) {
|
|
8267
|
+
return [
|
|
8268
|
+
{
|
|
8269
|
+
type: "input_text",
|
|
8270
|
+
text: `Codex cannot attach image at \`${toDisplayPath2(imagePath, runtime.cwd)}\`: image exceeds ${MAX_VIEW_IMAGE_BYTES} bytes.`
|
|
8271
|
+
}
|
|
8272
|
+
];
|
|
8273
|
+
}
|
|
8274
|
+
const mimeType = detectImageMimeType(bytes, imagePath);
|
|
8275
|
+
if (!mimeType) {
|
|
8276
|
+
return [
|
|
8277
|
+
{
|
|
8278
|
+
type: "input_text",
|
|
8279
|
+
text: `Codex cannot attach image at \`${toDisplayPath2(imagePath, runtime.cwd)}\`: unsupported image format.`
|
|
8280
|
+
}
|
|
8281
|
+
];
|
|
8282
|
+
}
|
|
8283
|
+
return [
|
|
8284
|
+
{
|
|
8285
|
+
type: "input_image",
|
|
8286
|
+
image_url: `data:${mimeType};base64,${bytes.toString("base64")}`
|
|
8287
|
+
}
|
|
8288
|
+
];
|
|
8289
|
+
}
|
|
8290
|
+
async function readBinaryFile(filesystem, filePath) {
|
|
8291
|
+
if (typeof filesystem.readBinaryFile === "function") {
|
|
8292
|
+
return await filesystem.readBinaryFile(filePath);
|
|
8293
|
+
}
|
|
8294
|
+
const text = await filesystem.readTextFile(filePath);
|
|
8295
|
+
return Buffer4.from(text, "utf8");
|
|
8296
|
+
}
|
|
8297
|
+
function detectImageMimeType(buffer, filePath) {
|
|
8298
|
+
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) {
|
|
8299
|
+
return "image/png";
|
|
8300
|
+
}
|
|
8301
|
+
if (buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) {
|
|
8302
|
+
return "image/jpeg";
|
|
8303
|
+
}
|
|
8304
|
+
if (buffer.length >= 6) {
|
|
8305
|
+
const signature = buffer.subarray(0, 6).toString("ascii");
|
|
8306
|
+
if (signature === "GIF87a" || signature === "GIF89a") {
|
|
8307
|
+
return "image/gif";
|
|
8308
|
+
}
|
|
8309
|
+
}
|
|
8310
|
+
if (buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
8311
|
+
return "image/webp";
|
|
8312
|
+
}
|
|
8313
|
+
const fromExtension = IMAGE_MIME_BY_EXTENSION[path5.extname(filePath).toLowerCase()];
|
|
8314
|
+
if (fromExtension && SUPPORTED_IMAGE_MIME_TYPES.has(fromExtension)) {
|
|
8315
|
+
return fromExtension;
|
|
8316
|
+
}
|
|
8317
|
+
return void 0;
|
|
8318
|
+
}
|
|
8319
|
+
function isPdfFile(buffer, filePath) {
|
|
8320
|
+
if (buffer.length >= 5 && buffer.subarray(0, 5).toString("ascii") === "%PDF-") {
|
|
8321
|
+
return true;
|
|
8322
|
+
}
|
|
8323
|
+
return path5.extname(filePath).toLowerCase() === ".pdf";
|
|
8324
|
+
}
|
|
8325
|
+
function isValidUtf8(buffer) {
|
|
8326
|
+
if (buffer.length === 0) {
|
|
8327
|
+
return true;
|
|
8328
|
+
}
|
|
8329
|
+
return Buffer4.from(buffer.toString("utf8"), "utf8").equals(buffer);
|
|
8330
|
+
}
|
|
8226
8331
|
async function readFileGemini(input, options) {
|
|
8227
8332
|
const runtime = resolveRuntime(options);
|
|
8228
8333
|
const filePath = resolvePathWithPolicy(input.file_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -8244,56 +8349,6 @@ async function readFileGemini(input, options) {
|
|
|
8244
8349
|
(line, index) => `L${offset + index + 1}: ${truncateAtCodePointBoundary(line ?? "", runtime.maxLineLength)}`
|
|
8245
8350
|
).join("\n");
|
|
8246
8351
|
}
|
|
8247
|
-
async function readFilesGemini(input, options) {
|
|
8248
|
-
const runtime = resolveRuntime(options);
|
|
8249
|
-
const useCharWindow = input.char_offset !== void 0 || input.char_limit !== void 0;
|
|
8250
|
-
const lineOffset = Math.max(0, input.line_offset ?? 0);
|
|
8251
|
-
const lineLimit = input.line_limit ?? DEFAULT_READ_FILES_LINE_LIMIT;
|
|
8252
|
-
const charOffset = Math.max(0, input.char_offset ?? 0);
|
|
8253
|
-
const charLimit = input.char_limit ?? DEFAULT_READ_FILES_CHAR_LIMIT;
|
|
8254
|
-
const includeLineNumbers = input.include_line_numbers !== false;
|
|
8255
|
-
const sections = [];
|
|
8256
|
-
for (const rawPath of input.paths) {
|
|
8257
|
-
const filePath = resolvePathWithPolicy(rawPath, runtime.cwd, runtime.allowOutsideCwd);
|
|
8258
|
-
await runAccessHook2(runtime, {
|
|
8259
|
-
cwd: runtime.cwd,
|
|
8260
|
-
tool: "read_files",
|
|
8261
|
-
action: "read",
|
|
8262
|
-
path: filePath
|
|
8263
|
-
});
|
|
8264
|
-
const content = await runtime.filesystem.readTextFile(filePath);
|
|
8265
|
-
const displayPath = normalizeSlashes(toDisplayPath2(filePath, runtime.cwd));
|
|
8266
|
-
sections.push(`==> ${displayPath} <==`);
|
|
8267
|
-
if (useCharWindow) {
|
|
8268
|
-
if (charOffset >= content.length) {
|
|
8269
|
-
sections.push("");
|
|
8270
|
-
continue;
|
|
8271
|
-
}
|
|
8272
|
-
const end2 = Math.min(content.length, charOffset + charLimit);
|
|
8273
|
-
sections.push(content.slice(charOffset, end2));
|
|
8274
|
-
continue;
|
|
8275
|
-
}
|
|
8276
|
-
const lines = splitLines(content);
|
|
8277
|
-
if (lineOffset >= lines.length) {
|
|
8278
|
-
sections.push("");
|
|
8279
|
-
continue;
|
|
8280
|
-
}
|
|
8281
|
-
const end = Math.min(lines.length, lineOffset + lineLimit);
|
|
8282
|
-
const selected = lines.slice(lineOffset, end);
|
|
8283
|
-
if (includeLineNumbers) {
|
|
8284
|
-
for (let index = 0; index < selected.length; index += 1) {
|
|
8285
|
-
const lineNumber = lineOffset + index + 1;
|
|
8286
|
-
const line = selected[index] ?? "";
|
|
8287
|
-
sections.push(
|
|
8288
|
-
`L${lineNumber}: ${truncateAtCodePointBoundary(line, runtime.maxLineLength)}`
|
|
8289
|
-
);
|
|
8290
|
-
}
|
|
8291
|
-
continue;
|
|
8292
|
-
}
|
|
8293
|
-
sections.push(selected.join("\n"));
|
|
8294
|
-
}
|
|
8295
|
-
return sections.join("\n");
|
|
8296
|
-
}
|
|
8297
8352
|
async function writeFileGemini(input, options) {
|
|
8298
8353
|
const runtime = resolveRuntime(options);
|
|
8299
8354
|
const filePath = resolvePathWithPolicy(input.file_path, runtime.cwd, runtime.allowOutsideCwd);
|
|
@@ -8602,117 +8657,6 @@ function truncateAtCodePointBoundary(value, maxLength) {
|
|
|
8602
8657
|
}
|
|
8603
8658
|
return Array.from(value).slice(0, maxLength).join("");
|
|
8604
8659
|
}
|
|
8605
|
-
function measureIndent(line, tabWidth) {
|
|
8606
|
-
let count = 0;
|
|
8607
|
-
for (const char of line) {
|
|
8608
|
-
if (char === " ") {
|
|
8609
|
-
count += 1;
|
|
8610
|
-
continue;
|
|
8611
|
-
}
|
|
8612
|
-
if (char === " ") {
|
|
8613
|
-
count += tabWidth;
|
|
8614
|
-
continue;
|
|
8615
|
-
}
|
|
8616
|
-
break;
|
|
8617
|
-
}
|
|
8618
|
-
return count;
|
|
8619
|
-
}
|
|
8620
|
-
function computeEffectiveIndents(records) {
|
|
8621
|
-
const effective = [];
|
|
8622
|
-
let previous = 0;
|
|
8623
|
-
for (const record of records) {
|
|
8624
|
-
if (record.raw.trim().length === 0) {
|
|
8625
|
-
effective.push(previous);
|
|
8626
|
-
} else {
|
|
8627
|
-
previous = record.indent;
|
|
8628
|
-
effective.push(previous);
|
|
8629
|
-
}
|
|
8630
|
-
}
|
|
8631
|
-
return effective;
|
|
8632
|
-
}
|
|
8633
|
-
function trimBoundaryBlankLines(records) {
|
|
8634
|
-
while (records.length > 0 && records[0]?.raw.trim().length === 0) {
|
|
8635
|
-
records.shift();
|
|
8636
|
-
}
|
|
8637
|
-
while (records.length > 0 && records[records.length - 1]?.raw.trim().length === 0) {
|
|
8638
|
-
records.pop();
|
|
8639
|
-
}
|
|
8640
|
-
}
|
|
8641
|
-
function isCommentLine(line) {
|
|
8642
|
-
const trimmed = line.trim();
|
|
8643
|
-
return trimmed.startsWith("#") || trimmed.startsWith("//") || trimmed.startsWith("--");
|
|
8644
|
-
}
|
|
8645
|
-
function readWithIndentationMode(params) {
|
|
8646
|
-
const { records, anchorLine, limit, maxLevels, includeSiblings, includeHeader, maxLines } = params;
|
|
8647
|
-
const anchorIndex = anchorLine - 1;
|
|
8648
|
-
const effectiveIndents = computeEffectiveIndents(records);
|
|
8649
|
-
const anchorIndent = effectiveIndents[anchorIndex] ?? 0;
|
|
8650
|
-
const minIndent = maxLevels === 0 ? 0 : Math.max(anchorIndent - maxLevels * DEFAULT_TAB_WIDTH, 0);
|
|
8651
|
-
const guardLimit = maxLines ?? limit;
|
|
8652
|
-
const finalLimit = Math.min(limit, guardLimit, records.length);
|
|
8653
|
-
if (finalLimit <= 1) {
|
|
8654
|
-
return [records[anchorIndex]].filter((entry) => Boolean(entry));
|
|
8655
|
-
}
|
|
8656
|
-
let upper = anchorIndex - 1;
|
|
8657
|
-
let lower = anchorIndex + 1;
|
|
8658
|
-
let upperMinIndentHits = 0;
|
|
8659
|
-
let lowerMinIndentHits = 0;
|
|
8660
|
-
const output = [records[anchorIndex]].filter(
|
|
8661
|
-
(entry) => Boolean(entry)
|
|
8662
|
-
);
|
|
8663
|
-
while (output.length < finalLimit) {
|
|
8664
|
-
let progressed = 0;
|
|
8665
|
-
if (upper >= 0) {
|
|
8666
|
-
const candidate = records[upper];
|
|
8667
|
-
const candidateIndent = effectiveIndents[upper] ?? 0;
|
|
8668
|
-
if (candidate && candidateIndent >= minIndent) {
|
|
8669
|
-
output.unshift(candidate);
|
|
8670
|
-
progressed += 1;
|
|
8671
|
-
upper -= 1;
|
|
8672
|
-
if (candidateIndent === minIndent && !includeSiblings) {
|
|
8673
|
-
const allowHeaderComment = includeHeader && isCommentLine(candidate.raw);
|
|
8674
|
-
const canTakeLine = allowHeaderComment || upperMinIndentHits === 0;
|
|
8675
|
-
if (canTakeLine) {
|
|
8676
|
-
upperMinIndentHits += 1;
|
|
8677
|
-
} else {
|
|
8678
|
-
output.shift();
|
|
8679
|
-
progressed -= 1;
|
|
8680
|
-
upper = -1;
|
|
8681
|
-
}
|
|
8682
|
-
}
|
|
8683
|
-
if (output.length >= finalLimit) {
|
|
8684
|
-
break;
|
|
8685
|
-
}
|
|
8686
|
-
} else {
|
|
8687
|
-
upper = -1;
|
|
8688
|
-
}
|
|
8689
|
-
}
|
|
8690
|
-
if (lower < records.length) {
|
|
8691
|
-
const candidate = records[lower];
|
|
8692
|
-
const candidateIndent = effectiveIndents[lower] ?? 0;
|
|
8693
|
-
if (candidate && candidateIndent >= minIndent) {
|
|
8694
|
-
output.push(candidate);
|
|
8695
|
-
progressed += 1;
|
|
8696
|
-
lower += 1;
|
|
8697
|
-
if (candidateIndent === minIndent && !includeSiblings) {
|
|
8698
|
-
if (lowerMinIndentHits > 0) {
|
|
8699
|
-
output.pop();
|
|
8700
|
-
progressed -= 1;
|
|
8701
|
-
lower = records.length;
|
|
8702
|
-
}
|
|
8703
|
-
lowerMinIndentHits += 1;
|
|
8704
|
-
}
|
|
8705
|
-
} else {
|
|
8706
|
-
lower = records.length;
|
|
8707
|
-
}
|
|
8708
|
-
}
|
|
8709
|
-
if (progressed === 0) {
|
|
8710
|
-
break;
|
|
8711
|
-
}
|
|
8712
|
-
}
|
|
8713
|
-
trimBoundaryBlankLines(output);
|
|
8714
|
-
return output;
|
|
8715
|
-
}
|
|
8716
8660
|
async function collectDirectoryEntries(filesystem, rootPath, depth, maxLineLength) {
|
|
8717
8661
|
const queue = [
|
|
8718
8662
|
{ path: rootPath, relativePrefix: "", remainingDepth: depth }
|
|
@@ -10030,10 +9974,10 @@ export {
|
|
|
10030
9974
|
createListDirectoryTool,
|
|
10031
9975
|
createModelAgnosticFilesystemToolSet,
|
|
10032
9976
|
createNodeAgentFilesystem,
|
|
10033
|
-
createReadFilesTool,
|
|
10034
9977
|
createReplaceTool,
|
|
10035
9978
|
createRgSearchTool,
|
|
10036
9979
|
createToolLoopSteeringChannel,
|
|
9980
|
+
createViewImageTool,
|
|
10037
9981
|
createWriteFileTool,
|
|
10038
9982
|
customTool,
|
|
10039
9983
|
encodeChatGptAuthJson,
|