pi-readseek 0.11.4 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/index.ts +341 -291
- package/package.json +3 -3
- package/prompts/assets.md +6 -0
- package/prompts/{find_definitions.md → def.md} +3 -3
- package/prompts/{edit_text.md → edit.md} +2 -2
- package/prompts/refs.md +10 -0
- package/prompts/{rename_symbol.md → rename.md} +1 -2
- package/prompts/{find_nodes.md → search.md} +3 -1
- package/prompts/show.md +16 -0
- package/prompts/find_references.md +0 -14
- package/prompts/show_assets.md +0 -11
- package/prompts/show_content.md +0 -34
- /package/prompts/{find_text.md → grep.md} +0 -0
- /package/prompts/{write_file.md → write.md} +0 -0
package/dist/index.ts
CHANGED
|
@@ -16,22 +16,22 @@ var EDIT_VARIANTS = [
|
|
|
16
16
|
];
|
|
17
17
|
var GIT_SCOPES = ["tracked", "untracked", "ignored", "all"];
|
|
18
18
|
var TOOL_NAMES = [
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
19
|
+
"show",
|
|
20
|
+
"tree",
|
|
21
|
+
"meta",
|
|
22
|
+
"assets",
|
|
23
|
+
"syntax",
|
|
24
|
+
"check",
|
|
25
|
+
"caption",
|
|
26
|
+
"objects",
|
|
27
|
+
"ocr",
|
|
28
|
+
"search",
|
|
29
|
+
"grep",
|
|
30
|
+
"def",
|
|
31
|
+
"refs",
|
|
32
|
+
"edit",
|
|
33
|
+
"rename",
|
|
34
|
+
"write"
|
|
35
35
|
];
|
|
36
36
|
var PARAM_DESCRIPTIONS = {
|
|
37
37
|
path: "Absolute or relative file path",
|
|
@@ -47,8 +47,8 @@ var PARAM_DESCRIPTIONS = {
|
|
|
47
47
|
name: "Qualified or unqualified symbol name",
|
|
48
48
|
refsName: "Identifier to find references for",
|
|
49
49
|
gitScope: "In a Git repository, which files to search: tracked, untracked, ignored (untracked plus ignored), or all. Defaults to tracked plus untracked.",
|
|
50
|
-
at: "Location selector: line:N[:COLUMN], hash:H[:COLUMN], symbol:NAME, page:N, node:ID, or asset:ID",
|
|
51
|
-
assetAt: "Document selector: page:N, node:ID, or asset:ID",
|
|
50
|
+
at: "Location selector: N[:COLUMN], START-END, H[:COLUMN], NAME, line:N[:COLUMN], hash:H[:COLUMN], symbol:NAME, page:N, node:ID, or asset:ID",
|
|
51
|
+
assetAt: "Document selector: N, page:N, node:ID, or asset:ID",
|
|
52
52
|
rule: "KDL node selection rule, @path, or '-' for standard input",
|
|
53
53
|
rules: "KDL structural checks, @path, or '-' for standard input",
|
|
54
54
|
stdinName: "File name hint when the target is '-'",
|
|
@@ -60,7 +60,7 @@ var PARAM_DESCRIPTIONS = {
|
|
|
60
60
|
kind: "Restrict structure to this node kind",
|
|
61
61
|
outline: "Show outline of document hierarchy or source symbols",
|
|
62
62
|
noAnchors: "Omit source line anchors",
|
|
63
|
-
text: "Literal native text query; adapter
|
|
63
|
+
text: "Literal native text query; adapter grep also supports regex via pattern",
|
|
64
64
|
edits: "Use set_line, replace_lines, insert_after, replace_symbol, or replace",
|
|
65
65
|
editVariant: "Exactly one nested edit variant",
|
|
66
66
|
setLine: 'Replace one line: {"set_line":{"anchor":"LINE:HASH","new_text":"..."}}',
|
|
@@ -97,22 +97,22 @@ var PARAM_DESCRIPTIONS = {
|
|
|
97
97
|
scopeContext: "Context lines within each symbol"
|
|
98
98
|
};
|
|
99
99
|
var TOOL_DESCRIPTIONS = {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
100
|
+
show: "Read source, document content, or image descriptors without inference. Obtain fresh `LINE:HASH` anchors before edits; use at with a column for cursor context. Document results include typed nodes and cached asset paths.",
|
|
101
|
+
tree: "Show parsed source or document hierarchy. Use shallow depth for file overviews.",
|
|
102
|
+
meta: "Show format, source identity, language, dimensions, or page count without decoding image content or inference.",
|
|
103
|
+
assets: "Return selected document asset descriptors with usable cached paths. Adapters attach images from those paths.",
|
|
104
|
+
syntax: "Check parser syntax diagnostics. Exit 0 is clean, 1 has findings, 2 is failure; this is not type checking.",
|
|
105
|
+
check: "Evaluate KDL structural assertions. Exit 0 is clean, 1 has findings, 2 is failure.",
|
|
106
|
+
caption: "Explicitly infer a caption using an installed model. Include text and objects to request OCR and detection too; never downloads models automatically.",
|
|
107
|
+
objects: "Explicitly infer object labels and bounding boxes using an installed model.",
|
|
108
|
+
ocr: "Explicitly recognize text from pixels using an installed model; reading never silently invokes OCR.",
|
|
109
|
+
search: "Find AST nodes by pattern or KDL selection rule. Returns edit-ready anchors. Use `grep` for text and regex.",
|
|
110
|
+
grep: "Search text or regex and return edit-ready `LINE:HASH` anchors. Native CLI text is literal; adapters preserve regex, glob, context, summary, and symbol grouping.",
|
|
111
|
+
def: "Find a symbol definition or declaration by qualified or unqualified name.",
|
|
112
|
+
refs: "Find identifier-name matches with name, or binding-scoped references with at. Use before renaming or deleting a symbol.",
|
|
113
|
+
edit: "Edit existing files with fresh `LINE:HASH` anchors. Each edits item contains exactly one set_line, replace_lines, insert_after, replace_symbol, or replace object. Preview before applying a verified plan.",
|
|
114
|
+
rename: "Rename a symbol at a line or hash cursor with binding-aware edits and stale-plan protection.",
|
|
115
|
+
write: "Create or replace a complete text file and return `LINE:HASH` anchors. Use `edit` for small changes."
|
|
116
116
|
};
|
|
117
117
|
function rewriteBacktickedToolNames(text, aliases = {}) {
|
|
118
118
|
return TOOL_NAMES.reduce((rewritten, toolName) => rewritten.replaceAll(`\`${toolName}\``, `\`${aliases[toolName] ?? toolName}\``), text);
|
|
@@ -205,22 +205,22 @@ function tool(name, title, properties, required) {
|
|
|
205
205
|
return { name, title, description: TOOL_DESCRIPTIONS[name], inputSchema: { type: "object", properties, required, additionalProperties: false } };
|
|
206
206
|
}
|
|
207
207
|
var TOOL_CONTRACTS = [
|
|
208
|
-
tool("
|
|
209
|
-
tool("
|
|
210
|
-
tool("
|
|
211
|
-
tool("
|
|
212
|
-
tool("
|
|
213
|
-
tool("
|
|
214
|
-
tool("
|
|
215
|
-
tool("
|
|
216
|
-
tool("
|
|
217
|
-
tool("
|
|
218
|
-
tool("
|
|
219
|
-
tool("
|
|
220
|
-
tool("
|
|
221
|
-
tool("
|
|
222
|
-
tool("
|
|
223
|
-
tool("
|
|
208
|
+
tool("show", "Show content", { ...path, ...at, ...lang, ...stdin, ...noAnchors, end: integer(PARAM_DESCRIPTIONS.end), limit: integer(PARAM_DESCRIPTIONS.limit) }, ["path"]),
|
|
209
|
+
tool("tree", "Show structure", { ...path, ...at, ...lang, ...stdin, depth: integer(PARAM_DESCRIPTIONS.depth, 0), kind: string(PARAM_DESCRIPTIONS.kind), outline: { type: "boolean", description: PARAM_DESCRIPTIONS.outline } }, ["path"]),
|
|
210
|
+
tool("meta", "Show metadata", { ...path, ...lang, ...stdin }, ["path"]),
|
|
211
|
+
tool("assets", "Show assets", { ...path, at: string(PARAM_DESCRIPTIONS.assetAt), ...stdin }, ["path"]),
|
|
212
|
+
tool("syntax", "Check syntax", { ...path, ...lang, ...stdin }, ["path"]),
|
|
213
|
+
tool("check", "Check rules", { path: string(PARAM_DESCRIPTIONS.searchPath), ...gitScopeSchema, rules: string(PARAM_DESCRIPTIONS.rules) }, ["rules"]),
|
|
214
|
+
tool("caption", "Generate caption", { ...path, ...at, ...stdin, ...level, include: { type: "array", items: { type: "string", enum: ["text", "objects"] }, minItems: 1, uniqueItems: true, description: PARAM_DESCRIPTIONS.include } }, ["path"]),
|
|
215
|
+
tool("objects", "Detect objects", { ...path, ...at, ...stdin, ...level }, ["path"]),
|
|
216
|
+
tool("ocr", "Recognize text", { ...path, ...at, ...stdin, ...level }, ["path"]),
|
|
217
|
+
tool("search", "Search AST nodes", { ...path, ...lang, ...stdin, ...limit, ...gitScopeSchema, ...noAnchors, pattern: string(PARAM_DESCRIPTIONS.pattern), context: string(PARAM_DESCRIPTIONS.patternContext), selector: string(PARAM_DESCRIPTIONS.selector), rule: string(PARAM_DESCRIPTIONS.rule) }, []),
|
|
218
|
+
tool("grep", "Search text", { ...path, ...limit, ...gitScopeSchema, text: string(PARAM_DESCRIPTIONS.text), pattern: string(PARAM_DESCRIPTIONS.grepPattern), glob: string(PARAM_DESCRIPTIONS.glob), ignoreCase: { type: "boolean", description: PARAM_DESCRIPTIONS.ignoreCase }, literal: { type: "boolean", description: PARAM_DESCRIPTIONS.literal }, context: integer(PARAM_DESCRIPTIONS.context, 0), summary: { type: "boolean", description: PARAM_DESCRIPTIONS.summary }, scope: { type: "string", enum: ["symbol"], description: PARAM_DESCRIPTIONS.grepScope }, scopeContext: integer(PARAM_DESCRIPTIONS.scopeContext, 0) }, []),
|
|
219
|
+
tool("def", "Find definitions", { ...path, ...lang, ...gitScopeSchema, ...noAnchors, name: string(PARAM_DESCRIPTIONS.name) }, ["name"]),
|
|
220
|
+
tool("refs", "Find references", { ...path, ...at, ...lang, ...gitScopeSchema, ...noAnchors, name: string(PARAM_DESCRIPTIONS.refsName) }, []),
|
|
221
|
+
tool("edit", "Hash-verified edit", { ...path, ...lang, ...gitScopeSchema, ...apply, edits: { type: "array", minItems: 1, items: editItemSchema, description: PARAM_DESCRIPTIONS.edits }, postEditVerify: { type: "boolean", description: PARAM_DESCRIPTIONS.postEditVerify } }, ["path", "edits"]),
|
|
222
|
+
tool("rename", "Rename symbol", { ...path, ...at, ...lang, ...gitScopeSchema, ...apply, to: string(PARAM_DESCRIPTIONS.to), workspace: { type: "boolean", description: PARAM_DESCRIPTIONS.workspace } }, ["path", "at", "to"]),
|
|
223
|
+
tool("write", "Write file", { ...path, content: string(PARAM_DESCRIPTIONS.content) }, ["path", "content"])
|
|
224
224
|
];
|
|
225
225
|
function getToolContract(name) {
|
|
226
226
|
const contract = TOOL_CONTRACTS.find((entry) => entry.name === name);
|
|
@@ -231,44 +231,44 @@ function getToolContract(name) {
|
|
|
231
231
|
// ../readseek-api/src/policy.ts
|
|
232
232
|
var REPLACEABLE_TOOLS = [
|
|
233
233
|
{
|
|
234
|
-
tool: "
|
|
234
|
+
tool: "show",
|
|
235
235
|
builtIn: "read",
|
|
236
236
|
benefit: "it returns LINE:HASH anchors for safe edits."
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
|
-
tool: "
|
|
239
|
+
tool: "edit",
|
|
240
240
|
builtIn: "edit",
|
|
241
241
|
benefit: "it verifies fresh LINE:HASH anchors."
|
|
242
242
|
},
|
|
243
243
|
{
|
|
244
|
-
tool: "
|
|
244
|
+
tool: "grep",
|
|
245
245
|
builtIn: "grep",
|
|
246
246
|
benefit: "it returns LINE:HASH anchors."
|
|
247
247
|
},
|
|
248
248
|
{
|
|
249
|
-
tool: "
|
|
249
|
+
tool: "write",
|
|
250
250
|
builtIn: "write",
|
|
251
251
|
benefit: "it returns LINE:HASH anchors."
|
|
252
252
|
}
|
|
253
253
|
];
|
|
254
254
|
var TOOL_COMPACT_GUIDELINES = {
|
|
255
|
-
|
|
256
|
-
"Use `
|
|
255
|
+
show: [
|
|
256
|
+
"Use `tree` for shallow overviews and `syntax` for diagnostics; use `def`, `refs`, or `search` for targeted symbol questions."
|
|
257
257
|
],
|
|
258
|
-
|
|
258
|
+
edit: [
|
|
259
259
|
"Prefer set_line, replace_lines, and insert_after; use replace only when anchors are impractical."
|
|
260
260
|
],
|
|
261
|
-
|
|
262
|
-
"Use `
|
|
261
|
+
grep: [
|
|
262
|
+
"Use `grep` with summary first for broad searches, then narrow by path, glob, or pattern."
|
|
263
263
|
],
|
|
264
|
-
|
|
265
|
-
"Use anchored edits rather than `
|
|
264
|
+
write: [
|
|
265
|
+
"Use anchored edits rather than `write` for small changes or appends."
|
|
266
266
|
],
|
|
267
|
-
|
|
268
|
-
"Use `
|
|
267
|
+
search: [
|
|
268
|
+
"Use `search` for AST patterns; use `grep` for plain text."
|
|
269
269
|
],
|
|
270
|
-
|
|
271
|
-
"Use `
|
|
270
|
+
refs: [
|
|
271
|
+
"Use `refs` before changing a symbol; use at with line:N:C to follow one binding."
|
|
272
272
|
]
|
|
273
273
|
};
|
|
274
274
|
function resolveToolName(name, aliases = {}) {
|
|
@@ -279,21 +279,21 @@ function renderCompactGuidelines(name, aliases = {}) {
|
|
|
279
279
|
}
|
|
280
280
|
function renderToolRoutingPolicy(options = {}) {
|
|
281
281
|
const aliases = options.aliases ?? {};
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
const
|
|
282
|
+
const show = resolveToolName("show", aliases);
|
|
283
|
+
const edit = resolveToolName("edit", aliases);
|
|
284
|
+
const write = resolveToolName("write", aliases);
|
|
285
|
+
const grep = resolveToolName("grep", aliases);
|
|
286
|
+
const search = resolveToolName("search", aliases);
|
|
287
|
+
const def = resolveToolName("def", aliases);
|
|
288
|
+
const refs = resolveToolName("refs", aliases);
|
|
289
|
+
const rename = resolveToolName("rename", aliases);
|
|
290
|
+
const assets = resolveToolName("assets", aliases);
|
|
291
291
|
const title = options.title ?? "ReadSeek tool policy:";
|
|
292
292
|
const bullets = [];
|
|
293
293
|
if (options.preferOverBuiltIns) {
|
|
294
294
|
bullets.push("- Prefer ReadSeek tools over built-ins when they can do the job.");
|
|
295
295
|
}
|
|
296
|
-
bullets.push(`- Read with ${
|
|
296
|
+
bullets.push(`- Read with ${show} first; ${edit} needs fresh LINE:HASH anchors.`, `- Use ${grep} for text/regex, ${search} for AST patterns, ${def}/${refs} for targeted symbols, and shallow ${resolveToolName("tree", aliases)} structures only for file overviews.`, `- Use ${edit} for existing files, ${write} for whole-file creation or replacement, and ${rename} for symbol renames.`, `- Use ${resolveToolName("tree", aliases)} for document structure; run ${resolveToolName("syntax", aliases)} after source edits for a quick syntax check.`, `- Use ${assets} to materialize selected document assets and read their returned paths.`);
|
|
297
297
|
if (options.demoteBuiltIns && options.demoteBuiltIns.length > 0) {
|
|
298
298
|
bullets.push(`- Do not use built-in ${options.demoteBuiltIns.join(", ")} when a ReadSeek tool can do the job.`);
|
|
299
299
|
}
|
|
@@ -459,50 +459,111 @@ var SELECTOR_KINDS = ["line", "hash", "symbol", "page", "node", "asset"];
|
|
|
459
459
|
function isSelectorKind(value) {
|
|
460
460
|
return SELECTOR_KINDS.includes(value);
|
|
461
461
|
}
|
|
462
|
+
function parsePositiveSelectorInt(raw, name) {
|
|
463
|
+
if (!/^-?\d+$/.test(raw))
|
|
464
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
465
|
+
const parsed = Number(raw);
|
|
466
|
+
if (!Number.isSafeInteger(parsed))
|
|
467
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
468
|
+
if (parsed < 1)
|
|
469
|
+
throw new Error(`${name} must be greater than zero`);
|
|
470
|
+
return parsed;
|
|
471
|
+
}
|
|
472
|
+
function parseLineSelector(value, explicitKind) {
|
|
473
|
+
const parts = value.split(":");
|
|
474
|
+
if (parts.length > 2)
|
|
475
|
+
throw new Error("selector has too many components");
|
|
476
|
+
const head = parts[0];
|
|
477
|
+
if (parts.length === 2) {
|
|
478
|
+
if (head.slice(1).includes("-"))
|
|
479
|
+
throw new Error("line range cannot include a column");
|
|
480
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
481
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
482
|
+
return { kind: "line", value: String(line), column, explicitKind };
|
|
483
|
+
}
|
|
484
|
+
const dash = head.indexOf("-", 1);
|
|
485
|
+
if (dash > 0) {
|
|
486
|
+
const start = parsePositiveSelectorInt(head.slice(0, dash), "line");
|
|
487
|
+
const endLine = parsePositiveSelectorInt(head.slice(dash + 1), "end line");
|
|
488
|
+
if (endLine < start)
|
|
489
|
+
throw new Error(`end line ${endLine} precedes start line ${start}`);
|
|
490
|
+
return { kind: "line", value: String(start), endLine, explicitKind };
|
|
491
|
+
}
|
|
492
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
493
|
+
return { kind: "line", value: String(line), explicitKind };
|
|
494
|
+
}
|
|
495
|
+
function parseHashSelector(value, explicitKind) {
|
|
496
|
+
const parts = value.split(":");
|
|
497
|
+
if (parts.length > 2)
|
|
498
|
+
throw new Error("selector has too many components");
|
|
499
|
+
const head = parts[0];
|
|
500
|
+
if (!/^[0-9a-fA-F]{6}$/.test(head))
|
|
501
|
+
throw new Error(`invalid line hash \`${head}\``);
|
|
502
|
+
if (parts.length === 2) {
|
|
503
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
504
|
+
return { kind: "hash", value: head, column, explicitKind };
|
|
505
|
+
}
|
|
506
|
+
return { kind: "hash", value: head, explicitKind };
|
|
507
|
+
}
|
|
508
|
+
function isDocumentSelector(parsed) {
|
|
509
|
+
return ["page", "node", "asset"].includes(parsed.kind) || parsed.kind === "line" && !parsed.explicitKind && parsed.column === undefined && parsed.endLine === undefined;
|
|
510
|
+
}
|
|
511
|
+
function isBindingSelector(parsed) {
|
|
512
|
+
if (parsed.endLine !== undefined)
|
|
513
|
+
return false;
|
|
514
|
+
if (parsed.kind === "line" || parsed.kind === "hash")
|
|
515
|
+
return true;
|
|
516
|
+
return parsed.kind === "symbol" && !parsed.explicitKind && /^[0-9a-fA-F]{6}$/.test(parsed.value);
|
|
517
|
+
}
|
|
462
518
|
function parseSelector(text) {
|
|
519
|
+
if (text.length === 0)
|
|
520
|
+
throw new Error("selector must not be empty");
|
|
463
521
|
const separator = text.indexOf(":");
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
522
|
+
const hasSingleColon = separator >= 0 && text[separator + 1] !== ":";
|
|
523
|
+
if (hasSingleColon) {
|
|
524
|
+
const kind = text.slice(0, separator);
|
|
525
|
+
const value = text.slice(separator + 1);
|
|
526
|
+
if (isSelectorKind(kind)) {
|
|
527
|
+
if (value.length === 0)
|
|
528
|
+
throw new Error(`${kind} selector must not be empty`);
|
|
529
|
+
if (kind === "line")
|
|
530
|
+
return parseLineSelector(value, true);
|
|
531
|
+
if (kind === "hash")
|
|
532
|
+
return parseHashSelector(value, true);
|
|
533
|
+
if (kind === "page") {
|
|
534
|
+
if (value.includes(":"))
|
|
535
|
+
throw new Error("page selector has too many components");
|
|
536
|
+
parsePositiveSelectorInt(value, "page");
|
|
537
|
+
}
|
|
538
|
+
return { kind, value, explicitKind: true };
|
|
539
|
+
}
|
|
540
|
+
if (/^\d+$/.test(kind))
|
|
541
|
+
return parseLineSelector(text, false);
|
|
542
|
+
if (/^[0-9a-fA-F]{6}$/.test(kind) && /^\d+$/.test(value))
|
|
543
|
+
return parseHashSelector(text, false);
|
|
472
544
|
throw new Error(`unknown selector kind \`${kind}\`; expected line, hash, symbol, page, node, or asset`);
|
|
473
545
|
}
|
|
474
|
-
if (
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
throw new Error("selector has too many components");
|
|
478
|
-
if (parts.length === 2) {
|
|
479
|
-
const column = Number(parts[1]);
|
|
480
|
-
if (!Number.isSafeInteger(column))
|
|
481
|
-
throw new Error(`invalid column \`${parts[1]}\``);
|
|
482
|
-
if (column < 1)
|
|
483
|
-
throw new Error("column must be greater than zero");
|
|
484
|
-
return { kind, value: parts[0], column };
|
|
546
|
+
if (/^[0-9-]/.test(text)) {
|
|
547
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /[a-fA-F]/.test(text)) {
|
|
548
|
+
return parseHashSelector(text, false);
|
|
485
549
|
}
|
|
550
|
+
return parseLineSelector(text, false);
|
|
486
551
|
}
|
|
487
|
-
if (
|
|
488
|
-
|
|
489
|
-
throw new Error("page selector has too many components");
|
|
490
|
-
const page = Number(value);
|
|
491
|
-
if (!Number.isSafeInteger(page))
|
|
492
|
-
throw new Error(`invalid page \`${value}\``);
|
|
493
|
-
if (page < 1)
|
|
494
|
-
throw new Error("page must be greater than zero");
|
|
552
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /\d/.test(text)) {
|
|
553
|
+
return parseHashSelector(text, false);
|
|
495
554
|
}
|
|
496
|
-
|
|
555
|
+
if (/\s/.test(text))
|
|
556
|
+
throw new Error(`invalid selector \`${text}\``);
|
|
557
|
+
return { kind: "symbol", value: text, explicitKind: false };
|
|
497
558
|
}
|
|
498
|
-
function start(
|
|
559
|
+
function start(command, input) {
|
|
499
560
|
if (!input.path)
|
|
500
|
-
throw new Error(`${
|
|
561
|
+
throw new Error(`${command} requires a path`);
|
|
501
562
|
if (input.stdinName !== undefined && input.path !== "-")
|
|
502
563
|
throw new Error("stdinName requires '-' as the target");
|
|
503
564
|
const args = [];
|
|
504
565
|
pushOptionalString(args, "--readseek-dir", input.readseekDir);
|
|
505
|
-
args.push(
|
|
566
|
+
args.push(command, input.path);
|
|
506
567
|
pushOptionalString(args, "--stdin-name", input.stdinName);
|
|
507
568
|
return args;
|
|
508
569
|
}
|
|
@@ -528,12 +589,12 @@ function anchors(args, input) {
|
|
|
528
589
|
if (input.noAnchors)
|
|
529
590
|
args.push("--no-anchors");
|
|
530
591
|
}
|
|
531
|
-
function
|
|
592
|
+
function buildShowArgs(input) {
|
|
532
593
|
if (input.end !== undefined)
|
|
533
594
|
validatePositiveInteger(input.end, "end");
|
|
534
595
|
if (input.end !== undefined && input.limit !== undefined)
|
|
535
596
|
throw new Error("cannot combine end with limit");
|
|
536
|
-
const args = start("show",
|
|
597
|
+
const args = start("show", input);
|
|
537
598
|
at2(args, input.at);
|
|
538
599
|
pushOptionalNumber(args, "--end", input.end);
|
|
539
600
|
limit2(args, input.limit);
|
|
@@ -541,10 +602,10 @@ function buildShowContentArgs(input) {
|
|
|
541
602
|
anchors(args, input);
|
|
542
603
|
return finish(args);
|
|
543
604
|
}
|
|
544
|
-
function
|
|
605
|
+
function buildTreeArgs(input) {
|
|
545
606
|
if (input.depth !== undefined && (!Number.isSafeInteger(input.depth) || input.depth < 0))
|
|
546
607
|
throw new Error("depth must be a non-negative integer");
|
|
547
|
-
const args = start("
|
|
608
|
+
const args = start("tree", input);
|
|
548
609
|
at2(args, input.at);
|
|
549
610
|
pushOptionalNumber(args, "--depth", input.depth);
|
|
550
611
|
pushOptionalString(args, "--kind", input.kind);
|
|
@@ -553,35 +614,35 @@ function buildShowStructureArgs(input) {
|
|
|
553
614
|
args.push("--outline");
|
|
554
615
|
return finish(args);
|
|
555
616
|
}
|
|
556
|
-
function
|
|
557
|
-
const args = start("
|
|
617
|
+
function buildMetaArgs(input) {
|
|
618
|
+
const args = start("meta", input);
|
|
558
619
|
language(args, input);
|
|
559
620
|
return finish(args);
|
|
560
621
|
}
|
|
561
|
-
function
|
|
562
|
-
if (input.at !== undefined && !
|
|
622
|
+
function buildAssetsArgs(input) {
|
|
623
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
563
624
|
throw new Error("assets requires a page, node, or asset selector");
|
|
564
|
-
const args = start("
|
|
625
|
+
const args = start("assets", input);
|
|
565
626
|
at2(args, input.at);
|
|
566
627
|
return finish(args);
|
|
567
628
|
}
|
|
568
|
-
function
|
|
569
|
-
const args = start("
|
|
629
|
+
function buildSyntaxArgs(input) {
|
|
630
|
+
const args = start("syntax", input);
|
|
570
631
|
language(args, input);
|
|
571
632
|
return finish(args);
|
|
572
633
|
}
|
|
573
|
-
function visionArgs(
|
|
634
|
+
function visionArgs(command, input) {
|
|
574
635
|
if (input.level !== undefined && !VISION_LEVELS.includes(input.level))
|
|
575
636
|
throw new Error("invalid vision level");
|
|
576
|
-
if (input.at !== undefined && !
|
|
637
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
577
638
|
throw new Error("vision requires a document selector");
|
|
578
|
-
const args = start(
|
|
639
|
+
const args = start(command, input);
|
|
579
640
|
at2(args, input.at);
|
|
580
641
|
pushOptionalString(args, "--level", input.level);
|
|
581
642
|
return args;
|
|
582
643
|
}
|
|
583
|
-
function
|
|
584
|
-
const args = visionArgs("
|
|
644
|
+
function buildCaptionArgs(input) {
|
|
645
|
+
const args = visionArgs("caption", input);
|
|
585
646
|
if (input.include !== undefined) {
|
|
586
647
|
if (input.include.length === 0 || input.include.some((task) => task !== "text" && task !== "objects"))
|
|
587
648
|
throw new Error("include requires text or objects");
|
|
@@ -589,13 +650,13 @@ function buildGenerateCaptionArgs(input) {
|
|
|
589
650
|
}
|
|
590
651
|
return finish(args);
|
|
591
652
|
}
|
|
592
|
-
function
|
|
593
|
-
return finish(visionArgs("
|
|
653
|
+
function buildObjectsArgs(input) {
|
|
654
|
+
return finish(visionArgs("objects", input));
|
|
594
655
|
}
|
|
595
|
-
function
|
|
596
|
-
return finish(visionArgs("
|
|
656
|
+
function buildOcrArgs(input) {
|
|
657
|
+
return finish(visionArgs("ocr", input));
|
|
597
658
|
}
|
|
598
|
-
function
|
|
659
|
+
function buildSearchArgs(input) {
|
|
599
660
|
const hasPattern = Boolean(input.pattern);
|
|
600
661
|
const hasRule = Boolean(input.rule);
|
|
601
662
|
const hasContext = Boolean(input.context);
|
|
@@ -603,7 +664,7 @@ function buildFindNodesArgs(input) {
|
|
|
603
664
|
if (hasPattern || hasContext || input.selector)
|
|
604
665
|
throw new Error("rule cannot be combined with pattern, context, or selector");
|
|
605
666
|
} else if (!hasPattern && !hasContext) {
|
|
606
|
-
throw new Error("
|
|
667
|
+
throw new Error("search requires pattern, context, or rule");
|
|
607
668
|
}
|
|
608
669
|
if (hasContext && !input.selector) {
|
|
609
670
|
throw new Error("context requires selector");
|
|
@@ -611,7 +672,7 @@ function buildFindNodesArgs(input) {
|
|
|
611
672
|
if (hasPattern && hasContext) {
|
|
612
673
|
throw new Error("pattern and context cannot be combined");
|
|
613
674
|
}
|
|
614
|
-
const args = start("
|
|
675
|
+
const args = start("search", input);
|
|
615
676
|
pushOptionalString(args, "--pattern", input.pattern);
|
|
616
677
|
pushOptionalString(args, "--context", input.context);
|
|
617
678
|
pushOptionalString(args, "--selector", input.selector);
|
|
@@ -622,28 +683,28 @@ function buildFindNodesArgs(input) {
|
|
|
622
683
|
anchors(args, input);
|
|
623
684
|
return finish(args);
|
|
624
685
|
}
|
|
625
|
-
function
|
|
626
|
-
const args = start("
|
|
686
|
+
function buildGrepArgs(input) {
|
|
687
|
+
const args = start("grep", input);
|
|
627
688
|
args.push("--text", input.text);
|
|
628
689
|
limit2(args, input.limit);
|
|
629
690
|
appendGitScopeArgs(args, input);
|
|
630
691
|
return finish(args);
|
|
631
692
|
}
|
|
632
|
-
function
|
|
633
|
-
const args = start("
|
|
693
|
+
function buildDefArgs(input) {
|
|
694
|
+
const args = start("def", input);
|
|
634
695
|
args.push("--name", input.name);
|
|
635
696
|
language(args, input);
|
|
636
697
|
appendGitScopeArgs(args, input);
|
|
637
698
|
anchors(args, input);
|
|
638
699
|
return finish(args);
|
|
639
700
|
}
|
|
640
|
-
function
|
|
701
|
+
function buildRefsArgs(input) {
|
|
641
702
|
const validated = validateReferencesSelection(input);
|
|
642
703
|
if (!validated.ok)
|
|
643
704
|
throw new Error(validated.error);
|
|
644
|
-
if (input.at !== undefined && !
|
|
705
|
+
if (input.at !== undefined && !isBindingSelector(parseSelector(input.at)))
|
|
645
706
|
throw new Error("references requires a line or hash selector");
|
|
646
|
-
const args = start("
|
|
707
|
+
const args = start("refs", input);
|
|
647
708
|
pushOptionalString(args, "--name", input.name);
|
|
648
709
|
at2(args, input.at);
|
|
649
710
|
language(args, input);
|
|
@@ -651,14 +712,14 @@ function buildFindReferencesArgs(input) {
|
|
|
651
712
|
anchors(args, input);
|
|
652
713
|
return finish(args);
|
|
653
714
|
}
|
|
654
|
-
function
|
|
655
|
-
const args = start("check",
|
|
715
|
+
function buildCheckArgs(input) {
|
|
716
|
+
const args = start("check", input);
|
|
656
717
|
args.push("--rules", input.rules);
|
|
657
718
|
appendGitScopeArgs(args, input);
|
|
658
719
|
return finish(args);
|
|
659
720
|
}
|
|
660
|
-
function
|
|
661
|
-
const args = start("edit",
|
|
721
|
+
function buildEditArgs(input) {
|
|
722
|
+
const args = start("edit", input);
|
|
662
723
|
appendApplyAndPlanHash(args, input);
|
|
663
724
|
language(args, input);
|
|
664
725
|
appendGitScopeArgs(args, input);
|
|
@@ -666,10 +727,10 @@ function buildEditTextArgs(input) {
|
|
|
666
727
|
args.push("--edits", "-");
|
|
667
728
|
return finish(args);
|
|
668
729
|
}
|
|
669
|
-
function
|
|
670
|
-
if (!
|
|
730
|
+
function buildRenameArgs(input) {
|
|
731
|
+
if (!isBindingSelector(parseSelector(input.at)))
|
|
671
732
|
throw new Error("rename requires a line or hash selector");
|
|
672
|
-
const args = start("rename",
|
|
733
|
+
const args = start("rename", input);
|
|
673
734
|
at2(args, input.at);
|
|
674
735
|
args.push("--to", input.to);
|
|
675
736
|
if (input.workspace !== undefined)
|
|
@@ -1200,71 +1261,71 @@ function runOptions(options, vision = false) {
|
|
|
1200
1261
|
}
|
|
1201
1262
|
function createReadSeekClient(runner) {
|
|
1202
1263
|
return {
|
|
1203
|
-
async
|
|
1204
|
-
const value = await runner.kdl(
|
|
1264
|
+
async show(path, options = {}) {
|
|
1265
|
+
const value = await runner.kdl(buildShowArgs({ ...options, path }), runOptions(options));
|
|
1205
1266
|
return parseContentOutput(value);
|
|
1206
1267
|
},
|
|
1207
|
-
async
|
|
1208
|
-
const value = await runner.kdl(
|
|
1268
|
+
async tree(path, options = {}) {
|
|
1269
|
+
const value = await runner.kdl(buildTreeArgs({ ...options, path }), runOptions(options));
|
|
1209
1270
|
return parseStructureEnvelope(value);
|
|
1210
1271
|
},
|
|
1211
|
-
async
|
|
1212
|
-
const value = await runner.kdl(
|
|
1272
|
+
async meta(path, options = {}) {
|
|
1273
|
+
const value = await runner.kdl(buildMetaArgs({ ...options, path }), runOptions(options));
|
|
1213
1274
|
return parsePdfMetadata(value) ?? parseDetectOutput(value?.metadata);
|
|
1214
1275
|
},
|
|
1215
|
-
async
|
|
1216
|
-
const value = await runner.kdl(
|
|
1276
|
+
async assets(path, options = {}) {
|
|
1277
|
+
const value = await runner.kdl(buildAssetsArgs({ ...options, path }), runOptions(options));
|
|
1217
1278
|
return parseAssetsOutput(value);
|
|
1218
1279
|
},
|
|
1219
|
-
async
|
|
1220
|
-
const value = await runner.kdl(
|
|
1280
|
+
async syntax(path, options = {}) {
|
|
1281
|
+
const value = await runner.kdl(buildSyntaxArgs({ ...options, path }), runOptions(options));
|
|
1221
1282
|
return parseCheckOutput(value?.diagnostics ?? value);
|
|
1222
1283
|
},
|
|
1223
|
-
async
|
|
1224
|
-
const value = await runner.kdl(
|
|
1284
|
+
async check(path, options) {
|
|
1285
|
+
const value = await runner.kdl(buildCheckArgs({ ...options, path }), runOptions(options));
|
|
1225
1286
|
return parseRulesOutput(value);
|
|
1226
1287
|
},
|
|
1227
|
-
async
|
|
1228
|
-
const value = await runner.kdl(
|
|
1288
|
+
async caption(path, options = {}) {
|
|
1289
|
+
const value = await runner.kdl(buildCaptionArgs({ ...options, path }), runOptions(options, true));
|
|
1229
1290
|
return parseContentOutput(value);
|
|
1230
1291
|
},
|
|
1231
|
-
async
|
|
1232
|
-
const value = await runner.kdl(
|
|
1292
|
+
async objects(path, options = {}) {
|
|
1293
|
+
const value = await runner.kdl(buildObjectsArgs({ ...options, path }), runOptions(options, true));
|
|
1233
1294
|
return parseContentOutput(value);
|
|
1234
1295
|
},
|
|
1235
|
-
async
|
|
1236
|
-
const value = await runner.kdl(
|
|
1296
|
+
async ocr(path, options = {}) {
|
|
1297
|
+
const value = await runner.kdl(buildOcrArgs({ ...options, path }), runOptions(options, true));
|
|
1237
1298
|
return parseContentOutput(value);
|
|
1238
1299
|
},
|
|
1239
|
-
async
|
|
1240
|
-
const value = await runner.kdl(
|
|
1300
|
+
async search(path, options) {
|
|
1301
|
+
const value = await runner.kdl(buildSearchArgs({ ...options, path }), runOptions(options));
|
|
1241
1302
|
return parseSearchOutput(value);
|
|
1242
1303
|
},
|
|
1243
|
-
async
|
|
1244
|
-
const value = await runner.kdl(
|
|
1304
|
+
async grep(path, options) {
|
|
1305
|
+
const value = await runner.kdl(buildGrepArgs({ ...options, path }), runOptions(options));
|
|
1245
1306
|
return parseTextSearchOutput(value);
|
|
1246
1307
|
},
|
|
1247
|
-
async
|
|
1248
|
-
const value = await runner.kdl(
|
|
1308
|
+
async def(path, options) {
|
|
1309
|
+
const value = await runner.kdl(buildDefArgs({ ...options, path }), runOptions(options));
|
|
1249
1310
|
return parseDefOutput(value);
|
|
1250
1311
|
},
|
|
1251
|
-
async
|
|
1252
|
-
const value = await runner.kdl(
|
|
1312
|
+
async refs(path, options) {
|
|
1313
|
+
const value = await runner.kdl(buildRefsArgs({ ...options, path }), runOptions(options));
|
|
1253
1314
|
return parseRefsOutput(value);
|
|
1254
1315
|
},
|
|
1255
|
-
async
|
|
1316
|
+
async edit(path, edits, options = {}) {
|
|
1256
1317
|
const stdin = serializeEditPlan(edits);
|
|
1257
|
-
return parseEditOutput(await runner.kdl(
|
|
1318
|
+
return parseEditOutput(await runner.kdl(buildEditArgs({ ...options, path, requestFromStdin: true }), runOptions({ ...options, stdin })));
|
|
1258
1319
|
},
|
|
1259
|
-
async
|
|
1260
|
-
const value = await runner.kdl(
|
|
1320
|
+
async rename(path, options) {
|
|
1321
|
+
const value = await runner.kdl(buildRenameArgs({ ...options, path }), runOptions(options));
|
|
1261
1322
|
return parseRenameOutput(value);
|
|
1262
1323
|
}
|
|
1263
1324
|
};
|
|
1264
1325
|
}
|
|
1265
1326
|
// ../readseek-api/src/show-presentation.ts
|
|
1266
1327
|
function isShowTool(name) {
|
|
1267
|
-
return name === "
|
|
1328
|
+
return name === "show" || name === "tree" || name === "meta" || name === "assets";
|
|
1268
1329
|
}
|
|
1269
1330
|
function record(value) {
|
|
1270
1331
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -1379,7 +1440,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1379
1440
|
const path = inline(options.path || output.source || output.file || content.file || structure.file || metadata.file || cursor.file) || "(unknown path)";
|
|
1380
1441
|
const summary = [];
|
|
1381
1442
|
const result = { summary: "", body: "", notices: [], metadata: {} };
|
|
1382
|
-
if (tool === "
|
|
1443
|
+
if (tool === "meta") {
|
|
1383
1444
|
const data = Object.keys(metadata).length > 0 ? metadata : output;
|
|
1384
1445
|
if (text(data.format || data.language || data.type))
|
|
1385
1446
|
summary.push(inline(data.format || data.language || data.type));
|
|
@@ -1388,7 +1449,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1388
1449
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1389
1450
|
}
|
|
1390
1451
|
result.body = fields(data) || "No metadata available.";
|
|
1391
|
-
} else if (tool === "
|
|
1452
|
+
} else if (tool === "assets") {
|
|
1392
1453
|
const assets = records(output.assets);
|
|
1393
1454
|
result.metadata.assets = assets.length;
|
|
1394
1455
|
summary.push(plural(assets.length, "asset"));
|
|
@@ -1402,7 +1463,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1402
1463
|
summary.push(plural(nodes.length, "node"));
|
|
1403
1464
|
if (result.metadata.pages !== undefined)
|
|
1404
1465
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1405
|
-
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "
|
|
1466
|
+
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "show")];
|
|
1406
1467
|
if (assets.length > 0) {
|
|
1407
1468
|
result.metadata.assets = assets.length;
|
|
1408
1469
|
sections.push(`Assets
|
|
@@ -1411,7 +1472,7 @@ ${assetList(assets)}`);
|
|
|
1411
1472
|
result.body = sections.filter(Boolean).join(`
|
|
1412
1473
|
|
|
1413
1474
|
`) || "No content in this selection.";
|
|
1414
|
-
} else if (tool === "
|
|
1475
|
+
} else if (tool === "tree") {
|
|
1415
1476
|
const symbols = records(structure.symbols);
|
|
1416
1477
|
result.metadata.symbols = symbols.length;
|
|
1417
1478
|
summary.push(plural(symbols.length, "symbol"));
|
|
@@ -1465,7 +1526,7 @@ ${assetList(assets)}`);
|
|
|
1465
1526
|
const description = Object.keys(content).length > 0 ? content : output;
|
|
1466
1527
|
result.body = fields(description) || "No content in this selection.";
|
|
1467
1528
|
}
|
|
1468
|
-
if (tool === "
|
|
1529
|
+
if (tool === "tree")
|
|
1469
1530
|
result.notices.push("Structure is limited to the requested depth, kind, and outline. Use a deeper depth or focus with at to inspect further.");
|
|
1470
1531
|
if (text(output.warning))
|
|
1471
1532
|
result.notices.push(safe(text(output.warning)));
|
|
@@ -1905,7 +1966,7 @@ function acceptsReadSeekExitCode(args, exitCode) {
|
|
|
1905
1966
|
index++;
|
|
1906
1967
|
continue;
|
|
1907
1968
|
}
|
|
1908
|
-
return arg === "
|
|
1969
|
+
return arg === "grep" || arg === "search" || arg === "def" || arg === "refs" || arg === "syntax" || arg === "check";
|
|
1909
1970
|
}
|
|
1910
1971
|
return false;
|
|
1911
1972
|
}
|
|
@@ -2491,7 +2552,7 @@ function formatReplaceHint(edits, noopEdits) {
|
|
|
2491
2552
|
return;
|
|
2492
2553
|
if (counts.replace !== counts.total)
|
|
2493
2554
|
return;
|
|
2494
|
-
return "[info: this edit used replace (unverified). For safer future edits, prefer set_line/replace_lines with an anchor from
|
|
2555
|
+
return "[info: this edit used replace (unverified). For safer future edits, prefer set_line/replace_lines with an anchor from readSeek_show/readSeek_grep/readSeek_search.]";
|
|
2495
2556
|
}
|
|
2496
2557
|
function buildEditOutput(input) {
|
|
2497
2558
|
const summary = `Updated ${input.displayPath}`;
|
|
@@ -2591,10 +2652,10 @@ import { readFileSync, statSync as statSync2 } from "node:fs";
|
|
|
2591
2652
|
import { homedir as homedir2 } from "node:os";
|
|
2592
2653
|
import { join } from "node:path";
|
|
2593
2654
|
var READSEEK_TOOL_REPLACEMENTS = {
|
|
2594
|
-
read: "
|
|
2595
|
-
edit: "
|
|
2596
|
-
grep: "
|
|
2597
|
-
write: "
|
|
2655
|
+
read: "readSeek_show",
|
|
2656
|
+
edit: "readSeek_edit",
|
|
2657
|
+
grep: "readSeek_grep",
|
|
2658
|
+
write: "readSeek_write"
|
|
2598
2659
|
};
|
|
2599
2660
|
var READSEEK_KEYS = ["overrideTools", "imageMode", "syntaxValidation", "timeoutMs", "grep", "display"];
|
|
2600
2661
|
var READSEEK_GREP_KEYS = ["maxLines", "maxBytes"];
|
|
@@ -2830,7 +2891,7 @@ async function ensureDefaultReadSeekDir() {
|
|
|
2830
2891
|
return null;
|
|
2831
2892
|
if (directoryExists(dir))
|
|
2832
2893
|
return dir;
|
|
2833
|
-
defaultReadSeekDirInit ??= runReadSeekNodeText(readSeekBinaryPath(), ["--readseek-dir", dir, "
|
|
2894
|
+
defaultReadSeekDirInit ??= runReadSeekNodeText(readSeekBinaryPath(), ["--readseek-dir", dir, "init"], { timeoutMs: readSeekTimeoutMs() }).then(() => directoryExists(dir) ? dir : null).catch(() => null).finally(() => {
|
|
2834
2895
|
defaultReadSeekDirInit = undefined;
|
|
2835
2896
|
});
|
|
2836
2897
|
return defaultReadSeekDirInit;
|
|
@@ -2848,18 +2909,7 @@ function hasProjectReadSeekDir(cwd = process.cwd()) {
|
|
|
2848
2909
|
}
|
|
2849
2910
|
function supportsReadSeekDir(args) {
|
|
2850
2911
|
const first = args[0];
|
|
2851
|
-
|
|
2852
|
-
if (first === "initialize" && second === "index")
|
|
2853
|
-
return true;
|
|
2854
|
-
if (first === "show" && (second === "content" || second === "assets"))
|
|
2855
|
-
return true;
|
|
2856
|
-
if (first === "generate" && second === "caption")
|
|
2857
|
-
return true;
|
|
2858
|
-
if (first === "detect" && second === "objects")
|
|
2859
|
-
return true;
|
|
2860
|
-
if (first === "recognize" && second === "text")
|
|
2861
|
-
return true;
|
|
2862
|
-
return false;
|
|
2912
|
+
return first === "init" || first === "show" || first === "assets" || first === "caption" || first === "objects" || first === "ocr";
|
|
2863
2913
|
}
|
|
2864
2914
|
async function readSeekInvocationArgs(args) {
|
|
2865
2915
|
if (!supportsReadSeekDir(args) || hasProjectReadSeekDir())
|
|
@@ -2917,22 +2967,22 @@ var runner = {
|
|
|
2917
2967
|
kdl: async (args, options = {}) => parseReadSeekKdl(await runner.text(args, options))
|
|
2918
2968
|
};
|
|
2919
2969
|
var client2 = createReadSeekClient(runner);
|
|
2920
|
-
var
|
|
2921
|
-
var
|
|
2922
|
-
var
|
|
2923
|
-
var
|
|
2924
|
-
var
|
|
2925
|
-
var
|
|
2926
|
-
var
|
|
2927
|
-
var
|
|
2928
|
-
var
|
|
2929
|
-
var
|
|
2930
|
-
var
|
|
2931
|
-
var
|
|
2932
|
-
var
|
|
2933
|
-
var
|
|
2970
|
+
var readSeekShow = client2.show;
|
|
2971
|
+
var readSeekTree = client2.tree;
|
|
2972
|
+
var readSeekMeta = client2.meta;
|
|
2973
|
+
var readSeekAssets = client2.assets;
|
|
2974
|
+
var readSeekCaption = client2.caption;
|
|
2975
|
+
var readSeekObjects = client2.objects;
|
|
2976
|
+
var readSeekOcr = client2.ocr;
|
|
2977
|
+
var readSeekSearch = client2.search;
|
|
2978
|
+
var readSeekRefs = client2.refs;
|
|
2979
|
+
var readSeekDef = client2.def;
|
|
2980
|
+
var readSeekSyntax = client2.syntax;
|
|
2981
|
+
var readSeekCheck = client2.check;
|
|
2982
|
+
var readSeekEdit = client2.edit;
|
|
2983
|
+
var readSeekRename = client2.rename;
|
|
2934
2984
|
async function readSeekMap(filePath, options = {}) {
|
|
2935
|
-
const envelope = await client2.
|
|
2985
|
+
const envelope = await client2.tree(filePath, { depth: DEFAULT_STRUCTURE_DEPTH, signal: options.signal });
|
|
2936
2986
|
const map = "structure" in envelope ? envelope.structure : undefined;
|
|
2937
2987
|
if (!map || map.language === "unknown" && map.symbols.length === 0)
|
|
2938
2988
|
return null;
|
|
@@ -2958,8 +3008,8 @@ async function validateSyntaxRegression(input, options = {}) {
|
|
|
2958
3008
|
let before;
|
|
2959
3009
|
let after;
|
|
2960
3010
|
try {
|
|
2961
|
-
before = input.before === undefined ? EMPTY : await
|
|
2962
|
-
after = await
|
|
3011
|
+
before = input.before === undefined ? EMPTY : await readSeekSyntax("-", { stdinName: input.filePath, stdin: input.before, signal: options.signal });
|
|
3012
|
+
after = await readSeekSyntax("-", { stdinName: input.filePath, stdin: input.after, signal: options.signal });
|
|
2963
3013
|
} catch {
|
|
2964
3014
|
return null;
|
|
2965
3015
|
}
|
|
@@ -3645,7 +3695,7 @@ async function executeEdit(opts) {
|
|
|
3645
3695
|
return await withFileMutationQueue(absolutePath, async () => {
|
|
3646
3696
|
throwIfAborted(signal);
|
|
3647
3697
|
if (wasReadInSession && !wasReadInSession(absolutePath)) {
|
|
3648
|
-
const hint = `Call
|
|
3698
|
+
const hint = `Call readSeek_show(${JSON.stringify(rawPath)}) first, or use readSeek_grep, readSeek_search, or readSeek_write to produce fresh anchors for this file.`;
|
|
3649
3699
|
return buildEditError(absolutePath, "file-not-read", `You must get fresh anchors for ${absolutePath} before editing it. ${hint}`, hint);
|
|
3650
3700
|
}
|
|
3651
3701
|
const parsedEdits = validateExactlyOneEditVariant(parsed.edits ?? []);
|
|
@@ -3655,7 +3705,7 @@ async function executeEdit(opts) {
|
|
|
3655
3705
|
const edits = parsedEdits.edits;
|
|
3656
3706
|
let plan;
|
|
3657
3707
|
try {
|
|
3658
|
-
plan = await
|
|
3708
|
+
plan = await readSeekEdit(absolutePath, edits, { signal, language: parsed.language });
|
|
3659
3709
|
} catch (err) {
|
|
3660
3710
|
throwIfAborted(signal);
|
|
3661
3711
|
const failure = classifyReadSeekFailure(err);
|
|
@@ -3691,7 +3741,7 @@ async function executeEdit(opts) {
|
|
|
3691
3741
|
throwIfAborted(signal);
|
|
3692
3742
|
let applied;
|
|
3693
3743
|
try {
|
|
3694
|
-
applied = await
|
|
3744
|
+
applied = await readSeekEdit(absolutePath, edits, {
|
|
3695
3745
|
apply: true,
|
|
3696
3746
|
planHash: plan.plan_hash,
|
|
3697
3747
|
language: parsed.language,
|
|
@@ -3759,9 +3809,9 @@ async function executeEdit(opts) {
|
|
|
3759
3809
|
}
|
|
3760
3810
|
}
|
|
3761
3811
|
function registerEditTool(pi, options = {}) {
|
|
3762
|
-
const name = options.name ?? "
|
|
3812
|
+
const name = options.name ?? "readSeek_edit";
|
|
3763
3813
|
const promptMetadata = defineToolPromptMetadata({
|
|
3764
|
-
toolName: "
|
|
3814
|
+
toolName: "edit",
|
|
3765
3815
|
promptSnippet: "Edit existing files with fresh LINE:HASH anchors",
|
|
3766
3816
|
registeredName: name,
|
|
3767
3817
|
toolAliases: options.toolAliases
|
|
@@ -4626,9 +4676,9 @@ ${warning}` } : item),
|
|
|
4626
4676
|
};
|
|
4627
4677
|
}
|
|
4628
4678
|
function registerGrepTool(pi, options = {}) {
|
|
4629
|
-
const name = options.name ?? "
|
|
4679
|
+
const name = options.name ?? "readSeek_grep";
|
|
4630
4680
|
const promptMetadata = defineToolPromptMetadata({
|
|
4631
|
-
toolName: "
|
|
4681
|
+
toolName: "grep",
|
|
4632
4682
|
promptSnippet: "Search text or regex with edit-ready LINE:HASH anchors",
|
|
4633
4683
|
registeredName: name
|
|
4634
4684
|
});
|
|
@@ -4774,7 +4824,7 @@ function mergeRanges(ranges) {
|
|
|
4774
4824
|
return merged;
|
|
4775
4825
|
}
|
|
4776
4826
|
var SEARCH_PROMPT_METADATA = defineToolPromptMetadata({
|
|
4777
|
-
toolName: "
|
|
4827
|
+
toolName: "search",
|
|
4778
4828
|
promptSnippet: "Search code by AST structure using ast-grep-style patterns"
|
|
4779
4829
|
});
|
|
4780
4830
|
function linesFromSearchResult(result, ranges) {
|
|
@@ -4814,7 +4864,7 @@ async function executeSearch(opts) {
|
|
|
4814
4864
|
const searchPathIsFile = statResult.stats.isFile();
|
|
4815
4865
|
try {
|
|
4816
4866
|
const effectiveLang = readSeekLanguageForPath(p.language, searchPath, searchPathIsFile);
|
|
4817
|
-
const results = await
|
|
4867
|
+
const results = await readSeekSearch(searchPath, {
|
|
4818
4868
|
pattern: p.pattern,
|
|
4819
4869
|
context: p.context,
|
|
4820
4870
|
selector: p.selector,
|
|
@@ -4878,7 +4928,7 @@ async function executeSearch(opts) {
|
|
|
4878
4928
|
}
|
|
4879
4929
|
function registerSearchTool(pi, options = {}) {
|
|
4880
4930
|
const tool = registerReadSeekTool(pi, {
|
|
4881
|
-
name: "
|
|
4931
|
+
name: "readSeek_search",
|
|
4882
4932
|
label: "Structural Search",
|
|
4883
4933
|
description: SEARCH_PROMPT_METADATA.description,
|
|
4884
4934
|
promptSnippet: SEARCH_PROMPT_METADATA.promptSnippet,
|
|
@@ -4898,14 +4948,14 @@ function registerSearchTool(pi, options = {}) {
|
|
|
4898
4948
|
},
|
|
4899
4949
|
renderCall(args, theme, ...rest) {
|
|
4900
4950
|
return renderReadSeekSearchCall(args, theme, rest, {
|
|
4901
|
-
label: "
|
|
4951
|
+
label: "readSeek_search",
|
|
4902
4952
|
accent: `/${args.pattern ?? args.context ?? args.rule}/`,
|
|
4903
4953
|
flags: [args.gitScope && `git-scope=${args.gitScope}`]
|
|
4904
4954
|
});
|
|
4905
4955
|
},
|
|
4906
4956
|
renderResult(result, options, theme, ...rest) {
|
|
4907
4957
|
return renderAnchoredFilesResult(result, options, theme, rest, {
|
|
4908
|
-
pendingLabel: "pending
|
|
4958
|
+
pendingLabel: "pending readSeek_search",
|
|
4909
4959
|
emptyLabel: "no matches",
|
|
4910
4960
|
unitSingular: "match",
|
|
4911
4961
|
unitPlural: "matches"
|
|
@@ -4948,7 +4998,7 @@ function buildRefsOutput(input) {
|
|
|
4948
4998
|
|
|
4949
4999
|
// src/refs.ts
|
|
4950
5000
|
var REFS_PROMPT_METADATA = defineToolPromptMetadata({
|
|
4951
|
-
toolName: "
|
|
5001
|
+
toolName: "refs",
|
|
4952
5002
|
promptSnippet: "Find references by identifier name or cursor binding"
|
|
4953
5003
|
});
|
|
4954
5004
|
function refsLine(reference) {
|
|
@@ -4990,7 +5040,7 @@ async function executeRefs(opts) {
|
|
|
4990
5040
|
if (!statResult.ok)
|
|
4991
5041
|
return statResult.error;
|
|
4992
5042
|
try {
|
|
4993
|
-
const references = await
|
|
5043
|
+
const references = await readSeekRefs(searchPath, {
|
|
4994
5044
|
name: p.name,
|
|
4995
5045
|
at: p.at,
|
|
4996
5046
|
language: p.language,
|
|
@@ -5020,7 +5070,7 @@ async function executeRefs(opts) {
|
|
|
5020
5070
|
}
|
|
5021
5071
|
function registerRefsTool(pi, options = {}) {
|
|
5022
5072
|
const tool = registerReadSeekTool(pi, {
|
|
5023
|
-
name: "
|
|
5073
|
+
name: "readSeek_refs",
|
|
5024
5074
|
label: "References",
|
|
5025
5075
|
description: REFS_PROMPT_METADATA.description,
|
|
5026
5076
|
promptSnippet: REFS_PROMPT_METADATA.promptSnippet,
|
|
@@ -5038,14 +5088,14 @@ function registerRefsTool(pi, options = {}) {
|
|
|
5038
5088
|
renderCall(args, theme, ...rest) {
|
|
5039
5089
|
const accent = args.name ?? args.at ?? "?";
|
|
5040
5090
|
return renderReadSeekSearchCall(args, theme, rest, {
|
|
5041
|
-
label: "
|
|
5091
|
+
label: "readSeek_refs",
|
|
5042
5092
|
accent,
|
|
5043
5093
|
flags: [args.at && "binding", args.gitScope && `git-scope=${args.gitScope}`]
|
|
5044
5094
|
});
|
|
5045
5095
|
},
|
|
5046
5096
|
renderResult(result, options, theme, ...rest) {
|
|
5047
5097
|
return renderAnchoredFilesResult(result, options, theme, rest, {
|
|
5048
|
-
pendingLabel: "pending
|
|
5098
|
+
pendingLabel: "pending readSeek_refs",
|
|
5049
5099
|
emptyLabel: "no references",
|
|
5050
5100
|
unitSingular: "reference",
|
|
5051
5101
|
unitPlural: "references"
|
|
@@ -5060,7 +5110,7 @@ import { Type as Type8 } from "@sinclair/typebox";
|
|
|
5060
5110
|
import path8 from "node:path";
|
|
5061
5111
|
import { Text as Text5 } from "@earendil-works/pi-tui";
|
|
5062
5112
|
var RENAME_PROMPT_METADATA = defineToolPromptMetadata({
|
|
5063
|
-
toolName: "
|
|
5113
|
+
toolName: "rename",
|
|
5064
5114
|
promptSnippet: "Rename a symbol at a source location with verified edits"
|
|
5065
5115
|
});
|
|
5066
5116
|
var renameSchema = Type8.Object({
|
|
@@ -5076,12 +5126,12 @@ async function executeRename(opts) {
|
|
|
5076
5126
|
if (!p.to.trim()) {
|
|
5077
5127
|
return buildToolErrorResult("rename", "invalid-parameter", "rename parameter 'to' must not be empty");
|
|
5078
5128
|
}
|
|
5079
|
-
if (typeof p.at !== "string" || !/^(line:[1-9][0-9]*|hash:[0-9a-fA-F]
|
|
5080
|
-
return buildToolErrorResult("
|
|
5129
|
+
if (typeof p.at !== "string" || !/^(line:[1-9][0-9]*|hash:[0-9a-fA-F]+|[1-9][0-9]*|[0-9a-fA-F]{6})(:[1-9][0-9]*)?$/.test(p.at)) {
|
|
5130
|
+
return buildToolErrorResult("rename", "invalid-parameter", "at must be a line or hash location with an optional positive column");
|
|
5081
5131
|
}
|
|
5082
5132
|
const filePath = resolveToCwd(p.path, cwd);
|
|
5083
5133
|
try {
|
|
5084
|
-
const output = await
|
|
5134
|
+
const output = await readSeekRename(filePath, {
|
|
5085
5135
|
to: p.to,
|
|
5086
5136
|
at: p.at,
|
|
5087
5137
|
workspace: p.workspace ? cwd : undefined,
|
|
@@ -5138,7 +5188,7 @@ First conflict at ${firstConflict.line}:${firstConflict.column}: ${firstConflict
|
|
|
5138
5188
|
}
|
|
5139
5189
|
function registerRenameTool(pi, options = {}) {
|
|
5140
5190
|
registerReadSeekTool(pi, {
|
|
5141
|
-
name: "
|
|
5191
|
+
name: "readSeek_rename",
|
|
5142
5192
|
label: "Rename",
|
|
5143
5193
|
description: RENAME_PROMPT_METADATA.description,
|
|
5144
5194
|
promptSnippet: RENAME_PROMPT_METADATA.promptSnippet,
|
|
@@ -5151,7 +5201,7 @@ function registerRenameTool(pi, options = {}) {
|
|
|
5151
5201
|
const context = rest[0] ?? {};
|
|
5152
5202
|
const cwd = context.cwd ?? process.cwd();
|
|
5153
5203
|
const displayPath = typeof args?.path === "string" ? args.path : "?";
|
|
5154
|
-
let text = theme.fg("toolTitle", theme.bold("
|
|
5204
|
+
let text = theme.fg("toolTitle", theme.bold("readSeek_rename"));
|
|
5155
5205
|
text += ` ${linkToolPath(theme.fg("accent", displayPath), displayPath, cwd)}`;
|
|
5156
5206
|
if (args?.to)
|
|
5157
5207
|
text += theme.fg("dim", ` → ${args.to}`);
|
|
@@ -5160,13 +5210,13 @@ function registerRenameTool(pi, options = {}) {
|
|
|
5160
5210
|
renderResult(result, options, theme, ...rest) {
|
|
5161
5211
|
const { isPartial, isError, expanded, cwd, width } = resolveRenderResultContext(options, rest);
|
|
5162
5212
|
if (isPartial)
|
|
5163
|
-
return renderPendingResult("pending
|
|
5213
|
+
return renderPendingResult("pending readSeek_rename", width, theme);
|
|
5164
5214
|
const content = result.content?.[0];
|
|
5165
5215
|
const textContent = content?.type === "text" ? content.text : "";
|
|
5166
5216
|
const readSeekValue = result.details?.readSeekValue;
|
|
5167
5217
|
const output = readSeekValue?.output;
|
|
5168
5218
|
if (isError || result.isError) {
|
|
5169
|
-
return renderErrorResult(textContent, { expanded, width, fallback: "
|
|
5219
|
+
return renderErrorResult(textContent, { expanded, width, fallback: "readSeek_rename failed", theme });
|
|
5170
5220
|
}
|
|
5171
5221
|
const outputs = output ? [output, ...output.others] : [];
|
|
5172
5222
|
const editCount = outputs.reduce((total, file) => total + file.edits.length, 0);
|
|
@@ -5404,7 +5454,7 @@ async function executeWrite(opts) {
|
|
|
5404
5454
|
const warnings = [];
|
|
5405
5455
|
const readSeekWarnings = [];
|
|
5406
5456
|
if (hasBareCarriageReturn(content)) {
|
|
5407
|
-
const message = "File content contains bare CR (\\r) line endings;
|
|
5457
|
+
const message = "File content contains bare CR (\\r) line endings; readSeek_write refuses to emit anchors that readSeek_show/readSeek_edit would normalize differently.";
|
|
5408
5458
|
warnings.push(message);
|
|
5409
5459
|
readSeekWarnings.push(buildReadSeekWarning("bare-cr", message));
|
|
5410
5460
|
return buildToolErrorResult("write", "bare-cr", `Cannot write ${filePath}
|
|
@@ -5483,9 +5533,9 @@ async function executeWrite(opts) {
|
|
|
5483
5533
|
};
|
|
5484
5534
|
}
|
|
5485
5535
|
function registerWriteTool(pi, options = {}) {
|
|
5486
|
-
const name = options.name ?? "
|
|
5536
|
+
const name = options.name ?? "readSeek_write";
|
|
5487
5537
|
const promptMetadata = defineToolPromptMetadata({
|
|
5488
|
-
toolName: "
|
|
5538
|
+
toolName: "write",
|
|
5489
5539
|
promptSnippet: "Create or replace a complete file with LINE:HASH anchors",
|
|
5490
5540
|
registeredName: name
|
|
5491
5541
|
});
|
|
@@ -5599,21 +5649,21 @@ function registerWriteTool(pi, options = {}) {
|
|
|
5599
5649
|
import { Type as Type10 } from "@sinclair/typebox";
|
|
5600
5650
|
import path9 from "node:path";
|
|
5601
5651
|
var DEF_PROMPT_METADATA = defineToolPromptMetadata({
|
|
5602
|
-
toolName: "
|
|
5652
|
+
toolName: "def",
|
|
5603
5653
|
promptSnippet: "Go to a symbol definition or declaration by name"
|
|
5604
5654
|
});
|
|
5605
5655
|
async function executeDef(opts) {
|
|
5606
5656
|
const { params, signal, cwd, onFileAnchored } = opts;
|
|
5607
5657
|
const p = params;
|
|
5608
5658
|
if (!p.name || !p.name.trim()) {
|
|
5609
|
-
return buildToolErrorResult("def", "invalid-parameter", "
|
|
5659
|
+
return buildToolErrorResult("def", "invalid-parameter", "readSeek_def requires 'name'");
|
|
5610
5660
|
}
|
|
5611
5661
|
const searchPath = resolveToCwd(p.path ?? ".", cwd);
|
|
5612
5662
|
const statResult = await statSearchPathOrError("def", p.path, searchPath);
|
|
5613
5663
|
if (!statResult.ok)
|
|
5614
5664
|
return statResult.error;
|
|
5615
5665
|
try {
|
|
5616
|
-
const definitions = await
|
|
5666
|
+
const definitions = await readSeekDef(searchPath, {
|
|
5617
5667
|
name: p.name,
|
|
5618
5668
|
language: p.language,
|
|
5619
5669
|
gitScope: p.gitScope,
|
|
@@ -5662,7 +5712,7 @@ async function executeDef(opts) {
|
|
|
5662
5712
|
}
|
|
5663
5713
|
function registerDefTool(pi, options = {}) {
|
|
5664
5714
|
registerReadSeekTool(pi, {
|
|
5665
|
-
name: "
|
|
5715
|
+
name: "readSeek_def",
|
|
5666
5716
|
label: "Definition",
|
|
5667
5717
|
description: DEF_PROMPT_METADATA.description,
|
|
5668
5718
|
promptSnippet: DEF_PROMPT_METADATA.promptSnippet,
|
|
@@ -5678,14 +5728,14 @@ function registerDefTool(pi, options = {}) {
|
|
|
5678
5728
|
},
|
|
5679
5729
|
renderCall(args, theme, ...rest) {
|
|
5680
5730
|
return renderReadSeekSearchCall(args, theme, rest, {
|
|
5681
|
-
label: "
|
|
5731
|
+
label: "readSeek_def",
|
|
5682
5732
|
accent: args.name,
|
|
5683
5733
|
flags: [args.gitScope && `git-scope=${args.gitScope}`]
|
|
5684
5734
|
});
|
|
5685
5735
|
},
|
|
5686
5736
|
renderResult(result, options, theme, ...rest) {
|
|
5687
5737
|
return renderAnchoredFilesResult(result, options, theme, rest, {
|
|
5688
|
-
pendingLabel: "pending
|
|
5738
|
+
pendingLabel: "pending readSeek_def",
|
|
5689
5739
|
emptyLabel: "no definitions",
|
|
5690
5740
|
unitSingular: "definition",
|
|
5691
5741
|
unitPlural: "definitions"
|
|
@@ -5699,32 +5749,32 @@ import { Text as Text7, wrapTextWithAnsi as wrapTextWithAnsi2 } from "@earendil-
|
|
|
5699
5749
|
import { Type as Type11 } from "@sinclair/typebox";
|
|
5700
5750
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
5701
5751
|
var operations = {
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5752
|
+
show: readSeekShow,
|
|
5753
|
+
tree: readSeekTree,
|
|
5754
|
+
meta: readSeekMeta,
|
|
5755
|
+
assets: readSeekAssets,
|
|
5756
|
+
syntax: readSeekSyntax,
|
|
5757
|
+
check: readSeekCheck,
|
|
5758
|
+
caption: readSeekCaption,
|
|
5759
|
+
objects: readSeekObjects,
|
|
5760
|
+
ocr: readSeekOcr
|
|
5711
5761
|
};
|
|
5712
5762
|
function resolveNonShowSummary(tool, envelope) {
|
|
5713
|
-
if (tool === "
|
|
5763
|
+
if (tool === "syntax") {
|
|
5714
5764
|
const errorCount = envelope?.diagnostics?.error_count ?? 0;
|
|
5715
5765
|
return errorCount === 0 ? "clean" : `${errorCount} syntax error${errorCount === 1 ? "" : "s"}`;
|
|
5716
5766
|
}
|
|
5717
|
-
if (tool === "
|
|
5767
|
+
if (tool === "check") {
|
|
5718
5768
|
const violations = Array.isArray(envelope?.violations) ? envelope.violations.length : 0;
|
|
5719
5769
|
return violations === 0 ? "clean" : `${violations} rule violation${violations === 1 ? "" : "s"}`;
|
|
5720
5770
|
}
|
|
5721
|
-
if (tool === "
|
|
5771
|
+
if (tool === "objects") {
|
|
5722
5772
|
const objects = Array.isArray(envelope?.objects) ? envelope.objects.length : 0;
|
|
5723
5773
|
return `${objects} object${objects === 1 ? "" : "s"}`;
|
|
5724
5774
|
}
|
|
5725
|
-
if (tool === "
|
|
5775
|
+
if (tool === "caption")
|
|
5726
5776
|
return "caption generated";
|
|
5727
|
-
if (tool === "
|
|
5777
|
+
if (tool === "ocr")
|
|
5728
5778
|
return "text recognized";
|
|
5729
5779
|
return "complete";
|
|
5730
5780
|
}
|
|
@@ -5799,7 +5849,7 @@ async function executeAccess(opts) {
|
|
|
5799
5849
|
if (key === "stdinName" || !Object.hasOwn(contract.inputSchema.properties, key))
|
|
5800
5850
|
return buildToolErrorResult(opts.tool, "invalid-parameter", `Unknown parameter: ${key}`);
|
|
5801
5851
|
}
|
|
5802
|
-
const path = p.path === undefined && opts.tool === "
|
|
5852
|
+
const path = p.path === undefined && opts.tool === "check" ? "." : p.path;
|
|
5803
5853
|
if (typeof path !== "string" || !path.trim())
|
|
5804
5854
|
return buildToolErrorResult(opts.tool, "invalid-parameter", "path is required");
|
|
5805
5855
|
if (path === "-")
|
|
@@ -5814,7 +5864,7 @@ async function executeAccess(opts) {
|
|
|
5814
5864
|
const content = [
|
|
5815
5865
|
{ type: "text", text: presentation ? formatShowResult(presentation) : JSON.stringify(envelope) }
|
|
5816
5866
|
];
|
|
5817
|
-
if (opts.tool === "
|
|
5867
|
+
if (opts.tool === "show" || opts.tool === "assets") {
|
|
5818
5868
|
for (const [imagePath, mimeType] of imagePaths(envelope)) {
|
|
5819
5869
|
if (opts.imageMode === "off")
|
|
5820
5870
|
content.push({ type: "text", text: `Image available at ${imagePath}; image attachments are disabled by readseek.imageMode.` });
|
|
@@ -5832,7 +5882,7 @@ async function executeAccess(opts) {
|
|
|
5832
5882
|
}
|
|
5833
5883
|
function registerAccessTools(pi, options = {}) {
|
|
5834
5884
|
for (const name of Object.keys(operations)) {
|
|
5835
|
-
const registeredName = name === "
|
|
5885
|
+
const registeredName = name === "show" ? options.name ?? `readSeek_${name}` : `readSeek_${name}`;
|
|
5836
5886
|
const contract = getToolContract(name);
|
|
5837
5887
|
const metadata = defineToolPromptMetadata({
|
|
5838
5888
|
toolName: name,
|
|
@@ -5919,37 +5969,37 @@ class SessionAnchors {
|
|
|
5919
5969
|
|
|
5920
5970
|
// index.ts
|
|
5921
5971
|
var READSEEK_TOOL_ENTRIES = [
|
|
5922
|
-
{ builtIn: "edit", readSeekName: "
|
|
5923
|
-
{ builtIn: "grep", readSeekName: "
|
|
5924
|
-
{ builtIn: null, readSeekName: "
|
|
5925
|
-
{ builtIn: null, readSeekName: "
|
|
5926
|
-
{ builtIn: null, readSeekName: "
|
|
5927
|
-
{ builtIn: "write", readSeekName: "
|
|
5928
|
-
{ builtIn: null, readSeekName: "
|
|
5929
|
-
{ builtIn: "read", readSeekName: "
|
|
5930
|
-
{ builtIn: null, readSeekName: "
|
|
5931
|
-
{ builtIn: null, readSeekName: "
|
|
5932
|
-
{ builtIn: null, readSeekName: "
|
|
5933
|
-
{ builtIn: null, readSeekName: "
|
|
5934
|
-
{ builtIn: null, readSeekName: "
|
|
5935
|
-
{ builtIn: null, readSeekName: "
|
|
5936
|
-
{ builtIn: null, readSeekName: "
|
|
5937
|
-
{ builtIn: null, readSeekName: "
|
|
5972
|
+
{ builtIn: "edit", readSeekName: "readSeek_edit" },
|
|
5973
|
+
{ builtIn: "grep", readSeekName: "readSeek_grep" },
|
|
5974
|
+
{ builtIn: null, readSeekName: "readSeek_search" },
|
|
5975
|
+
{ builtIn: null, readSeekName: "readSeek_refs" },
|
|
5976
|
+
{ builtIn: null, readSeekName: "readSeek_rename" },
|
|
5977
|
+
{ builtIn: "write", readSeekName: "readSeek_write" },
|
|
5978
|
+
{ builtIn: null, readSeekName: "readSeek_def" },
|
|
5979
|
+
{ builtIn: "read", readSeekName: "readSeek_show" },
|
|
5980
|
+
{ builtIn: null, readSeekName: "readSeek_tree" },
|
|
5981
|
+
{ builtIn: null, readSeekName: "readSeek_meta" },
|
|
5982
|
+
{ builtIn: null, readSeekName: "readSeek_assets" },
|
|
5983
|
+
{ builtIn: null, readSeekName: "readSeek_syntax" },
|
|
5984
|
+
{ builtIn: null, readSeekName: "readSeek_check" },
|
|
5985
|
+
{ builtIn: null, readSeekName: "readSeek_caption" },
|
|
5986
|
+
{ builtIn: null, readSeekName: "readSeek_objects" },
|
|
5987
|
+
{ builtIn: null, readSeekName: "readSeek_ocr" }
|
|
5938
5988
|
];
|
|
5939
5989
|
function piReadSeekExtension(pi) {
|
|
5940
5990
|
const sessionAnchors = new SessionAnchors;
|
|
5941
5991
|
const { settings } = resolveReadSeekJsonSettings();
|
|
5942
5992
|
const replacedBuiltIns = new Set(settings.overrideTools ?? []);
|
|
5943
5993
|
const swap = (builtIn, readSeekName) => replacedBuiltIns.has(builtIn) ? builtIn : readSeekName;
|
|
5944
|
-
const readName = swap("read", "
|
|
5945
|
-
const editName = swap("edit", "
|
|
5946
|
-
const writeName = swap("write", "
|
|
5947
|
-
const grepName = swap("grep", "
|
|
5994
|
+
const readName = swap("read", "readSeek_show");
|
|
5995
|
+
const editName = swap("edit", "readSeek_edit");
|
|
5996
|
+
const writeName = swap("write", "readSeek_write");
|
|
5997
|
+
const grepName = swap("grep", "readSeek_grep");
|
|
5948
5998
|
const toolAliases = {
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5999
|
+
readSeek_show: readName,
|
|
6000
|
+
readSeek_edit: editName,
|
|
6001
|
+
readSeek_grep: grepName,
|
|
6002
|
+
readSeek_write: writeName
|
|
5953
6003
|
};
|
|
5954
6004
|
const policyAliases = Object.fromEntries(TOOL_NAMES.map((name) => {
|
|
5955
6005
|
const readSeekName = `readSeek_${name}`;
|