pi-readseek 0.5.7 → 0.5.9

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/index.ts CHANGED
@@ -68,9 +68,15 @@ export default function piReadSeekExtension(pi: ExtensionAPI): void {
68
68
  const editName = swap("edit", "readSeek_edit");
69
69
  const writeName = swap("write", "readSeek_write");
70
70
  const grepName = swap("grep", "readSeek_grep");
71
+ const toolAliases = {
72
+ readSeek_read: readName,
73
+ readSeek_edit: editName,
74
+ readSeek_grep: grepName,
75
+ readSeek_write: writeName,
76
+ };
71
77
 
72
78
  registerReadTool(pi, { onSuccessfulRead: markAnchored, name: readName });
73
- registerEditTool(pi, { wasReadInSession: hasFreshAnchors, name: editName });
79
+ registerEditTool(pi, { wasReadInSession: hasFreshAnchors, name: editName, toolAliases });
74
80
  registerGrepTool(pi, { onFileAnchored: markAnchored, name: grepName });
75
81
  registerSgTool(pi, { onFileAnchored: markAnchored });
76
82
  registerRefsTool(pi, { onFileAnchored: markAnchored });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-readseek",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "Pi extension for readseek-backed hash-anchored read/edit/grep, structural code maps, structural search, and file exploration",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,7 +39,7 @@
39
39
  "node": ">=20.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@jarkkojs/readseek": "^0.5.1",
42
+ "@jarkkojs/readseek": "^0.5.2",
43
43
  "diff": "^8.0.3",
44
44
  "xxhash-wasm": "^1.1.0"
45
45
  },
package/src/def.ts CHANGED
@@ -15,7 +15,7 @@ import type { FileAnchoredCallback } from "./tool-types.js";
15
15
 
16
16
  const DEF_PROMPT_METADATA = defineToolPromptMetadata({
17
17
  promptUrl: new URL("../prompts/def.md", import.meta.url),
18
- promptSnippet: "Find structural symbol definitions with readseek",
18
+ promptSnippet: "Find structural definitions for a symbol",
19
19
  });
20
20
 
21
21
  type DefParams = {
package/src/edit.ts CHANGED
@@ -69,10 +69,6 @@ const hashlineEditSchema = Type.Object(
69
69
 
70
70
  type HashlineParams = Static<typeof hashlineEditSchema>;
71
71
 
72
- const EDIT_PROMPT_METADATA = defineToolPromptMetadata({
73
- promptUrl: new URL("../prompts/edit.md", import.meta.url),
74
- promptSnippet: "Edit files using hash-verified anchors from readSeek_read/readSeek_grep/readSeek_search/readSeek_write",
75
- });
76
72
 
77
73
  function buildEditError(
78
74
  path: string,
@@ -111,6 +107,7 @@ export interface EditToolOptions {
111
107
  wasReadInSession?: FreshAnchorsPredicate;
112
108
  syntaxValidate?: SyntaxValidateOptions["syntaxValidate"];
113
109
  name?: string;
110
+ toolAliases?: Readonly<Record<string, string>>;
114
111
  }
115
112
 
116
113
  export interface ExecuteEditOptions {
@@ -565,12 +562,19 @@ export async function executeEdit(opts: ExecuteEditOptions): Promise<any> {
565
562
 
566
563
 
567
564
  export function registerEditTool(pi: ExtensionAPI, options: EditToolOptions = {}) {
565
+ const name = options.name ?? "readSeek_edit";
566
+ const promptMetadata = defineToolPromptMetadata({
567
+ promptUrl: new URL("../prompts/edit.md", import.meta.url),
568
+ promptSnippet: "Edit with fresh hash-verified anchors",
569
+ registeredName: name,
570
+ toolAliases: options.toolAliases,
571
+ });
568
572
  const tool = registerReadSeekTool(pi, {
569
- name: options.name ?? "readSeek_edit",
573
+ name,
570
574
  label: "Edit",
571
- description: EDIT_PROMPT_METADATA.description,
572
- promptSnippet: EDIT_PROMPT_METADATA.promptSnippet,
573
- promptGuidelines: EDIT_PROMPT_METADATA.promptGuidelines,
575
+ description: promptMetadata.description,
576
+ promptSnippet: promptMetadata.promptSnippet,
577
+ promptGuidelines: promptMetadata.promptGuidelines,
574
578
  parameters: hashlineEditSchema,
575
579
  renderShell: "default" as const,
576
580
  async execute(_toolCallId, params, signal, _onUpdate, ctx) {
package/src/grep.ts CHANGED
@@ -24,10 +24,6 @@ import type { FileAnchoredCallback } from "./tool-types.js";
24
24
  import { optionalIntOrString, registerReadSeekTool } from "./register-tool.js";
25
25
  import { searchPathParam } from "./readseek-params.js";
26
26
 
27
- const GREP_PROMPT_METADATA = defineToolPromptMetadata({
28
- promptUrl: new URL("../prompts/grep.md", import.meta.url),
29
- promptSnippet: "Search file contents and return edit-ready hashline anchors",
30
- });
31
27
 
32
28
  const grepSchema = Type.Object({
33
29
  pattern: Type.String({ description: "Pattern to search" }),
@@ -514,13 +510,19 @@ export async function executeGrep(opts: ExecuteGrepOptions): Promise<any> {
514
510
  }
515
511
 
516
512
  export function registerGrepTool(pi: ExtensionAPI, options: GrepToolOptions = {}) {
513
+ const name = options.name ?? "readSeek_grep";
514
+ const promptMetadata = defineToolPromptMetadata({
515
+ promptUrl: new URL("../prompts/grep.md", import.meta.url),
516
+ promptSnippet: "Search file text with edit-ready anchors",
517
+ registeredName: name,
518
+ });
517
519
  const tool = registerReadSeekTool(pi, {
518
- name: options.name ?? "readSeek_grep",
520
+ name,
519
521
  label: "grep",
520
- description: GREP_PROMPT_METADATA.description,
522
+ description: promptMetadata.description,
521
523
  parameters: grepSchema,
522
- promptSnippet: GREP_PROMPT_METADATA.promptSnippet,
523
- promptGuidelines: GREP_PROMPT_METADATA.promptGuidelines,
524
+ promptSnippet: promptMetadata.promptSnippet,
525
+ promptGuidelines: promptMetadata.promptGuidelines,
524
526
  async execute(toolCallId, params, signal, onUpdate, ctx) {
525
527
  return executeGrep({
526
528
  toolCallId,
package/src/hover.ts CHANGED
@@ -15,7 +15,7 @@ import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult,
15
15
 
16
16
  const HOVER_PROMPT_METADATA = defineToolPromptMetadata({
17
17
  promptUrl: new URL("../prompts/hover.md", import.meta.url),
18
- promptSnippet: "Identify the identifier and enclosing symbol at a cursor position",
18
+ promptSnippet: "Identify a cursor token and enclosing symbol",
19
19
  });
20
20
 
21
21
  const hoverSchema = Type.Object({
package/src/read.ts CHANGED
@@ -33,10 +33,6 @@ import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult,
33
33
  import type { FileAnchoredCallback } from "./tool-types.js";
34
34
  import { filePathParam, mapParam, optionalIntOrString, registerReadSeekTool } from "./register-tool.js";
35
35
 
36
- const READ_PROMPT_METADATA = defineToolPromptMetadata({
37
- promptUrl: new URL("../prompts/read.md", import.meta.url),
38
- promptSnippet: "Read text files or images; text reads include hashline anchors and optional maps/symbol lookup, image reads include the attachment plus OCR text, an image caption, and detected objects",
39
- });
40
36
 
41
37
  interface ReadParams {
42
38
  path: string;
@@ -460,12 +456,18 @@ function splitReadSeekLines(text: string): string[] {
460
456
  }
461
457
 
462
458
  export function registerReadTool(pi: ExtensionAPI, options: ReadToolOptions = {}) {
459
+ const name = options.name ?? "readSeek_read";
460
+ const promptMetadata = defineToolPromptMetadata({
461
+ promptUrl: new URL("../prompts/read.md", import.meta.url),
462
+ promptSnippet: "Read files or images with anchors, maps, symbols, and OCR",
463
+ registeredName: name,
464
+ });
463
465
  const tool = registerReadSeekTool(pi, {
464
- name: options.name ?? "readSeek_read",
466
+ name,
465
467
  label: "Read",
466
- description: READ_PROMPT_METADATA.description,
467
- promptSnippet: READ_PROMPT_METADATA.promptSnippet,
468
- promptGuidelines: READ_PROMPT_METADATA.promptGuidelines,
468
+ description: promptMetadata.description,
469
+ promptSnippet: promptMetadata.promptSnippet,
470
+ promptGuidelines: promptMetadata.promptGuidelines,
469
471
  parameters: Type.Object({
470
472
  path: filePathParam(),
471
473
  offset: optionalIntOrString("Start line (1-indexed)"),
package/src/refs.ts CHANGED
@@ -27,7 +27,7 @@ type RefsParams = {
27
27
 
28
28
  const REFS_PROMPT_METADATA = defineToolPromptMetadata({
29
29
  promptUrl: new URL("../prompts/refs.md", import.meta.url),
30
- promptSnippet: "Find references to an identifier with readseek and return edit-ready anchors",
30
+ promptSnippet: "Find identifier references with enclosing symbols",
31
31
  });
32
32
 
33
33
  interface RefsToolOptions {
package/src/rename.ts CHANGED
@@ -13,7 +13,7 @@ import { clampLineToWidth, clampLinesToWidth, linkToolPath, renderPendingResult,
13
13
 
14
14
  const RENAME_PROMPT_METADATA = defineToolPromptMetadata({
15
15
  promptUrl: new URL("../prompts/rename.md", import.meta.url),
16
- promptSnippet: "Rename an identifier with binding-accurate readseek rename",
16
+ promptSnippet: "Rename a binding accurately from its cursor",
17
17
  });
18
18
 
19
19
  const renameSchema = Type.Object({
package/src/sg.ts CHANGED
@@ -49,7 +49,7 @@ export function mergeRanges(ranges: SgRange[]): SgRange[] {
49
49
 
50
50
  const SG_PROMPT_METADATA = defineToolPromptMetadata({
51
51
  promptUrl: new URL("../prompts/sg.md", import.meta.url),
52
- promptSnippet: "Search code structurally with readseek and return edit-ready anchors",
52
+ promptSnippet: "Search code by AST pattern with edit-ready anchors",
53
53
  });
54
54
 
55
55
  interface SgToolOptions {
@@ -12,24 +12,42 @@ const COMPACT_DESCRIPTIONS: Record<string, string> = {
12
12
  "refs.md": "Find references to an identifier and return anchored usages with enclosing symbols.",
13
13
  };
14
14
 
15
+ const REPLACEABLE_TOOL_GUIDELINES: Record<string, { readSeekName: string; builtInName: string; benefit: string }> = {
16
+ "read.md": {
17
+ readSeekName: "readSeek_read",
18
+ builtInName: "read",
19
+ benefit: "it provides LINE:HASH anchors for safe edits.",
20
+ },
21
+ "edit.md": {
22
+ readSeekName: "readSeek_edit",
23
+ builtInName: "edit",
24
+ benefit: "it verifies fresh LINE:HASH anchors.",
25
+ },
26
+ "grep.md": {
27
+ readSeekName: "readSeek_grep",
28
+ builtInName: "grep",
29
+ benefit: "it returns edit-ready anchors.",
30
+ },
31
+ "write.md": {
32
+ readSeekName: "readSeek_write",
33
+ builtInName: "write",
34
+ benefit: "it returns LINE:HASH anchors.",
35
+ },
36
+ };
37
+
15
38
  const COMPACT_GUIDELINES: Record<string, string[]> = {
16
39
  "read.md": [
17
- "Use readSeek_read for file contents, images/screenshots, ranges, symbols, and edit anchors.",
18
- "Use map or symbol mode before pulling large code files into context.",
19
- "Use readSeek_read for images; it returns the image attachment plus OCR text, a caption, and detected objects, so you don't need separate OCR tools.",
40
+ "Use readSeek_read map or symbol mode before pulling large code files into context.",
41
+ "Use readSeek_read for images; it returns the image attachment plus OCR text, a caption, and detected objects.",
20
42
  ],
21
43
  "edit.md": [
22
- "Use readSeek_edit with fresh LINE:HASH anchors for existing files.",
23
- "Prefer set_line, replace_lines, and insert_after; use replace only when anchors are impractical.",
44
+ "With readSeek_edit, prefer set_line, replace_lines, and insert_after; use replace only when anchors are impractical.",
24
45
  ],
25
46
  "grep.md": [
26
- "Use readSeek_grep for text search and edit-ready matching anchors.",
27
47
  "Use readSeek_grep summary mode for broad count/file discovery before narrowing.",
28
48
  ],
29
-
30
49
  "write.md": [
31
- "Use readSeek_write to create files or intentionally overwrite whole files.",
32
- "Use readSeek_edit rather than readSeek_write for small changes or appends to existing files.",
50
+ "Use anchored edits rather than readSeek_write for small changes or appends to existing files.",
33
51
  ],
34
52
  "sg.md": [
35
53
  "Use readSeek_search for AST-shaped code patterns.",
@@ -62,16 +80,41 @@ function promptFileName(promptUrl: URL): string {
62
80
  return promptUrl.pathname.split("/").pop() ?? "";
63
81
  }
64
82
 
83
+ function rewriteToolAliases(value: string, toolAliases: Readonly<Record<string, string>> | undefined): string {
84
+ if (!toolAliases) return value;
85
+ return Object.entries(toolAliases).reduce(
86
+ (rewritten, [canonicalName, registeredName]) => rewritten.replaceAll(canonicalName, registeredName),
87
+ value,
88
+ );
89
+ }
90
+
65
91
  export function defineToolPromptMetadata(options: {
66
92
  promptUrl: URL;
67
93
  promptSnippet: string;
94
+ registeredName?: string;
95
+ toolAliases?: Readonly<Record<string, string>>;
68
96
  }): ToolPromptMetadata {
69
97
  const prompt = loadPrompt(options.promptUrl);
70
98
  const fileName = promptFileName(options.promptUrl);
71
99
  const compactDescription = COMPACT_DESCRIPTIONS[fileName];
100
+ const replaceable = REPLACEABLE_TOOL_GUIDELINES[fileName];
101
+ const registeredName = options.registeredName ?? replaceable?.readSeekName;
102
+ const preferenceGuideline = replaceable && registeredName
103
+ ? registeredName === replaceable.readSeekName
104
+ ? `Prefer ${registeredName} over ${replaceable.builtInName} when both are available; ${replaceable.benefit}`
105
+ : `Use ${registeredName}; ${replaceable.benefit}`
106
+ : undefined;
72
107
  return {
73
- description: compactDescription ?? firstPromptParagraph(prompt),
74
- promptSnippet: options.promptSnippet,
75
- promptGuidelines: COMPACT_GUIDELINES[fileName] ?? [],
108
+ description: rewriteToolAliases(compactDescription ?? firstPromptParagraph(prompt), options.toolAliases),
109
+ promptSnippet: rewriteToolAliases(options.promptSnippet, options.toolAliases),
110
+ promptGuidelines: [
111
+ ...(preferenceGuideline ? [preferenceGuideline] : []),
112
+ ...(COMPACT_GUIDELINES[fileName] ?? []).map((guideline) =>
113
+ rewriteToolAliases(
114
+ registeredName && replaceable ? guideline.replaceAll(replaceable.readSeekName, registeredName) : guideline,
115
+ options.toolAliases,
116
+ ),
117
+ ),
118
+ ],
76
119
  };
77
120
  }
package/src/write.ts CHANGED
@@ -66,10 +66,6 @@ function pendingWritePreviewParts(summary: string, preview: PendingDiffPreviewRe
66
66
  return { lines: [summary, headerLine], diffData: expanded ? diffData : undefined };
67
67
  }
68
68
 
69
- const WRITE_PROMPT_METADATA = defineToolPromptMetadata({
70
- promptUrl: new URL("../prompts/write.md", import.meta.url),
71
- promptSnippet: "Create or overwrite a complete file and return edit anchors",
72
- });
73
69
 
74
70
  type WriteDiffFields = {
75
71
  diff?: string;
@@ -242,12 +238,18 @@ export async function executeWrite(opts: {
242
238
  }
243
239
 
244
240
  export function registerWriteTool(pi: ExtensionAPI, options: WriteToolOptions = {}) {
241
+ const name = options.name ?? "readSeek_write";
242
+ const promptMetadata = defineToolPromptMetadata({
243
+ promptUrl: new URL("../prompts/write.md", import.meta.url),
244
+ promptSnippet: "Create or overwrite a file with edit anchors",
245
+ registeredName: name,
246
+ });
245
247
  const tool = registerReadSeekTool(pi, {
246
- name: options.name ?? "readSeek_write",
248
+ name,
247
249
  label: "write",
248
- description: WRITE_PROMPT_METADATA.description,
249
- promptSnippet: WRITE_PROMPT_METADATA.promptSnippet,
250
- promptGuidelines: WRITE_PROMPT_METADATA.promptGuidelines,
250
+ description: promptMetadata.description,
251
+ promptSnippet: promptMetadata.promptSnippet,
252
+ promptGuidelines: promptMetadata.promptGuidelines,
251
253
  parameters: Type.Object({
252
254
  path: filePathParam(),
253
255
  content: Type.String({ description: "File content" }),