opencode-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 +16 -16
- package/dist/index.js +297 -236
- package/dist/v2.js +15 -15
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -42,17 +42,17 @@ macOS/Windows supplied by `@jarkkojs/readseek`. Set
|
|
|
42
42
|
|
|
43
43
|
## Tools
|
|
44
44
|
|
|
45
|
-
- Read without inference: `
|
|
46
|
-
`
|
|
47
|
-
- Check: `
|
|
48
|
-
- Explicit inference: `
|
|
49
|
-
`
|
|
50
|
-
- Find: `
|
|
51
|
-
`
|
|
52
|
-
- Mutate: `
|
|
53
|
-
|
|
54
|
-
Tool names mirror native
|
|
55
|
-
`
|
|
45
|
+
- Read without inference: `readseek_show`, `readseek_tree`,
|
|
46
|
+
`readseek_meta`, `readseek_assets`.
|
|
47
|
+
- Check: `readseek_syntax`, `readseek_check`.
|
|
48
|
+
- Explicit inference: `readseek_caption`, `readseek_objects`,
|
|
49
|
+
`readseek_ocr`.
|
|
50
|
+
- Find: `readseek_grep`, `readseek_search`, `readseek_def`,
|
|
51
|
+
`readseek_refs`.
|
|
52
|
+
- Mutate: `readseek_edit`, `readseek_rename`, `readseek_write`.
|
|
53
|
+
|
|
54
|
+
Tool names mirror native flat single-word commands, such as `show`,
|
|
55
|
+
`search`, and `edit`. Paths resolve against the project directory.
|
|
56
56
|
Use `at` selectors (`line:N[:COLUMN]`, `hash:H[:COLUMN]`, `symbol:NAME`,
|
|
57
57
|
`page:N`, `node:ID`, or `asset:ID`) where supported. Structure defaults to
|
|
58
58
|
`depth: 1`. Use separate structure, metadata, and syntax tools rather than
|
|
@@ -63,20 +63,20 @@ lines, document sections, structure trees, metadata fields, and asset paths.
|
|
|
63
63
|
Notices identify omitted ranges and how to continue. The unchanged native result
|
|
64
64
|
is retained separately in `metadata.readseek`; image attachments are unchanged.
|
|
65
65
|
|
|
66
|
-
`
|
|
67
|
-
`
|
|
66
|
+
`readseek_search` accepts `pattern`, `context` with `selector`, or `rule`.
|
|
67
|
+
`readseek_refs` requires exactly one of `name` or `at`; binding
|
|
68
68
|
references and renames use line or hash cursors. KDL selection/check rules
|
|
69
69
|
may be inline or `@path`; tool calls cannot supply standard input.
|
|
70
70
|
|
|
71
|
-
`
|
|
71
|
+
`readseek_grep` accepts exactly one of literal `text` or regex `pattern`.
|
|
72
72
|
The adapter also supports `literal`, `ignoreCase`, `glob`, `context`, `limit`,
|
|
73
|
-
and per-file `summary`. Native `
|
|
73
|
+
and per-file `summary`. Native `grep` searches literally.
|
|
74
74
|
|
|
75
75
|
Read fresh `LINE:HASH` anchors before editing. Each edit item contains exactly
|
|
76
76
|
one nested `set_line`, `replace_lines`, `insert_after`, `replace_symbol`, or
|
|
77
77
|
`replace` object. Edits and renames default to applying after a verified plan
|
|
78
78
|
and edit permission; use `apply: false` to preview and `planHash` to require
|
|
79
|
-
that plan when applying. `
|
|
79
|
+
that plan when applying. `write` replaces complete text files.
|
|
80
80
|
|
|
81
81
|
Syntax and rule checks treat exit 1 as findings, not transport failure;
|
|
82
82
|
exit 0 is clean and exit 2 is failure. Syntax checks do not typecheck.
|
package/dist/index.js
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,48 +205,48 @@ 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
|
// ../readseek-api/src/policy.ts
|
|
226
226
|
var BUILTIN_FALLBACKS = {
|
|
227
|
-
read: "
|
|
228
|
-
edit: "
|
|
229
|
-
write: "
|
|
230
|
-
grep: "
|
|
231
|
-
apply_patch: "
|
|
227
|
+
read: "show",
|
|
228
|
+
edit: "edit",
|
|
229
|
+
write: "write",
|
|
230
|
+
grep: "grep",
|
|
231
|
+
apply_patch: "edit"
|
|
232
232
|
};
|
|
233
233
|
var PREFERENCE_LEADS = {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
234
|
+
show: "Preferred for reading source with anchors.",
|
|
235
|
+
edit: "Preferred for editing existing text files with fresh LINE:HASH anchors.",
|
|
236
|
+
write: "Preferred for creating or replacing a complete text file; returns LINE:HASH anchors.",
|
|
237
|
+
grep: "Preferred text/regex search; returns edit-ready LINE:HASH anchors.",
|
|
238
|
+
search: "Preferred for AST or structural code search with ast-grep-style patterns.",
|
|
239
|
+
def: "Preferred for go-to-definition or declaration lookup by name.",
|
|
240
|
+
refs: "Preferred for finding identifier-name matches or binding-specific references before `rename` or delete.",
|
|
241
|
+
rename: "Preferred for renaming a symbol with binding-aware, verified edits.",
|
|
242
|
+
assets: "Preferred for materializing selected document assets with usable cached paths."
|
|
243
243
|
};
|
|
244
244
|
var FALLBACK_TEMPLATES = {
|
|
245
|
-
read: "Prefer `
|
|
246
|
-
edit: "Prefer `
|
|
247
|
-
write: "Prefer `
|
|
248
|
-
grep: "Prefer `
|
|
249
|
-
apply_patch: "Prefer `
|
|
245
|
+
read: "Prefer `show` with fresh LINE:HASH anchors.",
|
|
246
|
+
edit: "Prefer `edit` with fresh LINE:HASH anchors.",
|
|
247
|
+
write: "Prefer `write` so the result returns LINE:HASH anchors.",
|
|
248
|
+
grep: "Prefer `grep` for text/regex search with edit-ready anchors.",
|
|
249
|
+
apply_patch: "Prefer `edit` for existing text files."
|
|
250
250
|
};
|
|
251
251
|
function resolveToolName(name, aliases = {}) {
|
|
252
252
|
return aliases[name] ?? name;
|
|
@@ -262,21 +262,21 @@ function renderFallbackToolDescription(builtIn, aliases = {}) {
|
|
|
262
262
|
}
|
|
263
263
|
function renderToolRoutingPolicy(options = {}) {
|
|
264
264
|
const aliases = options.aliases ?? {};
|
|
265
|
-
const
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
const
|
|
265
|
+
const show = resolveToolName("show", aliases);
|
|
266
|
+
const edit = resolveToolName("edit", aliases);
|
|
267
|
+
const write = resolveToolName("write", aliases);
|
|
268
|
+
const grep = resolveToolName("grep", aliases);
|
|
269
|
+
const search = resolveToolName("search", aliases);
|
|
270
|
+
const def = resolveToolName("def", aliases);
|
|
271
|
+
const refs = resolveToolName("refs", aliases);
|
|
272
|
+
const rename = resolveToolName("rename", aliases);
|
|
273
|
+
const assets = resolveToolName("assets", aliases);
|
|
274
274
|
const title = options.title ?? "ReadSeek tool policy:";
|
|
275
275
|
const bullets = [];
|
|
276
276
|
if (options.preferOverBuiltIns) {
|
|
277
277
|
bullets.push("- Prefer ReadSeek tools over built-ins when they can do the job.");
|
|
278
278
|
}
|
|
279
|
-
bullets.push(`- Read with ${
|
|
279
|
+
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.`);
|
|
280
280
|
if (options.demoteBuiltIns && options.demoteBuiltIns.length > 0) {
|
|
281
281
|
bullets.push(`- Do not use built-in ${options.demoteBuiltIns.join(", ")} when a ReadSeek tool can do the job.`);
|
|
282
282
|
}
|
|
@@ -420,50 +420,111 @@ var SELECTOR_KINDS = ["line", "hash", "symbol", "page", "node", "asset"];
|
|
|
420
420
|
function isSelectorKind(value) {
|
|
421
421
|
return SELECTOR_KINDS.includes(value);
|
|
422
422
|
}
|
|
423
|
+
function parsePositiveSelectorInt(raw, name) {
|
|
424
|
+
if (!/^-?\d+$/.test(raw))
|
|
425
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
426
|
+
const parsed = Number(raw);
|
|
427
|
+
if (!Number.isSafeInteger(parsed))
|
|
428
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
429
|
+
if (parsed < 1)
|
|
430
|
+
throw new Error(`${name} must be greater than zero`);
|
|
431
|
+
return parsed;
|
|
432
|
+
}
|
|
433
|
+
function parseLineSelector(value, explicitKind) {
|
|
434
|
+
const parts = value.split(":");
|
|
435
|
+
if (parts.length > 2)
|
|
436
|
+
throw new Error("selector has too many components");
|
|
437
|
+
const head = parts[0];
|
|
438
|
+
if (parts.length === 2) {
|
|
439
|
+
if (head.slice(1).includes("-"))
|
|
440
|
+
throw new Error("line range cannot include a column");
|
|
441
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
442
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
443
|
+
return { kind: "line", value: String(line), column, explicitKind };
|
|
444
|
+
}
|
|
445
|
+
const dash = head.indexOf("-", 1);
|
|
446
|
+
if (dash > 0) {
|
|
447
|
+
const start = parsePositiveSelectorInt(head.slice(0, dash), "line");
|
|
448
|
+
const endLine = parsePositiveSelectorInt(head.slice(dash + 1), "end line");
|
|
449
|
+
if (endLine < start)
|
|
450
|
+
throw new Error(`end line ${endLine} precedes start line ${start}`);
|
|
451
|
+
return { kind: "line", value: String(start), endLine, explicitKind };
|
|
452
|
+
}
|
|
453
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
454
|
+
return { kind: "line", value: String(line), explicitKind };
|
|
455
|
+
}
|
|
456
|
+
function parseHashSelector(value, explicitKind) {
|
|
457
|
+
const parts = value.split(":");
|
|
458
|
+
if (parts.length > 2)
|
|
459
|
+
throw new Error("selector has too many components");
|
|
460
|
+
const head = parts[0];
|
|
461
|
+
if (!/^[0-9a-fA-F]{6}$/.test(head))
|
|
462
|
+
throw new Error(`invalid line hash \`${head}\``);
|
|
463
|
+
if (parts.length === 2) {
|
|
464
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
465
|
+
return { kind: "hash", value: head, column, explicitKind };
|
|
466
|
+
}
|
|
467
|
+
return { kind: "hash", value: head, explicitKind };
|
|
468
|
+
}
|
|
469
|
+
function isDocumentSelector(parsed) {
|
|
470
|
+
return ["page", "node", "asset"].includes(parsed.kind) || parsed.kind === "line" && !parsed.explicitKind && parsed.column === undefined && parsed.endLine === undefined;
|
|
471
|
+
}
|
|
472
|
+
function isBindingSelector(parsed) {
|
|
473
|
+
if (parsed.endLine !== undefined)
|
|
474
|
+
return false;
|
|
475
|
+
if (parsed.kind === "line" || parsed.kind === "hash")
|
|
476
|
+
return true;
|
|
477
|
+
return parsed.kind === "symbol" && !parsed.explicitKind && /^[0-9a-fA-F]{6}$/.test(parsed.value);
|
|
478
|
+
}
|
|
423
479
|
function parseSelector(text) {
|
|
480
|
+
if (text.length === 0)
|
|
481
|
+
throw new Error("selector must not be empty");
|
|
424
482
|
const separator = text.indexOf(":");
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
483
|
+
const hasSingleColon = separator >= 0 && text[separator + 1] !== ":";
|
|
484
|
+
if (hasSingleColon) {
|
|
485
|
+
const kind = text.slice(0, separator);
|
|
486
|
+
const value = text.slice(separator + 1);
|
|
487
|
+
if (isSelectorKind(kind)) {
|
|
488
|
+
if (value.length === 0)
|
|
489
|
+
throw new Error(`${kind} selector must not be empty`);
|
|
490
|
+
if (kind === "line")
|
|
491
|
+
return parseLineSelector(value, true);
|
|
492
|
+
if (kind === "hash")
|
|
493
|
+
return parseHashSelector(value, true);
|
|
494
|
+
if (kind === "page") {
|
|
495
|
+
if (value.includes(":"))
|
|
496
|
+
throw new Error("page selector has too many components");
|
|
497
|
+
parsePositiveSelectorInt(value, "page");
|
|
498
|
+
}
|
|
499
|
+
return { kind, value, explicitKind: true };
|
|
500
|
+
}
|
|
501
|
+
if (/^\d+$/.test(kind))
|
|
502
|
+
return parseLineSelector(text, false);
|
|
503
|
+
if (/^[0-9a-fA-F]{6}$/.test(kind) && /^\d+$/.test(value))
|
|
504
|
+
return parseHashSelector(text, false);
|
|
433
505
|
throw new Error(`unknown selector kind \`${kind}\`; expected line, hash, symbol, page, node, or asset`);
|
|
434
506
|
}
|
|
435
|
-
if (
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
throw new Error("selector has too many components");
|
|
439
|
-
if (parts.length === 2) {
|
|
440
|
-
const column = Number(parts[1]);
|
|
441
|
-
if (!Number.isSafeInteger(column))
|
|
442
|
-
throw new Error(`invalid column \`${parts[1]}\``);
|
|
443
|
-
if (column < 1)
|
|
444
|
-
throw new Error("column must be greater than zero");
|
|
445
|
-
return { kind, value: parts[0], column };
|
|
507
|
+
if (/^[0-9-]/.test(text)) {
|
|
508
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /[a-fA-F]/.test(text)) {
|
|
509
|
+
return parseHashSelector(text, false);
|
|
446
510
|
}
|
|
511
|
+
return parseLineSelector(text, false);
|
|
447
512
|
}
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
throw new Error("page selector has too many components");
|
|
451
|
-
const page = Number(value);
|
|
452
|
-
if (!Number.isSafeInteger(page))
|
|
453
|
-
throw new Error(`invalid page \`${value}\``);
|
|
454
|
-
if (page < 1)
|
|
455
|
-
throw new Error("page must be greater than zero");
|
|
513
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /\d/.test(text)) {
|
|
514
|
+
return parseHashSelector(text, false);
|
|
456
515
|
}
|
|
457
|
-
|
|
516
|
+
if (/\s/.test(text))
|
|
517
|
+
throw new Error(`invalid selector \`${text}\``);
|
|
518
|
+
return { kind: "symbol", value: text, explicitKind: false };
|
|
458
519
|
}
|
|
459
|
-
function start(
|
|
520
|
+
function start(command, input) {
|
|
460
521
|
if (!input.path)
|
|
461
|
-
throw new Error(`${
|
|
522
|
+
throw new Error(`${command} requires a path`);
|
|
462
523
|
if (input.stdinName !== undefined && input.path !== "-")
|
|
463
524
|
throw new Error("stdinName requires '-' as the target");
|
|
464
525
|
const args = [];
|
|
465
526
|
pushOptionalString(args, "--readseek-dir", input.readseekDir);
|
|
466
|
-
args.push(
|
|
527
|
+
args.push(command, input.path);
|
|
467
528
|
pushOptionalString(args, "--stdin-name", input.stdinName);
|
|
468
529
|
return args;
|
|
469
530
|
}
|
|
@@ -489,12 +550,12 @@ function anchors(args, input) {
|
|
|
489
550
|
if (input.noAnchors)
|
|
490
551
|
args.push("--no-anchors");
|
|
491
552
|
}
|
|
492
|
-
function
|
|
553
|
+
function buildShowArgs(input) {
|
|
493
554
|
if (input.end !== undefined)
|
|
494
555
|
validatePositiveInteger(input.end, "end");
|
|
495
556
|
if (input.end !== undefined && input.limit !== undefined)
|
|
496
557
|
throw new Error("cannot combine end with limit");
|
|
497
|
-
const args = start("show",
|
|
558
|
+
const args = start("show", input);
|
|
498
559
|
at2(args, input.at);
|
|
499
560
|
pushOptionalNumber(args, "--end", input.end);
|
|
500
561
|
limit2(args, input.limit);
|
|
@@ -502,10 +563,10 @@ function buildShowContentArgs(input) {
|
|
|
502
563
|
anchors(args, input);
|
|
503
564
|
return finish(args);
|
|
504
565
|
}
|
|
505
|
-
function
|
|
566
|
+
function buildTreeArgs(input) {
|
|
506
567
|
if (input.depth !== undefined && (!Number.isSafeInteger(input.depth) || input.depth < 0))
|
|
507
568
|
throw new Error("depth must be a non-negative integer");
|
|
508
|
-
const args = start("
|
|
569
|
+
const args = start("tree", input);
|
|
509
570
|
at2(args, input.at);
|
|
510
571
|
pushOptionalNumber(args, "--depth", input.depth);
|
|
511
572
|
pushOptionalString(args, "--kind", input.kind);
|
|
@@ -514,35 +575,35 @@ function buildShowStructureArgs(input) {
|
|
|
514
575
|
args.push("--outline");
|
|
515
576
|
return finish(args);
|
|
516
577
|
}
|
|
517
|
-
function
|
|
518
|
-
const args = start("
|
|
578
|
+
function buildMetaArgs(input) {
|
|
579
|
+
const args = start("meta", input);
|
|
519
580
|
language(args, input);
|
|
520
581
|
return finish(args);
|
|
521
582
|
}
|
|
522
|
-
function
|
|
523
|
-
if (input.at !== undefined && !
|
|
583
|
+
function buildAssetsArgs(input) {
|
|
584
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
524
585
|
throw new Error("assets requires a page, node, or asset selector");
|
|
525
|
-
const args = start("
|
|
586
|
+
const args = start("assets", input);
|
|
526
587
|
at2(args, input.at);
|
|
527
588
|
return finish(args);
|
|
528
589
|
}
|
|
529
|
-
function
|
|
530
|
-
const args = start("
|
|
590
|
+
function buildSyntaxArgs(input) {
|
|
591
|
+
const args = start("syntax", input);
|
|
531
592
|
language(args, input);
|
|
532
593
|
return finish(args);
|
|
533
594
|
}
|
|
534
|
-
function visionArgs(
|
|
595
|
+
function visionArgs(command, input) {
|
|
535
596
|
if (input.level !== undefined && !VISION_LEVELS.includes(input.level))
|
|
536
597
|
throw new Error("invalid vision level");
|
|
537
|
-
if (input.at !== undefined && !
|
|
598
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
538
599
|
throw new Error("vision requires a document selector");
|
|
539
|
-
const args = start(
|
|
600
|
+
const args = start(command, input);
|
|
540
601
|
at2(args, input.at);
|
|
541
602
|
pushOptionalString(args, "--level", input.level);
|
|
542
603
|
return args;
|
|
543
604
|
}
|
|
544
|
-
function
|
|
545
|
-
const args = visionArgs("
|
|
605
|
+
function buildCaptionArgs(input) {
|
|
606
|
+
const args = visionArgs("caption", input);
|
|
546
607
|
if (input.include !== undefined) {
|
|
547
608
|
if (input.include.length === 0 || input.include.some((task) => task !== "text" && task !== "objects"))
|
|
548
609
|
throw new Error("include requires text or objects");
|
|
@@ -550,13 +611,13 @@ function buildGenerateCaptionArgs(input) {
|
|
|
550
611
|
}
|
|
551
612
|
return finish(args);
|
|
552
613
|
}
|
|
553
|
-
function
|
|
554
|
-
return finish(visionArgs("
|
|
614
|
+
function buildObjectsArgs(input) {
|
|
615
|
+
return finish(visionArgs("objects", input));
|
|
555
616
|
}
|
|
556
|
-
function
|
|
557
|
-
return finish(visionArgs("
|
|
617
|
+
function buildOcrArgs(input) {
|
|
618
|
+
return finish(visionArgs("ocr", input));
|
|
558
619
|
}
|
|
559
|
-
function
|
|
620
|
+
function buildSearchArgs(input) {
|
|
560
621
|
const hasPattern = Boolean(input.pattern);
|
|
561
622
|
const hasRule = Boolean(input.rule);
|
|
562
623
|
const hasContext = Boolean(input.context);
|
|
@@ -564,7 +625,7 @@ function buildFindNodesArgs(input) {
|
|
|
564
625
|
if (hasPattern || hasContext || input.selector)
|
|
565
626
|
throw new Error("rule cannot be combined with pattern, context, or selector");
|
|
566
627
|
} else if (!hasPattern && !hasContext) {
|
|
567
|
-
throw new Error("
|
|
628
|
+
throw new Error("search requires pattern, context, or rule");
|
|
568
629
|
}
|
|
569
630
|
if (hasContext && !input.selector) {
|
|
570
631
|
throw new Error("context requires selector");
|
|
@@ -572,7 +633,7 @@ function buildFindNodesArgs(input) {
|
|
|
572
633
|
if (hasPattern && hasContext) {
|
|
573
634
|
throw new Error("pattern and context cannot be combined");
|
|
574
635
|
}
|
|
575
|
-
const args = start("
|
|
636
|
+
const args = start("search", input);
|
|
576
637
|
pushOptionalString(args, "--pattern", input.pattern);
|
|
577
638
|
pushOptionalString(args, "--context", input.context);
|
|
578
639
|
pushOptionalString(args, "--selector", input.selector);
|
|
@@ -583,28 +644,28 @@ function buildFindNodesArgs(input) {
|
|
|
583
644
|
anchors(args, input);
|
|
584
645
|
return finish(args);
|
|
585
646
|
}
|
|
586
|
-
function
|
|
587
|
-
const args = start("
|
|
647
|
+
function buildGrepArgs(input) {
|
|
648
|
+
const args = start("grep", input);
|
|
588
649
|
args.push("--text", input.text);
|
|
589
650
|
limit2(args, input.limit);
|
|
590
651
|
appendGitScopeArgs(args, input);
|
|
591
652
|
return finish(args);
|
|
592
653
|
}
|
|
593
|
-
function
|
|
594
|
-
const args = start("
|
|
654
|
+
function buildDefArgs(input) {
|
|
655
|
+
const args = start("def", input);
|
|
595
656
|
args.push("--name", input.name);
|
|
596
657
|
language(args, input);
|
|
597
658
|
appendGitScopeArgs(args, input);
|
|
598
659
|
anchors(args, input);
|
|
599
660
|
return finish(args);
|
|
600
661
|
}
|
|
601
|
-
function
|
|
662
|
+
function buildRefsArgs(input) {
|
|
602
663
|
const validated = validateReferencesSelection(input);
|
|
603
664
|
if (!validated.ok)
|
|
604
665
|
throw new Error(validated.error);
|
|
605
|
-
if (input.at !== undefined && !
|
|
666
|
+
if (input.at !== undefined && !isBindingSelector(parseSelector(input.at)))
|
|
606
667
|
throw new Error("references requires a line or hash selector");
|
|
607
|
-
const args = start("
|
|
668
|
+
const args = start("refs", input);
|
|
608
669
|
pushOptionalString(args, "--name", input.name);
|
|
609
670
|
at2(args, input.at);
|
|
610
671
|
language(args, input);
|
|
@@ -612,14 +673,14 @@ function buildFindReferencesArgs(input) {
|
|
|
612
673
|
anchors(args, input);
|
|
613
674
|
return finish(args);
|
|
614
675
|
}
|
|
615
|
-
function
|
|
616
|
-
const args = start("check",
|
|
676
|
+
function buildCheckArgs(input) {
|
|
677
|
+
const args = start("check", input);
|
|
617
678
|
args.push("--rules", input.rules);
|
|
618
679
|
appendGitScopeArgs(args, input);
|
|
619
680
|
return finish(args);
|
|
620
681
|
}
|
|
621
|
-
function
|
|
622
|
-
const args = start("edit",
|
|
682
|
+
function buildEditArgs(input) {
|
|
683
|
+
const args = start("edit", input);
|
|
623
684
|
appendApplyAndPlanHash(args, input);
|
|
624
685
|
language(args, input);
|
|
625
686
|
appendGitScopeArgs(args, input);
|
|
@@ -627,10 +688,10 @@ function buildEditTextArgs(input) {
|
|
|
627
688
|
args.push("--edits", "-");
|
|
628
689
|
return finish(args);
|
|
629
690
|
}
|
|
630
|
-
function
|
|
631
|
-
if (!
|
|
691
|
+
function buildRenameArgs(input) {
|
|
692
|
+
if (!isBindingSelector(parseSelector(input.at)))
|
|
632
693
|
throw new Error("rename requires a line or hash selector");
|
|
633
|
-
const args = start("rename",
|
|
694
|
+
const args = start("rename", input);
|
|
634
695
|
at2(args, input.at);
|
|
635
696
|
args.push("--to", input.to);
|
|
636
697
|
if (input.workspace !== undefined)
|
|
@@ -1016,7 +1077,7 @@ function serializeEditPlan(edits) {
|
|
|
1016
1077
|
}
|
|
1017
1078
|
// ../readseek-api/src/show-presentation.ts
|
|
1018
1079
|
function isShowTool(name) {
|
|
1019
|
-
return name === "
|
|
1080
|
+
return name === "show" || name === "tree" || name === "meta" || name === "assets";
|
|
1020
1081
|
}
|
|
1021
1082
|
function record(value) {
|
|
1022
1083
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -1131,7 +1192,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1131
1192
|
const path = inline(options.path || output.source || output.file || content.file || structure.file || metadata.file || cursor.file) || "(unknown path)";
|
|
1132
1193
|
const summary = [];
|
|
1133
1194
|
const result = { summary: "", body: "", notices: [], metadata: {} };
|
|
1134
|
-
if (tool === "
|
|
1195
|
+
if (tool === "meta") {
|
|
1135
1196
|
const data = Object.keys(metadata).length > 0 ? metadata : output;
|
|
1136
1197
|
if (text(data.format || data.language || data.type))
|
|
1137
1198
|
summary.push(inline(data.format || data.language || data.type));
|
|
@@ -1140,7 +1201,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1140
1201
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1141
1202
|
}
|
|
1142
1203
|
result.body = fields(data) || "No metadata available.";
|
|
1143
|
-
} else if (tool === "
|
|
1204
|
+
} else if (tool === "assets") {
|
|
1144
1205
|
const assets = records(output.assets);
|
|
1145
1206
|
result.metadata.assets = assets.length;
|
|
1146
1207
|
summary.push(plural(assets.length, "asset"));
|
|
@@ -1154,7 +1215,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1154
1215
|
summary.push(plural(nodes.length, "node"));
|
|
1155
1216
|
if (result.metadata.pages !== undefined)
|
|
1156
1217
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1157
|
-
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "
|
|
1218
|
+
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "show")];
|
|
1158
1219
|
if (assets.length > 0) {
|
|
1159
1220
|
result.metadata.assets = assets.length;
|
|
1160
1221
|
sections.push(`Assets
|
|
@@ -1163,7 +1224,7 @@ ${assetList(assets)}`);
|
|
|
1163
1224
|
result.body = sections.filter(Boolean).join(`
|
|
1164
1225
|
|
|
1165
1226
|
`) || "No content in this selection.";
|
|
1166
|
-
} else if (tool === "
|
|
1227
|
+
} else if (tool === "tree") {
|
|
1167
1228
|
const symbols = records(structure.symbols);
|
|
1168
1229
|
result.metadata.symbols = symbols.length;
|
|
1169
1230
|
summary.push(plural(symbols.length, "symbol"));
|
|
@@ -1217,7 +1278,7 @@ ${assetList(assets)}`);
|
|
|
1217
1278
|
const description = Object.keys(content).length > 0 ? content : output;
|
|
1218
1279
|
result.body = fields(description) || "No content in this selection.";
|
|
1219
1280
|
}
|
|
1220
|
-
if (tool === "
|
|
1281
|
+
if (tool === "tree")
|
|
1221
1282
|
result.notices.push("Structure is limited to the requested depth, kind, and outline. Use a deeper depth or focus with at to inspect further.");
|
|
1222
1283
|
if (text(output.warning))
|
|
1223
1284
|
result.notices.push(safe(text(output.warning)));
|
|
@@ -1672,7 +1733,7 @@ function acceptsReadSeekExitCode(args, exitCode) {
|
|
|
1672
1733
|
index++;
|
|
1673
1734
|
continue;
|
|
1674
1735
|
}
|
|
1675
|
-
return arg === "
|
|
1736
|
+
return arg === "grep" || arg === "search" || arg === "def" || arg === "refs" || arg === "syntax" || arg === "check";
|
|
1676
1737
|
}
|
|
1677
1738
|
return false;
|
|
1678
1739
|
}
|
|
@@ -1873,12 +1934,12 @@ function resolveImagePolicy(options) {
|
|
|
1873
1934
|
throw new Error('opencode-readseek imageMode must be "on", "auto", or "off"');
|
|
1874
1935
|
}
|
|
1875
1936
|
function contentArgs(filePath, options = {}) {
|
|
1876
|
-
return
|
|
1937
|
+
return buildShowArgs({ path: filePath, ...options, at: options.at ?? (options.end === undefined ? undefined : "line:1") });
|
|
1877
1938
|
}
|
|
1878
1939
|
function requireContent(envelope) {
|
|
1879
1940
|
const value = record2(envelope).content;
|
|
1880
1941
|
if (value === undefined || value === null || typeof value !== "object") {
|
|
1881
|
-
throw new Error("show
|
|
1942
|
+
throw new Error("show returned no source content");
|
|
1882
1943
|
}
|
|
1883
1944
|
return value;
|
|
1884
1945
|
}
|
|
@@ -1954,7 +2015,7 @@ async function ensureReadSeekCache(context) {
|
|
|
1954
2015
|
if (error.code !== "ENOENT")
|
|
1955
2016
|
throw error;
|
|
1956
2017
|
}
|
|
1957
|
-
readSeekCacheInit ??= runReadSeekRaw(context, ["--readseek-dir", cacheDir, "
|
|
2018
|
+
readSeekCacheInit ??= runReadSeekRaw(context, ["--readseek-dir", cacheDir, "init"], { cancelable: false }).then(() => cacheDir).finally(() => {
|
|
1958
2019
|
readSeekCacheInit = undefined;
|
|
1959
2020
|
});
|
|
1960
2021
|
return readSeekCacheInit;
|
|
@@ -2372,31 +2433,31 @@ import { pathToFileURL } from "node:url";
|
|
|
2372
2433
|
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
2373
2434
|
function initialTitle(kind, args) {
|
|
2374
2435
|
switch (kind) {
|
|
2375
|
-
case "
|
|
2376
|
-
case "
|
|
2377
|
-
case "
|
|
2378
|
-
case "
|
|
2379
|
-
case "
|
|
2380
|
-
case "
|
|
2381
|
-
case "
|
|
2382
|
-
return `${kind
|
|
2383
|
-
case "
|
|
2436
|
+
case "tree":
|
|
2437
|
+
case "meta":
|
|
2438
|
+
case "syntax":
|
|
2439
|
+
case "check":
|
|
2440
|
+
case "caption":
|
|
2441
|
+
case "objects":
|
|
2442
|
+
case "ocr":
|
|
2443
|
+
return `${kind} ${args.path}`;
|
|
2444
|
+
case "show":
|
|
2384
2445
|
return `Show content ${args.path}`;
|
|
2385
|
-
case "
|
|
2446
|
+
case "assets":
|
|
2386
2447
|
return `Show assets ${args.path}`;
|
|
2387
|
-
case "
|
|
2448
|
+
case "search":
|
|
2388
2449
|
return `Find nodes ${args.pattern ?? args.context ?? args.rule}`;
|
|
2389
|
-
case "
|
|
2450
|
+
case "grep":
|
|
2390
2451
|
return `Find text ${args.pattern ?? args.text}`;
|
|
2391
|
-
case "
|
|
2452
|
+
case "def":
|
|
2392
2453
|
return `Find definition ${args.name}`;
|
|
2393
|
-
case "
|
|
2454
|
+
case "refs":
|
|
2394
2455
|
return `Find references to ${args.name ?? args.at}`;
|
|
2395
|
-
case "
|
|
2456
|
+
case "rename":
|
|
2396
2457
|
return `Rename ${args.path}:${args.at} to ${args.to}`;
|
|
2397
|
-
case "
|
|
2458
|
+
case "edit":
|
|
2398
2459
|
return `Edit ${args.path}`;
|
|
2399
|
-
case "
|
|
2460
|
+
case "write":
|
|
2400
2461
|
return `Write ${args.path}`;
|
|
2401
2462
|
}
|
|
2402
2463
|
}
|
|
@@ -2407,18 +2468,18 @@ function resultPresentation(kind, args, value) {
|
|
|
2407
2468
|
return { title: presentation.summary, metadata: presentation.metadata };
|
|
2408
2469
|
}
|
|
2409
2470
|
switch (kind) {
|
|
2410
|
-
case "
|
|
2471
|
+
case "syntax": {
|
|
2411
2472
|
const diagnostics = record2(output.diagnostics ?? output);
|
|
2412
2473
|
const errors = typeof diagnostics.error_count === "number" ? diagnostics.error_count : 0;
|
|
2413
2474
|
const missing = typeof diagnostics.missing_count === "number" ? diagnostics.missing_count : 0;
|
|
2414
2475
|
return { title: `Syntax ${args.path} (${errors} errors, ${missing} missing)`, metadata: { error_count: errors, missing_count: missing } };
|
|
2415
2476
|
}
|
|
2416
|
-
case "
|
|
2477
|
+
case "search": {
|
|
2417
2478
|
const results = items(output.results);
|
|
2418
2479
|
const matches = results.reduce((total, result) => total + items(record2(result).matches).length, 0);
|
|
2419
2480
|
return { title: `Found ${matches} matches`, metadata: { results: results.length, matches } };
|
|
2420
2481
|
}
|
|
2421
|
-
case "
|
|
2482
|
+
case "grep": {
|
|
2422
2483
|
const results = items(output.results);
|
|
2423
2484
|
const matches = results.reduce((total, result) => {
|
|
2424
2485
|
const entry = record2(result);
|
|
@@ -2426,15 +2487,15 @@ function resultPresentation(kind, args, value) {
|
|
|
2426
2487
|
}, 0);
|
|
2427
2488
|
return { title: `Found ${matches} matches`, metadata: { results: results.length, matches } };
|
|
2428
2489
|
}
|
|
2429
|
-
case "
|
|
2490
|
+
case "def": {
|
|
2430
2491
|
const locations = items(output.locations).length;
|
|
2431
2492
|
return { title: `Found ${locations} definitions`, metadata: { locations } };
|
|
2432
2493
|
}
|
|
2433
|
-
case "
|
|
2494
|
+
case "refs": {
|
|
2434
2495
|
const references = items(output.references).length;
|
|
2435
2496
|
return { title: `Found ${references} references`, metadata: { references } };
|
|
2436
2497
|
}
|
|
2437
|
-
case "
|
|
2498
|
+
case "rename": {
|
|
2438
2499
|
const oldName = output.old_name;
|
|
2439
2500
|
const newName = output.new_name;
|
|
2440
2501
|
const otherOutputs = items(output.others).map(record2);
|
|
@@ -2444,10 +2505,10 @@ function resultPresentation(kind, args, value) {
|
|
|
2444
2505
|
const title = typeof oldName === "string" && typeof newName === "string" ? `${output.applied === true ? "Renamed" : "Plan"} ${oldName} -> ${newName}` : initialTitle(kind, args);
|
|
2445
2506
|
return { title, metadata: { edits, conflicts, others } };
|
|
2446
2507
|
}
|
|
2447
|
-
case "
|
|
2448
|
-
case "
|
|
2508
|
+
case "edit":
|
|
2509
|
+
case "write": {
|
|
2449
2510
|
const preview = typeof output.preview_error === "string" ? " (preview unavailable)" : "";
|
|
2450
|
-
return { title: `${kind === "
|
|
2511
|
+
return { title: `${kind === "edit" ? "Edited" : "Wrote"} ${args.path}${preview}`, metadata: {} };
|
|
2451
2512
|
}
|
|
2452
2513
|
}
|
|
2453
2514
|
return { title: initialTitle(kind, args), metadata: {} };
|
|
@@ -2493,7 +2554,7 @@ function readseekTool(description, args, kind, execute, imagePolicy) {
|
|
|
2493
2554
|
function createReadSeekTools(imagePolicy) {
|
|
2494
2555
|
return {
|
|
2495
2556
|
...createAccessTools(imagePolicy),
|
|
2496
|
-
|
|
2557
|
+
readseek_grep: readseekTool(openCodeToolDescription("grep"), {
|
|
2497
2558
|
pattern: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.grepPattern),
|
|
2498
2559
|
text: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.text),
|
|
2499
2560
|
summary: tool3.schema.boolean().optional().describe(PARAM_DESCRIPTIONS.summary),
|
|
@@ -2503,7 +2564,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2503
2564
|
ignoreCase: tool3.schema.boolean().optional().describe(PARAM_DESCRIPTIONS.ignoreCase),
|
|
2504
2565
|
context: tool3.schema.number().int().nonnegative().optional().describe(PARAM_DESCRIPTIONS.context),
|
|
2505
2566
|
limit: tool3.schema.number().int().positive().optional().describe(PARAM_DESCRIPTIONS.matchLimit)
|
|
2506
|
-
}, "
|
|
2567
|
+
}, "grep", async (input, context) => {
|
|
2507
2568
|
const target = resolvePath(context.directory, input.path ?? ".");
|
|
2508
2569
|
if (input.pattern === undefined === (input.text === undefined)) {
|
|
2509
2570
|
throw new Error("exactly one of pattern or text is required");
|
|
@@ -2511,7 +2572,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2511
2572
|
const pattern = input.pattern ?? input.text;
|
|
2512
2573
|
await authorizeSearch(context, target, pattern);
|
|
2513
2574
|
if (input.text !== undefined && !input.glob && !input.ignoreCase && !input.context && !input.summary) {
|
|
2514
|
-
return runReadSeek(context,
|
|
2575
|
+
return runReadSeek(context, buildGrepArgs({ path: target, text: pattern, limit: input.limit }));
|
|
2515
2576
|
}
|
|
2516
2577
|
let expression;
|
|
2517
2578
|
try {
|
|
@@ -2593,7 +2654,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2593
2654
|
}
|
|
2594
2655
|
return { results, truncated };
|
|
2595
2656
|
}),
|
|
2596
|
-
|
|
2657
|
+
readseek_search: readseekTool(openCodeToolDescription("search"), {
|
|
2597
2658
|
pattern: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.pattern),
|
|
2598
2659
|
context: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.patternContext),
|
|
2599
2660
|
selector: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.selector),
|
|
@@ -2602,9 +2663,9 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2602
2663
|
path: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.projectSearchPath),
|
|
2603
2664
|
language: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.language),
|
|
2604
2665
|
gitScope: tool3.schema.enum(GIT_SCOPES).optional().describe(PARAM_DESCRIPTIONS.gitScope)
|
|
2605
|
-
}, "
|
|
2666
|
+
}, "search", async (input, context) => {
|
|
2606
2667
|
const target = resolvePath(context.directory, input.path ?? ".");
|
|
2607
|
-
const args =
|
|
2668
|
+
const args = buildSearchArgs({
|
|
2608
2669
|
path: target,
|
|
2609
2670
|
pattern: input.pattern,
|
|
2610
2671
|
context: input.context,
|
|
@@ -2622,14 +2683,14 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2622
2683
|
throw new Error("rule stdin is unavailable in OpenCode tools; use inline KDL or @path");
|
|
2623
2684
|
return runReadSeek(context, args);
|
|
2624
2685
|
}),
|
|
2625
|
-
|
|
2686
|
+
readseek_def: readseekTool(openCodeToolDescription("def"), {
|
|
2626
2687
|
name: tool3.schema.string().describe(PARAM_DESCRIPTIONS.name),
|
|
2627
2688
|
path: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.projectSearchPath),
|
|
2628
2689
|
language: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.language),
|
|
2629
2690
|
gitScope: tool3.schema.enum(GIT_SCOPES).optional().describe(PARAM_DESCRIPTIONS.gitScope)
|
|
2630
|
-
}, "
|
|
2691
|
+
}, "def", async (input, context) => {
|
|
2631
2692
|
const target = resolvePath(context.directory, input.path ?? ".");
|
|
2632
|
-
const args =
|
|
2693
|
+
const args = buildDefArgs({
|
|
2633
2694
|
path: target,
|
|
2634
2695
|
name: input.name,
|
|
2635
2696
|
language: input.language,
|
|
@@ -2638,16 +2699,16 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2638
2699
|
await authorizeSearch(context, target, input.name);
|
|
2639
2700
|
return runReadSeek(context, args);
|
|
2640
2701
|
}),
|
|
2641
|
-
|
|
2702
|
+
readseek_refs: readseekTool(openCodeToolDescription("refs"), {
|
|
2642
2703
|
name: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.refsName),
|
|
2643
2704
|
path: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.projectSearchPath),
|
|
2644
2705
|
language: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.language),
|
|
2645
2706
|
at: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.at),
|
|
2646
2707
|
gitScope: tool3.schema.enum(GIT_SCOPES).optional().describe(PARAM_DESCRIPTIONS.gitScope)
|
|
2647
|
-
}, "
|
|
2708
|
+
}, "refs", async (input, context) => {
|
|
2648
2709
|
const target = resolvePath(context.directory, input.path ?? ".");
|
|
2649
2710
|
const name = input.name;
|
|
2650
|
-
const args =
|
|
2711
|
+
const args = buildRefsArgs({
|
|
2651
2712
|
path: target,
|
|
2652
2713
|
name,
|
|
2653
2714
|
at: input.at,
|
|
@@ -2657,7 +2718,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2657
2718
|
await authorizeSearch(context, target, name ?? "*");
|
|
2658
2719
|
return runReadSeek(context, args);
|
|
2659
2720
|
}),
|
|
2660
|
-
|
|
2721
|
+
readseek_rename: readseekTool(openCodeToolDescription("rename"), {
|
|
2661
2722
|
path: tool3.schema.string().describe(PARAM_DESCRIPTIONS.projectPath),
|
|
2662
2723
|
at: tool3.schema.string().describe(PARAM_DESCRIPTIONS.at),
|
|
2663
2724
|
to: tool3.schema.string().min(1).describe(PARAM_DESCRIPTIONS.to),
|
|
@@ -2666,7 +2727,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2666
2727
|
planHash: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.planHash),
|
|
2667
2728
|
language: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.language),
|
|
2668
2729
|
gitScope: tool3.schema.enum(GIT_SCOPES).optional().describe(PARAM_DESCRIPTIONS.gitScope)
|
|
2669
|
-
}, "
|
|
2730
|
+
}, "rename", async (input, context) => {
|
|
2670
2731
|
const filePath = resolvePath(context.directory, input.path);
|
|
2671
2732
|
await authorizeRead(context, filePath);
|
|
2672
2733
|
if (input.workspace) {
|
|
@@ -2676,7 +2737,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2676
2737
|
throw new Error("readseek could not identify a binding at the rename cursor");
|
|
2677
2738
|
await authorizeSearch(context, context.directory, name);
|
|
2678
2739
|
}
|
|
2679
|
-
const args =
|
|
2740
|
+
const args = buildRenameArgs({
|
|
2680
2741
|
path: filePath,
|
|
2681
2742
|
to: input.to,
|
|
2682
2743
|
at: input.at,
|
|
@@ -2696,7 +2757,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2696
2757
|
throw new Error("readseek rename plan did not include a plan hash");
|
|
2697
2758
|
}
|
|
2698
2759
|
await authorizeEdit(context, files);
|
|
2699
|
-
return runReadSeek(context,
|
|
2760
|
+
return runReadSeek(context, buildRenameArgs({
|
|
2700
2761
|
path: filePath,
|
|
2701
2762
|
to: input.to,
|
|
2702
2763
|
at: input.at,
|
|
@@ -2710,7 +2771,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2710
2771
|
timeoutMs: DEFAULT_READSEEK_TIMEOUT_MS
|
|
2711
2772
|
});
|
|
2712
2773
|
}),
|
|
2713
|
-
|
|
2774
|
+
readseek_edit: readseekTool(openCodeToolDescription("edit"), {
|
|
2714
2775
|
path: tool3.schema.string().describe(PARAM_DESCRIPTIONS.projectPath),
|
|
2715
2776
|
edits: tool3.schema.array(tool3.schema.union([
|
|
2716
2777
|
tool3.schema.object({
|
|
@@ -2750,7 +2811,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2750
2811
|
apply: tool3.schema.boolean().optional().describe(PARAM_DESCRIPTIONS.applyDefaultTrue),
|
|
2751
2812
|
planHash: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.planHash),
|
|
2752
2813
|
gitScope: tool3.schema.enum(GIT_SCOPES).optional().describe(PARAM_DESCRIPTIONS.gitScope)
|
|
2753
|
-
}, "
|
|
2814
|
+
}, "edit", async (input, context) => {
|
|
2754
2815
|
const filePath = resolvePath(context.directory, input.path);
|
|
2755
2816
|
validateEdits(input.edits);
|
|
2756
2817
|
return withFileMutationQueue(filePath, async () => {
|
|
@@ -2759,7 +2820,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2759
2820
|
await rejectSymlinkMutation(filePath);
|
|
2760
2821
|
const edits = input.edits;
|
|
2761
2822
|
const request = serializeEditPlan(edits);
|
|
2762
|
-
const baseArgs =
|
|
2823
|
+
const baseArgs = buildEditArgs({
|
|
2763
2824
|
path: filePath,
|
|
2764
2825
|
language: input.language,
|
|
2765
2826
|
gitScope: input.gitScope,
|
|
@@ -2783,7 +2844,7 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2783
2844
|
}
|
|
2784
2845
|
await authorizeEdit(context, [filePath], simpleDiff(filePath, before, after), false);
|
|
2785
2846
|
context.abort.throwIfAborted();
|
|
2786
|
-
const applied = record2(await runReadSeek(context,
|
|
2847
|
+
const applied = record2(await runReadSeek(context, buildEditArgs({
|
|
2787
2848
|
path: filePath,
|
|
2788
2849
|
language: input.language,
|
|
2789
2850
|
gitScope: input.gitScope,
|
|
@@ -2801,10 +2862,10 @@ function createReadSeekTools(imagePolicy) {
|
|
|
2801
2862
|
return postMutationPreview(context, previewArgs, filePath, true);
|
|
2802
2863
|
});
|
|
2803
2864
|
}),
|
|
2804
|
-
|
|
2865
|
+
readseek_write: readseekTool(openCodeToolDescription("write"), {
|
|
2805
2866
|
path: tool3.schema.string().describe(PARAM_DESCRIPTIONS.projectPath),
|
|
2806
2867
|
content: tool3.schema.string().describe(PARAM_DESCRIPTIONS.content)
|
|
2807
|
-
}, "
|
|
2868
|
+
}, "write", async (input, context) => {
|
|
2808
2869
|
const filePath = resolvePath(context.directory, input.path);
|
|
2809
2870
|
await authorizeExternal(context, filePath);
|
|
2810
2871
|
return withFileMutationQueue(filePath, async () => {
|
|
@@ -2828,37 +2889,37 @@ function createAccessTools(imagePolicy) {
|
|
|
2828
2889
|
const languageSchema = { language: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.language) };
|
|
2829
2890
|
const levelSchema = { level: tool3.schema.enum(VISION_LEVEL_VALUES).optional().describe(PARAM_DESCRIPTIONS.level) };
|
|
2830
2891
|
const definitions = {
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2892
|
+
show: { build: buildShowArgs, args: { ...pathSchema, ...atSchema, ...languageSchema, end: tool3.schema.number().int().positive().optional(), limit: tool3.schema.number().int().positive().optional(), noAnchors: tool3.schema.boolean().optional() } },
|
|
2893
|
+
tree: { build: buildTreeArgs, args: { ...pathSchema, ...atSchema, ...languageSchema, depth: tool3.schema.number().int().nonnegative().optional(), kind: tool3.schema.string().optional(), outline: tool3.schema.boolean().optional() } },
|
|
2894
|
+
meta: { build: buildMetaArgs, args: { ...pathSchema, ...languageSchema } },
|
|
2895
|
+
assets: { build: buildAssetsArgs, args: { ...pathSchema, ...atSchema } },
|
|
2896
|
+
syntax: { build: buildSyntaxArgs, args: { ...pathSchema, ...languageSchema } },
|
|
2897
|
+
check: { build: buildCheckArgs, args: { path: tool3.schema.string().optional().describe(PARAM_DESCRIPTIONS.projectSearchPath), rules: tool3.schema.string().min(1), gitScope: tool3.schema.enum(GIT_SCOPES).optional() } },
|
|
2898
|
+
caption: { build: buildCaptionArgs, args: { ...pathSchema, ...atSchema, ...levelSchema, include: tool3.schema.array(tool3.schema.enum(["text", "objects"])).min(1).optional() } },
|
|
2899
|
+
objects: { build: buildObjectsArgs, args: { ...pathSchema, ...atSchema, ...levelSchema } },
|
|
2900
|
+
ocr: { build: buildOcrArgs, args: { ...pathSchema, ...atSchema, ...levelSchema } }
|
|
2840
2901
|
};
|
|
2841
2902
|
return Object.fromEntries(Object.entries(definitions).map(([name, definition]) => [
|
|
2842
2903
|
`readseek_${name}`,
|
|
2843
2904
|
readseekTool(openCodeToolDescription(name), definition.args, name, async (input, context) => {
|
|
2844
2905
|
const filePath = resolvePath(context.directory, input.path ?? ".");
|
|
2845
|
-
const buildInput = { ...input, path: filePath, ...name === "
|
|
2906
|
+
const buildInput = { ...input, path: filePath, ...name === "tree" ? { depth: input.depth ?? DEFAULT_STRUCTURE_DEPTH } : {} };
|
|
2846
2907
|
let args = definition.build(buildInput);
|
|
2847
2908
|
await authorizeRead(context, filePath);
|
|
2848
|
-
if (name === "
|
|
2909
|
+
if (name === "check") {
|
|
2849
2910
|
if (input.rules === "-")
|
|
2850
2911
|
throw new Error("rules stdin is unavailable in OpenCode tools; use inline KDL or @path");
|
|
2851
2912
|
await authorizeSearch(context, filePath, input.rules);
|
|
2852
2913
|
if (input.rules.startsWith("@"))
|
|
2853
2914
|
await authorizeRead(context, resolvePath(context.directory, input.rules.slice(1)));
|
|
2854
2915
|
}
|
|
2855
|
-
const inference = ["
|
|
2856
|
-
if (name === "
|
|
2916
|
+
const inference = ["caption", "objects", "ocr"].includes(name);
|
|
2917
|
+
if (name === "show" || name === "assets" || inference) {
|
|
2857
2918
|
const readseekDir = await ensureReadSeekCache(context);
|
|
2858
2919
|
args = definition.build({ ...buildInput, readseekDir });
|
|
2859
2920
|
}
|
|
2860
2921
|
return runReadSeek(context, args, { timeoutMs: inference ? DEFAULT_VISION_TIMEOUT_MS : DEFAULT_READSEEK_TIMEOUT_MS });
|
|
2861
|
-
}, name === "
|
|
2922
|
+
}, name === "show" || name === "assets" ? imagePolicy : undefined)
|
|
2862
2923
|
]));
|
|
2863
2924
|
}
|
|
2864
2925
|
|
|
@@ -2873,28 +2934,28 @@ var SKILL = {
|
|
|
2873
2934
|
|
|
2874
2935
|
When ReadSeek tools are unavailable, use the readseek CLI for structural navigation and anchored edits if it is installed and available on PATH. Run \`readseek --help\` to inspect supported commands before invoking them. Get fresh anchors before editing; re-read after external file changes.
|
|
2875
2936
|
|
|
2876
|
-
Commands use
|
|
2937
|
+
Commands use flat single-word verbs, with target and primary query arguments positional:
|
|
2877
2938
|
|
|
2878
2939
|
\`\`\`sh
|
|
2879
|
-
readseek show
|
|
2880
|
-
readseek
|
|
2881
|
-
readseek
|
|
2882
|
-
readseek
|
|
2883
|
-
readseek
|
|
2884
|
-
readseek check
|
|
2885
|
-
readseek
|
|
2886
|
-
readseek
|
|
2887
|
-
readseek
|
|
2888
|
-
readseek
|
|
2889
|
-
readseek edit
|
|
2890
|
-
readseek rename
|
|
2940
|
+
readseek show file.ts --at line:10 --limit 40 --kdl
|
|
2941
|
+
readseek tree file.ts --depth 1 --kdl
|
|
2942
|
+
readseek meta paper.pdf --kdl
|
|
2943
|
+
readseek assets paper.pdf --at page:2 --kdl
|
|
2944
|
+
readseek syntax file.ts --kdl
|
|
2945
|
+
readseek check . @checks.kdl --kdl
|
|
2946
|
+
readseek search 'console.log($$$ARGS)' src --kdl
|
|
2947
|
+
readseek grep 'TODO' src --kdl
|
|
2948
|
+
readseek def main src --kdl
|
|
2949
|
+
readseek refs file.ts --at line:10:3 --kdl
|
|
2950
|
+
readseek edit file.ts @edits.kdl --kdl
|
|
2951
|
+
readseek rename file.ts --at line:10:3 nextName --kdl
|
|
2891
2952
|
\`\`\`
|
|
2892
2953
|
|
|
2893
|
-
Native \`
|
|
2954
|
+
Native \`grep\` is literal, not regex. Reference selection requires either a symbol \`name\` or \`--at\`; rename requires a line or hash cursor. Preview mutations first, then use \`--apply --plan-hash HASH\` with the returned plan hash. Edit requests are KDL: for example, \`set_line anchor="10:HASH" new_text="replacement"\`.
|
|
2894
2955
|
|
|
2895
2956
|
Syntax and rule checks return exit 0 when clean, 1 for findings, and 2 on failure. Exit 1 is not a transport failure. Syntax checks are parser checks, not type checking.
|
|
2896
2957
|
|
|
2897
|
-
Content and assets return cached paths; assets auto-materialize. Read those paths directly. There is no extract command or asset destination option. Reading does not invoke inference. Request inference explicitly with \`
|
|
2958
|
+
Content and assets return cached paths; assets auto-materialize. Read those paths directly. There is no extract command or asset destination option. Reading does not invoke inference. Request inference explicitly with \`caption\` (optionally \`--include text,objects\`), \`objects\`, or \`ocr\`, using \`--level low|medium|high\` and an installed model; models are never downloaded automatically.
|
|
2898
2959
|
|
|
2899
2960
|
This V2 plugin supplies guidance only; it does not register readseek_* tools. If the CLI is unavailable, use OpenCode's built-in tools instead.`
|
|
2900
2961
|
};
|
|
@@ -2951,7 +3012,7 @@ var ReadSeekPlugin = async (_input, options) => {
|
|
|
2951
3012
|
return;
|
|
2952
3013
|
try {
|
|
2953
3014
|
const result = output.metadata.readseek ?? JSON.parse(output.output);
|
|
2954
|
-
if (input.tool === "
|
|
3015
|
+
if (input.tool === "readseek_rename") {
|
|
2955
3016
|
anchors.planRename(input.sessionID, result);
|
|
2956
3017
|
if (record2(result).applied === true) {
|
|
2957
3018
|
for (const filePath of renameFiles(result))
|
package/dist/v2.js
CHANGED
|
@@ -9,28 +9,28 @@ var SKILL = {
|
|
|
9
9
|
|
|
10
10
|
When ReadSeek tools are unavailable, use the readseek CLI for structural navigation and anchored edits if it is installed and available on PATH. Run \`readseek --help\` to inspect supported commands before invoking them. Get fresh anchors before editing; re-read after external file changes.
|
|
11
11
|
|
|
12
|
-
Commands use
|
|
12
|
+
Commands use flat single-word verbs, with target and primary query arguments positional:
|
|
13
13
|
|
|
14
14
|
\`\`\`sh
|
|
15
|
-
readseek show
|
|
16
|
-
readseek
|
|
17
|
-
readseek
|
|
18
|
-
readseek
|
|
19
|
-
readseek
|
|
20
|
-
readseek check
|
|
21
|
-
readseek
|
|
22
|
-
readseek
|
|
23
|
-
readseek
|
|
24
|
-
readseek
|
|
25
|
-
readseek edit
|
|
26
|
-
readseek rename
|
|
15
|
+
readseek show file.ts --at line:10 --limit 40 --kdl
|
|
16
|
+
readseek tree file.ts --depth 1 --kdl
|
|
17
|
+
readseek meta paper.pdf --kdl
|
|
18
|
+
readseek assets paper.pdf --at page:2 --kdl
|
|
19
|
+
readseek syntax file.ts --kdl
|
|
20
|
+
readseek check . @checks.kdl --kdl
|
|
21
|
+
readseek search 'console.log($$$ARGS)' src --kdl
|
|
22
|
+
readseek grep 'TODO' src --kdl
|
|
23
|
+
readseek def main src --kdl
|
|
24
|
+
readseek refs file.ts --at line:10:3 --kdl
|
|
25
|
+
readseek edit file.ts @edits.kdl --kdl
|
|
26
|
+
readseek rename file.ts --at line:10:3 nextName --kdl
|
|
27
27
|
\`\`\`
|
|
28
28
|
|
|
29
|
-
Native \`
|
|
29
|
+
Native \`grep\` is literal, not regex. Reference selection requires either a symbol \`name\` or \`--at\`; rename requires a line or hash cursor. Preview mutations first, then use \`--apply --plan-hash HASH\` with the returned plan hash. Edit requests are KDL: for example, \`set_line anchor="10:HASH" new_text="replacement"\`.
|
|
30
30
|
|
|
31
31
|
Syntax and rule checks return exit 0 when clean, 1 for findings, and 2 on failure. Exit 1 is not a transport failure. Syntax checks are parser checks, not type checking.
|
|
32
32
|
|
|
33
|
-
Content and assets return cached paths; assets auto-materialize. Read those paths directly. There is no extract command or asset destination option. Reading does not invoke inference. Request inference explicitly with \`
|
|
33
|
+
Content and assets return cached paths; assets auto-materialize. Read those paths directly. There is no extract command or asset destination option. Reading does not invoke inference. Request inference explicitly with \`caption\` (optionally \`--include text,objects\`), \`objects\`, or \`ocr\`, using \`--level low|medium|high\` and an installed model; models are never downloaded automatically.
|
|
34
34
|
|
|
35
35
|
This V2 plugin supplies guidance only; it does not register readseek_* tools. If the CLI is unavailable, use OpenCode's built-in tools instead.`
|
|
36
36
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-readseek",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "OpenCode plugin for anchored file operations and structural code navigation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"node": ">=20.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@jarkkojs/readseek": "^0.
|
|
37
|
-
"@jarkkojs/readseek-api": "^0.
|
|
36
|
+
"@jarkkojs/readseek": "^0.12.0",
|
|
37
|
+
"@jarkkojs/readseek-api": "^0.12.0",
|
|
38
38
|
"@opencode-ai/plugin": "^1.18.18"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|