opencode-readseek 0.8.18 → 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 +48 -32
- package/index.ts +33 -34
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# opencode-readseek
|
|
2
2
|
|
|
3
|
-
<img alt="
|
|
3
|
+
<img alt="OpenCode running opencode-readseek" src="screenshot.png" width="800">
|
|
4
4
|
|
|
5
|
-
`opencode-readseek` adds
|
|
6
|
-
|
|
5
|
+
`opencode-readseek` adds anchored file operations, structural search, symbol
|
|
6
|
+
navigation, and PDF tools to OpenCode.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Install
|
|
9
9
|
|
|
10
|
-
Add the
|
|
10
|
+
Add the package to `opencode.json`:
|
|
11
11
|
|
|
12
12
|
```json
|
|
13
13
|
{
|
|
@@ -15,29 +15,34 @@ Add the plugin to `opencode.json`:
|
|
|
15
15
|
}
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
OpenCode installs the package and its platform-specific
|
|
19
|
-
|
|
18
|
+
OpenCode installs the package and its platform-specific
|
|
19
|
+
`@jarkkojs/readseek` dependency with Bun.
|
|
20
20
|
|
|
21
21
|
## Tools
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
and
|
|
23
|
+
| Tool | Purpose |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `readseek_read` | Read text with `LINE:HASH` anchors; read images or one PDF page |
|
|
26
|
+
| `readseek_edit` | Apply hash-verified edits to an existing text file |
|
|
27
|
+
| `readseek_write` | Create or replace a complete text file |
|
|
28
|
+
| `readseek_grep` | Search text or regex and return anchors |
|
|
29
|
+
| `readseek_map` | Show a source file's symbol outline |
|
|
30
|
+
| `readseek_search` | Search AST patterns |
|
|
31
|
+
| `readseek_def` | Find symbol definitions |
|
|
32
|
+
| `readseek_refs` | Find identifier usages, optionally scoped to a cursor binding |
|
|
33
|
+
| `readseek_hover` | Identify the token and enclosing symbol at a cursor |
|
|
34
|
+
| `readseek_rename` | Apply a binding-aware rename; set `apply: false` for a dry run |
|
|
35
|
+
| `readseek_check` | Report parser errors and missing syntax |
|
|
36
|
+
| `readseek_view` | View or narrow a structural PDF index |
|
|
37
|
+
|
|
38
|
+
The plugin requests read, grep, external-directory, and edit permissions as
|
|
39
|
+
needed. Mutations invalidate remembered anchors; compaction preserves fresh
|
|
40
|
+
paths and pending rename plans. Text reads return at most 2,000 lines by
|
|
41
|
+
default.
|
|
42
|
+
|
|
43
|
+
OpenCode is instructed to prefer ReadSeek over the built-in `read`, `edit`,
|
|
44
|
+
`write`, `grep`, and `apply_patch` tools when ReadSeek can do the job. Built-ins
|
|
45
|
+
remain available as fallbacks.
|
|
41
46
|
|
|
42
47
|
## Configuration
|
|
43
48
|
|
|
@@ -49,13 +54,24 @@ Pass options with OpenCode's plugin tuple syntax:
|
|
|
49
54
|
}
|
|
50
55
|
```
|
|
51
56
|
|
|
52
|
-
`imageMode`
|
|
53
|
-
`objects`. `"on"` omits `none`; `"off"` skips images and PDFs. Omitting `image`
|
|
54
|
-
also skips visual files.
|
|
57
|
+
`imageMode` accepts:
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
- `"auto"` (default): expose `none`, `all`, `ocr`, `caption`, and `objects`.
|
|
60
|
+
- `"on"`: expose local analysis modes and omit `none`.
|
|
61
|
+
- `"off"`: skip image and PDF reads.
|
|
57
62
|
|
|
58
|
-
`
|
|
59
|
-
|
|
63
|
+
Omitting `image` from a read also skips visual files.
|
|
64
|
+
|
|
65
|
+
## Development
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
bun install
|
|
69
|
+
bun test
|
|
70
|
+
bun run typecheck
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
`opencode-readseek` is Apache-2.0; see [LICENSE](LICENSE).
|
|
60
76
|
`@jarkkojs/readseek` is licensed separately under
|
|
61
|
-
|
|
77
|
+
Apache-2.0 AND LGPL-2.1-or-later.
|
package/index.ts
CHANGED
|
@@ -16,33 +16,32 @@ const MAX_DOCUMENT_OUTPUT_BYTES = 256 * 1024;
|
|
|
16
16
|
const MAX_DOCUMENT_OUTPUT_LINES = 2000;
|
|
17
17
|
const TOOL_POLICY = [
|
|
18
18
|
"ReadSeek tool policy:",
|
|
19
|
-
"- Prefer readseek_* tools over
|
|
20
|
-
"-
|
|
21
|
-
"-
|
|
22
|
-
"-
|
|
23
|
-
"-
|
|
24
|
-
"-
|
|
25
|
-
"- Use readseek_check after source edits for a quick syntax check.",
|
|
19
|
+
"- Prefer readseek_* tools over built-ins when they can do the job.",
|
|
20
|
+
"- Read with readseek_read first; readseek_edit needs fresh LINE:HASH anchors.",
|
|
21
|
+
"- Use readseek_grep for text/regex, readseek_search for AST patterns, and readseek_map/def/refs/hover for symbol navigation.",
|
|
22
|
+
"- Use readseek_edit for existing files, readseek_write for whole-file creation or replacement, and readseek_rename for symbol renames.",
|
|
23
|
+
"- Do not use built-in read, edit, write, grep, or apply_patch when a ReadSeek tool can do the job.",
|
|
24
|
+
"- Run readseek_check after source edits for a quick syntax check.",
|
|
26
25
|
].join("\n");
|
|
27
26
|
const PREFERRED_TOOL_DESCRIPTIONS: Record<string, string> = {
|
|
28
|
-
readseek_read: "Preferred file reader; returns LINE:HASH anchors
|
|
29
|
-
readseek_edit: "Preferred tool for editing existing text files with
|
|
30
|
-
readseek_write: "Preferred tool for creating or replacing a complete text file.",
|
|
31
|
-
readseek_rename: "Preferred tool for renaming
|
|
27
|
+
readseek_read: "Preferred file reader; returns LINE:HASH anchors for durable references.",
|
|
28
|
+
readseek_edit: "Preferred tool for editing existing text files with fresh LINE:HASH anchors.",
|
|
29
|
+
readseek_write: "Preferred tool for creating or replacing a complete text file; returns LINE:HASH anchors.",
|
|
30
|
+
readseek_rename: "Preferred tool for renaming a symbol while preserving same-named bindings.",
|
|
32
31
|
readseek_grep: "Preferred text/regex search; returns edit-ready LINE:HASH anchors.",
|
|
33
|
-
readseek_search: "Preferred
|
|
34
|
-
readseek_map: "Preferred
|
|
32
|
+
readseek_search: "Preferred AST search for code shapes and call sites.",
|
|
33
|
+
readseek_map: "Preferred symbol outline for a source file.",
|
|
35
34
|
readseek_def: "Preferred symbol definition lookup.",
|
|
36
|
-
readseek_refs: "Preferred identifier usage finder before rename or delete.",
|
|
35
|
+
readseek_refs: "Preferred identifier usage finder; use before rename or delete.",
|
|
37
36
|
readseek_hover: "Preferred cursor token and enclosing-symbol inspector.",
|
|
38
37
|
readseek_view: "Preferred PDF structure and content viewer.",
|
|
39
38
|
readseek_check: "Preferred quick syntax check after source edits.",
|
|
40
39
|
};
|
|
41
40
|
const FALLBACK_TOOL_DESCRIPTIONS: Record<string, string> = {
|
|
42
|
-
read: "Fallback only. Prefer readseek_read
|
|
43
|
-
edit: "Fallback only. Prefer readseek_edit with
|
|
41
|
+
read: "Fallback only. Prefer readseek_read so edits can use LINE:HASH anchors.",
|
|
42
|
+
edit: "Fallback only. Prefer readseek_edit with fresh LINE:HASH anchors.",
|
|
44
43
|
write: "Fallback only. Prefer readseek_write so the result returns LINE:HASH anchors.",
|
|
45
|
-
grep: "Fallback only. Prefer readseek_grep for
|
|
44
|
+
grep: "Fallback only. Prefer readseek_grep for text/regex search with edit-ready anchors.",
|
|
46
45
|
apply_patch: "Fallback only. Prefer readseek_edit for existing text files.",
|
|
47
46
|
};
|
|
48
47
|
const READSEEK_PLATFORM_PACKAGES: Record<string, string> = {
|
|
@@ -1017,8 +1016,8 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1017
1016
|
tool: {
|
|
1018
1017
|
readseek_read: readseekTool(
|
|
1019
1018
|
imagePolicy === "off"
|
|
1020
|
-
? "Read text with LINE:HASH anchors
|
|
1021
|
-
: `Read text with LINE:HASH anchors
|
|
1019
|
+
? "Read text with LINE:HASH anchors. Image and PDF reads are disabled."
|
|
1020
|
+
: `Read text with LINE:HASH anchors. For an image or PDF, select image (${imageModes.join(", ")}); omit it to skip visual files.`,
|
|
1022
1021
|
{
|
|
1023
1022
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1024
1023
|
offset: tool.schema.number().int().positive().optional().describe("One-based starting line"),
|
|
@@ -1029,7 +1028,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1029
1028
|
? {}
|
|
1030
1029
|
: {
|
|
1031
1030
|
image: tool.schema.enum(imageModes as [ImageMode, ...ImageMode[]]).optional()
|
|
1032
|
-
.describe("Image
|
|
1031
|
+
.describe("Image/PDF processing mode")
|
|
1033
1032
|
}),
|
|
1034
1033
|
},
|
|
1035
1034
|
"read",
|
|
@@ -1065,7 +1064,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1065
1064
|
formatReadResult,
|
|
1066
1065
|
),
|
|
1067
1066
|
readseek_view: readseekTool(
|
|
1068
|
-
"View
|
|
1067
|
+
"View PDF structure or selected content. Start with the overview, then narrow by page or node.",
|
|
1069
1068
|
{
|
|
1070
1069
|
path: tool.schema.string().describe("PDF path relative to the project directory"),
|
|
1071
1070
|
node: tool.schema.string().min(1).optional().describe("Node ID to use as the view root"),
|
|
@@ -1090,7 +1089,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1090
1089
|
(result) => ({ output: boundDocumentOutput(String(result)) }),
|
|
1091
1090
|
),
|
|
1092
1091
|
readseek_map: readseekTool(
|
|
1093
|
-
"
|
|
1092
|
+
"Show a source file's symbol outline without reading the full file.",
|
|
1094
1093
|
{
|
|
1095
1094
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1096
1095
|
language: tool.schema.string().optional().describe("Language override when auto-detection is ambiguous"),
|
|
@@ -1105,7 +1104,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1105
1104
|
},
|
|
1106
1105
|
),
|
|
1107
1106
|
readseek_grep: readseekTool(
|
|
1108
|
-
"Search text or
|
|
1107
|
+
"Search text or regex and return matching LINE:HASH anchors. Set literal for exact text.",
|
|
1109
1108
|
{
|
|
1110
1109
|
pattern: tool.schema.string().describe("Text or regular expression to search for"),
|
|
1111
1110
|
path: tool.schema.string().optional().describe("File or directory, defaulting to the project directory"),
|
|
@@ -1167,9 +1166,9 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1167
1166
|
},
|
|
1168
1167
|
),
|
|
1169
1168
|
readseek_search: readseekTool(
|
|
1170
|
-
"Search
|
|
1169
|
+
"Search AST patterns (ast-grep style) and return LINE:HASH anchors. Use for code structure; use readseek_grep for plain text.",
|
|
1171
1170
|
{
|
|
1172
|
-
pattern: tool.schema.string().describe("ast-grep
|
|
1171
|
+
pattern: tool.schema.string().describe("AST pattern (ast-grep style), such as console.log($$$ARGS)"),
|
|
1173
1172
|
path: tool.schema.string().optional().describe("File or directory, defaulting to the project directory"),
|
|
1174
1173
|
language: tool.schema.string().optional().describe("Language override when auto-detection is ambiguous"),
|
|
1175
1174
|
cached: tool.schema.boolean().optional().describe("Search tracked or indexed files in a Git repository"),
|
|
@@ -1188,7 +1187,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1188
1187
|
},
|
|
1189
1188
|
),
|
|
1190
1189
|
readseek_def: readseekTool(
|
|
1191
|
-
"Find symbol declarations by name and return LINE:HASH anchors.
|
|
1190
|
+
"Find symbol declarations by name and return LINE:HASH anchors. Prefer this to text search for definitions.",
|
|
1192
1191
|
{
|
|
1193
1192
|
name: tool.schema.string().describe("Symbol name"),
|
|
1194
1193
|
path: tool.schema.string().optional().describe("File or directory, defaulting to the project directory"),
|
|
@@ -1208,7 +1207,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1208
1207
|
},
|
|
1209
1208
|
),
|
|
1210
1209
|
readseek_refs: readseekTool(
|
|
1211
|
-
"Find identifier usages with enclosing symbols. Use before
|
|
1210
|
+
"Find identifier usages with enclosing symbols. Use before renaming or deleting a symbol; add cursor scope to exclude same-named bindings.",
|
|
1212
1211
|
{
|
|
1213
1212
|
name: tool.schema.string().describe("Identifier name"),
|
|
1214
1213
|
path: tool.schema.string().optional().describe("File or directory, defaulting to the project directory"),
|
|
@@ -1238,7 +1237,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1238
1237
|
},
|
|
1239
1238
|
),
|
|
1240
1239
|
readseek_hover: readseekTool(
|
|
1241
|
-
"Identify the token and enclosing symbol at a cursor. Use before definition lookup or rename
|
|
1240
|
+
"Identify the token and enclosing symbol at a cursor. Use before definition lookup or rename.",
|
|
1242
1241
|
{
|
|
1243
1242
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1244
1243
|
line: tool.schema.number().int().positive().describe("One-based cursor line"),
|
|
@@ -1256,11 +1255,11 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1256
1255
|
},
|
|
1257
1256
|
),
|
|
1258
1257
|
readseek_rename: readseekTool(
|
|
1259
|
-
"Rename
|
|
1258
|
+
"Rename the symbol at a cursor while preserving same-named bindings. Applies verified edits atomically by default; set apply to false for a dry-run plan.",
|
|
1260
1259
|
{
|
|
1261
1260
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1262
|
-
line: tool.schema.number().int().positive().describe("One-based line of the symbol to rename"),
|
|
1263
|
-
column: tool.schema.number().int().positive().optional().describe("One-based byte column for disambiguation"),
|
|
1261
|
+
line: tool.schema.number().int().positive().describe("One-based cursor line of the symbol to rename"),
|
|
1262
|
+
column: tool.schema.number().int().positive().optional().describe("One-based cursor byte column for disambiguation"),
|
|
1264
1263
|
to: tool.schema.string().min(1).describe("New symbol name"),
|
|
1265
1264
|
workspace: tool.schema.boolean().optional().describe("Include project-wide occurrences"),
|
|
1266
1265
|
apply: tool.schema.boolean().optional().describe("Apply verified edits atomically; defaults to true"),
|
|
@@ -1291,7 +1290,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1291
1290
|
},
|
|
1292
1291
|
),
|
|
1293
1292
|
readseek_edit: readseekTool(
|
|
1294
|
-
"Edit an existing text file
|
|
1293
|
+
"Edit an existing text file with fresh LINE:HASH anchors. Stale hashes are rejected before writing.",
|
|
1295
1294
|
{
|
|
1296
1295
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1297
1296
|
edits: tool.schema.array(tool.schema.union([
|
|
@@ -1308,7 +1307,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1308
1307
|
tool.schema.object({
|
|
1309
1308
|
insert_after: tool.schema.object({ anchor: tool.schema.string(), new_text: tool.schema.string() }).strict(),
|
|
1310
1309
|
}).strict(),
|
|
1311
|
-
])).min(1).describe("
|
|
1310
|
+
])).min(1).describe("LINE:HASH-anchored edits to apply"),
|
|
1312
1311
|
},
|
|
1313
1312
|
"edit",
|
|
1314
1313
|
async (input, context) => {
|
|
@@ -1359,7 +1358,7 @@ export const ReadSeekPlugin: Plugin = async (_input, options) => {
|
|
|
1359
1358
|
},
|
|
1360
1359
|
),
|
|
1361
1360
|
readseek_check: readseekTool(
|
|
1362
|
-
"
|
|
1361
|
+
"Run a quick syntax check on a source file. Reports parser errors and missing syntax; not a compiler or linter.",
|
|
1363
1362
|
{
|
|
1364
1363
|
path: tool.schema.string().describe("Path relative to the project directory"),
|
|
1365
1364
|
language: tool.schema.string().optional().describe("Language override when auto-detection is ambiguous"),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-readseek",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "OpenCode plugin for
|
|
3
|
+
"version": "0.8.20",
|
|
4
|
+
"description": "OpenCode plugin for anchored file operations and structural code navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
7
7
|
"exports": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"node": ">=20.0.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@jarkkojs/readseek": "^0.8.
|
|
34
|
+
"@jarkkojs/readseek": "^0.8.20",
|
|
35
35
|
"@opencode-ai/plugin": "^1.17.20"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|