pi-readseek 0.11.2 → 0.11.3

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.
Files changed (2) hide show
  1. package/dist/index.ts +102 -82
  2. package/package.json +3 -3
package/dist/index.ts CHANGED
@@ -39,7 +39,6 @@ var PARAM_DESCRIPTIONS = {
39
39
  projectSearchPath: "File or directory to search; defaults to the project directory",
40
40
  searchPath: "File or directory to search; defaults to the current directory",
41
41
  language: "Language override when auto-detection is ambiguous",
42
- languageOverride: "Language override",
43
42
  languageSymbol: "Language override for symbol replacement",
44
43
  pattern: "AST pattern (ast-grep style), such as console.log($$$ARGS)",
45
44
  patternContext: "Surrounding code context for sub-statement patterns",
@@ -56,14 +55,10 @@ var PARAM_DESCRIPTIONS = {
56
55
  end: "Last line to include",
57
56
  limit: "Maximum number of lines to include",
58
57
  depth: "Maximum structural depth for structure output; defaults to 1 in agent tools",
59
- offset: "One-based starting line",
60
- readLimit: "Maximum lines to return",
61
- symbolRead: "Symbol name to read",
62
- bundle: "Include related symbols from the same file; requires symbol",
63
58
  level: "Explicit inference level: low (default), medium, or high",
64
59
  include: "Additional caption tasks: text and/or objects",
65
60
  kind: "Restrict structure to this node kind",
66
- outline: "Return a symbol outline",
61
+ outline: "Show outline of document hierarchy or source symbols",
67
62
  noAnchors: "Omit source line anchors",
68
63
  text: "Literal native text query; adapter find_text also supports regex via pattern",
69
64
  edits: "Use set_line, replace_lines, insert_after, replace_symbol, or replace",
@@ -119,11 +114,14 @@ var TOOL_DESCRIPTIONS = {
119
114
  rename_symbol: "Rename a symbol at a line or hash cursor with binding-aware edits and stale-plan protection.",
120
115
  write_file: "Create or replace a complete text file and return `LINE:HASH` anchors. Use `edit_text` for small changes."
121
116
  };
117
+ function rewriteBacktickedToolNames(text, aliases = {}) {
118
+ return TOOL_NAMES.reduce((rewritten, toolName) => rewritten.replaceAll(`\`${toolName}\``, `\`${aliases[toolName] ?? toolName}\``), text);
119
+ }
122
120
  function renderToolDescription(name, aliases = {}) {
123
121
  const desc = TOOL_DESCRIPTIONS[name];
124
122
  if (!desc)
125
123
  throw new Error(`Missing TOOL_DESCRIPTIONS for ${name}`);
126
- return TOOL_NAMES.reduce((description, toolName) => description.replaceAll(`\`${toolName}\``, `\`${aliases[toolName] ?? toolName}\``), desc);
124
+ return rewriteBacktickedToolNames(desc, aliases);
127
125
  }
128
126
  var gitScopeSchema = {
129
127
  gitScope: {
@@ -212,7 +210,7 @@ var TOOL_CONTRACTS = [
212
210
  tool("show_metadata", "Show metadata", { ...path, ...lang, ...stdin }, ["path"]),
213
211
  tool("show_assets", "Show assets", { ...path, at: string(PARAM_DESCRIPTIONS.assetAt), ...stdin }, ["path"]),
214
212
  tool("check_syntax", "Check syntax", { ...path, ...lang, ...stdin }, ["path"]),
215
- tool("check_rules", "Check rules", { ...path, ...gitScopeSchema, rules: string(PARAM_DESCRIPTIONS.rules) }, ["rules"]),
213
+ tool("check_rules", "Check rules", { path: string(PARAM_DESCRIPTIONS.searchPath), ...gitScopeSchema, rules: string(PARAM_DESCRIPTIONS.rules) }, ["rules"]),
216
214
  tool("generate_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"]),
217
215
  tool("detect_objects", "Detect objects", { ...path, ...at, ...stdin, ...level }, ["path"]),
218
216
  tool("recognize_text", "Recognize text", { ...path, ...at, ...stdin, ...level }, ["path"]),
@@ -276,9 +274,6 @@ var TOOL_COMPACT_GUIDELINES = {
276
274
  function resolveToolName(name, aliases = {}) {
277
275
  return aliases[name] ?? name;
278
276
  }
279
- function rewriteBacktickedToolNames(text, aliases = {}) {
280
- return TOOL_NAMES.reduce((rewritten, toolName) => rewritten.replaceAll(`\`${toolName}\``, `\`${resolveToolName(toolName, aliases)}\``), text);
281
- }
282
277
  function renderCompactGuidelines(name, aliases = {}) {
283
278
  return (TOOL_COMPACT_GUIDELINES[name] ?? []).map((guideline) => rewriteBacktickedToolNames(guideline, aliases));
284
279
  }
@@ -293,15 +288,6 @@ function renderToolRoutingPolicy(options = {}) {
293
288
  const find_references = resolveToolName("find_references", aliases);
294
289
  const rename_symbol = resolveToolName("rename_symbol", aliases);
295
290
  const show_assets = resolveToolName("show_assets", aliases);
296
- if (options.style === "server") {
297
- return [
298
- "Structural code navigation, document inspection, and hash-verified edits with readseek.",
299
- "For structural questions, prefer these tools to text Grep/Bash: targeted definitions, references, and AST patterns; shallow show_structure views; check_syntax diagnostics and show_content cursor context; and document inspection.",
300
- `Use ${edit_text} for LINE:HASH-anchored mutations (preview with apply=false; apply defaults to true and re-checks plan_hash).`,
301
- "Paths resolve against CLAUDE_PROJECT_DIR. Native Read/Grep/Edit hooks provide passive context;",
302
- "call MCP tools for active navigation, document questions, or anchored edits."
303
- ].join(" ");
304
- }
305
291
  const title = options.title ?? "ReadSeek tool policy:";
306
292
  const bullets = [];
307
293
  if (options.preferOverBuiltIns) {
@@ -404,8 +390,38 @@ function validateExactlyOneEditVariant(edits) {
404
390
  }
405
391
  return { ok: true, edits: normalized };
406
392
  }
393
+ var BASE10_INT_RE = /^-?\d+$/;
407
394
  var MIN_SAFE_INTEGER = BigInt(Number.MIN_SAFE_INTEGER);
408
395
  var MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
396
+ function formatReceived(value) {
397
+ if (typeof value === "number" || typeof value === "bigint")
398
+ return String(value);
399
+ return JSON.stringify(value) ?? String(value);
400
+ }
401
+ function invalidInteger(value, name) {
402
+ return {
403
+ ok: false,
404
+ message: `Invalid ${name}: expected a safe base-10 integer, received ${formatReceived(value)}.`
405
+ };
406
+ }
407
+ function coerceObviousBase10Int(value, name) {
408
+ if (value === undefined || typeof value === "string" && value.trim() === "") {
409
+ return { ok: true, value: undefined };
410
+ }
411
+ if (typeof value === "number") {
412
+ if (Number.isSafeInteger(value)) {
413
+ return { ok: true, value };
414
+ }
415
+ return invalidInteger(value, name);
416
+ }
417
+ if (typeof value === "string" && BASE10_INT_RE.test(value)) {
418
+ const parsed = BigInt(value);
419
+ if (parsed >= MIN_SAFE_INTEGER && parsed <= MAX_SAFE_INTEGER) {
420
+ return { ok: true, value: Number(parsed) };
421
+ }
422
+ }
423
+ return invalidInteger(value, name);
424
+ }
409
425
  // ../readseek-api/src/argv.ts
410
426
  var DEFAULT_STRUCTURE_DEPTH = 1;
411
427
  function appendGitScopeArgs(args, input) {
@@ -1262,10 +1278,10 @@ function text(value) {
1262
1278
  function count(value) {
1263
1279
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
1264
1280
  }
1265
- function safe(value) {
1281
+ function safe(value, preserveTabs = false) {
1266
1282
  return value.replace(/[\x00-\x09\x0b-\x1f\x7f-\x9f]/g, (char) => {
1267
1283
  if (char === "\t")
1268
- return "\\t";
1284
+ return preserveTabs ? char : "\\t";
1269
1285
  if (char === "\r")
1270
1286
  return "\\r";
1271
1287
  return `\\x${char.charCodeAt(0).toString(16).padStart(2, "0")}`;
@@ -1425,7 +1441,7 @@ ${assetList(assets)}`);
1425
1441
  const lang = text(metadata.language || content.language);
1426
1442
  if (lang)
1427
1443
  summary.push(inline(lang));
1428
- const rows = lines.map((line) => `${line.line}${options.noAnchors ? "" : `:${text(line.hash)}`} | ${safe(text(line.text)).replaceAll("\\n", "\\\\n")}`);
1444
+ const rows = lines.map((line) => `${line.line}${options.noAnchors ? "" : `:${text(line.hash)}`} | ${safe(text(line.text), true)}`);
1429
1445
  const identifier = record(cursor.identifier);
1430
1446
  if (count(cursor.line) !== undefined)
1431
1447
  result.metadata.line = cursor.line;
@@ -1524,6 +1540,23 @@ function resolveReadSeekBinaryFromPackages(resolver = resolveFromPackage, option
1524
1540
  accessSync(binaryPath, fsConstants.X_OK);
1525
1541
  return binaryPath;
1526
1542
  }
1543
+ // ../readseek-api/src/path.ts
1544
+ import { homedir } from "node:os";
1545
+ import path3 from "node:path";
1546
+ var UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
1547
+ function expandUserPath(filePath, homedirFn = homedir) {
1548
+ const withoutAt = filePath.startsWith("@") ? filePath.slice(1) : filePath;
1549
+ const normalized = withoutAt.replace(UNICODE_SPACES, " ");
1550
+ if (normalized === "~")
1551
+ return homedirFn();
1552
+ if (normalized.startsWith("~/"))
1553
+ return homedirFn() + normalized.slice(1);
1554
+ return normalized;
1555
+ }
1556
+ function resolveToCwd(filePath, cwd, homedirFn = homedir) {
1557
+ const expanded = expandUserPath(filePath, homedirFn);
1558
+ return path3.isAbsolute(expanded) ? expanded : path3.resolve(cwd, expanded);
1559
+ }
1527
1560
  // ../readseek-api/src/error.ts
1528
1561
  var READSEEK_USAGE_HINT = /(?:^|\n)\s*Run readseek(?: [\w-]+)* --help for more information\.?\s*$/;
1529
1562
  function cleanReadSeekErrorText(stderr) {
@@ -2013,8 +2046,7 @@ function descriptionAliases(toolName, registeredName, toolAliases) {
2013
2046
  }));
2014
2047
  }
2015
2048
  function defineToolPromptMetadata(options) {
2016
- const fileName = promptFileName(options.promptUrl);
2017
- const toolName = toolNameFromPrompt(fileName);
2049
+ const toolName = options.toolName ?? toolNameFromPrompt(promptFileName(options.promptUrl));
2018
2050
  const replaceable = REPLACEABLE_BY_TOOL.get(toolName);
2019
2051
  const defaultReadSeekName = `readSeek_${toolName}`;
2020
2052
  const registeredName = options.registeredName ?? (replaceable ? defaultReadSeekName : undefined);
@@ -2221,13 +2253,6 @@ function generateCompactOrFullDiff(oldContent, newContent, contextLines = 4) {
2221
2253
  }
2222
2254
  return generateDiffString(oldContent, newContent, contextLines);
2223
2255
  }
2224
-
2225
- // src/path-utils.ts
2226
- import {
2227
- expandUserPath as expandUserPath2,
2228
- resolveToCwd as resolveToCwd2
2229
- } from "@jarkkojs/readseek-api";
2230
-
2231
2256
  // src/runtime.ts
2232
2257
  function throwIfAborted(signal) {
2233
2258
  if (signal?.aborted)
@@ -2558,12 +2583,12 @@ function classifyEdit(oldContent, newContent) {
2558
2583
  // src/readseek-client.ts
2559
2584
  import { existsSync as existsSync2, statSync as statSync3 } from "node:fs";
2560
2585
  import { createRequire as createRequire2 } from "node:module";
2561
- import { homedir as homedir2 } from "node:os";
2562
- import path3 from "node:path";
2586
+ import { homedir as homedir3 } from "node:os";
2587
+ import path4 from "node:path";
2563
2588
 
2564
2589
  // src/readseek-settings.ts
2565
2590
  import { readFileSync, statSync as statSync2 } from "node:fs";
2566
- import { homedir } from "node:os";
2591
+ import { homedir as homedir2 } from "node:os";
2567
2592
  import { join } from "node:path";
2568
2593
  var READSEEK_TOOL_REPLACEMENTS = {
2569
2594
  read: "readSeek_show_content",
@@ -2750,7 +2775,7 @@ function mergeSettings(base, override) {
2750
2775
  return settings;
2751
2776
  }
2752
2777
  function resolveReadSeekJsonSettings() {
2753
- const globalResult = readSettingsFile(join(homedir(), ".pi/agent/settings.json"));
2778
+ const globalResult = readSettingsFile(join(homedir2(), ".pi/agent/settings.json"));
2754
2779
  const projectResult = readSettingsFile(join(process.cwd(), ".pi/settings.json"));
2755
2780
  return {
2756
2781
  settings: mergeSettings(globalResult.settings, projectResult.settings),
@@ -2785,8 +2810,8 @@ function readSeekBinaryAvailability() {
2785
2810
  }
2786
2811
  var defaultReadSeekDirInit;
2787
2812
  function defaultReadSeekDir() {
2788
- const home = homedir2();
2789
- return home ? path3.join(home, ".pi", "readseek") : null;
2813
+ const home = homedir3();
2814
+ return home ? path4.join(home, ".pi", "readseek") : null;
2790
2815
  }
2791
2816
  function directoryExists(dir) {
2792
2817
  try {
@@ -2811,11 +2836,11 @@ async function ensureDefaultReadSeekDir() {
2811
2836
  return defaultReadSeekDirInit;
2812
2837
  }
2813
2838
  function hasProjectReadSeekDir(cwd = process.cwd()) {
2814
- let dir = path3.resolve(cwd);
2839
+ let dir = path4.resolve(cwd);
2815
2840
  while (true) {
2816
- if (existsSync2(path3.join(dir, ".readseek")))
2841
+ if (existsSync2(path4.join(dir, ".readseek")))
2817
2842
  return true;
2818
- const parent = path3.dirname(dir);
2843
+ const parent = path4.dirname(dir);
2819
2844
  if (parent === dir)
2820
2845
  return false;
2821
2846
  dir = parent;
@@ -3212,7 +3237,7 @@ function linkToolPath(styledText, rawPath, cwd) {
3212
3237
  try {
3213
3238
  if (!getCapabilities().hyperlinks)
3214
3239
  return styledText;
3215
- const absolutePath = resolveToCwd2(rawPath, cwd);
3240
+ const absolutePath = resolveToCwd(rawPath, cwd);
3216
3241
  return hyperlink(styledText, pathToFileURL(absolutePath).href);
3217
3242
  } catch {
3218
3243
  return styledText;
@@ -3614,7 +3639,7 @@ async function executeEdit(opts) {
3614
3639
  const parsed = params;
3615
3640
  const rawPath = parsed.path;
3616
3641
  const path = rawPath.replace(/^@/, "");
3617
- const absolutePath = resolveToCwd2(path, cwd);
3642
+ const absolutePath = resolveToCwd(path, cwd);
3618
3643
  throwIfAborted(signal);
3619
3644
  try {
3620
3645
  return await withFileMutationQueue(absolutePath, async () => {
@@ -3736,7 +3761,7 @@ async function executeEdit(opts) {
3736
3761
  function registerEditTool(pi, options = {}) {
3737
3762
  const name = options.name ?? "readSeek_edit_text";
3738
3763
  const promptMetadata = defineToolPromptMetadata({
3739
- promptUrl: new URL("../prompts/edit_text.md", import.meta.url),
3764
+ toolName: "edit_text",
3740
3765
  promptSnippet: "Edit existing files with fresh LINE:HASH anchors",
3741
3766
  registeredName: name,
3742
3767
  toolAliases: options.toolAliases
@@ -3833,7 +3858,7 @@ ${theme.fg("error", info.errorText)}`;
3833
3858
 
3834
3859
  // src/grep.ts
3835
3860
  import { readFile as fsReadFile2, stat as fsStat } from "node:fs/promises";
3836
- import path4 from "node:path";
3861
+ import path5 from "node:path";
3837
3862
  import { createGrepTool } from "@earendil-works/pi-coding-agent";
3838
3863
  import { Type as Type5 } from "@sinclair/typebox";
3839
3864
  import { Text as Text4 } from "@earendil-works/pi-tui";
@@ -4200,12 +4225,6 @@ function formatGrepResultText(input) {
4200
4225
  errorText: undefined
4201
4226
  };
4202
4227
  }
4203
-
4204
- // src/coerce-obvious-int.ts
4205
- import {
4206
- coerceObviousBase10Int
4207
- } from "@jarkkojs/readseek-api";
4208
-
4209
4228
  // src/tui-source-render.ts
4210
4229
  var GREP_ANCHOR_RE = /^(.*?):(>>| )(\d+):([0-9a-zA-Z]{1,16})\|(.*)$/;
4211
4230
  function renderGrepSourceForDisplay(text, anchors, renderPath = (path) => path) {
@@ -4365,7 +4384,7 @@ async function executeGrep(opts) {
4365
4384
  if (!textBlock?.text)
4366
4385
  return result;
4367
4386
  const { path: rawSearchPath } = p;
4368
- const searchPath = resolveToCwd2(rawSearchPath || ".", cwd);
4387
+ const searchPath = resolveToCwd(rawSearchPath || ".", cwd);
4369
4388
  let searchPathIsDirectory = false;
4370
4389
  try {
4371
4390
  searchPathIsDirectory = (await fsStat(searchPath)).isDirectory();
@@ -4419,7 +4438,7 @@ async function executeGrep(opts) {
4419
4438
  };
4420
4439
  const toAbsolutePath = (displayPath) => {
4421
4440
  if (searchPathIsDirectory)
4422
- return path4.resolve(searchPath, displayPath);
4441
+ return path5.resolve(searchPath, displayPath);
4423
4442
  return searchPath;
4424
4443
  };
4425
4444
  const groupsByPath = new Map;
@@ -4609,7 +4628,7 @@ ${warning}` } : item),
4609
4628
  function registerGrepTool(pi, options = {}) {
4610
4629
  const name = options.name ?? "readSeek_find_text";
4611
4630
  const promptMetadata = defineToolPromptMetadata({
4612
- promptUrl: new URL("../prompts/find_text.md", import.meta.url),
4631
+ toolName: "find_text",
4613
4632
  promptSnippet: "Search text or regex with edit-ready LINE:HASH anchors",
4614
4633
  registeredName: name
4615
4634
  });
@@ -4696,7 +4715,7 @@ function registerGrepTool(pi, options = {}) {
4696
4715
  }
4697
4716
 
4698
4717
  // src/search.ts
4699
- import path5 from "node:path";
4718
+ import path6 from "node:path";
4700
4719
  import { Type as Type6 } from "@sinclair/typebox";
4701
4720
 
4702
4721
  // src/stat-search-path.ts
@@ -4755,7 +4774,7 @@ function mergeRanges(ranges) {
4755
4774
  return merged;
4756
4775
  }
4757
4776
  var SEARCH_PROMPT_METADATA = defineToolPromptMetadata({
4758
- promptUrl: new URL("../prompts/find_nodes.md", import.meta.url),
4777
+ toolName: "find_nodes",
4759
4778
  promptSnippet: "Search code by AST structure using ast-grep-style patterns"
4760
4779
  });
4761
4780
  function linesFromSearchResult(result, ranges) {
@@ -4781,14 +4800,14 @@ function linesFromSearchResult(result, ranges) {
4781
4800
  return lines;
4782
4801
  }
4783
4802
  function readSeekLanguageForPath(language, searchPath, isFile) {
4784
- if (language === "typescript" && isFile && path5.extname(searchPath).toLowerCase() === ".tsx")
4803
+ if (language === "typescript" && isFile && path6.extname(searchPath).toLowerCase() === ".tsx")
4785
4804
  return "tsx";
4786
4805
  return language;
4787
4806
  }
4788
4807
  async function executeSearch(opts) {
4789
4808
  const { params, signal, cwd, onFileAnchored } = opts;
4790
4809
  const p = params;
4791
- const searchPath = resolveToCwd2(p.path ?? ".", cwd);
4810
+ const searchPath = resolveToCwd(p.path ?? ".", cwd);
4792
4811
  const statResult = await statSearchPathOrError("search", p.path, searchPath);
4793
4812
  if (!statResult.ok)
4794
4813
  return statResult.error;
@@ -4816,8 +4835,8 @@ async function executeSearch(opts) {
4816
4835
  }
4817
4836
  const readSeekFiles = [];
4818
4837
  for (const result of results) {
4819
- const abs = path5.isAbsolute(result.file) ? result.file : path5.resolve(cwd, result.file);
4820
- const display = path5.relative(cwd, abs) || abs;
4838
+ const abs = path6.isAbsolute(result.file) ? result.file : path6.resolve(cwd, result.file);
4839
+ const display = path6.relative(cwd, abs) || abs;
4821
4840
  const ranges = result.matches.map((match) => ({ startLine: match.start_line, endLine: match.end_line }));
4822
4841
  const mergedRanges = mergeRanges(ranges);
4823
4842
  const lines = linesFromSearchResult(result, mergedRanges);
@@ -4898,7 +4917,7 @@ function registerSearchTool(pi, options = {}) {
4898
4917
 
4899
4918
  // src/refs.ts
4900
4919
  import { Type as Type7 } from "@sinclair/typebox";
4901
- import path6 from "node:path";
4920
+ import path7 from "node:path";
4902
4921
 
4903
4922
  // src/refs-output.ts
4904
4923
  function refsQueryLabel(input) {
@@ -4929,7 +4948,7 @@ function buildRefsOutput(input) {
4929
4948
 
4930
4949
  // src/refs.ts
4931
4950
  var REFS_PROMPT_METADATA = defineToolPromptMetadata({
4932
- promptUrl: new URL("../prompts/find_references.md", import.meta.url),
4951
+ toolName: "find_references",
4933
4952
  promptSnippet: "Find references by identifier name or cursor binding"
4934
4953
  });
4935
4954
  function refsLine(reference) {
@@ -4942,14 +4961,14 @@ function groupReferences(references, cwd) {
4942
4961
  const files = new Map;
4943
4962
  const seen = new Set;
4944
4963
  for (const reference of references) {
4945
- const abs = path6.isAbsolute(reference.file) ? reference.file : path6.resolve(cwd, reference.file);
4964
+ const abs = path7.isAbsolute(reference.file) ? reference.file : path7.resolve(cwd, reference.file);
4946
4965
  const dedupeKey = `${abs}:${reference.line}:${reference.column}`;
4947
4966
  if (seen.has(dedupeKey))
4948
4967
  continue;
4949
4968
  seen.add(dedupeKey);
4950
4969
  let file = files.get(abs);
4951
4970
  if (!file) {
4952
- file = { displayPath: path6.relative(cwd, abs) || abs, path: abs, lines: [] };
4971
+ file = { displayPath: path7.relative(cwd, abs) || abs, path: abs, lines: [] };
4953
4972
  files.set(abs, file);
4954
4973
  }
4955
4974
  file.lines.push(refsLine(reference));
@@ -4966,7 +4985,7 @@ async function executeRefs(opts) {
4966
4985
  if (!scopeError.ok) {
4967
4986
  return buildToolErrorResult("refs", "invalid-parameter", `refs parameter: ${scopeError.error}`);
4968
4987
  }
4969
- const searchPath = resolveToCwd2(p.path ?? ".", cwd);
4988
+ const searchPath = resolveToCwd(p.path ?? ".", cwd);
4970
4989
  const statResult = await statSearchPathOrError("refs", p.path, searchPath);
4971
4990
  if (!statResult.ok)
4972
4991
  return statResult.error;
@@ -5038,10 +5057,10 @@ function registerRefsTool(pi, options = {}) {
5038
5057
 
5039
5058
  // src/rename.ts
5040
5059
  import { Type as Type8 } from "@sinclair/typebox";
5041
- import path7 from "node:path";
5060
+ import path8 from "node:path";
5042
5061
  import { Text as Text5 } from "@earendil-works/pi-tui";
5043
5062
  var RENAME_PROMPT_METADATA = defineToolPromptMetadata({
5044
- promptUrl: new URL("../prompts/rename_symbol.md", import.meta.url),
5063
+ toolName: "rename_symbol",
5045
5064
  promptSnippet: "Rename a symbol at a source location with verified edits"
5046
5065
  });
5047
5066
  var renameSchema = Type8.Object({
@@ -5060,7 +5079,7 @@ async function executeRename(opts) {
5060
5079
  if (typeof p.at !== "string" || !/^(line:[1-9][0-9]*|hash:[0-9a-fA-F]+)(:[1-9][0-9]*)?$/.test(p.at)) {
5061
5080
  return buildToolErrorResult("rename_symbol", "invalid-parameter", "at must be a line or hash location with an optional positive column");
5062
5081
  }
5063
- const filePath = resolveToCwd2(p.path, cwd);
5082
+ const filePath = resolveToCwd(p.path, cwd);
5064
5083
  try {
5065
5084
  const output = await readSeekRenameSymbol(filePath, {
5066
5085
  to: p.to,
@@ -5073,14 +5092,14 @@ async function executeRename(opts) {
5073
5092
  for (const file of [output, ...output.others]) {
5074
5093
  if (file.edits.length === 0)
5075
5094
  continue;
5076
- const absoluteFile = path7.isAbsolute(file.file) ? file.file : path7.resolve(cwd, file.file);
5095
+ const absoluteFile = path8.isAbsolute(file.file) ? file.file : path8.resolve(cwd, file.file);
5077
5096
  onFileMutated?.(absoluteFile);
5078
5097
  }
5079
5098
  }
5080
- const primaryAbs = path7.isAbsolute(output.file) ? output.file : path7.resolve(cwd, output.file);
5099
+ const primaryAbs = path8.isAbsolute(output.file) ? output.file : path8.resolve(cwd, output.file);
5081
5100
  const files = [primaryAbs];
5082
5101
  for (const other of output.others) {
5083
- const abs = path7.isAbsolute(other.file) ? other.file : path7.resolve(cwd, other.file);
5102
+ const abs = path8.isAbsolute(other.file) ? other.file : path8.resolve(cwd, other.file);
5084
5103
  if (!files.includes(abs))
5085
5104
  files.push(abs);
5086
5105
  }
@@ -5162,7 +5181,7 @@ function registerRenameTool(pi, options = {}) {
5162
5181
  });
5163
5182
  if (expanded && output) {
5164
5183
  for (const file of outputs) {
5165
- const display = path7.relative(cwd, file.file) || file.file;
5184
+ const display = path8.relative(cwd, file.file) || file.file;
5166
5185
  text += `
5167
5186
  ${linkedPathLine(theme, file.file, display, cwd, ` (${file.edits.length} edits)`, width)}`;
5168
5187
  }
@@ -5466,7 +5485,7 @@ async function executeWrite(opts) {
5466
5485
  function registerWriteTool(pi, options = {}) {
5467
5486
  const name = options.name ?? "readSeek_write_file";
5468
5487
  const promptMetadata = defineToolPromptMetadata({
5469
- promptUrl: new URL("../prompts/write_file.md", import.meta.url),
5488
+ toolName: "write_file",
5470
5489
  promptSnippet: "Create or replace a complete file with LINE:HASH anchors",
5471
5490
  registeredName: name
5472
5491
  });
@@ -5482,7 +5501,7 @@ function registerWriteTool(pi, options = {}) {
5482
5501
  }),
5483
5502
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
5484
5503
  const cwd = ctx?.cwd ?? process.cwd();
5485
- const absolutePath = resolveToCwd2(params.path, cwd);
5504
+ const absolutePath = resolveToCwd(params.path, cwd);
5486
5505
  try {
5487
5506
  return await withFileMutationQueue2(absolutePath, async () => {
5488
5507
  let result;
@@ -5578,9 +5597,9 @@ function registerWriteTool(pi, options = {}) {
5578
5597
 
5579
5598
  // src/def.ts
5580
5599
  import { Type as Type10 } from "@sinclair/typebox";
5581
- import path8 from "node:path";
5600
+ import path9 from "node:path";
5582
5601
  var DEF_PROMPT_METADATA = defineToolPromptMetadata({
5583
- promptUrl: new URL("../prompts/find_definitions.md", import.meta.url),
5602
+ toolName: "find_definitions",
5584
5603
  promptSnippet: "Go to a symbol definition or declaration by name"
5585
5604
  });
5586
5605
  async function executeDef(opts) {
@@ -5589,7 +5608,7 @@ async function executeDef(opts) {
5589
5608
  if (!p.name || !p.name.trim()) {
5590
5609
  return buildToolErrorResult("def", "invalid-parameter", "readSeek_find_definitions requires 'name'");
5591
5610
  }
5592
- const searchPath = resolveToCwd2(p.path ?? ".", cwd);
5611
+ const searchPath = resolveToCwd(p.path ?? ".", cwd);
5593
5612
  const statResult = await statSearchPathOrError("def", p.path, searchPath);
5594
5613
  if (!statResult.ok)
5595
5614
  return statResult.error;
@@ -5610,10 +5629,10 @@ async function executeDef(opts) {
5610
5629
  }
5611
5630
  const files = new Map;
5612
5631
  for (const def of definitions) {
5613
- const abs = path8.isAbsolute(def.file) ? def.file : path8.resolve(cwd, def.file);
5632
+ const abs = path9.isAbsolute(def.file) ? def.file : path9.resolve(cwd, def.file);
5614
5633
  let file = files.get(abs);
5615
5634
  if (!file) {
5616
- file = { displayPath: path8.relative(cwd, abs) || abs, path: abs, lines: [] };
5635
+ file = { displayPath: path9.relative(cwd, abs) || abs, path: abs, lines: [] };
5617
5636
  files.set(abs, file);
5618
5637
  }
5619
5638
  file.lines.push(buildReadSeekLineWithHash(def.line, def.line_hash, def.text));
@@ -5785,7 +5804,7 @@ async function executeAccess(opts) {
5785
5804
  return buildToolErrorResult(opts.tool, "invalid-parameter", "path is required");
5786
5805
  if (path === "-")
5787
5806
  return buildToolErrorResult(opts.tool, "invalid-parameter", "Agent tools require a file path; stdin is available through the CLI or API");
5788
- const filePath = resolveToCwd2(path, opts.cwd);
5807
+ const filePath = resolveToCwd(path, opts.cwd);
5789
5808
  try {
5790
5809
  const { path: _path, ...options } = p;
5791
5810
  const envelope = await operations[opts.tool](filePath, { ...options, signal: opts.signal });
@@ -5816,7 +5835,7 @@ function registerAccessTools(pi, options = {}) {
5816
5835
  const registeredName = name === "show_content" ? options.name ?? `readSeek_${name}` : `readSeek_${name}`;
5817
5836
  const contract = getToolContract(name);
5818
5837
  const metadata = defineToolPromptMetadata({
5819
- promptUrl: new URL(`../prompts/${name}.md`, import.meta.url),
5838
+ toolName: name,
5820
5839
  promptSnippet: contract.title,
5821
5840
  registeredName,
5822
5841
  toolAliases: options.toolAliases
@@ -5872,7 +5891,8 @@ function registerAccessTools(pi, options = {}) {
5872
5891
  }
5873
5892
  const nonShowSummary = resolveNonShowSummary(name, envelope);
5874
5893
  const summary = summaryLine(nonShowSummary, { hidden: !!text && !expanded, theme, style: "success" });
5875
- return new Text7(clampLinesToWidth((expanded ? `${summary}\\n${text}` : summary).split(`
5894
+ return new Text7(clampLinesToWidth((expanded ? `${summary}
5895
+ ${text}` : summary).split(`
5876
5896
  `), width).join(`
5877
5897
  `), 0, 0);
5878
5898
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-readseek",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Pi extension for LINE:HASH-anchored file operations and structural code navigation",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,8 +39,8 @@
39
39
  "node": ">=20.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@jarkkojs/readseek": "^0.11.2",
43
- "@jarkkojs/readseek-api": "^0.11.2",
42
+ "@jarkkojs/readseek": "^0.11.3",
43
+ "@jarkkojs/readseek-api": "^0.11.3",
44
44
  "diff": "^9.0.0",
45
45
  "xxhash-wasm": "^1.1.0"
46
46
  },