pi-readseek 0.8.19 → 0.8.20
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 +9 -11
- package/dist/index.ts +44 -18
- package/package.json +2 -2
- package/prompts/edit.md +1 -1
- package/prompts/read.md +5 -5
- package/prompts/refs.md +1 -1
- package/prompts/rename.md +1 -1
- package/prompts/view.md +1 -1
- package/prompts/write.md +1 -1
package/README.md
CHANGED
|
@@ -26,13 +26,12 @@ supported platforms.
|
|
|
26
26
|
| `readSeek_def` | Find symbol definitions |
|
|
27
27
|
| `readSeek_refs` | Find identifier usages, optionally scoped to a cursor binding |
|
|
28
28
|
| `readSeek_hover` | Identify the token and enclosing symbol at a cursor |
|
|
29
|
-
| `readSeek_rename` |
|
|
29
|
+
| `readSeek_rename` | Rename a cursor symbol; set `apply: false` to preview the plan |
|
|
30
30
|
| `readSeek_check` | Report parser errors and missing syntax |
|
|
31
31
|
| `readSeek_view` | View or narrow a structural PDF index |
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
prefer fresh `LINE:HASH` anchors and run a quick syntax check after source edits.
|
|
33
|
+
The extension also tells Pi to get fresh anchors before editing and to run a
|
|
34
|
+
syntax check after source edits.
|
|
36
35
|
|
|
37
36
|
## Settings
|
|
38
37
|
|
|
@@ -62,13 +61,12 @@ Defaults:
|
|
|
62
61
|
```
|
|
63
62
|
|
|
64
63
|
- `replacedTools`: any of `"read"`, `"edit"`, `"write"`, and `"grep"`.
|
|
65
|
-
- `imageMode`:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
in `"auto"` mode, embedded PDF images.
|
|
64
|
+
- `imageMode`: `"auto"` uses Pi's native image input when available, `"on"`
|
|
65
|
+
always runs local analysis, and `"off"` skips images while still reading PDF
|
|
66
|
+
text. Standalone images require `image`; values are `all`, `ocr`, `caption`, and
|
|
67
|
+
`objects`. In `"auto"`, `none` returns a prepared standalone image without local
|
|
68
|
+
analysis. Local analysis uses
|
|
69
|
+
[Qwen3-VL-2B-Instruct](../../docs/models/qwen3-vl-2b-instruct.md).
|
|
72
70
|
- `syntaxValidation`: `"warn"` (write and warn), `"block"` (abort), or `"off"`.
|
|
73
71
|
Validation triggers only when an edit increases parser error or missing-node
|
|
74
72
|
counts.
|
package/dist/index.ts
CHANGED
|
@@ -50,8 +50,7 @@ var COMPACT_GUIDELINES = {
|
|
|
50
50
|
"Use readSeek_search for AST patterns; use readSeek_grep for plain text."
|
|
51
51
|
],
|
|
52
52
|
"refs.md": [
|
|
53
|
-
"Use readSeek_refs before
|
|
54
|
-
"Use readSeek_refs with scope plus line/column to follow one binding and exclude same-named bindings."
|
|
53
|
+
"Use readSeek_refs before changing a symbol; add scope plus line/column to follow one binding."
|
|
55
54
|
]
|
|
56
55
|
};
|
|
57
56
|
function loadPrompt(promptUrl) {
|
|
@@ -3661,17 +3660,17 @@ function registerReadTool(pi, options = {}) {
|
|
|
3661
3660
|
const imageModes = imageMode === "auto" ? ["none", "all", "ocr", "caption", "objects"] : ["all", "ocr", "caption", "objects"];
|
|
3662
3661
|
const promptMetadata = defineToolPromptMetadata({
|
|
3663
3662
|
promptUrl: new URL("../prompts/read.md", import.meta.url),
|
|
3664
|
-
promptSnippet: "Read anchored text, symbols, maps, images, or PDFs",
|
|
3663
|
+
promptSnippet: imageMode === "off" ? "Read anchored text, symbols, maps, or PDF text" : "Read anchored text, symbols, maps, images, or PDFs",
|
|
3665
3664
|
registeredName: name
|
|
3666
3665
|
});
|
|
3667
3666
|
const tool = registerReadSeekTool(pi, {
|
|
3668
3667
|
name,
|
|
3669
3668
|
label: "Read",
|
|
3670
|
-
description: imageMode === "off" ? "Read anchored text by range,
|
|
3669
|
+
description: imageMode === "off" ? "Read anchored text by range, symbol, or map. Images are disabled; PDFs still return text." : promptMetadata.description,
|
|
3671
3670
|
promptSnippet: promptMetadata.promptSnippet,
|
|
3672
3671
|
promptGuidelines: [
|
|
3673
3672
|
...promptMetadata.promptGuidelines,
|
|
3674
|
-
imageMode === "
|
|
3673
|
+
...imageMode === "auto" ? ["Image-capable Pi models receive prepared images directly. For standalone images, image=none skips local analysis; other modes use ReadSeek when native vision is unavailable."] : []
|
|
3675
3674
|
],
|
|
3676
3675
|
parameters: Type2.Object({
|
|
3677
3676
|
path: filePathParam(),
|
|
@@ -3685,7 +3684,7 @@ function registerReadTool(pi, options = {}) {
|
|
|
3685
3684
|
})),
|
|
3686
3685
|
...imageMode === "off" ? {} : {
|
|
3687
3686
|
image: Type2.Optional(Type2.Union(imageModes.map((mode) => Type2.Literal(mode)), {
|
|
3688
|
-
description: `Standalone/PDF-embedded image mode: ${imageModes.join(", ")}. Required for standalone images
|
|
3687
|
+
description: `Standalone/PDF-embedded image mode: ${imageModes.join(", ")}. Required for standalone images.${imageMode === "auto" ? " For standalone images, none skips local analysis." : ""}`
|
|
3689
3688
|
}))
|
|
3690
3689
|
}
|
|
3691
3690
|
}),
|
|
@@ -4793,13 +4792,36 @@ function pendingPreviewLines(summary, preview, expanded) {
|
|
|
4793
4792
|
const headerLine = summaryLine(preview.data.headerLabel, { hidden: !expanded });
|
|
4794
4793
|
return { lines: [summary, headerLine], diffData: expanded ? diffData : undefined, headerLabel: preview.data.headerLabel };
|
|
4795
4794
|
}
|
|
4796
|
-
var hashlineEditItemSchema = Type3.
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4795
|
+
var hashlineEditItemSchema = Type3.Object({
|
|
4796
|
+
set_line: Type3.Optional(Type3.Object({
|
|
4797
|
+
anchor: Type3.String({ description: "Fresh LINE:HASH anchor for the line to replace" }),
|
|
4798
|
+
new_text: Type3.String({ description: "Replacement text; use an empty string to delete the line" })
|
|
4799
|
+
}, { description: 'Replace one line: {"set_line":{"anchor":"LINE:HASH","new_text":"..."}}' })),
|
|
4800
|
+
replace_lines: Type3.Optional(Type3.Object({
|
|
4801
|
+
start_anchor: Type3.String({ description: "Fresh LINE:HASH anchor for the first line in the range" }),
|
|
4802
|
+
end_anchor: Type3.String({ description: "Fresh LINE:HASH anchor for the last line in the range" }),
|
|
4803
|
+
new_text: Type3.String({ description: "Replacement text; use an empty string to delete the range" })
|
|
4804
|
+
}, { description: 'Replace a range: {"replace_lines":{"start_anchor":"LINE:HASH","end_anchor":"LINE:HASH","new_text":"..."}}' })),
|
|
4805
|
+
insert_after: Type3.Optional(Type3.Object({
|
|
4806
|
+
anchor: Type3.String({ description: "Fresh LINE:HASH anchor for the line after which to insert" }),
|
|
4807
|
+
new_text: Type3.String({ description: "Text to insert after the anchored line" })
|
|
4808
|
+
}, { description: 'Insert text: {"insert_after":{"anchor":"LINE:HASH","new_text":"..."}}' })),
|
|
4809
|
+
replace: Type3.Optional(Type3.Object({
|
|
4810
|
+
old_text: Type3.String({ description: "Exact text to find" }),
|
|
4811
|
+
new_text: Type3.String({ description: "Replacement text" }),
|
|
4812
|
+
all: Type3.Optional(Type3.Boolean({ description: "Replace every exact match" })),
|
|
4813
|
+
fuzzy: Type3.Optional(Type3.Boolean({ description: "Allow unverified fuzzy matching when exact text is absent" }))
|
|
4814
|
+
}, { description: 'Replace text: {"replace":{"old_text":"...","new_text":"..."}}' })),
|
|
4815
|
+
replace_symbol: Type3.Optional(Type3.Object({
|
|
4816
|
+
symbol: Type3.String({ description: "Mapped symbol name" }),
|
|
4817
|
+
new_body: Type3.String({ description: "Complete replacement body for the symbol" })
|
|
4818
|
+
}, { description: 'Replace a symbol: {"replace_symbol":{"symbol":"name","new_body":"..."}}' }))
|
|
4819
|
+
}, {
|
|
4820
|
+
additionalProperties: false,
|
|
4821
|
+
minProperties: 1,
|
|
4822
|
+
maxProperties: 1,
|
|
4823
|
+
description: "Exactly one nested edit variant"
|
|
4824
|
+
});
|
|
4803
4825
|
var hashlineEditSchema = Type3.Object({
|
|
4804
4826
|
path: filePathParam(),
|
|
4805
4827
|
edits: Type3.Optional(Type3.Array(hashlineEditItemSchema, {
|
|
@@ -4860,7 +4882,12 @@ async function executeEdit(opts) {
|
|
|
4860
4882
|
}
|
|
4861
4883
|
for (let i = 0;i < edits.length; i++) {
|
|
4862
4884
|
throwIfAborted(signal);
|
|
4863
|
-
const
|
|
4885
|
+
const edit = edits[i];
|
|
4886
|
+
if (!edit || typeof edit !== "object" || Array.isArray(edit)) {
|
|
4887
|
+
const message = `edits[${i}] must be an object containing exactly one edit variant.`;
|
|
4888
|
+
return buildEditError(absolutePath, "invalid-edit-variant", message);
|
|
4889
|
+
}
|
|
4890
|
+
const e = edit;
|
|
4864
4891
|
if ((("old_text" in e) || ("new_text" in e)) && !("replace" in e)) {
|
|
4865
4892
|
const message = `edits[${i}] has top-level 'old_text'/'new_text'. Use {replace: {old_text, new_text}} or {set_line}, {replace_lines}, {insert_after}.`;
|
|
4866
4893
|
return buildEditError(absolutePath, "invalid-edit-variant", message);
|
|
@@ -4870,7 +4897,7 @@ async function executeEdit(opts) {
|
|
|
4870
4897
|
return buildEditError(absolutePath, "invalid-edit-variant", message);
|
|
4871
4898
|
}
|
|
4872
4899
|
const variantCount = Number("set_line" in e) + Number("replace_lines" in e) + Number("insert_after" in e) + Number("replace" in e) + Number("replace_symbol" in e);
|
|
4873
|
-
if (variantCount !== 1) {
|
|
4900
|
+
if (variantCount !== 1 || Object.keys(e).length !== 1) {
|
|
4874
4901
|
const message = `edits[${i}] must contain exactly one of: 'set_line', 'replace_lines', 'insert_after', 'replace', 'replace_symbol'. Got: [${Object.keys(e).join(", ")}].`;
|
|
4875
4902
|
return buildEditError(absolutePath, "invalid-edit-variant", message);
|
|
4876
4903
|
}
|
|
@@ -6463,7 +6490,7 @@ import path5 from "node:path";
|
|
|
6463
6490
|
import { Text as Text6 } from "@earendil-works/pi-tui";
|
|
6464
6491
|
var RENAME_PROMPT_METADATA = defineToolPromptMetadata({
|
|
6465
6492
|
promptUrl: new URL("../prompts/rename.md", import.meta.url),
|
|
6466
|
-
promptSnippet: "Rename
|
|
6493
|
+
promptSnippet: "Rename a cursor symbol with verified edits"
|
|
6467
6494
|
});
|
|
6468
6495
|
var renameSchema = Type8.Object({
|
|
6469
6496
|
path: filePathParam(),
|
|
@@ -7262,7 +7289,7 @@ function registerViewTool(pi) {
|
|
|
7262
7289
|
parameters: Type13.Object({
|
|
7263
7290
|
path: filePathParam(),
|
|
7264
7291
|
node: Type13.Optional(Type13.String({ description: "Node ID to use as the view root" })),
|
|
7265
|
-
page: optionalIntOrString("One-based
|
|
7292
|
+
page: optionalIntOrString("One-based PDF page"),
|
|
7266
7293
|
kind: Type13.Optional(Type13.Union(NODE_KINDS.map((kind) => Type13.Literal(kind)), {
|
|
7267
7294
|
description: "Node kind filter"
|
|
7268
7295
|
})),
|
|
@@ -7343,7 +7370,6 @@ function editingPolicy(readName, editName, writeName) {
|
|
|
7343
7370
|
"ReadSeek editing policy:",
|
|
7344
7371
|
`- Read first with ${readName} when preparing to edit; ${editName} needs fresh LINE:HASH anchors.`,
|
|
7345
7372
|
`- Use ${editName} for existing files, ${writeName} for whole-file creation or replacement, and readSeek_rename for symbol renames.`,
|
|
7346
|
-
"- Do not use Pi's built-in read, edit, write, or grep when the corresponding ReadSeek tool is available.",
|
|
7347
7373
|
"- Run readSeek_check after source edits for a quick syntax check."
|
|
7348
7374
|
].join(`
|
|
7349
7375
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-readseek",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20",
|
|
4
4
|
"description": "Pi extension for LINE:HASH-anchored file operations and structural code navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node": ">=20.0.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@jarkkojs/readseek": "^0.8.
|
|
43
|
+
"@jarkkojs/readseek": "^0.8.20",
|
|
44
44
|
"diff": "^9.0.0",
|
|
45
45
|
"xxhash-wasm": "^1.1.0"
|
|
46
46
|
},
|
package/prompts/edit.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Edit existing text files with fresh `LINE:HASH` anchors. Read or search the file first when no fresh anchors are available.
|
|
1
|
+
Edit existing text files with fresh `LINE:HASH` anchors. Read or search the file first when no fresh anchors are available. Each `edits[]` item must use exactly one nested object: `{"set_line":{"anchor":"LINE:HASH","new_text":"..."}}`, `{"replace_lines":{"start_anchor":"LINE:HASH","end_anchor":"LINE:HASH","new_text":"..."}}`, `{"insert_after":{"anchor":"LINE:HASH","new_text":"..."}}`, `{"replace_symbol":{"symbol":"name","new_body":"..."}}`, or `{"replace":{"old_text":"...","new_text":"..."}}`.
|
|
2
2
|
|
|
3
3
|
Anchors come from `readSeek_read`, `readSeek_grep`, `readSeek_search`, or
|
|
4
4
|
`readSeek_write`.
|
package/prompts/read.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Read anchored text by range,
|
|
1
|
+
Read anchored text by range, symbol, or map. Standalone images require an explicit mode; PDF text is always returned.
|
|
2
2
|
|
|
3
3
|
## Choose a read
|
|
4
4
|
|
|
@@ -23,10 +23,10 @@ Text output is capped at {{DEFAULT_MAX_LINES}} lines or {{DEFAULT_MAX_BYTES}}.
|
|
|
23
23
|
A truncated full-file read appends a map when available; use its ranges for
|
|
24
24
|
follow-up reads.
|
|
25
25
|
|
|
26
|
-
Standalone images require
|
|
27
|
-
|
|
28
|
-
`
|
|
29
|
-
|
|
26
|
+
Standalone images require `image`. In `"auto"`, `image: "none"` returns a
|
|
27
|
+
prepared standalone image without local analysis. PDF text is always read;
|
|
28
|
+
without `image`, embedded images are skipped unless an image-capable Pi model is
|
|
29
|
+
active in `"auto"` mode. That model receives prepared images directly.
|
|
30
30
|
|
|
31
31
|
## Symbol lookup
|
|
32
32
|
|
package/prompts/refs.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Find identifier usages with enclosing symbols and edit-ready `LINE:HASH` anchors.
|
|
1
|
+
Find identifier usages with enclosing symbols and edit-ready `LINE:HASH` anchors. Add cursor scope to follow one binding and exclude shadows.
|
|
2
2
|
|
|
3
3
|
## Parameters
|
|
4
4
|
|
package/prompts/rename.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Rename the symbol at a cursor while preserving resolvable same-named bindings.
|
|
1
|
+
Rename the symbol at a cursor while preserving resolvable same-named bindings. Set `apply: false` to preview the verified plan.
|
|
2
2
|
|
|
3
3
|
## Parameters
|
|
4
4
|
|
package/prompts/view.md
CHANGED
|
@@ -4,7 +4,7 @@ View the structure or selected content of a PDF. Start with the overview, then n
|
|
|
4
4
|
|
|
5
5
|
- `path` — PDF file.
|
|
6
6
|
- `node` — node ID to use as the view root.
|
|
7
|
-
- `page` — one-based
|
|
7
|
+
- `page` — one-based PDF page.
|
|
8
8
|
- `kind` — node kind filter.
|
|
9
9
|
- `depth` — maximum depth below selected roots.
|
|
10
10
|
- `outline` — return outline nodes only.
|
package/prompts/write.md
CHANGED
|
@@ -13,4 +13,4 @@ rejected before writing.
|
|
|
13
13
|
|
|
14
14
|
Text output uses `LINE:HASH|content` and is capped at {{DEFAULT_MAX_LINES}} lines
|
|
15
15
|
or {{DEFAULT_MAX_BYTES}}. Complete anchors remain in `readSeekValue`. Results
|
|
16
|
-
also include a compact diff
|
|
16
|
+
also include a compact diff and structured `details.diffData`.
|