@jarkkojs/readseek-api 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 +8 -10
- package/dist/argv.d.ts +32 -30
- package/dist/client.d.ts +29 -29
- package/dist/contract.d.ts +20 -20
- package/dist/index.js +276 -215
- package/dist/show-presentation.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ platform binary; plugins declare both packages directly.
|
|
|
21
21
|
|
|
22
22
|
```ts
|
|
23
23
|
import {
|
|
24
|
-
|
|
24
|
+
buildTreeArgs,
|
|
25
25
|
resolveReadSeekBinaryFromPackages,
|
|
26
26
|
resolveReadSeekBinaryOverride,
|
|
27
27
|
runReadSeekNodeKdl,
|
|
@@ -29,14 +29,13 @@ import {
|
|
|
29
29
|
|
|
30
30
|
const binary =
|
|
31
31
|
resolveReadSeekBinaryOverride() ?? resolveReadSeekBinaryFromPackages();
|
|
32
|
-
const args =
|
|
32
|
+
const args = buildTreeArgs({ path: "src/index.ts", depth: 2 });
|
|
33
33
|
const result = await runReadSeekNodeKdl(binary, args);
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The API follows the CLI's
|
|
37
|
-
`
|
|
38
|
-
`
|
|
39
|
-
`recognizeText`, `editText`, and `renameSymbol`. Selection uses `at`.
|
|
36
|
+
The API follows the CLI's single-word command grammar: `show`, `tree`,
|
|
37
|
+
`meta`, `assets`, `search`, `grep`, `def`, `refs`, `syntax`, `check`,
|
|
38
|
+
`caption`, `objects`, `ocr`, `edit`, and `rename`. Selection uses `at`.
|
|
40
39
|
|
|
41
40
|
Document content and asset results include usable cached image paths. There is no
|
|
42
41
|
separate extraction step or destination argument. Cache population is an internal
|
|
@@ -44,14 +43,13 @@ write; reading never invokes inference. Syntax checks return diagnostics even
|
|
|
44
43
|
when the native process exits 1 (findings); exit 2 is a failure.
|
|
45
44
|
|
|
46
45
|
`presentShowResult()` and `formatShowResult()` provide shared readable output for
|
|
47
|
-
`
|
|
46
|
+
`show`, `tree`, `meta`, and `assets`. Summaries
|
|
48
47
|
identify selections and counts; bodies contain anchored lines, document sections,
|
|
49
48
|
structure trees, fields, or asset paths. Notices identify omitted source ranges
|
|
50
49
|
and how to continue. Formatting never mutates the decoded result.
|
|
51
50
|
|
|
52
|
-
This is a breaking contract: legacy `inspect`/`extract`
|
|
53
|
-
and old command names are removed, not aliased.
|
|
54
|
-
|
|
51
|
+
This is a breaking contract: two-word verb-object methods, legacy `inspect`/`extract`
|
|
52
|
+
methods, and old command names are removed, not aliased.
|
|
55
53
|
## Licensing
|
|
56
54
|
|
|
57
55
|
`@jarkkojs/readseek-api` is licensed under the Apache 2.0 license. See
|
package/dist/argv.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ type ParsedSelector = {
|
|
|
18
18
|
kind: SelectorKind;
|
|
19
19
|
value: string;
|
|
20
20
|
column?: number;
|
|
21
|
+
endLine?: number;
|
|
22
|
+
explicitKind: boolean;
|
|
21
23
|
};
|
|
22
24
|
/** Mirrors core::ParseSelector so wrappers reject the same selectors natively. */
|
|
23
25
|
export declare function parseSelector(text: string): ParsedSelector;
|
|
@@ -26,39 +28,39 @@ export type AccessArgsInput = {
|
|
|
26
28
|
stdinName?: string;
|
|
27
29
|
readseekDir?: string;
|
|
28
30
|
};
|
|
29
|
-
export type
|
|
31
|
+
export type ShowArgsInput = AccessArgsInput & {
|
|
30
32
|
at?: string;
|
|
31
33
|
end?: number;
|
|
32
34
|
limit?: number;
|
|
33
35
|
language?: string;
|
|
34
36
|
noAnchors?: boolean;
|
|
35
37
|
};
|
|
36
|
-
export type
|
|
38
|
+
export type TreeArgsInput = AccessArgsInput & {
|
|
37
39
|
at?: string;
|
|
38
40
|
depth?: number;
|
|
39
41
|
kind?: string;
|
|
40
42
|
outline?: boolean;
|
|
41
43
|
language?: string;
|
|
42
44
|
};
|
|
43
|
-
export type
|
|
45
|
+
export type MetaArgsInput = AccessArgsInput & {
|
|
44
46
|
language?: string;
|
|
45
47
|
};
|
|
46
|
-
export type
|
|
48
|
+
export type AssetsArgsInput = AccessArgsInput & {
|
|
47
49
|
at?: string;
|
|
48
50
|
};
|
|
49
|
-
export type
|
|
51
|
+
export type SyntaxArgsInput = AccessArgsInput & {
|
|
50
52
|
language?: string;
|
|
51
53
|
};
|
|
52
54
|
export type VisionArgsInput = AccessArgsInput & {
|
|
53
55
|
at?: string;
|
|
54
56
|
level?: VisionLevel;
|
|
55
57
|
};
|
|
56
|
-
export type
|
|
58
|
+
export type CaptionArgsInput = VisionArgsInput & {
|
|
57
59
|
include?: ("text" | "objects")[];
|
|
58
60
|
};
|
|
59
|
-
export type
|
|
60
|
-
export type
|
|
61
|
-
export type
|
|
61
|
+
export type ObjectsArgsInput = VisionArgsInput;
|
|
62
|
+
export type OcrArgsInput = VisionArgsInput;
|
|
63
|
+
export type SearchArgsInput = AccessArgsInput & GitScopeInput & {
|
|
62
64
|
pattern?: string;
|
|
63
65
|
context?: string;
|
|
64
66
|
selector?: string;
|
|
@@ -67,29 +69,29 @@ export type FindNodesArgsInput = AccessArgsInput & GitScopeInput & {
|
|
|
67
69
|
limit?: number;
|
|
68
70
|
noAnchors?: boolean;
|
|
69
71
|
};
|
|
70
|
-
export type
|
|
72
|
+
export type GrepArgsInput = {
|
|
71
73
|
path: string;
|
|
72
74
|
text: string;
|
|
73
75
|
limit?: number;
|
|
74
76
|
} & GitScopeInput;
|
|
75
|
-
export type
|
|
77
|
+
export type DefArgsInput = {
|
|
76
78
|
path: string;
|
|
77
79
|
name: string;
|
|
78
80
|
language?: string;
|
|
79
81
|
noAnchors?: boolean;
|
|
80
82
|
} & GitScopeInput;
|
|
81
|
-
export type
|
|
83
|
+
export type RefsArgsInput = {
|
|
82
84
|
path: string;
|
|
83
85
|
name?: string;
|
|
84
86
|
at?: string;
|
|
85
87
|
language?: string;
|
|
86
88
|
noAnchors?: boolean;
|
|
87
89
|
} & GitScopeInput;
|
|
88
|
-
export type
|
|
90
|
+
export type CheckArgsInput = {
|
|
89
91
|
path: string;
|
|
90
92
|
rules: string;
|
|
91
93
|
} & GitScopeInput;
|
|
92
|
-
export type
|
|
94
|
+
export type EditArgsInput = {
|
|
93
95
|
path: string;
|
|
94
96
|
apply?: boolean;
|
|
95
97
|
planHash?: string;
|
|
@@ -97,7 +99,7 @@ export type EditTextArgsInput = {
|
|
|
97
99
|
requestFromStdin?: boolean;
|
|
98
100
|
flagOrder?: ApplyPlanHashOrder;
|
|
99
101
|
} & GitScopeInput;
|
|
100
|
-
export type
|
|
102
|
+
export type RenameArgsInput = {
|
|
101
103
|
path: string;
|
|
102
104
|
to: string;
|
|
103
105
|
at: string;
|
|
@@ -107,19 +109,19 @@ export type RenameSymbolArgsInput = {
|
|
|
107
109
|
language?: string;
|
|
108
110
|
flagOrder?: ApplyPlanHashOrder;
|
|
109
111
|
} & GitScopeInput;
|
|
110
|
-
export declare function
|
|
111
|
-
export declare function
|
|
112
|
-
export declare function
|
|
113
|
-
export declare function
|
|
114
|
-
export declare function
|
|
115
|
-
export declare function
|
|
116
|
-
export declare function
|
|
117
|
-
export declare function
|
|
118
|
-
export declare function
|
|
119
|
-
export declare function
|
|
120
|
-
export declare function
|
|
121
|
-
export declare function
|
|
122
|
-
export declare function
|
|
123
|
-
export declare function
|
|
124
|
-
export declare function
|
|
112
|
+
export declare function buildShowArgs(input: ShowArgsInput): string[];
|
|
113
|
+
export declare function buildTreeArgs(input: TreeArgsInput): string[];
|
|
114
|
+
export declare function buildMetaArgs(input: MetaArgsInput): string[];
|
|
115
|
+
export declare function buildAssetsArgs(input: AssetsArgsInput): string[];
|
|
116
|
+
export declare function buildSyntaxArgs(input: SyntaxArgsInput): string[];
|
|
117
|
+
export declare function buildCaptionArgs(input: CaptionArgsInput): string[];
|
|
118
|
+
export declare function buildObjectsArgs(input: ObjectsArgsInput): string[];
|
|
119
|
+
export declare function buildOcrArgs(input: OcrArgsInput): string[];
|
|
120
|
+
export declare function buildSearchArgs(input: SearchArgsInput): string[];
|
|
121
|
+
export declare function buildGrepArgs(input: GrepArgsInput): string[];
|
|
122
|
+
export declare function buildDefArgs(input: DefArgsInput): string[];
|
|
123
|
+
export declare function buildRefsArgs(input: RefsArgsInput): string[];
|
|
124
|
+
export declare function buildCheckArgs(input: CheckArgsInput): string[];
|
|
125
|
+
export declare function buildEditArgs(input: EditArgsInput): string[];
|
|
126
|
+
export declare function buildRenameArgs(input: RenameArgsInput): string[];
|
|
125
127
|
export {};
|
package/dist/client.d.ts
CHANGED
|
@@ -13,20 +13,20 @@ export interface ReadSeekRunner {
|
|
|
13
13
|
kdl(args: readonly string[], options?: ReadSeekRunOptions): Promise<unknown>;
|
|
14
14
|
}
|
|
15
15
|
type Options<T> = Omit<T, "path" | "requestFromStdin" | "flagOrder"> & Omit<ReadSeekRunOptions, "vision">;
|
|
16
|
-
export type
|
|
17
|
-
export type
|
|
18
|
-
export type
|
|
19
|
-
export type ReadSeekAssetsOptions = Options<argv.
|
|
20
|
-
export type ReadSeekSyntaxOptions = Options<argv.
|
|
21
|
-
export type
|
|
22
|
-
export type ReadSeekCaptionOptions = Options<argv.
|
|
23
|
-
export type ReadSeekVisionOptions = Options<argv.
|
|
24
|
-
export type
|
|
25
|
-
export type
|
|
26
|
-
export type
|
|
27
|
-
export type
|
|
28
|
-
export type ReadSeekEditOptions = Options<argv.
|
|
29
|
-
export type ReadSeekRenameOptions = Options<argv.
|
|
16
|
+
export type ReadSeekShowOptions = Options<argv.ShowArgsInput>;
|
|
17
|
+
export type ReadSeekTreeOptions = Options<argv.TreeArgsInput>;
|
|
18
|
+
export type ReadSeekMetaOptions = Options<argv.MetaArgsInput>;
|
|
19
|
+
export type ReadSeekAssetsOptions = Options<argv.AssetsArgsInput>;
|
|
20
|
+
export type ReadSeekSyntaxOptions = Options<argv.SyntaxArgsInput>;
|
|
21
|
+
export type ReadSeekCheckOptions = Options<argv.CheckArgsInput>;
|
|
22
|
+
export type ReadSeekCaptionOptions = Options<argv.CaptionArgsInput>;
|
|
23
|
+
export type ReadSeekVisionOptions = Options<argv.ObjectsArgsInput>;
|
|
24
|
+
export type ReadSeekSearchOptions = Options<argv.SearchArgsInput>;
|
|
25
|
+
export type ReadSeekGrepOptions = Options<argv.GrepArgsInput>;
|
|
26
|
+
export type ReadSeekDefOptions = Options<argv.DefArgsInput>;
|
|
27
|
+
export type ReadSeekRefsOptions = Options<argv.RefsArgsInput>;
|
|
28
|
+
export type ReadSeekEditOptions = Options<argv.EditArgsInput>;
|
|
29
|
+
export type ReadSeekRenameOptions = Options<argv.RenameArgsInput>;
|
|
30
30
|
export interface ReadSeekFailure {
|
|
31
31
|
code: "readseek-not-installed" | "readseek-execution-error";
|
|
32
32
|
message: string;
|
|
@@ -39,20 +39,20 @@ export interface ReadSeekFailure {
|
|
|
39
39
|
*/
|
|
40
40
|
export declare function classifyReadSeekFailure(err: unknown): ReadSeekFailure;
|
|
41
41
|
export interface ReadSeekClient {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
show(path: string, options?: ReadSeekShowOptions): Promise<output.ReadSeekContentOutput>;
|
|
43
|
+
tree(path: string, options?: ReadSeekTreeOptions): Promise<output.ReadSeekStructureOutputEnvelope>;
|
|
44
|
+
meta(path: string, options?: ReadSeekMetaOptions): Promise<output.ReadSeekDetection>;
|
|
45
|
+
assets(path: string, options?: ReadSeekAssetsOptions): Promise<output.ReadSeekAssetsOutput>;
|
|
46
|
+
syntax(path: string, options?: ReadSeekSyntaxOptions): Promise<output.ReadSeekCheckOutput>;
|
|
47
|
+
check(path: string, options: ReadSeekCheckOptions): Promise<output.ReadSeekRulesOutput>;
|
|
48
|
+
caption(path: string, options?: ReadSeekCaptionOptions): Promise<output.ReadSeekContentOutput>;
|
|
49
|
+
objects(path: string, options?: ReadSeekVisionOptions): Promise<output.ReadSeekContentOutput>;
|
|
50
|
+
ocr(path: string, options?: ReadSeekVisionOptions): Promise<output.ReadSeekContentOutput>;
|
|
51
|
+
search(path: string, options: ReadSeekSearchOptions): Promise<output.ReadSeekSearchOutput>;
|
|
52
|
+
grep(path: string, options: ReadSeekGrepOptions): Promise<output.ReadSeekTextSearchOutput>;
|
|
53
|
+
def(path: string, options: ReadSeekDefOptions): Promise<output.DefLocation[]>;
|
|
54
|
+
refs(path: string, options: ReadSeekRefsOptions): Promise<output.ReadSeekReference[]>;
|
|
55
|
+
edit(path: string, edits: unknown[], options?: ReadSeekEditOptions): Promise<output.EditOutput>;
|
|
56
|
+
rename(path: string, options: ReadSeekRenameOptions): Promise<output.RenameOutput>;
|
|
57
57
|
}
|
|
58
58
|
export declare function createReadSeekClient(runner: ReadSeekRunner): ReadSeekClient;
|
package/dist/contract.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const EDIT_VARIANTS: readonly ["set_line", "replace_lines", "inse
|
|
|
4
4
|
export type EditVariant = (typeof EDIT_VARIANTS)[number];
|
|
5
5
|
export declare const GIT_SCOPES: readonly ["tracked", "untracked", "ignored", "all"];
|
|
6
6
|
export type GitScope = (typeof GIT_SCOPES)[number];
|
|
7
|
-
export declare const TOOL_NAMES: readonly ["
|
|
7
|
+
export declare const TOOL_NAMES: readonly ["show", "tree", "meta", "assets", "syntax", "check", "caption", "objects", "ocr", "search", "grep", "def", "refs", "edit", "rename", "write"];
|
|
8
8
|
export type ToolName = (typeof TOOL_NAMES)[number];
|
|
9
9
|
export declare const PARAM_DESCRIPTIONS: {
|
|
10
10
|
readonly path: "Absolute or relative file path";
|
|
@@ -20,8 +20,8 @@ export declare const PARAM_DESCRIPTIONS: {
|
|
|
20
20
|
readonly name: "Qualified or unqualified symbol name";
|
|
21
21
|
readonly refsName: "Identifier to find references for";
|
|
22
22
|
readonly gitScope: "In a Git repository, which files to search: tracked, untracked, ignored (untracked plus ignored), or all. Defaults to tracked plus untracked.";
|
|
23
|
-
readonly at: "Location selector: line:N[:COLUMN], hash:H[:COLUMN], symbol:NAME, page:N, node:ID, or asset:ID";
|
|
24
|
-
readonly assetAt: "Document selector: page:N, node:ID, or asset:ID";
|
|
23
|
+
readonly 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";
|
|
24
|
+
readonly assetAt: "Document selector: N, page:N, node:ID, or asset:ID";
|
|
25
25
|
readonly rule: "KDL node selection rule, @path, or '-' for standard input";
|
|
26
26
|
readonly rules: "KDL structural checks, @path, or '-' for standard input";
|
|
27
27
|
readonly stdinName: "File name hint when the target is '-'";
|
|
@@ -33,7 +33,7 @@ export declare const PARAM_DESCRIPTIONS: {
|
|
|
33
33
|
readonly kind: "Restrict structure to this node kind";
|
|
34
34
|
readonly outline: "Show outline of document hierarchy or source symbols";
|
|
35
35
|
readonly noAnchors: "Omit source line anchors";
|
|
36
|
-
readonly text: "Literal native text query; adapter
|
|
36
|
+
readonly text: "Literal native text query; adapter grep also supports regex via pattern";
|
|
37
37
|
readonly edits: "Use set_line, replace_lines, insert_after, replace_symbol, or replace";
|
|
38
38
|
readonly editVariant: "Exactly one nested edit variant";
|
|
39
39
|
readonly setLine: "Replace one line: {\"set_line\":{\"anchor\":\"LINE:HASH\",\"new_text\":\"...\"}}";
|
|
@@ -70,22 +70,22 @@ export declare const PARAM_DESCRIPTIONS: {
|
|
|
70
70
|
readonly scopeContext: "Context lines within each symbol";
|
|
71
71
|
};
|
|
72
72
|
export declare const TOOL_DESCRIPTIONS: {
|
|
73
|
-
readonly
|
|
74
|
-
readonly
|
|
75
|
-
readonly
|
|
76
|
-
readonly
|
|
77
|
-
readonly
|
|
78
|
-
readonly
|
|
79
|
-
readonly
|
|
80
|
-
readonly
|
|
81
|
-
readonly
|
|
82
|
-
readonly
|
|
83
|
-
readonly
|
|
84
|
-
readonly
|
|
85
|
-
readonly
|
|
86
|
-
readonly
|
|
87
|
-
readonly
|
|
88
|
-
readonly
|
|
73
|
+
readonly 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.";
|
|
74
|
+
readonly tree: "Show parsed source or document hierarchy. Use shallow depth for file overviews.";
|
|
75
|
+
readonly meta: "Show format, source identity, language, dimensions, or page count without decoding image content or inference.";
|
|
76
|
+
readonly assets: "Return selected document asset descriptors with usable cached paths. Adapters attach images from those paths.";
|
|
77
|
+
readonly syntax: "Check parser syntax diagnostics. Exit 0 is clean, 1 has findings, 2 is failure; this is not type checking.";
|
|
78
|
+
readonly check: "Evaluate KDL structural assertions. Exit 0 is clean, 1 has findings, 2 is failure.";
|
|
79
|
+
readonly caption: "Explicitly infer a caption using an installed model. Include text and objects to request OCR and detection too; never downloads models automatically.";
|
|
80
|
+
readonly objects: "Explicitly infer object labels and bounding boxes using an installed model.";
|
|
81
|
+
readonly ocr: "Explicitly recognize text from pixels using an installed model; reading never silently invokes OCR.";
|
|
82
|
+
readonly search: "Find AST nodes by pattern or KDL selection rule. Returns edit-ready anchors. Use `grep` for text and regex.";
|
|
83
|
+
readonly 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.";
|
|
84
|
+
readonly def: "Find a symbol definition or declaration by qualified or unqualified name.";
|
|
85
|
+
readonly refs: "Find identifier-name matches with name, or binding-scoped references with at. Use before renaming or deleting a symbol.";
|
|
86
|
+
readonly 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.";
|
|
87
|
+
readonly rename: "Rename a symbol at a line or hash cursor with binding-aware edits and stale-plan protection.";
|
|
88
|
+
readonly write: "Create or replace a complete text file and return `LINE:HASH` anchors. Use `edit` for small changes.";
|
|
89
89
|
};
|
|
90
90
|
export declare function rewriteBacktickedToolNames(text: string, aliases?: Readonly<Partial<Record<ToolName, string>>>): string;
|
|
91
91
|
export declare function renderToolDescription(name: ToolName, aliases?: Readonly<Partial<Record<ToolName, string>>>): string;
|
package/dist/index.js
CHANGED
|
@@ -9,22 +9,22 @@ var EDIT_VARIANTS = [
|
|
|
9
9
|
];
|
|
10
10
|
var GIT_SCOPES = ["tracked", "untracked", "ignored", "all"];
|
|
11
11
|
var TOOL_NAMES = [
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
12
|
+
"show",
|
|
13
|
+
"tree",
|
|
14
|
+
"meta",
|
|
15
|
+
"assets",
|
|
16
|
+
"syntax",
|
|
17
|
+
"check",
|
|
18
|
+
"caption",
|
|
19
|
+
"objects",
|
|
20
|
+
"ocr",
|
|
21
|
+
"search",
|
|
22
|
+
"grep",
|
|
23
|
+
"def",
|
|
24
|
+
"refs",
|
|
25
|
+
"edit",
|
|
26
|
+
"rename",
|
|
27
|
+
"write"
|
|
28
28
|
];
|
|
29
29
|
var PARAM_DESCRIPTIONS = {
|
|
30
30
|
path: "Absolute or relative file path",
|
|
@@ -40,8 +40,8 @@ var PARAM_DESCRIPTIONS = {
|
|
|
40
40
|
name: "Qualified or unqualified symbol name",
|
|
41
41
|
refsName: "Identifier to find references for",
|
|
42
42
|
gitScope: "In a Git repository, which files to search: tracked, untracked, ignored (untracked plus ignored), or all. Defaults to tracked plus untracked.",
|
|
43
|
-
at: "Location selector: line:N[:COLUMN], hash:H[:COLUMN], symbol:NAME, page:N, node:ID, or asset:ID",
|
|
44
|
-
assetAt: "Document selector: page:N, node:ID, or asset:ID",
|
|
43
|
+
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",
|
|
44
|
+
assetAt: "Document selector: N, page:N, node:ID, or asset:ID",
|
|
45
45
|
rule: "KDL node selection rule, @path, or '-' for standard input",
|
|
46
46
|
rules: "KDL structural checks, @path, or '-' for standard input",
|
|
47
47
|
stdinName: "File name hint when the target is '-'",
|
|
@@ -53,7 +53,7 @@ var PARAM_DESCRIPTIONS = {
|
|
|
53
53
|
kind: "Restrict structure to this node kind",
|
|
54
54
|
outline: "Show outline of document hierarchy or source symbols",
|
|
55
55
|
noAnchors: "Omit source line anchors",
|
|
56
|
-
text: "Literal native text query; adapter
|
|
56
|
+
text: "Literal native text query; adapter grep also supports regex via pattern",
|
|
57
57
|
edits: "Use set_line, replace_lines, insert_after, replace_symbol, or replace",
|
|
58
58
|
editVariant: "Exactly one nested edit variant",
|
|
59
59
|
setLine: 'Replace one line: {"set_line":{"anchor":"LINE:HASH","new_text":"..."}}',
|
|
@@ -90,22 +90,22 @@ var PARAM_DESCRIPTIONS = {
|
|
|
90
90
|
scopeContext: "Context lines within each symbol"
|
|
91
91
|
};
|
|
92
92
|
var TOOL_DESCRIPTIONS = {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
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.",
|
|
94
|
+
tree: "Show parsed source or document hierarchy. Use shallow depth for file overviews.",
|
|
95
|
+
meta: "Show format, source identity, language, dimensions, or page count without decoding image content or inference.",
|
|
96
|
+
assets: "Return selected document asset descriptors with usable cached paths. Adapters attach images from those paths.",
|
|
97
|
+
syntax: "Check parser syntax diagnostics. Exit 0 is clean, 1 has findings, 2 is failure; this is not type checking.",
|
|
98
|
+
check: "Evaluate KDL structural assertions. Exit 0 is clean, 1 has findings, 2 is failure.",
|
|
99
|
+
caption: "Explicitly infer a caption using an installed model. Include text and objects to request OCR and detection too; never downloads models automatically.",
|
|
100
|
+
objects: "Explicitly infer object labels and bounding boxes using an installed model.",
|
|
101
|
+
ocr: "Explicitly recognize text from pixels using an installed model; reading never silently invokes OCR.",
|
|
102
|
+
search: "Find AST nodes by pattern or KDL selection rule. Returns edit-ready anchors. Use `grep` for text and regex.",
|
|
103
|
+
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.",
|
|
104
|
+
def: "Find a symbol definition or declaration by qualified or unqualified name.",
|
|
105
|
+
refs: "Find identifier-name matches with name, or binding-scoped references with at. Use before renaming or deleting a symbol.",
|
|
106
|
+
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.",
|
|
107
|
+
rename: "Rename a symbol at a line or hash cursor with binding-aware edits and stale-plan protection.",
|
|
108
|
+
write: "Create or replace a complete text file and return `LINE:HASH` anchors. Use `edit` for small changes."
|
|
109
109
|
};
|
|
110
110
|
function rewriteBacktickedToolNames(text, aliases = {}) {
|
|
111
111
|
return TOOL_NAMES.reduce((rewritten, toolName) => rewritten.replaceAll(`\`${toolName}\``, `\`${aliases[toolName] ?? toolName}\``), text);
|
|
@@ -198,22 +198,22 @@ function tool(name, title, properties, required) {
|
|
|
198
198
|
return { name, title, description: TOOL_DESCRIPTIONS[name], inputSchema: { type: "object", properties, required, additionalProperties: false } };
|
|
199
199
|
}
|
|
200
200
|
var TOOL_CONTRACTS = [
|
|
201
|
-
tool("
|
|
202
|
-
tool("
|
|
203
|
-
tool("
|
|
204
|
-
tool("
|
|
205
|
-
tool("
|
|
206
|
-
tool("
|
|
207
|
-
tool("
|
|
208
|
-
tool("
|
|
209
|
-
tool("
|
|
210
|
-
tool("
|
|
211
|
-
tool("
|
|
212
|
-
tool("
|
|
213
|
-
tool("
|
|
214
|
-
tool("
|
|
215
|
-
tool("
|
|
216
|
-
tool("
|
|
201
|
+
tool("show", "Show content", { ...path, ...at, ...lang, ...stdin, ...noAnchors, end: integer(PARAM_DESCRIPTIONS.end), limit: integer(PARAM_DESCRIPTIONS.limit) }, ["path"]),
|
|
202
|
+
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"]),
|
|
203
|
+
tool("meta", "Show metadata", { ...path, ...lang, ...stdin }, ["path"]),
|
|
204
|
+
tool("assets", "Show assets", { ...path, at: string(PARAM_DESCRIPTIONS.assetAt), ...stdin }, ["path"]),
|
|
205
|
+
tool("syntax", "Check syntax", { ...path, ...lang, ...stdin }, ["path"]),
|
|
206
|
+
tool("check", "Check rules", { path: string(PARAM_DESCRIPTIONS.searchPath), ...gitScopeSchema, rules: string(PARAM_DESCRIPTIONS.rules) }, ["rules"]),
|
|
207
|
+
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"]),
|
|
208
|
+
tool("objects", "Detect objects", { ...path, ...at, ...stdin, ...level }, ["path"]),
|
|
209
|
+
tool("ocr", "Recognize text", { ...path, ...at, ...stdin, ...level }, ["path"]),
|
|
210
|
+
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) }, []),
|
|
211
|
+
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) }, []),
|
|
212
|
+
tool("def", "Find definitions", { ...path, ...lang, ...gitScopeSchema, ...noAnchors, name: string(PARAM_DESCRIPTIONS.name) }, ["name"]),
|
|
213
|
+
tool("refs", "Find references", { ...path, ...at, ...lang, ...gitScopeSchema, ...noAnchors, name: string(PARAM_DESCRIPTIONS.refsName) }, []),
|
|
214
|
+
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"]),
|
|
215
|
+
tool("rename", "Rename symbol", { ...path, ...at, ...lang, ...gitScopeSchema, ...apply, to: string(PARAM_DESCRIPTIONS.to), workspace: { type: "boolean", description: PARAM_DESCRIPTIONS.workspace } }, ["path", "at", "to"]),
|
|
216
|
+
tool("write", "Write file", { ...path, content: string(PARAM_DESCRIPTIONS.content) }, ["path", "content"])
|
|
217
217
|
];
|
|
218
218
|
function getToolContract(name) {
|
|
219
219
|
const contract = TOOL_CONTRACTS.find((entry) => entry.name === name);
|
|
@@ -224,70 +224,70 @@ function getToolContract(name) {
|
|
|
224
224
|
// src/policy.ts
|
|
225
225
|
var REPLACEABLE_TOOLS = [
|
|
226
226
|
{
|
|
227
|
-
tool: "
|
|
227
|
+
tool: "show",
|
|
228
228
|
builtIn: "read",
|
|
229
229
|
benefit: "it returns LINE:HASH anchors for safe edits."
|
|
230
230
|
},
|
|
231
231
|
{
|
|
232
|
-
tool: "
|
|
232
|
+
tool: "edit",
|
|
233
233
|
builtIn: "edit",
|
|
234
234
|
benefit: "it verifies fresh LINE:HASH anchors."
|
|
235
235
|
},
|
|
236
236
|
{
|
|
237
|
-
tool: "
|
|
237
|
+
tool: "grep",
|
|
238
238
|
builtIn: "grep",
|
|
239
239
|
benefit: "it returns LINE:HASH anchors."
|
|
240
240
|
},
|
|
241
241
|
{
|
|
242
|
-
tool: "
|
|
242
|
+
tool: "write",
|
|
243
243
|
builtIn: "write",
|
|
244
244
|
benefit: "it returns LINE:HASH anchors."
|
|
245
245
|
}
|
|
246
246
|
];
|
|
247
247
|
var TOOL_COMPACT_GUIDELINES = {
|
|
248
|
-
|
|
249
|
-
"Use `
|
|
248
|
+
show: [
|
|
249
|
+
"Use `tree` for shallow overviews and `syntax` for diagnostics; use `def`, `refs`, or `search` for targeted symbol questions."
|
|
250
250
|
],
|
|
251
|
-
|
|
251
|
+
edit: [
|
|
252
252
|
"Prefer set_line, replace_lines, and insert_after; use replace only when anchors are impractical."
|
|
253
253
|
],
|
|
254
|
-
|
|
255
|
-
"Use `
|
|
254
|
+
grep: [
|
|
255
|
+
"Use `grep` with summary first for broad searches, then narrow by path, glob, or pattern."
|
|
256
256
|
],
|
|
257
|
-
|
|
258
|
-
"Use anchored edits rather than `
|
|
257
|
+
write: [
|
|
258
|
+
"Use anchored edits rather than `write` for small changes or appends."
|
|
259
259
|
],
|
|
260
|
-
|
|
261
|
-
"Use `
|
|
260
|
+
search: [
|
|
261
|
+
"Use `search` for AST patterns; use `grep` for plain text."
|
|
262
262
|
],
|
|
263
|
-
|
|
264
|
-
"Use `
|
|
263
|
+
refs: [
|
|
264
|
+
"Use `refs` before changing a symbol; use at with line:N:C to follow one binding."
|
|
265
265
|
]
|
|
266
266
|
};
|
|
267
267
|
var BUILTIN_FALLBACKS = {
|
|
268
|
-
read: "
|
|
269
|
-
edit: "
|
|
270
|
-
write: "
|
|
271
|
-
grep: "
|
|
272
|
-
apply_patch: "
|
|
268
|
+
read: "show",
|
|
269
|
+
edit: "edit",
|
|
270
|
+
write: "write",
|
|
271
|
+
grep: "grep",
|
|
272
|
+
apply_patch: "edit"
|
|
273
273
|
};
|
|
274
274
|
var PREFERENCE_LEADS = {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
275
|
+
show: "Preferred for reading source with anchors.",
|
|
276
|
+
edit: "Preferred for editing existing text files with fresh LINE:HASH anchors.",
|
|
277
|
+
write: "Preferred for creating or replacing a complete text file; returns LINE:HASH anchors.",
|
|
278
|
+
grep: "Preferred text/regex search; returns edit-ready LINE:HASH anchors.",
|
|
279
|
+
search: "Preferred for AST or structural code search with ast-grep-style patterns.",
|
|
280
|
+
def: "Preferred for go-to-definition or declaration lookup by name.",
|
|
281
|
+
refs: "Preferred for finding identifier-name matches or binding-specific references before `rename` or delete.",
|
|
282
|
+
rename: "Preferred for renaming a symbol with binding-aware, verified edits.",
|
|
283
|
+
assets: "Preferred for materializing selected document assets with usable cached paths."
|
|
284
284
|
};
|
|
285
285
|
var FALLBACK_TEMPLATES = {
|
|
286
|
-
read: "Prefer `
|
|
287
|
-
edit: "Prefer `
|
|
288
|
-
write: "Prefer `
|
|
289
|
-
grep: "Prefer `
|
|
290
|
-
apply_patch: "Prefer `
|
|
286
|
+
read: "Prefer `show` with fresh LINE:HASH anchors.",
|
|
287
|
+
edit: "Prefer `edit` with fresh LINE:HASH anchors.",
|
|
288
|
+
write: "Prefer `write` so the result returns LINE:HASH anchors.",
|
|
289
|
+
grep: "Prefer `grep` for text/regex search with edit-ready anchors.",
|
|
290
|
+
apply_patch: "Prefer `edit` for existing text files."
|
|
291
291
|
};
|
|
292
292
|
function resolveToolName(name, aliases = {}) {
|
|
293
293
|
return aliases[name] ?? name;
|
|
@@ -306,21 +306,21 @@ function renderFallbackToolDescription(builtIn, aliases = {}) {
|
|
|
306
306
|
}
|
|
307
307
|
function renderToolRoutingPolicy(options = {}) {
|
|
308
308
|
const aliases = options.aliases ?? {};
|
|
309
|
-
const
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
const
|
|
315
|
-
const
|
|
316
|
-
const
|
|
317
|
-
const
|
|
309
|
+
const show = resolveToolName("show", aliases);
|
|
310
|
+
const edit = resolveToolName("edit", aliases);
|
|
311
|
+
const write = resolveToolName("write", aliases);
|
|
312
|
+
const grep = resolveToolName("grep", aliases);
|
|
313
|
+
const search = resolveToolName("search", aliases);
|
|
314
|
+
const def = resolveToolName("def", aliases);
|
|
315
|
+
const refs = resolveToolName("refs", aliases);
|
|
316
|
+
const rename = resolveToolName("rename", aliases);
|
|
317
|
+
const assets = resolveToolName("assets", aliases);
|
|
318
318
|
const title = options.title ?? "ReadSeek tool policy:";
|
|
319
319
|
const bullets = [];
|
|
320
320
|
if (options.preferOverBuiltIns) {
|
|
321
321
|
bullets.push("- Prefer ReadSeek tools over built-ins when they can do the job.");
|
|
322
322
|
}
|
|
323
|
-
bullets.push(`- Read with ${
|
|
323
|
+
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.`);
|
|
324
324
|
if (options.demoteBuiltIns && options.demoteBuiltIns.length > 0) {
|
|
325
325
|
bullets.push(`- Do not use built-in ${options.demoteBuiltIns.join(", ")} when a ReadSeek tool can do the job.`);
|
|
326
326
|
}
|
|
@@ -530,50 +530,111 @@ var SELECTOR_KINDS = ["line", "hash", "symbol", "page", "node", "asset"];
|
|
|
530
530
|
function isSelectorKind(value) {
|
|
531
531
|
return SELECTOR_KINDS.includes(value);
|
|
532
532
|
}
|
|
533
|
+
function parsePositiveSelectorInt(raw, name) {
|
|
534
|
+
if (!/^-?\d+$/.test(raw))
|
|
535
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
536
|
+
const parsed = Number(raw);
|
|
537
|
+
if (!Number.isSafeInteger(parsed))
|
|
538
|
+
throw new Error(`invalid ${name} \`${raw}\``);
|
|
539
|
+
if (parsed < 1)
|
|
540
|
+
throw new Error(`${name} must be greater than zero`);
|
|
541
|
+
return parsed;
|
|
542
|
+
}
|
|
543
|
+
function parseLineSelector(value, explicitKind) {
|
|
544
|
+
const parts = value.split(":");
|
|
545
|
+
if (parts.length > 2)
|
|
546
|
+
throw new Error("selector has too many components");
|
|
547
|
+
const head = parts[0];
|
|
548
|
+
if (parts.length === 2) {
|
|
549
|
+
if (head.slice(1).includes("-"))
|
|
550
|
+
throw new Error("line range cannot include a column");
|
|
551
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
552
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
553
|
+
return { kind: "line", value: String(line), column, explicitKind };
|
|
554
|
+
}
|
|
555
|
+
const dash = head.indexOf("-", 1);
|
|
556
|
+
if (dash > 0) {
|
|
557
|
+
const start = parsePositiveSelectorInt(head.slice(0, dash), "line");
|
|
558
|
+
const endLine = parsePositiveSelectorInt(head.slice(dash + 1), "end line");
|
|
559
|
+
if (endLine < start)
|
|
560
|
+
throw new Error(`end line ${endLine} precedes start line ${start}`);
|
|
561
|
+
return { kind: "line", value: String(start), endLine, explicitKind };
|
|
562
|
+
}
|
|
563
|
+
const line = parsePositiveSelectorInt(head, "line");
|
|
564
|
+
return { kind: "line", value: String(line), explicitKind };
|
|
565
|
+
}
|
|
566
|
+
function parseHashSelector(value, explicitKind) {
|
|
567
|
+
const parts = value.split(":");
|
|
568
|
+
if (parts.length > 2)
|
|
569
|
+
throw new Error("selector has too many components");
|
|
570
|
+
const head = parts[0];
|
|
571
|
+
if (!/^[0-9a-fA-F]{6}$/.test(head))
|
|
572
|
+
throw new Error(`invalid line hash \`${head}\``);
|
|
573
|
+
if (parts.length === 2) {
|
|
574
|
+
const column = parsePositiveSelectorInt(parts[1], "column");
|
|
575
|
+
return { kind: "hash", value: head, column, explicitKind };
|
|
576
|
+
}
|
|
577
|
+
return { kind: "hash", value: head, explicitKind };
|
|
578
|
+
}
|
|
579
|
+
function isDocumentSelector(parsed) {
|
|
580
|
+
return ["page", "node", "asset"].includes(parsed.kind) || parsed.kind === "line" && !parsed.explicitKind && parsed.column === undefined && parsed.endLine === undefined;
|
|
581
|
+
}
|
|
582
|
+
function isBindingSelector(parsed) {
|
|
583
|
+
if (parsed.endLine !== undefined)
|
|
584
|
+
return false;
|
|
585
|
+
if (parsed.kind === "line" || parsed.kind === "hash")
|
|
586
|
+
return true;
|
|
587
|
+
return parsed.kind === "symbol" && !parsed.explicitKind && /^[0-9a-fA-F]{6}$/.test(parsed.value);
|
|
588
|
+
}
|
|
533
589
|
function parseSelector(text) {
|
|
590
|
+
if (text.length === 0)
|
|
591
|
+
throw new Error("selector must not be empty");
|
|
534
592
|
const separator = text.indexOf(":");
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
593
|
+
const hasSingleColon = separator >= 0 && text[separator + 1] !== ":";
|
|
594
|
+
if (hasSingleColon) {
|
|
595
|
+
const kind = text.slice(0, separator);
|
|
596
|
+
const value = text.slice(separator + 1);
|
|
597
|
+
if (isSelectorKind(kind)) {
|
|
598
|
+
if (value.length === 0)
|
|
599
|
+
throw new Error(`${kind} selector must not be empty`);
|
|
600
|
+
if (kind === "line")
|
|
601
|
+
return parseLineSelector(value, true);
|
|
602
|
+
if (kind === "hash")
|
|
603
|
+
return parseHashSelector(value, true);
|
|
604
|
+
if (kind === "page") {
|
|
605
|
+
if (value.includes(":"))
|
|
606
|
+
throw new Error("page selector has too many components");
|
|
607
|
+
parsePositiveSelectorInt(value, "page");
|
|
608
|
+
}
|
|
609
|
+
return { kind, value, explicitKind: true };
|
|
610
|
+
}
|
|
611
|
+
if (/^\d+$/.test(kind))
|
|
612
|
+
return parseLineSelector(text, false);
|
|
613
|
+
if (/^[0-9a-fA-F]{6}$/.test(kind) && /^\d+$/.test(value))
|
|
614
|
+
return parseHashSelector(text, false);
|
|
543
615
|
throw new Error(`unknown selector kind \`${kind}\`; expected line, hash, symbol, page, node, or asset`);
|
|
544
616
|
}
|
|
545
|
-
if (
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
throw new Error("selector has too many components");
|
|
549
|
-
if (parts.length === 2) {
|
|
550
|
-
const column = Number(parts[1]);
|
|
551
|
-
if (!Number.isSafeInteger(column))
|
|
552
|
-
throw new Error(`invalid column \`${parts[1]}\``);
|
|
553
|
-
if (column < 1)
|
|
554
|
-
throw new Error("column must be greater than zero");
|
|
555
|
-
return { kind, value: parts[0], column };
|
|
617
|
+
if (/^[0-9-]/.test(text)) {
|
|
618
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /[a-fA-F]/.test(text)) {
|
|
619
|
+
return parseHashSelector(text, false);
|
|
556
620
|
}
|
|
621
|
+
return parseLineSelector(text, false);
|
|
557
622
|
}
|
|
558
|
-
if (
|
|
559
|
-
|
|
560
|
-
throw new Error("page selector has too many components");
|
|
561
|
-
const page = Number(value);
|
|
562
|
-
if (!Number.isSafeInteger(page))
|
|
563
|
-
throw new Error(`invalid page \`${value}\``);
|
|
564
|
-
if (page < 1)
|
|
565
|
-
throw new Error("page must be greater than zero");
|
|
623
|
+
if (/^[0-9a-fA-F]{6}$/.test(text) && /\d/.test(text)) {
|
|
624
|
+
return parseHashSelector(text, false);
|
|
566
625
|
}
|
|
567
|
-
|
|
626
|
+
if (/\s/.test(text))
|
|
627
|
+
throw new Error(`invalid selector \`${text}\``);
|
|
628
|
+
return { kind: "symbol", value: text, explicitKind: false };
|
|
568
629
|
}
|
|
569
|
-
function start(
|
|
630
|
+
function start(command, input) {
|
|
570
631
|
if (!input.path)
|
|
571
|
-
throw new Error(`${
|
|
632
|
+
throw new Error(`${command} requires a path`);
|
|
572
633
|
if (input.stdinName !== undefined && input.path !== "-")
|
|
573
634
|
throw new Error("stdinName requires '-' as the target");
|
|
574
635
|
const args = [];
|
|
575
636
|
pushOptionalString(args, "--readseek-dir", input.readseekDir);
|
|
576
|
-
args.push(
|
|
637
|
+
args.push(command, input.path);
|
|
577
638
|
pushOptionalString(args, "--stdin-name", input.stdinName);
|
|
578
639
|
return args;
|
|
579
640
|
}
|
|
@@ -599,12 +660,12 @@ function anchors(args, input) {
|
|
|
599
660
|
if (input.noAnchors)
|
|
600
661
|
args.push("--no-anchors");
|
|
601
662
|
}
|
|
602
|
-
function
|
|
663
|
+
function buildShowArgs(input) {
|
|
603
664
|
if (input.end !== undefined)
|
|
604
665
|
validatePositiveInteger(input.end, "end");
|
|
605
666
|
if (input.end !== undefined && input.limit !== undefined)
|
|
606
667
|
throw new Error("cannot combine end with limit");
|
|
607
|
-
const args = start("show",
|
|
668
|
+
const args = start("show", input);
|
|
608
669
|
at2(args, input.at);
|
|
609
670
|
pushOptionalNumber(args, "--end", input.end);
|
|
610
671
|
limit2(args, input.limit);
|
|
@@ -612,10 +673,10 @@ function buildShowContentArgs(input) {
|
|
|
612
673
|
anchors(args, input);
|
|
613
674
|
return finish(args);
|
|
614
675
|
}
|
|
615
|
-
function
|
|
676
|
+
function buildTreeArgs(input) {
|
|
616
677
|
if (input.depth !== undefined && (!Number.isSafeInteger(input.depth) || input.depth < 0))
|
|
617
678
|
throw new Error("depth must be a non-negative integer");
|
|
618
|
-
const args = start("
|
|
679
|
+
const args = start("tree", input);
|
|
619
680
|
at2(args, input.at);
|
|
620
681
|
pushOptionalNumber(args, "--depth", input.depth);
|
|
621
682
|
pushOptionalString(args, "--kind", input.kind);
|
|
@@ -624,35 +685,35 @@ function buildShowStructureArgs(input) {
|
|
|
624
685
|
args.push("--outline");
|
|
625
686
|
return finish(args);
|
|
626
687
|
}
|
|
627
|
-
function
|
|
628
|
-
const args = start("
|
|
688
|
+
function buildMetaArgs(input) {
|
|
689
|
+
const args = start("meta", input);
|
|
629
690
|
language(args, input);
|
|
630
691
|
return finish(args);
|
|
631
692
|
}
|
|
632
|
-
function
|
|
633
|
-
if (input.at !== undefined && !
|
|
693
|
+
function buildAssetsArgs(input) {
|
|
694
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
634
695
|
throw new Error("assets requires a page, node, or asset selector");
|
|
635
|
-
const args = start("
|
|
696
|
+
const args = start("assets", input);
|
|
636
697
|
at2(args, input.at);
|
|
637
698
|
return finish(args);
|
|
638
699
|
}
|
|
639
|
-
function
|
|
640
|
-
const args = start("
|
|
700
|
+
function buildSyntaxArgs(input) {
|
|
701
|
+
const args = start("syntax", input);
|
|
641
702
|
language(args, input);
|
|
642
703
|
return finish(args);
|
|
643
704
|
}
|
|
644
|
-
function visionArgs(
|
|
705
|
+
function visionArgs(command, input) {
|
|
645
706
|
if (input.level !== undefined && !VISION_LEVELS.includes(input.level))
|
|
646
707
|
throw new Error("invalid vision level");
|
|
647
|
-
if (input.at !== undefined && !
|
|
708
|
+
if (input.at !== undefined && !isDocumentSelector(parseSelector(input.at)))
|
|
648
709
|
throw new Error("vision requires a document selector");
|
|
649
|
-
const args = start(
|
|
710
|
+
const args = start(command, input);
|
|
650
711
|
at2(args, input.at);
|
|
651
712
|
pushOptionalString(args, "--level", input.level);
|
|
652
713
|
return args;
|
|
653
714
|
}
|
|
654
|
-
function
|
|
655
|
-
const args = visionArgs("
|
|
715
|
+
function buildCaptionArgs(input) {
|
|
716
|
+
const args = visionArgs("caption", input);
|
|
656
717
|
if (input.include !== undefined) {
|
|
657
718
|
if (input.include.length === 0 || input.include.some((task) => task !== "text" && task !== "objects"))
|
|
658
719
|
throw new Error("include requires text or objects");
|
|
@@ -660,13 +721,13 @@ function buildGenerateCaptionArgs(input) {
|
|
|
660
721
|
}
|
|
661
722
|
return finish(args);
|
|
662
723
|
}
|
|
663
|
-
function
|
|
664
|
-
return finish(visionArgs("
|
|
724
|
+
function buildObjectsArgs(input) {
|
|
725
|
+
return finish(visionArgs("objects", input));
|
|
665
726
|
}
|
|
666
|
-
function
|
|
667
|
-
return finish(visionArgs("
|
|
727
|
+
function buildOcrArgs(input) {
|
|
728
|
+
return finish(visionArgs("ocr", input));
|
|
668
729
|
}
|
|
669
|
-
function
|
|
730
|
+
function buildSearchArgs(input) {
|
|
670
731
|
const hasPattern = Boolean(input.pattern);
|
|
671
732
|
const hasRule = Boolean(input.rule);
|
|
672
733
|
const hasContext = Boolean(input.context);
|
|
@@ -674,7 +735,7 @@ function buildFindNodesArgs(input) {
|
|
|
674
735
|
if (hasPattern || hasContext || input.selector)
|
|
675
736
|
throw new Error("rule cannot be combined with pattern, context, or selector");
|
|
676
737
|
} else if (!hasPattern && !hasContext) {
|
|
677
|
-
throw new Error("
|
|
738
|
+
throw new Error("search requires pattern, context, or rule");
|
|
678
739
|
}
|
|
679
740
|
if (hasContext && !input.selector) {
|
|
680
741
|
throw new Error("context requires selector");
|
|
@@ -682,7 +743,7 @@ function buildFindNodesArgs(input) {
|
|
|
682
743
|
if (hasPattern && hasContext) {
|
|
683
744
|
throw new Error("pattern and context cannot be combined");
|
|
684
745
|
}
|
|
685
|
-
const args = start("
|
|
746
|
+
const args = start("search", input);
|
|
686
747
|
pushOptionalString(args, "--pattern", input.pattern);
|
|
687
748
|
pushOptionalString(args, "--context", input.context);
|
|
688
749
|
pushOptionalString(args, "--selector", input.selector);
|
|
@@ -693,28 +754,28 @@ function buildFindNodesArgs(input) {
|
|
|
693
754
|
anchors(args, input);
|
|
694
755
|
return finish(args);
|
|
695
756
|
}
|
|
696
|
-
function
|
|
697
|
-
const args = start("
|
|
757
|
+
function buildGrepArgs(input) {
|
|
758
|
+
const args = start("grep", input);
|
|
698
759
|
args.push("--text", input.text);
|
|
699
760
|
limit2(args, input.limit);
|
|
700
761
|
appendGitScopeArgs(args, input);
|
|
701
762
|
return finish(args);
|
|
702
763
|
}
|
|
703
|
-
function
|
|
704
|
-
const args = start("
|
|
764
|
+
function buildDefArgs(input) {
|
|
765
|
+
const args = start("def", input);
|
|
705
766
|
args.push("--name", input.name);
|
|
706
767
|
language(args, input);
|
|
707
768
|
appendGitScopeArgs(args, input);
|
|
708
769
|
anchors(args, input);
|
|
709
770
|
return finish(args);
|
|
710
771
|
}
|
|
711
|
-
function
|
|
772
|
+
function buildRefsArgs(input) {
|
|
712
773
|
const validated = validateReferencesSelection(input);
|
|
713
774
|
if (!validated.ok)
|
|
714
775
|
throw new Error(validated.error);
|
|
715
|
-
if (input.at !== undefined && !
|
|
776
|
+
if (input.at !== undefined && !isBindingSelector(parseSelector(input.at)))
|
|
716
777
|
throw new Error("references requires a line or hash selector");
|
|
717
|
-
const args = start("
|
|
778
|
+
const args = start("refs", input);
|
|
718
779
|
pushOptionalString(args, "--name", input.name);
|
|
719
780
|
at2(args, input.at);
|
|
720
781
|
language(args, input);
|
|
@@ -722,14 +783,14 @@ function buildFindReferencesArgs(input) {
|
|
|
722
783
|
anchors(args, input);
|
|
723
784
|
return finish(args);
|
|
724
785
|
}
|
|
725
|
-
function
|
|
726
|
-
const args = start("check",
|
|
786
|
+
function buildCheckArgs(input) {
|
|
787
|
+
const args = start("check", input);
|
|
727
788
|
args.push("--rules", input.rules);
|
|
728
789
|
appendGitScopeArgs(args, input);
|
|
729
790
|
return finish(args);
|
|
730
791
|
}
|
|
731
|
-
function
|
|
732
|
-
const args = start("edit",
|
|
792
|
+
function buildEditArgs(input) {
|
|
793
|
+
const args = start("edit", input);
|
|
733
794
|
appendApplyAndPlanHash(args, input);
|
|
734
795
|
language(args, input);
|
|
735
796
|
appendGitScopeArgs(args, input);
|
|
@@ -737,10 +798,10 @@ function buildEditTextArgs(input) {
|
|
|
737
798
|
args.push("--edits", "-");
|
|
738
799
|
return finish(args);
|
|
739
800
|
}
|
|
740
|
-
function
|
|
741
|
-
if (!
|
|
801
|
+
function buildRenameArgs(input) {
|
|
802
|
+
if (!isBindingSelector(parseSelector(input.at)))
|
|
742
803
|
throw new Error("rename requires a line or hash selector");
|
|
743
|
-
const args = start("rename",
|
|
804
|
+
const args = start("rename", input);
|
|
744
805
|
at2(args, input.at);
|
|
745
806
|
args.push("--to", input.to);
|
|
746
807
|
if (input.workspace !== undefined)
|
|
@@ -1271,71 +1332,71 @@ function runOptions(options, vision = false) {
|
|
|
1271
1332
|
}
|
|
1272
1333
|
function createReadSeekClient(runner) {
|
|
1273
1334
|
return {
|
|
1274
|
-
async
|
|
1275
|
-
const value = await runner.kdl(
|
|
1335
|
+
async show(path, options = {}) {
|
|
1336
|
+
const value = await runner.kdl(buildShowArgs({ ...options, path }), runOptions(options));
|
|
1276
1337
|
return parseContentOutput(value);
|
|
1277
1338
|
},
|
|
1278
|
-
async
|
|
1279
|
-
const value = await runner.kdl(
|
|
1339
|
+
async tree(path, options = {}) {
|
|
1340
|
+
const value = await runner.kdl(buildTreeArgs({ ...options, path }), runOptions(options));
|
|
1280
1341
|
return parseStructureEnvelope(value);
|
|
1281
1342
|
},
|
|
1282
|
-
async
|
|
1283
|
-
const value = await runner.kdl(
|
|
1343
|
+
async meta(path, options = {}) {
|
|
1344
|
+
const value = await runner.kdl(buildMetaArgs({ ...options, path }), runOptions(options));
|
|
1284
1345
|
return parsePdfMetadata(value) ?? parseDetectOutput(value?.metadata);
|
|
1285
1346
|
},
|
|
1286
|
-
async
|
|
1287
|
-
const value = await runner.kdl(
|
|
1347
|
+
async assets(path, options = {}) {
|
|
1348
|
+
const value = await runner.kdl(buildAssetsArgs({ ...options, path }), runOptions(options));
|
|
1288
1349
|
return parseAssetsOutput(value);
|
|
1289
1350
|
},
|
|
1290
|
-
async
|
|
1291
|
-
const value = await runner.kdl(
|
|
1351
|
+
async syntax(path, options = {}) {
|
|
1352
|
+
const value = await runner.kdl(buildSyntaxArgs({ ...options, path }), runOptions(options));
|
|
1292
1353
|
return parseCheckOutput(value?.diagnostics ?? value);
|
|
1293
1354
|
},
|
|
1294
|
-
async
|
|
1295
|
-
const value = await runner.kdl(
|
|
1355
|
+
async check(path, options) {
|
|
1356
|
+
const value = await runner.kdl(buildCheckArgs({ ...options, path }), runOptions(options));
|
|
1296
1357
|
return parseRulesOutput(value);
|
|
1297
1358
|
},
|
|
1298
|
-
async
|
|
1299
|
-
const value = await runner.kdl(
|
|
1359
|
+
async caption(path, options = {}) {
|
|
1360
|
+
const value = await runner.kdl(buildCaptionArgs({ ...options, path }), runOptions(options, true));
|
|
1300
1361
|
return parseContentOutput(value);
|
|
1301
1362
|
},
|
|
1302
|
-
async
|
|
1303
|
-
const value = await runner.kdl(
|
|
1363
|
+
async objects(path, options = {}) {
|
|
1364
|
+
const value = await runner.kdl(buildObjectsArgs({ ...options, path }), runOptions(options, true));
|
|
1304
1365
|
return parseContentOutput(value);
|
|
1305
1366
|
},
|
|
1306
|
-
async
|
|
1307
|
-
const value = await runner.kdl(
|
|
1367
|
+
async ocr(path, options = {}) {
|
|
1368
|
+
const value = await runner.kdl(buildOcrArgs({ ...options, path }), runOptions(options, true));
|
|
1308
1369
|
return parseContentOutput(value);
|
|
1309
1370
|
},
|
|
1310
|
-
async
|
|
1311
|
-
const value = await runner.kdl(
|
|
1371
|
+
async search(path, options) {
|
|
1372
|
+
const value = await runner.kdl(buildSearchArgs({ ...options, path }), runOptions(options));
|
|
1312
1373
|
return parseSearchOutput(value);
|
|
1313
1374
|
},
|
|
1314
|
-
async
|
|
1315
|
-
const value = await runner.kdl(
|
|
1375
|
+
async grep(path, options) {
|
|
1376
|
+
const value = await runner.kdl(buildGrepArgs({ ...options, path }), runOptions(options));
|
|
1316
1377
|
return parseTextSearchOutput(value);
|
|
1317
1378
|
},
|
|
1318
|
-
async
|
|
1319
|
-
const value = await runner.kdl(
|
|
1379
|
+
async def(path, options) {
|
|
1380
|
+
const value = await runner.kdl(buildDefArgs({ ...options, path }), runOptions(options));
|
|
1320
1381
|
return parseDefOutput(value);
|
|
1321
1382
|
},
|
|
1322
|
-
async
|
|
1323
|
-
const value = await runner.kdl(
|
|
1383
|
+
async refs(path, options) {
|
|
1384
|
+
const value = await runner.kdl(buildRefsArgs({ ...options, path }), runOptions(options));
|
|
1324
1385
|
return parseRefsOutput(value);
|
|
1325
1386
|
},
|
|
1326
|
-
async
|
|
1387
|
+
async edit(path, edits, options = {}) {
|
|
1327
1388
|
const stdin = serializeEditPlan(edits);
|
|
1328
|
-
return parseEditOutput(await runner.kdl(
|
|
1389
|
+
return parseEditOutput(await runner.kdl(buildEditArgs({ ...options, path, requestFromStdin: true }), runOptions({ ...options, stdin })));
|
|
1329
1390
|
},
|
|
1330
|
-
async
|
|
1331
|
-
const value = await runner.kdl(
|
|
1391
|
+
async rename(path, options) {
|
|
1392
|
+
const value = await runner.kdl(buildRenameArgs({ ...options, path }), runOptions(options));
|
|
1332
1393
|
return parseRenameOutput(value);
|
|
1333
1394
|
}
|
|
1334
1395
|
};
|
|
1335
1396
|
}
|
|
1336
1397
|
// src/show-presentation.ts
|
|
1337
1398
|
function isShowTool(name) {
|
|
1338
|
-
return name === "
|
|
1399
|
+
return name === "show" || name === "tree" || name === "meta" || name === "assets";
|
|
1339
1400
|
}
|
|
1340
1401
|
function record(value) {
|
|
1341
1402
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -1450,7 +1511,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1450
1511
|
const path = inline(options.path || output.source || output.file || content.file || structure.file || metadata.file || cursor.file) || "(unknown path)";
|
|
1451
1512
|
const summary = [];
|
|
1452
1513
|
const result = { summary: "", body: "", notices: [], metadata: {} };
|
|
1453
|
-
if (tool === "
|
|
1514
|
+
if (tool === "meta") {
|
|
1454
1515
|
const data = Object.keys(metadata).length > 0 ? metadata : output;
|
|
1455
1516
|
if (text(data.format || data.language || data.type))
|
|
1456
1517
|
summary.push(inline(data.format || data.language || data.type));
|
|
@@ -1459,7 +1520,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1459
1520
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1460
1521
|
}
|
|
1461
1522
|
result.body = fields(data) || "No metadata available.";
|
|
1462
|
-
} else if (tool === "
|
|
1523
|
+
} else if (tool === "assets") {
|
|
1463
1524
|
const assets = records(output.assets);
|
|
1464
1525
|
result.metadata.assets = assets.length;
|
|
1465
1526
|
summary.push(plural(assets.length, "asset"));
|
|
@@ -1473,7 +1534,7 @@ function presentShowResult(tool, value, options = {}) {
|
|
|
1473
1534
|
summary.push(plural(nodes.length, "node"));
|
|
1474
1535
|
if (result.metadata.pages !== undefined)
|
|
1475
1536
|
summary.push(plural(result.metadata.pages, "page"));
|
|
1476
|
-
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "
|
|
1537
|
+
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "show")];
|
|
1477
1538
|
if (assets.length > 0) {
|
|
1478
1539
|
result.metadata.assets = assets.length;
|
|
1479
1540
|
sections.push(`Assets
|
|
@@ -1482,7 +1543,7 @@ ${assetList(assets)}`);
|
|
|
1482
1543
|
result.body = sections.filter(Boolean).join(`
|
|
1483
1544
|
|
|
1484
1545
|
`) || "No content in this selection.";
|
|
1485
|
-
} else if (tool === "
|
|
1546
|
+
} else if (tool === "tree") {
|
|
1486
1547
|
const symbols = records(structure.symbols);
|
|
1487
1548
|
result.metadata.symbols = symbols.length;
|
|
1488
1549
|
summary.push(plural(symbols.length, "symbol"));
|
|
@@ -1536,7 +1597,7 @@ ${assetList(assets)}`);
|
|
|
1536
1597
|
const description = Object.keys(content).length > 0 ? content : output;
|
|
1537
1598
|
result.body = fields(description) || "No content in this selection.";
|
|
1538
1599
|
}
|
|
1539
|
-
if (tool === "
|
|
1600
|
+
if (tool === "tree")
|
|
1540
1601
|
result.notices.push("Structure is limited to the requested depth, kind, and outline. Use a deeper depth or focus with at to inspect further.");
|
|
1541
1602
|
if (text(output.warning))
|
|
1542
1603
|
result.notices.push(safe(text(output.warning)));
|
|
@@ -2049,7 +2110,7 @@ function acceptsReadSeekExitCode(args, exitCode) {
|
|
|
2049
2110
|
index++;
|
|
2050
2111
|
continue;
|
|
2051
2112
|
}
|
|
2052
|
-
return arg === "
|
|
2113
|
+
return arg === "grep" || arg === "search" || arg === "def" || arg === "refs" || arg === "syntax" || arg === "check";
|
|
2053
2114
|
}
|
|
2054
2115
|
return false;
|
|
2055
2116
|
}
|
|
@@ -2285,22 +2346,22 @@ export {
|
|
|
2285
2346
|
acceptsReadSeekExitCode,
|
|
2286
2347
|
appendApplyAndPlanHash,
|
|
2287
2348
|
appendGitScopeArgs,
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
buildFindReferencesArgs,
|
|
2295
|
-
buildFindTextArgs,
|
|
2296
|
-
buildGenerateCaptionArgs,
|
|
2349
|
+
buildAssetsArgs,
|
|
2350
|
+
buildCaptionArgs,
|
|
2351
|
+
buildCheckArgs,
|
|
2352
|
+
buildDefArgs,
|
|
2353
|
+
buildEditArgs,
|
|
2354
|
+
buildGrepArgs,
|
|
2297
2355
|
buildLineLocation,
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2356
|
+
buildMetaArgs,
|
|
2357
|
+
buildObjectsArgs,
|
|
2358
|
+
buildOcrArgs,
|
|
2359
|
+
buildRefsArgs,
|
|
2360
|
+
buildRenameArgs,
|
|
2361
|
+
buildSearchArgs,
|
|
2362
|
+
buildShowArgs,
|
|
2363
|
+
buildSyntaxArgs,
|
|
2364
|
+
buildTreeArgs,
|
|
2304
2365
|
canonicalPathKey,
|
|
2305
2366
|
classifyReadSeekFailure,
|
|
2306
2367
|
cleanReadSeekErrorText,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarkkojs/readseek-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Shared ReadSeek CLI contract, validation, argv builders, and bounded process runners",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"vitest": "^4.1.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@jarkkojs/readseek": "^0.
|
|
54
|
+
"@jarkkojs/readseek": "^0.12.0",
|
|
55
55
|
"@bgotink/kdl": "0.4.0",
|
|
56
56
|
"@sinclair/typebox": "0.34.52"
|
|
57
57
|
}
|