@code-yeongyu/senpi 2026.9.23-3 → 2026.9.23-4
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/CHANGELOG.md +21 -0
- package/dist/bundle/chunks/{app-server-command-U5Y46LHO.js → app-server-command-QRBQLEXY.js} +1 -1
- package/dist/bundle/chunks/{chunk-UCTYTLP3.js → chunk-3RN6BFG2.js} +2 -2
- package/dist/bundle/chunks/{chunk-XTXBPXZZ.js → chunk-EN6KDFY2.js} +1 -1
- package/dist/bundle/chunks/{chunk-2NFHX2FJ.js → chunk-J3QXPP4T.js} +1 -1
- package/dist/bundle/chunks/chunk-KBG7BJIL.js +8 -0
- package/dist/bundle/chunks/{chunk-TH4PERSI.js → chunk-N46LNXHU.js} +35 -53
- package/dist/bundle/chunks/{chunk-67Z5WNA4.js → chunk-PSMTQDII.js} +1 -1
- package/dist/bundle/chunks/{chunk-Y4AJLTFT.js → chunk-WUYBEF7C.js} +1 -1
- package/dist/bundle/chunks/{chunk-IDSOMHWS.js → chunk-WXIRFRXY.js} +1 -1
- package/dist/bundle/chunks/{chunk-R6F525XB.js → chunk-XDSQYM4F.js} +1 -1
- package/dist/bundle/chunks/{chunk-TUVSARCZ.js → chunk-ZEFQYQOU.js} +1 -1
- package/dist/bundle/chunks/{cli-main-65WMMIRT.js → cli-main-ROBDBYAB.js} +1 -1
- package/dist/bundle/chunks/cursor-agent.js +1 -1
- package/dist/bundle/chunks/{help-fast-path-VXAZDQ3Z.js → help-fast-path-QXVCHTP3.js} +1 -1
- package/dist/bundle/chunks/{host-command-5PEFD4N6.js → host-command-3PUZYQOK.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-BXW5C4JT.js → host-lifecycle-OHPSU5VU.js} +1 -1
- package/dist/bundle/chunks/{interactive-host-runtime-DUNYT24Q.js → interactive-host-runtime-57LEAJPU.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-SCG5PQZ6.js → interactive-mode-SLPAGRHH.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-QC6BZZNH.js → multi-session-host-3PACMEHC.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-23GULCVL.js → package-manager-cli-6UIUSRQO.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-B6RSUQKL.js → pi-messages-CAS467IY.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-ZIYWOB2N.js → rotation-stream-CZT4TRPD.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-ZQ4E6FFA.js → rpc-mode-47EVLL6X.js} +1 -1
- package/dist/bundle/chunks/{session-picker-CO2ZK3EC.js → session-picker-ZIBANFBQ.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +40 -58
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js +43 -26
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js.map +1 -1
- package/dist/core/extensions/builtin/nested-agents-md/index.js +1 -1
- package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -1
- package/dist/core/extensions/builtin/rule-activation/types.d.ts +2 -0
- package/dist/core/extensions/builtin/rule-activation/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rule-activation/types.js +7 -1
- package/dist/core/extensions/builtin/rule-activation/types.js.map +1 -1
- package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/index.js +2 -1
- package/dist/core/extensions/builtin/rules/index.js.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts +3 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +9 -3
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +87 -14
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +12 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +9 -6
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep/format.d.ts +3 -2
- package/dist/core/tools/grep/format.d.ts.map +1 -1
- package/dist/core/tools/grep/format.js +5 -3
- package/dist/core/tools/grep/format.js.map +1 -1
- package/dist/core/tools/grep/index.js +2 -2
- package/dist/core/tools/grep/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -3
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/model-only-text.d.ts +4 -0
- package/dist/core/tools/model-only-text.d.ts.map +1 -0
- package/dist/core/tools/model-only-text.js +12 -0
- package/dist/core/tools/model-only-text.js.map +1 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +15 -5
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +2 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +1 -25
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/grep.d.ts.map +1 -1
- package/dist/core/tools/renderers/grep.js +0 -25
- package/dist/core/tools/renderers/grep.js.map +1 -1
- package/dist/core/tools/renderers/read.d.ts +8 -0
- package/dist/core/tools/renderers/read.d.ts.map +1 -1
- package/dist/core/tools/renderers/read.js +2 -14
- package/dist/core/tools/renderers/read.js.map +1 -1
- package/dist/modes/interactive/components/exploration-call.d.ts +4 -1
- package/dist/modes/interactive/components/exploration-call.d.ts.map +1 -1
- package/dist/modes/interactive/components/exploration-call.js +17 -2
- package/dist/modes/interactive/components/exploration-call.js.map +1 -1
- package/dist/modes/interactive/components/exploration-group.d.ts +3 -1
- package/dist/modes/interactive/components/exploration-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/exploration-group.js +7 -1
- package/dist/modes/interactive/components/exploration-group.js.map +1 -1
- package/dist/modes/interactive/components/exploration-rules.d.ts +5 -0
- package/dist/modes/interactive/components/exploration-rules.d.ts.map +1 -0
- package/dist/modes/interactive/components/exploration-rules.js +15 -0
- package/dist/modes/interactive/components/exploration-rules.js.map +1 -0
- package/dist/modes/interactive/components/exploration-transcript-container.d.ts.map +1 -1
- package/dist/modes/interactive/components/exploration-transcript-container.js +10 -1
- package/dist/modes/interactive/components/exploration-transcript-container.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +4 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +4 -19
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +17 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.d.ts +18 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.js +103 -3
- package/node_modules/@earendil-works/pi-ai/dist/cursor/catalog-grouping.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts +3 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js +15 -3
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts +7 -2
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js +92 -20
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts +9 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-XPDV6SIX.js +0 -8
package/dist/core/tools/find.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from "path";
|
|
|
4
4
|
import { Type } from "typebox";
|
|
5
5
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
6
6
|
import { canonicalizeFilesystemPath } from "./filesystem-policy.js";
|
|
7
|
+
import { modelOnlyText } from "./model-only-text.js";
|
|
7
8
|
import { pathExists, resolveToCwd } from "./path-utils.js";
|
|
8
9
|
import { findRenderers } from "./renderers/find.js";
|
|
9
10
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
@@ -110,7 +111,6 @@ export function createFindToolDefinition(cwd, options) {
|
|
|
110
111
|
const resultLimitReached = relativized.length >= effectiveLimit;
|
|
111
112
|
const rawOutput = relativized.join("\n");
|
|
112
113
|
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
113
|
-
let resultOutput = truncation.content;
|
|
114
114
|
const details = {};
|
|
115
115
|
const notices = [];
|
|
116
116
|
if (resultLimitReached) {
|
|
@@ -121,11 +121,13 @@ export function createFindToolDefinition(cwd, options) {
|
|
|
121
121
|
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
122
122
|
details.truncation = truncation;
|
|
123
123
|
}
|
|
124
|
+
const content = [{ type: "text", text: truncation.content }];
|
|
124
125
|
if (notices.length > 0) {
|
|
125
|
-
|
|
126
|
+
content[0].text += "\n";
|
|
127
|
+
content.push(modelOnlyText(`[${notices.join(". ")}]`));
|
|
126
128
|
}
|
|
127
129
|
settle(() => resolve({
|
|
128
|
-
content
|
|
130
|
+
content,
|
|
129
131
|
details: Object.keys(details).length > 0 ? details : undefined,
|
|
130
132
|
}));
|
|
131
133
|
return;
|
|
@@ -226,7 +228,6 @@ export function createFindToolDefinition(cwd, options) {
|
|
|
226
228
|
const resultLimitReached = relativized.length >= effectiveLimit;
|
|
227
229
|
const rawOutput = relativized.join("\n");
|
|
228
230
|
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
229
|
-
let resultOutput = truncation.content;
|
|
230
231
|
const details = {};
|
|
231
232
|
const notices = [];
|
|
232
233
|
if (resultLimitReached) {
|
|
@@ -237,11 +238,13 @@ export function createFindToolDefinition(cwd, options) {
|
|
|
237
238
|
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
238
239
|
details.truncation = truncation;
|
|
239
240
|
}
|
|
241
|
+
const content = [{ type: "text", text: truncation.content }];
|
|
240
242
|
if (notices.length > 0) {
|
|
241
|
-
|
|
243
|
+
content[0].text += "\n";
|
|
244
|
+
content.push(modelOnlyText(`[${notices.join(". ")}]`));
|
|
242
245
|
}
|
|
243
246
|
settle(() => resolve({
|
|
244
|
-
content
|
|
247
|
+
content,
|
|
245
248
|
details: Object.keys(details).length > 0 ? details : undefined,
|
|
246
249
|
}));
|
|
247
250
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { spawn } from \"child_process\";\nimport path from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { ensureTool } from \"../../utils/tools-manager.ts\";\nimport type { ExtensionContext, FilesystemPolicyChecker, ToolDefinition } from \"../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"./filesystem-policy.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { findRenderers } from \"./renderers/find.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\n\n/** Relativize a find result against the search root and normalize it to posix separators. */\nexport function relativizeFindResultPath(\n\tresultPath: string,\n\tsearchPath: string,\n\tpathModule: typeof path.posix = path,\n): string {\n\tconst hadTrailingSeparator =\n\t\tresultPath.endsWith(pathModule.sep) || (pathModule.sep === \"\\\\\" && resultPath.endsWith(\"/\"));\n\tconst relativePath = pathModule.isAbsolute(resultPath) ? pathModule.relative(searchPath, resultPath) : resultPath;\n\tconst posixPath = relativePath.split(pathModule.sep).join(\"/\");\n\treturn hadTrailingSeparator && !posixPath.endsWith(\"/\") ? `${posixPath}/` : posixPath;\n}\n\nconst findSchema = Type.Object({\n\tpattern: Type.String({\n\t\tdescription: \"Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'\",\n\t}),\n\tpath: Type.Optional(Type.String({ description: \"Directory to search in (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of results (default: 1000)\" })),\n});\n\nexport const findToolSystemPromptContribution = {\n\tsnippet: \"Find files by glob pattern (respects .gitignore)\",\n\tguidelines: [],\n} as const;\n\nexport type FindToolInput = Static<typeof findSchema>;\n\nconst DEFAULT_LIMIT = 1000;\n\nexport interface FindToolDetails {\n\ttruncation?: TruncationResult;\n\tresultLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the find tool.\n * Override these to delegate file search to remote systems (for example SSH).\n */\nexport interface FindOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Find files matching glob pattern. Returns relative or absolute paths. */\n\tglob: (pattern: string, cwd: string, options: { ignore: string[]; limit: number }) => Promise<string[]> | string[];\n}\n\nconst defaultFindOperations: FindOperations = {\n\texists: pathExists,\n\t// This is a placeholder. Actual fd execution happens in execute() when no custom glob is provided.\n\tglob: () => [],\n};\n\nexport interface FindToolOptions {\n\t/** Custom operations for find. Default: local filesystem plus fd */\n\toperations?: FindOperations;\n\t/** Extension-registered filesystem policy checker. */\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nexport function createFindToolDefinition(\n\tcwd: string,\n\toptions?: FindToolOptions,\n): ToolDefinition<typeof findSchema, FindToolDetails | undefined> {\n\tconst customOps = options?.operations;\n\tconst filesystemPolicy = options?.filesystemPolicy;\n\treturn {\n\t\tname: \"find\",\n\t\tlabel: \"find\",\n\t\tdescription: `Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tpromptSnippet: findToolSystemPromptContribution.snippet,\n\t\tparameters: findSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ pattern, path: searchDir, limit }: { pattern: string; path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet settled = false;\n\t\t\t\tlet stopChild: (() => void) | undefined;\n\t\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tstopChild = undefined;\n\t\t\t\t\tfn();\n\t\t\t\t};\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tstopChild?.();\n\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t};\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst searchPath = resolveToCwd(searchDir || \".\", ctx?.cwd || cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\t\t\t\t\t\tconst ops = customOps ?? defaultFindOperations;\n\t\t\t\t\t\tif (filesystemPolicy) {\n\t\t\t\t\t\t\tconst decision = await filesystemPolicy({\n\t\t\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\t\t\tcanonicalPath: await canonicalizeFilesystemPath(searchPath),\n\t\t\t\t\t\t\t\ttoolName: \"find\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If custom operations provide glob(), use that instead of fd.\n\t\t\t\t\t\tif (customOps?.glob) {\n\t\t\t\t\t\t\tif (!(await ops.exists(searchPath))) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst results = await ops.glob(pattern, searchPath, {\n\t\t\t\t\t\t\t\tignore: [\"**/node_modules/**\", \"**/.git/**\"],\n\t\t\t\t\t\t\t\tlimit: effectiveLimit,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Relativize paths against the search root for stable output.\n\t\t\t\t\t\t\tconst relativized = results.map((p) => relativizeFindResultPath(p, searchPath));\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tlet resultOutput = truncation.content;\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} results limit reached`);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tresultOutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: resultOutput }],\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Default implementation uses fd.\n\t\t\t\t\t\tconst fdPath = await ensureTool(\"fd\");\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!fdPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"fd is not available and could not be downloaded\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst args: string[] = [\"--glob\", \"--color=never\", \"--hidden\"];\n\n\t\t\t\t\t\t// fd normally ignores .gitignore outside git repos, so keep --no-require-git\n\t\t\t\t\t\t// there. Inside repos, use fd's default git-aware behavior so parent\n\t\t\t\t\t\t// .gitignore rules stop at nested repo boundaries:\n\t\t\t\t\t\t// https://github.com/earendil-works/pi/issues/5960\n\t\t\t\t\t\tlet insideGitRepo = false;\n\t\t\t\t\t\tfor (let current = searchPath; ; ) {\n\t\t\t\t\t\t\tif (await pathExists(path.join(current, \".git\"))) {\n\t\t\t\t\t\t\t\tinsideGitRepo = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst parent = path.dirname(current);\n\t\t\t\t\t\t\tif (parent === current) break;\n\t\t\t\t\t\t\tcurrent = parent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!insideGitRepo) args.push(\"--no-require-git\");\n\t\t\t\t\t\targs.push(\"--max-results\", String(effectiveLimit));\n\n\t\t\t\t\t\t// fd --glob matches against the basename unless --full-path is set; in --full-path\n\t\t\t\t\t\t// mode it matches against the absolute candidate path, so a path-containing\n\t\t\t\t\t\t// pattern like 'src/**/*.spec.ts' needs a leading '**/' to match anything.\n\t\t\t\t\t\tlet effectivePattern = pattern;\n\t\t\t\t\t\tif (pattern.includes(\"/\")) {\n\t\t\t\t\t\t\targs.push(\"--full-path\");\n\t\t\t\t\t\t\tif (!pattern.startsWith(\"/\") && !pattern.startsWith(\"**/\") && pattern !== \"**\") {\n\t\t\t\t\t\t\t\teffectivePattern = `**/${pattern}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// fd matches full paths using native separators on Windows.\n\t\t\t\t\t\t\tif (process.platform === \"win32\")\n\t\t\t\t\t\t\t\teffectivePattern = effectivePattern.replaceAll(\"/\", String.raw`[/\\\\]`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\targs.push(\"--\", effectivePattern, searchPath);\n\n\t\t\t\t\t\tconst child = spawn(fdPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\t\tconst lines: string[] = [];\n\n\t\t\t\t\t\tstopChild = () => {\n\t\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\t\tchild.kill();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\t\trl.close();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Failed to run fd: ${error.message}`)));\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst output = lines.join(\"\\n\");\n\t\t\t\t\t\t\tif (code !== 0) {\n\t\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `fd exited with code ${code}`;\n\t\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst relativized: string[] = [];\n\t\t\t\t\t\t\tfor (const rawLine of lines) {\n\t\t\t\t\t\t\t\tconst line = rawLine.replace(/\\r$/, \"\").trim();\n\t\t\t\t\t\t\t\tif (!line) continue;\n\t\t\t\t\t\t\t\trelativized.push(relativizeFindResultPath(line, searchPath));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tlet resultOutput = truncation.content;\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`${effectiveLimit} results limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tresultOutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: resultOutput }],\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst error = e instanceof Error ? e : new Error(String(e));\n\t\t\t\t\t\tsettle(() => reject(error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\t...findRenderers,\n\t};\n}\n\nexport function createFindTool(cwd: string, options?: FindToolOptions): AgentTool<typeof findSchema> {\n\treturn wrapToolDefinition(createFindToolDefinition(cwd, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"find.js","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { TextContent } from \"@earendil-works/pi-ai\";\nimport { spawn } from \"child_process\";\nimport path from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { ensureTool } from \"../../utils/tools-manager.ts\";\nimport type { ExtensionContext, FilesystemPolicyChecker, ToolDefinition } from \"../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"./filesystem-policy.ts\";\nimport { modelOnlyText } from \"./model-only-text.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { findRenderers } from \"./renderers/find.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\n\n/** Relativize a find result against the search root and normalize it to posix separators. */\nexport function relativizeFindResultPath(\n\tresultPath: string,\n\tsearchPath: string,\n\tpathModule: typeof path.posix = path,\n): string {\n\tconst hadTrailingSeparator =\n\t\tresultPath.endsWith(pathModule.sep) || (pathModule.sep === \"\\\\\" && resultPath.endsWith(\"/\"));\n\tconst relativePath = pathModule.isAbsolute(resultPath) ? pathModule.relative(searchPath, resultPath) : resultPath;\n\tconst posixPath = relativePath.split(pathModule.sep).join(\"/\");\n\treturn hadTrailingSeparator && !posixPath.endsWith(\"/\") ? `${posixPath}/` : posixPath;\n}\n\nconst findSchema = Type.Object({\n\tpattern: Type.String({\n\t\tdescription: \"Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'\",\n\t}),\n\tpath: Type.Optional(Type.String({ description: \"Directory to search in (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of results (default: 1000)\" })),\n});\n\nexport const findToolSystemPromptContribution = {\n\tsnippet: \"Find files by glob pattern (respects .gitignore)\",\n\tguidelines: [],\n} as const;\n\nexport type FindToolInput = Static<typeof findSchema>;\n\nconst DEFAULT_LIMIT = 1000;\n\nexport interface FindToolDetails {\n\ttruncation?: TruncationResult;\n\tresultLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the find tool.\n * Override these to delegate file search to remote systems (for example SSH).\n */\nexport interface FindOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Find files matching glob pattern. Returns relative or absolute paths. */\n\tglob: (pattern: string, cwd: string, options: { ignore: string[]; limit: number }) => Promise<string[]> | string[];\n}\n\nconst defaultFindOperations: FindOperations = {\n\texists: pathExists,\n\t// This is a placeholder. Actual fd execution happens in execute() when no custom glob is provided.\n\tglob: () => [],\n};\n\nexport interface FindToolOptions {\n\t/** Custom operations for find. Default: local filesystem plus fd */\n\toperations?: FindOperations;\n\t/** Extension-registered filesystem policy checker. */\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nexport function createFindToolDefinition(\n\tcwd: string,\n\toptions?: FindToolOptions,\n): ToolDefinition<typeof findSchema, FindToolDetails | undefined> {\n\tconst customOps = options?.operations;\n\tconst filesystemPolicy = options?.filesystemPolicy;\n\treturn {\n\t\tname: \"find\",\n\t\tlabel: \"find\",\n\t\tdescription: `Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tpromptSnippet: findToolSystemPromptContribution.snippet,\n\t\tparameters: findSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ pattern, path: searchDir, limit }: { pattern: string; path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet settled = false;\n\t\t\t\tlet stopChild: (() => void) | undefined;\n\t\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tstopChild = undefined;\n\t\t\t\t\tfn();\n\t\t\t\t};\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tstopChild?.();\n\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t};\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst searchPath = resolveToCwd(searchDir || \".\", ctx?.cwd || cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\t\t\t\t\t\tconst ops = customOps ?? defaultFindOperations;\n\t\t\t\t\t\tif (filesystemPolicy) {\n\t\t\t\t\t\t\tconst decision = await filesystemPolicy({\n\t\t\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\t\t\tcanonicalPath: await canonicalizeFilesystemPath(searchPath),\n\t\t\t\t\t\t\t\ttoolName: \"find\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If custom operations provide glob(), use that instead of fd.\n\t\t\t\t\t\tif (customOps?.glob) {\n\t\t\t\t\t\t\tif (!(await ops.exists(searchPath))) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst results = await ops.glob(pattern, searchPath, {\n\t\t\t\t\t\t\t\tignore: [\"**/node_modules/**\", \"**/.git/**\"],\n\t\t\t\t\t\t\t\tlimit: effectiveLimit,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Relativize paths against the search root for stable output.\n\t\t\t\t\t\t\tconst relativized = results.map((p) => relativizeFindResultPath(p, searchPath));\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} results limit reached`);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst content: TextContent[] = [{ type: \"text\", text: truncation.content }];\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tcontent[0].text += \"\\n\";\n\t\t\t\t\t\t\t\tcontent.push(modelOnlyText(`[${notices.join(\". \")}]`));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Default implementation uses fd.\n\t\t\t\t\t\tconst fdPath = await ensureTool(\"fd\");\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!fdPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"fd is not available and could not be downloaded\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst args: string[] = [\"--glob\", \"--color=never\", \"--hidden\"];\n\n\t\t\t\t\t\t// fd normally ignores .gitignore outside git repos, so keep --no-require-git\n\t\t\t\t\t\t// there. Inside repos, use fd's default git-aware behavior so parent\n\t\t\t\t\t\t// .gitignore rules stop at nested repo boundaries:\n\t\t\t\t\t\t// https://github.com/earendil-works/pi/issues/5960\n\t\t\t\t\t\tlet insideGitRepo = false;\n\t\t\t\t\t\tfor (let current = searchPath; ; ) {\n\t\t\t\t\t\t\tif (await pathExists(path.join(current, \".git\"))) {\n\t\t\t\t\t\t\t\tinsideGitRepo = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst parent = path.dirname(current);\n\t\t\t\t\t\t\tif (parent === current) break;\n\t\t\t\t\t\t\tcurrent = parent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!insideGitRepo) args.push(\"--no-require-git\");\n\t\t\t\t\t\targs.push(\"--max-results\", String(effectiveLimit));\n\n\t\t\t\t\t\t// fd --glob matches against the basename unless --full-path is set; in --full-path\n\t\t\t\t\t\t// mode it matches against the absolute candidate path, so a path-containing\n\t\t\t\t\t\t// pattern like 'src/**/*.spec.ts' needs a leading '**/' to match anything.\n\t\t\t\t\t\tlet effectivePattern = pattern;\n\t\t\t\t\t\tif (pattern.includes(\"/\")) {\n\t\t\t\t\t\t\targs.push(\"--full-path\");\n\t\t\t\t\t\t\tif (!pattern.startsWith(\"/\") && !pattern.startsWith(\"**/\") && pattern !== \"**\") {\n\t\t\t\t\t\t\t\teffectivePattern = `**/${pattern}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// fd matches full paths using native separators on Windows.\n\t\t\t\t\t\t\tif (process.platform === \"win32\")\n\t\t\t\t\t\t\t\teffectivePattern = effectivePattern.replaceAll(\"/\", String.raw`[/\\\\]`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\targs.push(\"--\", effectivePattern, searchPath);\n\n\t\t\t\t\t\tconst child = spawn(fdPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\t\tconst lines: string[] = [];\n\n\t\t\t\t\t\tstopChild = () => {\n\t\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\t\tchild.kill();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\t\trl.close();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Failed to run fd: ${error.message}`)));\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst output = lines.join(\"\\n\");\n\t\t\t\t\t\t\tif (code !== 0) {\n\t\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `fd exited with code ${code}`;\n\t\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst relativized: string[] = [];\n\t\t\t\t\t\t\tfor (const rawLine of lines) {\n\t\t\t\t\t\t\t\tconst line = rawLine.replace(/\\r$/, \"\").trim();\n\t\t\t\t\t\t\t\tif (!line) continue;\n\t\t\t\t\t\t\t\trelativized.push(relativizeFindResultPath(line, searchPath));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`${effectiveLimit} results limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst content: TextContent[] = [{ type: \"text\", text: truncation.content }];\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tcontent[0].text += \"\\n\";\n\t\t\t\t\t\t\t\tcontent.push(modelOnlyText(`[${notices.join(\". \")}]`));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst error = e instanceof Error ? e : new Error(String(e));\n\t\t\t\t\t\tsettle(() => reject(error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\t...findRenderers,\n\t};\n}\n\nexport function createFindTool(cwd: string, options?: FindToolOptions): AgentTool<typeof findSchema> {\n\treturn wrapToolDefinition(createFindToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { TextContent } from "@earendil-works/pi-ai";
|
|
1
2
|
import type { GrepToolDetails } from "./index.ts";
|
|
2
3
|
export declare function displayPath(path: string): string;
|
|
3
4
|
/** now supplies the elapsed duration, allowing deterministic text in renderer tests. */
|
|
4
|
-
export declare function
|
|
5
|
+
export declare function formatGrepContent(result: GrepToolDetails, { now }?: {
|
|
5
6
|
now?: () => number;
|
|
6
|
-
}):
|
|
7
|
+
}): TextContent[];
|
|
7
8
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/grep/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wFAAwF;AACxF,wBAAgB,
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../src/core/tools/grep/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAiC,EAAE,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GAChE,WAAW,EAAE,CAgDf"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { modelOnlyText } from "../model-only-text.js";
|
|
1
2
|
export function displayPath(path) {
|
|
2
3
|
return /[\x00-\x1f\x7f]/.test(path) ? JSON.stringify(path) : path;
|
|
3
4
|
}
|
|
4
5
|
/** now supplies the elapsed duration, allowing deterministic text in renderer tests. */
|
|
5
|
-
export function
|
|
6
|
+
export function formatGrepContent(result, { now = () => result.scan.elapsedMs } = {}) {
|
|
6
7
|
const blocks = [];
|
|
7
8
|
if (result.matches.length) {
|
|
8
9
|
for (const file of result.fileMatches) {
|
|
@@ -41,7 +42,8 @@ export function formatGrepText(result, { now = () => result.scan.elapsedMs } = {
|
|
|
41
42
|
notes.push(`Pattern searched literally: ${scan.effectivePattern}`);
|
|
42
43
|
if (scan.patternKind === "sanitized")
|
|
43
44
|
notes.push(`Pattern sanitized: ${scan.effectivePattern}`);
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const footer = `[grep: matches=${result.matchCount ?? "n/a"} files=${result.fileCount} searched=${scan.filesSearched} elapsedMs=${Math.max(0, Math.round(now()))} engine=${result.engine} nextSkip=${result.nextSkip ?? "none"}]`;
|
|
46
|
+
const body = `${blocks.join("\n\n")}\n${notes.length ? `\n${notes.join("\n")}` : ""}`;
|
|
47
|
+
return [{ type: "text", text: body }, modelOnlyText(footer)];
|
|
46
48
|
}
|
|
47
49
|
//# sourceMappingURL=format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../src/core/tools/grep/format.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../src/core/tools/grep/format.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TextContent } from \"@earendil-works/pi-ai\";\nimport { modelOnlyText } from \"../model-only-text.ts\";\nimport type { GrepToolDetails } from \"./index.ts\";\n\nexport function displayPath(path: string): string {\n\treturn /[\\x00-\\x1f\\x7f]/.test(path) ? JSON.stringify(path) : path;\n}\n\n/** now supplies the elapsed duration, allowing deterministic text in renderer tests. */\nexport function formatGrepContent(\n\tresult: GrepToolDetails,\n\t{ now = () => result.scan.elapsedMs }: { now?: () => number } = {},\n): TextContent[] {\n\tconst blocks: string[] = [];\n\tif (result.matches.length) {\n\t\tfor (const file of result.fileMatches) {\n\t\t\tconst rows = result.matches.filter((match) => match.path === file.path);\n\t\t\tblocks.push(\n\t\t\t\t[displayPath(file.path), ...rows.map((row) => `${row.line}${row.isContext ? \"-\" : \":\"} ${row.text}`)].join(\n\t\t\t\t\t\"\\n\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} else if (result.fileCount) {\n\t\tblocks.push(\n\t\t\tresult.fileMatches\n\t\t\t\t.map((file) => (file.count === null ? displayPath(file.path) : `${displayPath(file.path)}: ${file.count}`))\n\t\t\t\t.join(\"\\n\"),\n\t\t);\n\t} else {\n\t\tblocks.push(\n\t\t\tresult.status === \"pageEnd\"\n\t\t\t\t? `No more results (skip=${result.skip})`\n\t\t\t\t: result.status === \"partial\"\n\t\t\t\t\t? \"No matches found in searched portion\"\n\t\t\t\t\t: \"No matches found\",\n\t\t);\n\t}\n\tconst notes: string[] = [];\n\tconst scan = result.scan;\n\tif (scan.prefixSearched)\n\t\tnotes.push(\n\t\t\t`Partial coverage: searched only the first 4 MiB of ${scan.prefixSearched} large file(s); later matches are omitted.`,\n\t\t);\n\tif (scan.skippedOversized) notes.push(`Skipped ${scan.skippedOversized} unreadable/unsearchable large file(s).`);\n\tif (scan.skippedBinary) notes.push(`Skipped ${scan.skippedBinary} binary file(s).`);\n\tif (scan.missingPaths.length)\n\t\tnotes.push(`Skipped missing path(s): ${scan.missingPaths.map(displayPath).join(\", \")}`);\n\tif (scan.timedOut)\n\t\tnotes.push(\n\t\t\tscan.warnings.find((w) => w.code === \"TIMED_OUT\")?.message ??\n\t\t\t\t\"Timed out after 30000 ms; showing the completed ordered prefix.\",\n\t\t);\n\tif (scan.regexEngine === \"pcre2\")\n\t\tnotes.push(\"Regex unsupported by the native engine; matched with ripgrep --pcre2.\");\n\tif (scan.patternKind === \"literal\") notes.push(`Pattern searched literally: ${scan.effectivePattern}`);\n\tif (scan.patternKind === \"sanitized\") notes.push(`Pattern sanitized: ${scan.effectivePattern}`);\n\tconst footer = `[grep: matches=${result.matchCount ?? \"n/a\"} files=${result.fileCount} searched=${scan.filesSearched} elapsedMs=${Math.max(0, Math.round(now()))} engine=${result.engine} nextSkip=${result.nextSkip ?? \"none\"}]`;\n\tconst body = `${blocks.join(\"\\n\\n\")}\\n${notes.length ? `\\n${notes.join(\"\\n\")}` : \"\"}`;\n\treturn [{ type: \"text\", text: body }, modelOnlyText(footer)];\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import { resolveToCwd } from "../path-utils.js";
|
|
|
6
6
|
import { grepRenderers } from "../renderers/grep.js";
|
|
7
7
|
import { wrapToolDefinition } from "../tool-definition-wrapper.js";
|
|
8
8
|
import { DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH } from "../truncate.js";
|
|
9
|
-
import {
|
|
9
|
+
import { formatGrepContent } from "./format.js";
|
|
10
10
|
import { searchPattern } from "./pattern.js";
|
|
11
11
|
import { resolveGrepEngine } from "./select-engine.js";
|
|
12
12
|
const strings = () => Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())]));
|
|
@@ -233,7 +233,7 @@ export function createGrepToolDefinition(cwd, options) {
|
|
|
233
233
|
scan,
|
|
234
234
|
linesTruncated: matches.some((row) => row.truncated),
|
|
235
235
|
};
|
|
236
|
-
return { content:
|
|
236
|
+
return { content: formatGrepContent(details), details };
|
|
237
237
|
},
|
|
238
238
|
...grepRenderers,
|
|
239
239
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/tools/grep/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { FilesystemPolicyChecker, ToolDefinition } from \"../../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"../filesystem-policy.ts\";\nimport { resolveToCwd } from \"../path-utils.ts\";\nimport { grepRenderers } from \"../renderers/grep.ts\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH, type TruncationResult } from \"../truncate.ts\";\nimport type { GrepEngineMatch, GrepEngineRequest, GrepEngineResult } from \"./engine.ts\";\nimport { formatGrepText } from \"./format.ts\";\nimport { searchPattern } from \"./pattern.ts\";\nimport { resolveGrepEngine } from \"./select-engine.ts\";\n\nconst strings = () => Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())]));\nconst grepSchema = Type.Object({\n\tpattern: Type.String(),\n\tpath: strings(),\n\tglob: strings(),\n\ttype: Type.Optional(Type.String()),\n\tignoreCase: Type.Optional(Type.Boolean()),\n\tliteral: Type.Optional(Type.Boolean()),\n\tmultiline: Type.Optional(Type.Boolean()),\n\tcontext: Type.Optional(Type.Number()),\n\tbefore: Type.Optional(Type.Number()),\n\tafter: Type.Optional(Type.Number()),\n\tmode: Type.Optional(Type.Union([Type.Literal(\"content\"), Type.Literal(\"count\"), Type.Literal(\"files\")])),\n\tlimit: Type.Optional(Type.Number()),\n\tskip: Type.Optional(Type.Number()),\n\ttimeoutMs: Type.Optional(Type.Number()),\n\thidden: Type.Optional(Type.Boolean()),\n\tgitignore: Type.Optional(Type.Boolean()),\n});\nexport type GrepToolInput = Static<typeof grepSchema>;\nexport const grepToolSystemPromptContribution = {\n\tsnippet: \"Search file contents (regex/literal) across paths with structured results; respects .gitignore\",\n\tguidelines: [\n\t\t\"Use tool.grep for content search instead of rg/grep in a shell; paginate with skip and narrow with glob/path when a page is full\",\n\t],\n};\nexport interface GrepToolDetails {\n\tversion: 1;\n\tengine: \"native\" | \"rg\";\n\tstatus: \"ok\" | \"noMatch\" | \"pageEnd\" | \"partial\";\n\tcwd: string;\n\tpaths: string[];\n\tmatches: GrepEngineMatch[];\n\tfileMatches: Array<{ path: string; count: number | null }>;\n\tmatchCount: number | null;\n\tfileCount: number;\n\tskip: number;\n\tnextSkip: number | null;\n\tfileLimitReached: boolean;\n\tperFileLimitReached: boolean;\n\ttotalLimitReached: boolean;\n\tscan: Omit<GrepEngineResult, \"matches\" | \"fileCounts\">;\n\ttruncation?: TruncationResult;\n\tlinesTruncated?: boolean;\n}\n/** @deprecated No longer honored; removed next release. Use the engine-backed local tool. */\nexport interface GrepOperations {\n\tisDirectory: (absolutePath: string) => Promise<boolean> | boolean;\n\treadFile: (absolutePath: string) => Promise<string> | string;\n}\nexport interface GrepToolOptions {\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nasync function pathStat(path: string) {\n\ttry {\n\t\treturn await stat(path);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n}\n\nexport function createGrepToolDefinition(\n\tcwd: string,\n\toptions?: GrepToolOptions,\n): ToolDefinition<typeof grepSchema, GrepToolDetails> {\n\tif (options && \"operations\" in options)\n\t\tthrow new TypeError(\"GrepToolOptions.operations is deprecated and no longer supported; removed next release\");\n\treturn {\n\t\tname: \"grep\",\n\t\tlabel: \"grep\",\n\t\texposure: \"eval\",\n\t\tdescription:\n\t\t\t\"Search file contents with tool.grep({ pattern, path }) inside eval. Supports regex/literal patterns, file pages with skip, context, count/files modes, and structured results. Respects .gitignore.\",\n\t\tpromptSnippet: grepToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: grepToolSystemPromptContribution.guidelines,\n\t\tparameters: grepSchema,\n\t\tasync execute(_id, input, signal, _update, ctx) {\n\t\t\tconst started = Date.now();\n\t\t\tif (!input.pattern) throw new Error(\"Pattern must not be empty\");\n\t\t\tconst requested = input.path === undefined ? [\".\"] : Array.isArray(input.path) ? input.path : [input.path];\n\t\t\tif (!requested.length || requested.some((p) => typeof p !== \"string\" || !p.length))\n\t\t\t\tthrow new Error(\"path must be a non-empty string or array of non-empty strings\");\n\t\t\tconst limit = input.limit ?? 100;\n\t\t\tif (!Number.isInteger(input.skip ?? 0) || (input.skip ?? 0) < 0)\n\t\t\t\tthrow new Error(\"skip must be a non-negative integer\");\n\t\t\tif (!Number.isInteger(limit) || limit <= 0) throw new Error(\"limit must be a positive integer\");\n\t\t\tconst workingCwd = ctx?.cwd || cwd;\n\t\t\tconst paths: string[] = [];\n\t\t\tconst missingPaths: string[] = [];\n\t\t\tlet lineStart: number | undefined;\n\t\t\tlet lineEnd: number | undefined;\n\t\t\tlet singleFile = false;\n\t\t\tfor (const raw of requested) {\n\t\t\t\tlet path = resolveToCwd(raw, workingCwd);\n\t\t\t\tlet info = await pathStat(path);\n\t\t\t\tif (!info) {\n\t\t\t\t\tconst selector = /^(.*):L(\\d+)-L?(\\d+)$/.exec(path);\n\t\t\t\t\tif (selector) {\n\t\t\t\t\t\tconst prefix = await pathStat(selector[1]);\n\t\t\t\t\t\tif (prefix?.isFile()) {\n\t\t\t\t\t\t\tif (requested.length !== 1 || +selector[2] < 1 || +selector[3] < +selector[2])\n\t\t\t\t\t\t\t\tthrow new Error(\"Invalid line selector\");\n\t\t\t\t\t\t\tpath = selector[1];\n\t\t\t\t\t\t\tinfo = prefix;\n\t\t\t\t\t\t\tlineStart = +selector[2];\n\t\t\t\t\t\t\tlineEnd = +selector[3];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst canonicalPath = await canonicalizeFilesystemPath(path);\n\t\t\t\tif (options?.filesystemPolicy) {\n\t\t\t\t\tconst decision = await options.filesystemPolicy({\n\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\tcanonicalPath,\n\t\t\t\t\t\ttoolName: \"grep\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t}\n\t\t\t\tif (!info) {\n\t\t\t\t\tmissingPaths.push(path);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tpaths.push(path);\n\t\t\t\tsingleFile = info.isFile();\n\t\t\t}\n\t\t\tif (!paths.length) throw new Error(`Path not found: ${missingPaths.join(\", \")}`);\n\t\t\tsingleFile = paths.length === 1 && singleFile;\n\t\t\tconst skip = singleFile ? 0 : (input.skip ?? 0);\n\t\t\tconst mode = input.mode ?? \"content\";\n\t\t\tconst pageSize = Math.min(20, limit);\n\t\t\tconst cap = singleFile ? 200 : 20;\n\t\t\tconst before = input.before ?? input.context ?? 0;\n\t\t\tconst after = input.after ?? input.context ?? 0;\n\t\t\tconst request: GrepEngineRequest = {\n\t\t\t\tpattern: input.pattern,\n\t\t\t\tpaths,\n\t\t\t\tcwd: workingCwd,\n\t\t\t\tglob: input.glob === undefined ? undefined : Array.isArray(input.glob) ? input.glob : [input.glob],\n\t\t\t\ttype: input.type,\n\t\t\t\tignoreCase: input.ignoreCase,\n\t\t\t\tliteral: input.literal,\n\t\t\t\tmultiline: input.multiline ?? (input.pattern.includes(\"\\n\") || input.pattern.includes(\"\\\\n\")),\n\t\t\t\thidden: input.hidden,\n\t\t\t\tgitignore: input.gitignore,\n\t\t\t\tcontextBefore: before,\n\t\t\t\tcontextAfter: after,\n\t\t\t\tmaxColumns: GREP_MAX_LINE_LENGTH,\n\t\t\t\ttimeoutMs: input.timeoutMs ?? 30000,\n\t\t\t\tlineStart,\n\t\t\t\tlineEnd,\n\t\t\t\tmode,\n\t\t\t};\n\t\t\tlet engine = await resolveGrepEngine();\n\t\t\tlet preselection: GrepEngineResult | undefined;\n\t\t\tlet selected: string[] = [];\n\t\t\tlet more = false;\n\t\t\tif (!singleFile) {\n\t\t\t\tconst first = await searchPattern(\n\t\t\t\t\tengine,\n\t\t\t\t\t{ ...request, mode: \"files\", maxCount: skip + pageSize + 1 },\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tengine = first.engine;\n\t\t\t\tpreselection = first.result;\n\t\t\t\tselected = first.result.fileCounts.slice(skip, skip + pageSize).map((file) => file.path);\n\t\t\t\tmore = first.result.fileCounts.length > skip + selected.length;\n\t\t\t}\n\t\t\tlet result: GrepEngineResult;\n\t\t\tif (!singleFile && !selected.length) result = preselection!;\n\t\t\telse if (mode === \"files\" && preselection)\n\t\t\t\tresult = { ...preselection, fileCounts: preselection.fileCounts.slice(skip, skip + pageSize) };\n\t\t\telse {\n\t\t\t\tconst response = await searchPattern(\n\t\t\t\t\tengine,\n\t\t\t\t\t{\n\t\t\t\t\t\t...request,\n\t\t\t\t\t\tpaths: singleFile ? paths : selected.map((path) => resolve(workingCwd, path)),\n\t\t\t\t\t\tmaxCountPerFile: mode === \"content\" ? cap + 1 : undefined,\n\t\t\t\t\t\ttimeoutMs: Math.max(0, (input.timeoutMs ?? 30000) - (Date.now() - started)),\n\t\t\t\t\t},\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tengine = response.engine;\n\t\t\t\tresult = response.result;\n\t\t\t}\n\t\t\tlet matches: GrepEngineMatch[] = [];\n\t\t\tlet fileMatches: Array<{ path: string; count: number | null }> = [];\n\t\t\tlet perFileLimitReached = false;\n\t\t\tlet totalLimitReached = false;\n\t\t\tif (mode === \"content\") {\n\t\t\t\tconst groups = new Map<string, GrepEngineMatch[]>();\n\t\t\t\tfor (const row of result.matches)\n\t\t\t\t\tif (!row.isContext) {\n\t\t\t\t\t\tconst rows = groups.get(row.path) ?? [];\n\t\t\t\t\t\trows.push(row);\n\t\t\t\t\t\tgroups.set(row.path, rows);\n\t\t\t\t\t}\n\t\t\t\tconst admitted = new Set<GrepEngineMatch>();\n\t\t\t\tfor (let round = 0; round < cap && admitted.size < limit; round++) {\n\t\t\t\t\tfor (const rows of groups.values()) {\n\t\t\t\t\t\tif (rows[round] && admitted.size < limit) admitted.add(rows[round]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tperFileLimitReached = [...groups.values()].some((rows) => rows.length > cap);\n\t\t\t\ttotalLimitReached =\n\t\t\t\t\t[...groups.values()].reduce((n, rows) => n + Math.min(cap, rows.length), 0) > admitted.size;\n\t\t\t\t// Context belongs only to admitted matches, not to discarded matches from the second phase.\n\t\t\t\tmatches = result.matches.filter(\n\t\t\t\t\t(row) =>\n\t\t\t\t\t\tadmitted.has(row) ||\n\t\t\t\t\t\t(row.isContext &&\n\t\t\t\t\t\t\t[...admitted].some(\n\t\t\t\t\t\t\t\t(match) =>\n\t\t\t\t\t\t\t\t\tmatch.path === row.path && row.line >= match.line - before && row.line <= match.line + after,\n\t\t\t\t\t\t\t)),\n\t\t\t\t);\n\t\t\t\tlet bytes = 0;\n\t\t\t\tmatches = matches.filter((row) => {\n\t\t\t\t\tbytes += Buffer.byteLength(`${row.path}\\n${row.line}: ${row.text}\\n`);\n\t\t\t\t\tif (bytes > DEFAULT_MAX_BYTES - 2048) {\n\t\t\t\t\t\ttotalLimitReached = true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tconst counts = new Map<string, number>();\n\t\t\t\tfor (const row of matches) if (!row.isContext) counts.set(row.path, (counts.get(row.path) ?? 0) + 1);\n\t\t\t\tmatches = matches.filter((row) => counts.has(row.path));\n\t\t\t\tfileMatches = [...counts].map(([path, count]) => ({ path, count }));\n\t\t\t} else if (singleFile || selected.length)\n\t\t\t\tfileMatches = result.fileCounts.map(({ path, count }) => ({ path, count }));\n\t\t\tconst { matches: _matches, fileCounts: _fileCounts, ...scan } = preselection ?? result;\n\t\t\tscan.missingPaths = missingPaths;\n\t\t\tscan.elapsedMs = Date.now() - started;\n\t\t\tscan.effectivePattern = result.effectivePattern;\n\t\t\tscan.patternKind = result.patternKind;\n\t\t\tscan.regexEngine = result.regexEngine;\n\t\t\tscan.timedOut ||= result.timedOut;\n\t\t\tif (result.timedOut && preselection) scan.warnings = [...scan.warnings, ...result.warnings];\n\t\t\tconst partial = scan.timedOut || scan.prefixSearched > 0 || scan.skippedOversized > 0;\n\t\t\tconst details: GrepToolDetails = {\n\t\t\t\tversion: 1,\n\t\t\t\tengine: engine.name,\n\t\t\t\tstatus: partial ? \"partial\" : fileMatches.length ? \"ok\" : skip ? \"pageEnd\" : \"noMatch\",\n\t\t\t\tcwd: workingCwd,\n\t\t\t\tpaths,\n\t\t\t\tmatches,\n\t\t\t\tfileMatches,\n\t\t\t\tmatchCount: mode === \"files\" ? null : fileMatches.reduce((n, file) => n + (file.count ?? 0), 0),\n\t\t\t\tfileCount: fileMatches.length,\n\t\t\t\tskip,\n\t\t\t\tnextSkip: more ? skip + selected.length : null,\n\t\t\t\tfileLimitReached: more,\n\t\t\t\tperFileLimitReached,\n\t\t\t\ttotalLimitReached,\n\t\t\t\tscan,\n\t\t\t\tlinesTruncated: matches.some((row) => row.truncated),\n\t\t\t};\n\t\t\treturn { content: [{ type: \"text\", text: formatGrepText(details) }], details };\n\t\t},\n\t\t...grepRenderers,\n\t};\n}\nexport function createGrepTool(cwd: string, options?: GrepToolOptions): AgentTool<typeof grepSchema> {\n\treturn wrapToolDefinition(createGrepToolDefinition(cwd, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/tools/grep/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAyB,MAAM,gBAAgB,CAAC;AAEhG,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5F,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE;IACtB,IAAI,EAAE,OAAO,EAAE;IACf,IAAI,EAAE,OAAO,EAAE;IACf,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAClC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACzC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACtC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACxC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACpC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACnC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxG,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACnC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACvC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IACrC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;CACxC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC/C,OAAO,EAAE,gGAAgG;IACzG,UAAU,EAAE;QACX,kIAAkI;KAClI;CACD,CAAC;AA6BF,KAAK,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,CAAC;QACJ,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACzE,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,GAAW,EACX,OAAyB;IAEzB,IAAI,OAAO,IAAI,YAAY,IAAI,OAAO;QACrC,MAAM,IAAI,SAAS,CAAC,wFAAwF,CAAC,CAAC;IAC/G,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,QAAQ,EAAE,MAAM;QAChB,WAAW,EACV,qMAAqM;QACtM,aAAa,EAAE,gCAAgC,CAAC,OAAO;QACvD,gBAAgB,EAAE,gCAAgC,CAAC,UAAU;QAC7D,UAAU,EAAE,UAAU;QACtB,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG;YAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACjE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3G,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;gBACjF,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;YAClF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC;gBAC9D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACxD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAChG,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC;YACnC,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAa,EAAE,CAAC;YAClC,IAAI,SAA6B,CAAC;YAClC,IAAI,OAA2B,CAAC;YAChC,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;gBAC7B,IAAI,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;gBACzC,IAAI,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACX,MAAM,QAAQ,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACpD,IAAI,QAAQ,EAAE,CAAC;wBACd,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC3C,IAAI,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;4BACtB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;gCAC5E,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;4BAC1C,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;4BACnB,IAAI,GAAG,MAAM,CAAC;4BACd,SAAS,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;4BACzB,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;wBACxB,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,MAAM,aAAa,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,CAAC;gBAC7D,IAAI,OAAO,EAAE,gBAAgB,EAAE,CAAC;oBAC/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC;wBAC/C,SAAS,EAAE,WAAW;wBACtB,aAAa;wBACb,QAAQ,EAAE,MAAM;qBAChB,CAAC,CAAC;oBACH,IAAI,CAAC,QAAQ,CAAC,KAAK;wBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACvD,CAAC;gBACD,IAAI,CAAC,IAAI,EAAE,CAAC;oBACX,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxB,SAAS;gBACV,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjF,UAAU,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC;YAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;YACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YAChD,MAAM,OAAO,GAAsB;gBAClC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK;gBACL,GAAG,EAAE,UAAU;gBACf,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAClG,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC7F,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,aAAa,EAAE,MAAM;gBACrB,YAAY,EAAE,KAAK;gBACnB,UAAU,EAAE,oBAAoB;gBAChC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK;gBACnC,SAAS;gBACT,OAAO;gBACP,IAAI;aACJ,CAAC;YACF,IAAI,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;YACvC,IAAI,YAA0C,CAAC;YAC/C,IAAI,QAAQ,GAAa,EAAE,CAAC;YAC5B,IAAI,IAAI,GAAG,KAAK,CAAC;YACjB,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjB,MAAM,KAAK,GAAG,MAAM,aAAa,CAChC,MAAM,EACN,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,GAAG,QAAQ,GAAG,CAAC,EAAE,EAC5D,MAAM,CACN,CAAC;gBACF,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;gBACtB,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC;gBAC5B,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzF,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC;YAChE,CAAC;YACD,IAAI,MAAwB,CAAC;YAC7B,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,MAAM;gBAAE,MAAM,GAAG,YAAa,CAAC;iBACvD,IAAI,IAAI,KAAK,OAAO,IAAI,YAAY;gBACxC,MAAM,GAAG,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC;iBAC3F,CAAC;gBACL,MAAM,QAAQ,GAAG,MAAM,aAAa,CACnC,MAAM,EACN;oBACC,GAAG,OAAO;oBACV,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBAC7E,eAAe,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;oBACzD,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC;iBAC3E,EACD,MAAM,CACN,CAAC;gBACF,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;gBACzB,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC1B,CAAC;YACD,IAAI,OAAO,GAAsB,EAAE,CAAC;YACpC,IAAI,WAAW,GAAkD,EAAE,CAAC;YACpE,IAAI,mBAAmB,GAAG,KAAK,CAAC;YAChC,IAAI,iBAAiB,GAAG,KAAK,CAAC;YAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;gBACpD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO;oBAC/B,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;wBACpB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;wBACxC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACf,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC5B,CAAC;gBACF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;gBAC5C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;oBACnE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;wBACpC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,GAAG,KAAK;4BAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBACrE,CAAC;gBACF,CAAC;gBACD,mBAAmB,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;gBAC7E,iBAAiB;oBAChB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;gBAC7F,4FAA4F;gBAC5F,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,EAAE,CACP,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;oBACjB,CAAC,GAAG,CAAC,SAAS;wBACb,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CACjB,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,CAC7F,CAAC,CACJ,CAAC;gBACF,IAAI,KAAK,GAAG,CAAC,CAAC;gBACd,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;oBAChC,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC;oBACtE,IAAI,KAAK,GAAG,iBAAiB,GAAG,IAAI,EAAE,CAAC;wBACtC,iBAAiB,GAAG,IAAI,CAAC;wBACzB,OAAO,KAAK,CAAC;oBACd,CAAC;oBACD,OAAO,IAAI,CAAC;gBACb,CAAC,CAAC,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;gBACzC,KAAK,MAAM,GAAG,IAAI,OAAO;oBAAE,IAAI,CAAC,GAAG,CAAC,SAAS;wBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrG,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBACxD,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;iBAAM,IAAI,UAAU,IAAI,QAAQ,CAAC,MAAM;gBACvC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAC7E,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,YAAY,IAAI,MAAM,CAAC;YACvF,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;YACjC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;YACtC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;YAChD,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;YACtC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;YACtC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC;YAClC,IAAI,MAAM,CAAC,QAAQ,IAAI,YAAY;gBAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5F,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;YACtF,MAAM,OAAO,GAAoB;gBAChC,OAAO,EAAE,CAAC;gBACV,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;gBACtF,GAAG,EAAE,UAAU;gBACf,KAAK;gBACL,OAAO;gBACP,WAAW;gBACX,UAAU,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC/F,SAAS,EAAE,WAAW,CAAC,MAAM;gBAC7B,IAAI;gBACJ,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;gBAC9C,gBAAgB,EAAE,IAAI;gBACtB,mBAAmB;gBACnB,iBAAiB;gBACjB,IAAI;gBACJ,cAAc,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;aACpD,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;QACzD,CAAC;QACD,GAAG,aAAa;KAChB,CAAC;AACH,CAAC;AACD,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAyB;IACpE,OAAO,kBAAkB,CAAC,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { type Static, Type } from \"typebox\";\nimport type { FilesystemPolicyChecker, ToolDefinition } from \"../../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"../filesystem-policy.ts\";\nimport { resolveToCwd } from \"../path-utils.ts\";\nimport { grepRenderers } from \"../renderers/grep.ts\";\nimport { wrapToolDefinition } from \"../tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH, type TruncationResult } from \"../truncate.ts\";\nimport type { GrepEngineMatch, GrepEngineRequest, GrepEngineResult } from \"./engine.ts\";\nimport { formatGrepContent } from \"./format.ts\";\nimport { searchPattern } from \"./pattern.ts\";\nimport { resolveGrepEngine } from \"./select-engine.ts\";\n\nconst strings = () => Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())]));\nconst grepSchema = Type.Object({\n\tpattern: Type.String(),\n\tpath: strings(),\n\tglob: strings(),\n\ttype: Type.Optional(Type.String()),\n\tignoreCase: Type.Optional(Type.Boolean()),\n\tliteral: Type.Optional(Type.Boolean()),\n\tmultiline: Type.Optional(Type.Boolean()),\n\tcontext: Type.Optional(Type.Number()),\n\tbefore: Type.Optional(Type.Number()),\n\tafter: Type.Optional(Type.Number()),\n\tmode: Type.Optional(Type.Union([Type.Literal(\"content\"), Type.Literal(\"count\"), Type.Literal(\"files\")])),\n\tlimit: Type.Optional(Type.Number()),\n\tskip: Type.Optional(Type.Number()),\n\ttimeoutMs: Type.Optional(Type.Number()),\n\thidden: Type.Optional(Type.Boolean()),\n\tgitignore: Type.Optional(Type.Boolean()),\n});\nexport type GrepToolInput = Static<typeof grepSchema>;\nexport const grepToolSystemPromptContribution = {\n\tsnippet: \"Search file contents (regex/literal) across paths with structured results; respects .gitignore\",\n\tguidelines: [\n\t\t\"Use tool.grep for content search instead of rg/grep in a shell; paginate with skip and narrow with glob/path when a page is full\",\n\t],\n};\nexport interface GrepToolDetails {\n\tversion: 1;\n\tengine: \"native\" | \"rg\";\n\tstatus: \"ok\" | \"noMatch\" | \"pageEnd\" | \"partial\";\n\tcwd: string;\n\tpaths: string[];\n\tmatches: GrepEngineMatch[];\n\tfileMatches: Array<{ path: string; count: number | null }>;\n\tmatchCount: number | null;\n\tfileCount: number;\n\tskip: number;\n\tnextSkip: number | null;\n\tfileLimitReached: boolean;\n\tperFileLimitReached: boolean;\n\ttotalLimitReached: boolean;\n\tscan: Omit<GrepEngineResult, \"matches\" | \"fileCounts\">;\n\ttruncation?: TruncationResult;\n\tlinesTruncated?: boolean;\n}\n/** @deprecated No longer honored; removed next release. Use the engine-backed local tool. */\nexport interface GrepOperations {\n\tisDirectory: (absolutePath: string) => Promise<boolean> | boolean;\n\treadFile: (absolutePath: string) => Promise<string> | string;\n}\nexport interface GrepToolOptions {\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nasync function pathStat(path: string) {\n\ttry {\n\t\treturn await stat(path);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n}\n\nexport function createGrepToolDefinition(\n\tcwd: string,\n\toptions?: GrepToolOptions,\n): ToolDefinition<typeof grepSchema, GrepToolDetails> {\n\tif (options && \"operations\" in options)\n\t\tthrow new TypeError(\"GrepToolOptions.operations is deprecated and no longer supported; removed next release\");\n\treturn {\n\t\tname: \"grep\",\n\t\tlabel: \"grep\",\n\t\texposure: \"eval\",\n\t\tdescription:\n\t\t\t\"Search file contents with tool.grep({ pattern, path }) inside eval. Supports regex/literal patterns, file pages with skip, context, count/files modes, and structured results. Respects .gitignore.\",\n\t\tpromptSnippet: grepToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: grepToolSystemPromptContribution.guidelines,\n\t\tparameters: grepSchema,\n\t\tasync execute(_id, input, signal, _update, ctx) {\n\t\t\tconst started = Date.now();\n\t\t\tif (!input.pattern) throw new Error(\"Pattern must not be empty\");\n\t\t\tconst requested = input.path === undefined ? [\".\"] : Array.isArray(input.path) ? input.path : [input.path];\n\t\t\tif (!requested.length || requested.some((p) => typeof p !== \"string\" || !p.length))\n\t\t\t\tthrow new Error(\"path must be a non-empty string or array of non-empty strings\");\n\t\t\tconst limit = input.limit ?? 100;\n\t\t\tif (!Number.isInteger(input.skip ?? 0) || (input.skip ?? 0) < 0)\n\t\t\t\tthrow new Error(\"skip must be a non-negative integer\");\n\t\t\tif (!Number.isInteger(limit) || limit <= 0) throw new Error(\"limit must be a positive integer\");\n\t\t\tconst workingCwd = ctx?.cwd || cwd;\n\t\t\tconst paths: string[] = [];\n\t\t\tconst missingPaths: string[] = [];\n\t\t\tlet lineStart: number | undefined;\n\t\t\tlet lineEnd: number | undefined;\n\t\t\tlet singleFile = false;\n\t\t\tfor (const raw of requested) {\n\t\t\t\tlet path = resolveToCwd(raw, workingCwd);\n\t\t\t\tlet info = await pathStat(path);\n\t\t\t\tif (!info) {\n\t\t\t\t\tconst selector = /^(.*):L(\\d+)-L?(\\d+)$/.exec(path);\n\t\t\t\t\tif (selector) {\n\t\t\t\t\t\tconst prefix = await pathStat(selector[1]);\n\t\t\t\t\t\tif (prefix?.isFile()) {\n\t\t\t\t\t\t\tif (requested.length !== 1 || +selector[2] < 1 || +selector[3] < +selector[2])\n\t\t\t\t\t\t\t\tthrow new Error(\"Invalid line selector\");\n\t\t\t\t\t\t\tpath = selector[1];\n\t\t\t\t\t\t\tinfo = prefix;\n\t\t\t\t\t\t\tlineStart = +selector[2];\n\t\t\t\t\t\t\tlineEnd = +selector[3];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst canonicalPath = await canonicalizeFilesystemPath(path);\n\t\t\t\tif (options?.filesystemPolicy) {\n\t\t\t\t\tconst decision = await options.filesystemPolicy({\n\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\tcanonicalPath,\n\t\t\t\t\t\ttoolName: \"grep\",\n\t\t\t\t\t});\n\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t}\n\t\t\t\tif (!info) {\n\t\t\t\t\tmissingPaths.push(path);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tpaths.push(path);\n\t\t\t\tsingleFile = info.isFile();\n\t\t\t}\n\t\t\tif (!paths.length) throw new Error(`Path not found: ${missingPaths.join(\", \")}`);\n\t\t\tsingleFile = paths.length === 1 && singleFile;\n\t\t\tconst skip = singleFile ? 0 : (input.skip ?? 0);\n\t\t\tconst mode = input.mode ?? \"content\";\n\t\t\tconst pageSize = Math.min(20, limit);\n\t\t\tconst cap = singleFile ? 200 : 20;\n\t\t\tconst before = input.before ?? input.context ?? 0;\n\t\t\tconst after = input.after ?? input.context ?? 0;\n\t\t\tconst request: GrepEngineRequest = {\n\t\t\t\tpattern: input.pattern,\n\t\t\t\tpaths,\n\t\t\t\tcwd: workingCwd,\n\t\t\t\tglob: input.glob === undefined ? undefined : Array.isArray(input.glob) ? input.glob : [input.glob],\n\t\t\t\ttype: input.type,\n\t\t\t\tignoreCase: input.ignoreCase,\n\t\t\t\tliteral: input.literal,\n\t\t\t\tmultiline: input.multiline ?? (input.pattern.includes(\"\\n\") || input.pattern.includes(\"\\\\n\")),\n\t\t\t\thidden: input.hidden,\n\t\t\t\tgitignore: input.gitignore,\n\t\t\t\tcontextBefore: before,\n\t\t\t\tcontextAfter: after,\n\t\t\t\tmaxColumns: GREP_MAX_LINE_LENGTH,\n\t\t\t\ttimeoutMs: input.timeoutMs ?? 30000,\n\t\t\t\tlineStart,\n\t\t\t\tlineEnd,\n\t\t\t\tmode,\n\t\t\t};\n\t\t\tlet engine = await resolveGrepEngine();\n\t\t\tlet preselection: GrepEngineResult | undefined;\n\t\t\tlet selected: string[] = [];\n\t\t\tlet more = false;\n\t\t\tif (!singleFile) {\n\t\t\t\tconst first = await searchPattern(\n\t\t\t\t\tengine,\n\t\t\t\t\t{ ...request, mode: \"files\", maxCount: skip + pageSize + 1 },\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tengine = first.engine;\n\t\t\t\tpreselection = first.result;\n\t\t\t\tselected = first.result.fileCounts.slice(skip, skip + pageSize).map((file) => file.path);\n\t\t\t\tmore = first.result.fileCounts.length > skip + selected.length;\n\t\t\t}\n\t\t\tlet result: GrepEngineResult;\n\t\t\tif (!singleFile && !selected.length) result = preselection!;\n\t\t\telse if (mode === \"files\" && preselection)\n\t\t\t\tresult = { ...preselection, fileCounts: preselection.fileCounts.slice(skip, skip + pageSize) };\n\t\t\telse {\n\t\t\t\tconst response = await searchPattern(\n\t\t\t\t\tengine,\n\t\t\t\t\t{\n\t\t\t\t\t\t...request,\n\t\t\t\t\t\tpaths: singleFile ? paths : selected.map((path) => resolve(workingCwd, path)),\n\t\t\t\t\t\tmaxCountPerFile: mode === \"content\" ? cap + 1 : undefined,\n\t\t\t\t\t\ttimeoutMs: Math.max(0, (input.timeoutMs ?? 30000) - (Date.now() - started)),\n\t\t\t\t\t},\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t\t\t\tengine = response.engine;\n\t\t\t\tresult = response.result;\n\t\t\t}\n\t\t\tlet matches: GrepEngineMatch[] = [];\n\t\t\tlet fileMatches: Array<{ path: string; count: number | null }> = [];\n\t\t\tlet perFileLimitReached = false;\n\t\t\tlet totalLimitReached = false;\n\t\t\tif (mode === \"content\") {\n\t\t\t\tconst groups = new Map<string, GrepEngineMatch[]>();\n\t\t\t\tfor (const row of result.matches)\n\t\t\t\t\tif (!row.isContext) {\n\t\t\t\t\t\tconst rows = groups.get(row.path) ?? [];\n\t\t\t\t\t\trows.push(row);\n\t\t\t\t\t\tgroups.set(row.path, rows);\n\t\t\t\t\t}\n\t\t\t\tconst admitted = new Set<GrepEngineMatch>();\n\t\t\t\tfor (let round = 0; round < cap && admitted.size < limit; round++) {\n\t\t\t\t\tfor (const rows of groups.values()) {\n\t\t\t\t\t\tif (rows[round] && admitted.size < limit) admitted.add(rows[round]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tperFileLimitReached = [...groups.values()].some((rows) => rows.length > cap);\n\t\t\t\ttotalLimitReached =\n\t\t\t\t\t[...groups.values()].reduce((n, rows) => n + Math.min(cap, rows.length), 0) > admitted.size;\n\t\t\t\t// Context belongs only to admitted matches, not to discarded matches from the second phase.\n\t\t\t\tmatches = result.matches.filter(\n\t\t\t\t\t(row) =>\n\t\t\t\t\t\tadmitted.has(row) ||\n\t\t\t\t\t\t(row.isContext &&\n\t\t\t\t\t\t\t[...admitted].some(\n\t\t\t\t\t\t\t\t(match) =>\n\t\t\t\t\t\t\t\t\tmatch.path === row.path && row.line >= match.line - before && row.line <= match.line + after,\n\t\t\t\t\t\t\t)),\n\t\t\t\t);\n\t\t\t\tlet bytes = 0;\n\t\t\t\tmatches = matches.filter((row) => {\n\t\t\t\t\tbytes += Buffer.byteLength(`${row.path}\\n${row.line}: ${row.text}\\n`);\n\t\t\t\t\tif (bytes > DEFAULT_MAX_BYTES - 2048) {\n\t\t\t\t\t\ttotalLimitReached = true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tconst counts = new Map<string, number>();\n\t\t\t\tfor (const row of matches) if (!row.isContext) counts.set(row.path, (counts.get(row.path) ?? 0) + 1);\n\t\t\t\tmatches = matches.filter((row) => counts.has(row.path));\n\t\t\t\tfileMatches = [...counts].map(([path, count]) => ({ path, count }));\n\t\t\t} else if (singleFile || selected.length)\n\t\t\t\tfileMatches = result.fileCounts.map(({ path, count }) => ({ path, count }));\n\t\t\tconst { matches: _matches, fileCounts: _fileCounts, ...scan } = preselection ?? result;\n\t\t\tscan.missingPaths = missingPaths;\n\t\t\tscan.elapsedMs = Date.now() - started;\n\t\t\tscan.effectivePattern = result.effectivePattern;\n\t\t\tscan.patternKind = result.patternKind;\n\t\t\tscan.regexEngine = result.regexEngine;\n\t\t\tscan.timedOut ||= result.timedOut;\n\t\t\tif (result.timedOut && preselection) scan.warnings = [...scan.warnings, ...result.warnings];\n\t\t\tconst partial = scan.timedOut || scan.prefixSearched > 0 || scan.skippedOversized > 0;\n\t\t\tconst details: GrepToolDetails = {\n\t\t\t\tversion: 1,\n\t\t\t\tengine: engine.name,\n\t\t\t\tstatus: partial ? \"partial\" : fileMatches.length ? \"ok\" : skip ? \"pageEnd\" : \"noMatch\",\n\t\t\t\tcwd: workingCwd,\n\t\t\t\tpaths,\n\t\t\t\tmatches,\n\t\t\t\tfileMatches,\n\t\t\t\tmatchCount: mode === \"files\" ? null : fileMatches.reduce((n, file) => n + (file.count ?? 0), 0),\n\t\t\t\tfileCount: fileMatches.length,\n\t\t\t\tskip,\n\t\t\t\tnextSkip: more ? skip + selected.length : null,\n\t\t\t\tfileLimitReached: more,\n\t\t\t\tperFileLimitReached,\n\t\t\t\ttotalLimitReached,\n\t\t\t\tscan,\n\t\t\t\tlinesTruncated: matches.some((row) => row.truncated),\n\t\t\t};\n\t\t\treturn { content: formatGrepContent(details), details };\n\t\t},\n\t\t...grepRenderers,\n\t};\n}\nexport function createGrepTool(cwd: string, options?: GrepToolOptions): AgentTool<typeof grepSchema> {\n\treturn wrapToolDefinition(createGrepToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAoB,uBAAuB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAMxG,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,QAAQ;;;EAGZ,CAAC;AAEH,eAAO,MAAM,8BAA8B;aAC1C,OAAO,EAAE,yBAAyB;aAClC,UAAU;CACD,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAIlD,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,wDAAwD;IACxD,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC,GAAG;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IACzG,6BAA6B;IAC7B,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CAChE;AAQD,MAAM,WAAW,aAAa;IAC7B,yEAAyE;IACzE,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;CAC3C;AAED,wBAAgB,sBAAsB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,GACrB,cAAc,CAAC,OAAO,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC,CA4H5D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAE7F"}
|
package/dist/core/tools/ls.js
CHANGED
|
@@ -2,6 +2,7 @@ import { readdir as fsReaddir, stat as fsStat } from "node:fs/promises";
|
|
|
2
2
|
import nodePath from "path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
4
|
import { canonicalizeFilesystemPath } from "./filesystem-policy.js";
|
|
5
|
+
import { modelOnlyText } from "./model-only-text.js";
|
|
5
6
|
import { pathExists, resolveToCwd } from "./path-utils.js";
|
|
6
7
|
import { lsRenderers } from "./renderers/ls.js";
|
|
7
8
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
@@ -101,7 +102,6 @@ export function createLsToolDefinition(cwd, options) {
|
|
|
101
102
|
const rawOutput = results.join("\n");
|
|
102
103
|
// Apply byte truncation. There is no separate line limit because entry count is already capped.
|
|
103
104
|
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
104
|
-
let output = truncation.content;
|
|
105
105
|
const details = {};
|
|
106
106
|
// Build actionable notices for truncation and entry limits.
|
|
107
107
|
const notices = [];
|
|
@@ -113,11 +113,13 @@ export function createLsToolDefinition(cwd, options) {
|
|
|
113
113
|
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
114
114
|
details.truncation = truncation;
|
|
115
115
|
}
|
|
116
|
+
const content = [{ type: "text", text: truncation.content }];
|
|
116
117
|
if (notices.length > 0) {
|
|
117
|
-
|
|
118
|
+
content[0].text += "\n";
|
|
119
|
+
content.push(modelOnlyText(`[${notices.join(". ")}]`));
|
|
118
120
|
}
|
|
119
121
|
resolve({
|
|
120
|
-
content
|
|
122
|
+
content,
|
|
121
123
|
details: Object.keys(details).length > 0 ? details : undefined,
|
|
122
124
|
});
|
|
123
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir as fsReaddir, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport nodePath from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, FilesystemPolicyChecker, ToolDefinition } from \"../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"./filesystem-policy.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { lsRenderers } from \"./renderers/ls.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\n\nconst lsSchema = Type.Object({\n\tpath: Type.Optional(Type.String({ description: \"Directory to list (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of entries to return (default: 500)\" })),\n});\n\nexport const lsToolSystemPromptContribution = {\n\tsnippet: \"List directory contents\",\n\tguidelines: [],\n} as const;\n\nexport type LsToolInput = Static<typeof lsSchema>;\n\nconst DEFAULT_LIMIT = 500;\n\nexport interface LsToolDetails {\n\ttruncation?: TruncationResult;\n\tentryLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the ls tool.\n * Override these to delegate directory listing to remote systems (for example SSH).\n */\nexport interface LsOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Get file or directory stats. Throws if not found. */\n\tstat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }> | { isDirectory: () => boolean };\n\t/** Read directory entries */\n\treaddir: (absolutePath: string) => Promise<string[]> | string[];\n}\n\nconst defaultLsOperations: LsOperations = {\n\texists: pathExists,\n\tstat: fsStat,\n\treaddir: fsReaddir,\n};\n\nexport interface LsToolOptions {\n\t/** Custom operations for directory listing. Default: local filesystem */\n\toperations?: LsOperations;\n\t/** Extension-registered filesystem policy checker. */\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nexport function createLsToolDefinition(\n\tcwd: string,\n\toptions?: LsToolOptions,\n): ToolDefinition<typeof lsSchema, LsToolDetails | undefined> {\n\tconst ops = options?.operations ?? defaultLsOperations;\n\tconst filesystemPolicy = options?.filesystemPolicy;\n\treturn {\n\t\tname: \"ls\",\n\t\tlabel: \"ls\",\n\t\tdescription: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tpromptSnippet: lsToolSystemPromptContribution.snippet,\n\t\tparameters: lsSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, limit }: { path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst onAbort = () => reject(new Error(\"Operation aborted\"));\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst dirPath = resolveToCwd(path || \".\", ctx?.cwd || cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\t\t\t\t\t\tif (filesystemPolicy) {\n\t\t\t\t\t\t\tconst decision = await filesystemPolicy({\n\t\t\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\t\t\tcanonicalPath: await canonicalizeFilesystemPath(dirPath),\n\t\t\t\t\t\t\t\ttoolName: \"ls\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path exists.\n\t\t\t\t\t\tif (!(await ops.exists(dirPath))) {\n\t\t\t\t\t\t\treject(new Error(`Path not found: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path is a directory.\n\t\t\t\t\t\tconst stat = await ops.stat(dirPath);\n\t\t\t\t\t\tif (!stat.isDirectory()) {\n\t\t\t\t\t\t\treject(new Error(`Not a directory: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read directory entries.\n\t\t\t\t\t\tlet entries: string[];\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tentries = await ops.readdir(dirPath);\n\t\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t\treject(new Error(`Cannot read directory: ${e.message}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sort alphabetically, case-insensitive.\n\t\t\t\t\t\tentries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));\n\n\t\t\t\t\t\t// Format entries with directory indicators.\n\t\t\t\t\t\tconst results: string[] = [];\n\t\t\t\t\t\tlet entryLimitReached = false;\n\t\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\t\tif (results.length >= effectiveLimit) {\n\t\t\t\t\t\t\t\tentryLimitReached = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst fullPath = nodePath.join(dirPath, entry);\n\t\t\t\t\t\t\tlet suffix = \"\";\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst entryStat = await ops.stat(fullPath);\n\t\t\t\t\t\t\t\tif (entryStat.isDirectory()) suffix = \"/\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip entries we cannot stat.\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults.push(entry + suffix);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"(empty directory)\" }], details: undefined });\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst rawOutput = results.join(\"\\n\");\n\t\t\t\t\t\t// Apply byte truncation. There is no separate line limit because entry count is already capped.\n\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\tconst details: LsToolDetails = {};\n\t\t\t\t\t\t// Build actionable notices for truncation and entry limits.\n\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\tif (entryLimitReached) {\n\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);\n\t\t\t\t\t\t\tdetails.entryLimitReached = effectiveLimit;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(e);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\t...lsRenderers,\n\t};\n}\n\nexport function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema> {\n\treturn wrapToolDefinition(createLsToolDefinition(cwd, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir as fsReaddir, stat as fsStat } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { TextContent } from \"@earendil-works/pi-ai\";\nimport nodePath from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, FilesystemPolicyChecker, ToolDefinition } from \"../extensions/types.ts\";\nimport { canonicalizeFilesystemPath } from \"./filesystem-policy.ts\";\nimport { modelOnlyText } from \"./model-only-text.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { lsRenderers } from \"./renderers/ls.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\n\nconst lsSchema = Type.Object({\n\tpath: Type.Optional(Type.String({ description: \"Directory to list (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of entries to return (default: 500)\" })),\n});\n\nexport const lsToolSystemPromptContribution = {\n\tsnippet: \"List directory contents\",\n\tguidelines: [],\n} as const;\n\nexport type LsToolInput = Static<typeof lsSchema>;\n\nconst DEFAULT_LIMIT = 500;\n\nexport interface LsToolDetails {\n\ttruncation?: TruncationResult;\n\tentryLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the ls tool.\n * Override these to delegate directory listing to remote systems (for example SSH).\n */\nexport interface LsOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Get file or directory stats. Throws if not found. */\n\tstat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }> | { isDirectory: () => boolean };\n\t/** Read directory entries */\n\treaddir: (absolutePath: string) => Promise<string[]> | string[];\n}\n\nconst defaultLsOperations: LsOperations = {\n\texists: pathExists,\n\tstat: fsStat,\n\treaddir: fsReaddir,\n};\n\nexport interface LsToolOptions {\n\t/** Custom operations for directory listing. Default: local filesystem */\n\toperations?: LsOperations;\n\t/** Extension-registered filesystem policy checker. */\n\tfilesystemPolicy?: FilesystemPolicyChecker;\n}\n\nexport function createLsToolDefinition(\n\tcwd: string,\n\toptions?: LsToolOptions,\n): ToolDefinition<typeof lsSchema, LsToolDetails | undefined> {\n\tconst ops = options?.operations ?? defaultLsOperations;\n\tconst filesystemPolicy = options?.filesystemPolicy;\n\treturn {\n\t\tname: \"ls\",\n\t\tlabel: \"ls\",\n\t\tdescription: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tpromptSnippet: lsToolSystemPromptContribution.snippet,\n\t\tparameters: lsSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, limit }: { path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst onAbort = () => reject(new Error(\"Operation aborted\"));\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst dirPath = resolveToCwd(path || \".\", ctx?.cwd || cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\t\t\t\t\t\tif (filesystemPolicy) {\n\t\t\t\t\t\t\tconst decision = await filesystemPolicy({\n\t\t\t\t\t\t\t\toperation: \"enumerate\",\n\t\t\t\t\t\t\t\tcanonicalPath: await canonicalizeFilesystemPath(dirPath),\n\t\t\t\t\t\t\t\ttoolName: \"ls\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (!decision.allow) throw new Error(decision.reason);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path exists.\n\t\t\t\t\t\tif (!(await ops.exists(dirPath))) {\n\t\t\t\t\t\t\treject(new Error(`Path not found: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path is a directory.\n\t\t\t\t\t\tconst stat = await ops.stat(dirPath);\n\t\t\t\t\t\tif (!stat.isDirectory()) {\n\t\t\t\t\t\t\treject(new Error(`Not a directory: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read directory entries.\n\t\t\t\t\t\tlet entries: string[];\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tentries = await ops.readdir(dirPath);\n\t\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t\treject(new Error(`Cannot read directory: ${e.message}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sort alphabetically, case-insensitive.\n\t\t\t\t\t\tentries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));\n\n\t\t\t\t\t\t// Format entries with directory indicators.\n\t\t\t\t\t\tconst results: string[] = [];\n\t\t\t\t\t\tlet entryLimitReached = false;\n\t\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\t\tif (results.length >= effectiveLimit) {\n\t\t\t\t\t\t\t\tentryLimitReached = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst fullPath = nodePath.join(dirPath, entry);\n\t\t\t\t\t\t\tlet suffix = \"\";\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst entryStat = await ops.stat(fullPath);\n\t\t\t\t\t\t\t\tif (entryStat.isDirectory()) suffix = \"/\";\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip entries we cannot stat.\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults.push(entry + suffix);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"(empty directory)\" }], details: undefined });\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst rawOutput = results.join(\"\\n\");\n\t\t\t\t\t\t// Apply byte truncation. There is no separate line limit because entry count is already capped.\n\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\tconst details: LsToolDetails = {};\n\t\t\t\t\t\t// Build actionable notices for truncation and entry limits.\n\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\tif (entryLimitReached) {\n\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);\n\t\t\t\t\t\t\tdetails.entryLimitReached = effectiveLimit;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst content: TextContent[] = [{ type: \"text\", text: truncation.content }];\n\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\tcontent[0].text += \"\\n\";\n\t\t\t\t\t\t\tcontent.push(modelOnlyText(`[${notices.join(\". \")}]`));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(e);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\t...lsRenderers,\n\t};\n}\n\nexport function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema> {\n\treturn wrapToolDefinition(createLsToolDefinition(cwd, options));\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-only-text.d.ts","sourceRoot":"","sources":["../../../src/core/tools/model-only-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAEvD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAStD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function modelOnlyText(text) {
|
|
2
|
+
return { type: "text", text, audience: "model" };
|
|
3
|
+
}
|
|
4
|
+
export function isModelOnlyText(part) {
|
|
5
|
+
return (typeof part === "object" &&
|
|
6
|
+
part !== null &&
|
|
7
|
+
"type" in part &&
|
|
8
|
+
part.type === "text" &&
|
|
9
|
+
"audience" in part &&
|
|
10
|
+
part.audience === "model");
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=model-only-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-only-text.js","sourceRoot":"","sources":["../../../src/core/tools/model-only-text.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAAC,IAAY;IACzC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAa;IAC5C,OAAO,CACN,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,MAAM,IAAI,IAAI;QACd,IAAI,CAAC,IAAI,KAAK,MAAM;QACpB,UAAU,IAAI,IAAI;QAClB,IAAI,CAAC,QAAQ,KAAK,OAAO,CACzB,CAAC;AACH,CAAC","sourcesContent":["import type { TextContent } from \"@earendil-works/pi-ai\";\n\nexport function modelOnlyText(text: string): TextContent {\n\treturn { type: \"text\", text, audience: \"model\" };\n}\n\nexport function isModelOnlyText(part: unknown): boolean {\n\treturn (\n\t\ttypeof part === \"object\" &&\n\t\tpart !== null &&\n\t\t\"type\" in part &&\n\t\tpart.type === \"text\" &&\n\t\t\"audience\" in part &&\n\t\tpart.audience === \"model\"\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EAGd,KAAK,UAAU,EAEf,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAoB,uBAAuB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,SAAS,EAGd,KAAK,UAAU,EAEf,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAoB,uBAAuB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAIxG,OAAO,EAAE,KAAK,eAAe,EAAiB,MAAM,qBAAqB,CAAC;AAE1E,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEtH,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,eAAO,MAAM,gCAAgC;aAC5C,OAAO,EAAE,oBAAoB;aAC7B,UAAU,YAAG,kDAAkD;CACtD,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAMD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,+CAA+C;IAC/C,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,sEAAsE;IACtE,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACnF;AAQD,MAAM,WAAW,eAAe;IAC/B,mGAAmG;IACnG,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;CAC3C;AASD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,eAAgD,GACvD,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAiKjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG"}
|
package/dist/core/tools/read.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Type } from "typebox";
|
|
|
5
5
|
import { processImage } from "../../utils/image-process.js";
|
|
6
6
|
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.js";
|
|
7
7
|
import { canonicalizeFilesystemPath } from "./filesystem-policy.js";
|
|
8
|
+
import { modelOnlyText } from "./model-only-text.js";
|
|
8
9
|
import { resolveReadPathAsync } from "./path-utils.js";
|
|
9
10
|
import { readRenderers } from "./renderers/read.js";
|
|
10
11
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
@@ -145,13 +146,15 @@ export function createReadToolDefinition(cwd, options = { folder: selectedReadFo
|
|
|
145
146
|
truncated: truncation.truncated,
|
|
146
147
|
});
|
|
147
148
|
let outputText;
|
|
149
|
+
let notice;
|
|
148
150
|
if (summary) {
|
|
149
151
|
outputText = summary.text;
|
|
150
152
|
}
|
|
151
153
|
else if (truncation.firstLineExceedsLimit) {
|
|
152
154
|
// First line alone exceeds the byte limit. Point the model at a bash fallback.
|
|
153
155
|
const firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], "utf-8"));
|
|
154
|
-
outputText =
|
|
156
|
+
outputText = "";
|
|
157
|
+
notice = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;
|
|
155
158
|
details = { truncation };
|
|
156
159
|
}
|
|
157
160
|
else if (truncation.truncated) {
|
|
@@ -160,10 +163,10 @@ export function createReadToolDefinition(cwd, options = { folder: selectedReadFo
|
|
|
160
163
|
const nextOffset = endLineDisplay + 1;
|
|
161
164
|
outputText = truncation.content;
|
|
162
165
|
if (truncation.truncatedBy === "lines") {
|
|
163
|
-
|
|
166
|
+
notice = `[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;
|
|
164
167
|
}
|
|
165
168
|
else {
|
|
166
|
-
|
|
169
|
+
notice = `[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;
|
|
167
170
|
}
|
|
168
171
|
details = { truncation };
|
|
169
172
|
}
|
|
@@ -171,13 +174,20 @@ export function createReadToolDefinition(cwd, options = { folder: selectedReadFo
|
|
|
171
174
|
// User-specified limit stopped early, but the file still has more content.
|
|
172
175
|
const remaining = allLines.length - (startLine + userLimitedLines);
|
|
173
176
|
const nextOffset = startLine + userLimitedLines + 1;
|
|
174
|
-
outputText =
|
|
177
|
+
outputText = truncation.content;
|
|
178
|
+
notice = `[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
|
|
175
179
|
}
|
|
176
180
|
else {
|
|
177
181
|
// No truncation and no remaining user-limited content.
|
|
178
182
|
outputText = truncation.content;
|
|
179
183
|
}
|
|
180
|
-
|
|
184
|
+
// Text adapters join parts with a newline; retain the original blank line.
|
|
185
|
+
content =
|
|
186
|
+
outputText || notice === undefined
|
|
187
|
+
? [{ type: "text", text: notice === undefined ? outputText : `${outputText}\n` }]
|
|
188
|
+
: [];
|
|
189
|
+
if (notice !== undefined)
|
|
190
|
+
content.push(modelOnlyText(notice));
|
|
181
191
|
}
|
|
182
192
|
if (aborted)
|
|
183
193
|
return;
|