@jarkkojs/readseek-api 0.9.9 → 0.9.10
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/dist/client.d.ts +358 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +687 -11
- package/dist/platform.d.ts +6 -0
- package/package.json +5 -5
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import type { DigestFacet, VisionAnalysisMode, VisionLevel, VisionMode } from "./contract.ts";
|
|
2
|
+
export interface ReadSeekHashline {
|
|
3
|
+
line: number;
|
|
4
|
+
hash: string;
|
|
5
|
+
text: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ReadSeekReadOutput {
|
|
8
|
+
file: string;
|
|
9
|
+
language: string;
|
|
10
|
+
line_count: number;
|
|
11
|
+
file_hash: string;
|
|
12
|
+
start_line: number;
|
|
13
|
+
end_line: number;
|
|
14
|
+
hashlines: ReadSeekHashline[];
|
|
15
|
+
}
|
|
16
|
+
export interface ReadSeekSymbol {
|
|
17
|
+
kind: string;
|
|
18
|
+
name: string;
|
|
19
|
+
qualified_name: string;
|
|
20
|
+
start_line: number;
|
|
21
|
+
end_line: number;
|
|
22
|
+
start_hash: string;
|
|
23
|
+
end_hash: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ReadSeekMapOutput {
|
|
26
|
+
file: string;
|
|
27
|
+
language: string;
|
|
28
|
+
line_count: number;
|
|
29
|
+
file_hash: string;
|
|
30
|
+
symbols: ReadSeekSymbol[];
|
|
31
|
+
}
|
|
32
|
+
export interface ReadSeekSearchCapture {
|
|
33
|
+
name: string;
|
|
34
|
+
start_line: number;
|
|
35
|
+
end_line: number;
|
|
36
|
+
start_hash: string;
|
|
37
|
+
end_hash: string;
|
|
38
|
+
hashlines: ReadSeekHashline[];
|
|
39
|
+
}
|
|
40
|
+
export interface ReadSeekSearchMatch {
|
|
41
|
+
pattern_index: number;
|
|
42
|
+
start_line: number;
|
|
43
|
+
end_line: number;
|
|
44
|
+
start_hash: string;
|
|
45
|
+
end_hash: string;
|
|
46
|
+
hashlines: ReadSeekHashline[];
|
|
47
|
+
captures: ReadSeekSearchCapture[];
|
|
48
|
+
}
|
|
49
|
+
export interface ReadSeekSearchFileOutput {
|
|
50
|
+
file: string;
|
|
51
|
+
language: string;
|
|
52
|
+
file_hash: string;
|
|
53
|
+
matches: ReadSeekSearchMatch[];
|
|
54
|
+
}
|
|
55
|
+
export interface ReadSeekReference {
|
|
56
|
+
file: string;
|
|
57
|
+
line: number;
|
|
58
|
+
column: number;
|
|
59
|
+
line_hash: string;
|
|
60
|
+
text: string;
|
|
61
|
+
enclosingSymbol?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface ReadSeekDiagnostic {
|
|
64
|
+
kind: "error" | "missing";
|
|
65
|
+
start_line: number;
|
|
66
|
+
end_line: number;
|
|
67
|
+
}
|
|
68
|
+
export interface ReadSeekCheckOutput {
|
|
69
|
+
errorCount: number;
|
|
70
|
+
missingCount: number;
|
|
71
|
+
diagnostics: ReadSeekDiagnostic[];
|
|
72
|
+
}
|
|
73
|
+
export type ReadSeekOcrText = string;
|
|
74
|
+
export interface ReadSeekDetectedObject {
|
|
75
|
+
label: string;
|
|
76
|
+
bbox: [number, number, number, number];
|
|
77
|
+
}
|
|
78
|
+
export type ReadSeekImageMode = VisionAnalysisMode;
|
|
79
|
+
export interface ReadSeekPreparedImage {
|
|
80
|
+
mime: string;
|
|
81
|
+
encoding: "base64";
|
|
82
|
+
data: string;
|
|
83
|
+
}
|
|
84
|
+
export interface ReadSeekDocumentCache {
|
|
85
|
+
content_hash: string;
|
|
86
|
+
state: "built" | "reused";
|
|
87
|
+
}
|
|
88
|
+
export type ReadSeekDetection = {
|
|
89
|
+
kind: "source";
|
|
90
|
+
type: string;
|
|
91
|
+
file: string;
|
|
92
|
+
language: string;
|
|
93
|
+
engine?: string;
|
|
94
|
+
supported: boolean;
|
|
95
|
+
mime?: string;
|
|
96
|
+
syntax?: string;
|
|
97
|
+
} | {
|
|
98
|
+
kind: "image";
|
|
99
|
+
type: string;
|
|
100
|
+
file: string;
|
|
101
|
+
mime?: string;
|
|
102
|
+
format: string;
|
|
103
|
+
width: number;
|
|
104
|
+
height: number;
|
|
105
|
+
animated: boolean;
|
|
106
|
+
encoding?: "base64";
|
|
107
|
+
data?: string;
|
|
108
|
+
ocr?: ReadSeekOcrText;
|
|
109
|
+
caption?: string;
|
|
110
|
+
objects?: ReadSeekDetectedObject[];
|
|
111
|
+
} | {
|
|
112
|
+
kind: "text";
|
|
113
|
+
type: string;
|
|
114
|
+
file: string;
|
|
115
|
+
mime?: string;
|
|
116
|
+
} | {
|
|
117
|
+
kind: "pdf";
|
|
118
|
+
type: "application/pdf";
|
|
119
|
+
file: string;
|
|
120
|
+
mime?: string;
|
|
121
|
+
format: "pdf";
|
|
122
|
+
pages: number;
|
|
123
|
+
};
|
|
124
|
+
export type ReadSeekImageDetection = Extract<ReadSeekDetection, {
|
|
125
|
+
kind: "image";
|
|
126
|
+
}>;
|
|
127
|
+
export interface IdentifierOutput {
|
|
128
|
+
text: string;
|
|
129
|
+
start_column: number;
|
|
130
|
+
end_column: number;
|
|
131
|
+
start_byte: number;
|
|
132
|
+
end_byte: number;
|
|
133
|
+
}
|
|
134
|
+
export interface IdentifyOutput {
|
|
135
|
+
file: string;
|
|
136
|
+
language: string;
|
|
137
|
+
engine?: string;
|
|
138
|
+
line_count: number;
|
|
139
|
+
file_hash: string;
|
|
140
|
+
line: number;
|
|
141
|
+
column: number;
|
|
142
|
+
line_hash: string;
|
|
143
|
+
identifier?: IdentifierOutput;
|
|
144
|
+
symbol?: {
|
|
145
|
+
name: string;
|
|
146
|
+
kind: string;
|
|
147
|
+
qualified_name: string;
|
|
148
|
+
start_line: number;
|
|
149
|
+
end_line: number;
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export interface EditOutput {
|
|
153
|
+
file: string;
|
|
154
|
+
before_hash: string;
|
|
155
|
+
file_hash: string;
|
|
156
|
+
plan_hash: string;
|
|
157
|
+
applied: boolean;
|
|
158
|
+
changed: boolean;
|
|
159
|
+
edit_count: number;
|
|
160
|
+
before_content?: string;
|
|
161
|
+
content?: string;
|
|
162
|
+
}
|
|
163
|
+
export interface RenameConflict {
|
|
164
|
+
line: number;
|
|
165
|
+
column: number;
|
|
166
|
+
reason: string;
|
|
167
|
+
}
|
|
168
|
+
export interface RenameEdit {
|
|
169
|
+
line: number;
|
|
170
|
+
start_column: number;
|
|
171
|
+
end_column: number;
|
|
172
|
+
start_byte: number;
|
|
173
|
+
end_byte: number;
|
|
174
|
+
occurrence: string;
|
|
175
|
+
line_hash: string;
|
|
176
|
+
text: string;
|
|
177
|
+
}
|
|
178
|
+
export interface RenameFileOutput {
|
|
179
|
+
file: string;
|
|
180
|
+
language: string;
|
|
181
|
+
engine?: string;
|
|
182
|
+
file_hash: string;
|
|
183
|
+
conflicts: RenameConflict[];
|
|
184
|
+
edits: RenameEdit[];
|
|
185
|
+
}
|
|
186
|
+
export interface RenameOutput {
|
|
187
|
+
file: string;
|
|
188
|
+
language: string;
|
|
189
|
+
engine?: string;
|
|
190
|
+
file_hash: string;
|
|
191
|
+
old_name: string;
|
|
192
|
+
new_name: string;
|
|
193
|
+
applied: boolean;
|
|
194
|
+
conflicts: RenameConflict[];
|
|
195
|
+
edits: RenameEdit[];
|
|
196
|
+
others: RenameFileOutput[];
|
|
197
|
+
}
|
|
198
|
+
export interface DefLocation {
|
|
199
|
+
file: string;
|
|
200
|
+
line: number;
|
|
201
|
+
column: number;
|
|
202
|
+
line_hash: string;
|
|
203
|
+
text: string;
|
|
204
|
+
kind?: string;
|
|
205
|
+
name?: string;
|
|
206
|
+
qualified_name?: string;
|
|
207
|
+
}
|
|
208
|
+
export interface ReadSeekDigestOptions {
|
|
209
|
+
select?: DigestFacet | DigestFacet[];
|
|
210
|
+
at?: string;
|
|
211
|
+
end?: number;
|
|
212
|
+
limit?: number;
|
|
213
|
+
language?: string;
|
|
214
|
+
visionMode?: VisionMode;
|
|
215
|
+
visionLevel?: VisionLevel;
|
|
216
|
+
stdin?: string;
|
|
217
|
+
stdinName?: string;
|
|
218
|
+
signal?: AbortSignal;
|
|
219
|
+
timeoutMs?: number;
|
|
220
|
+
/** Route through the runner's vision path (serialized, long timeout). */
|
|
221
|
+
vision?: boolean;
|
|
222
|
+
}
|
|
223
|
+
export interface ReadSeekDigestOutput {
|
|
224
|
+
metadata: ReadSeekDetection;
|
|
225
|
+
cache?: ReadSeekDocumentCache;
|
|
226
|
+
content?: unknown;
|
|
227
|
+
map?: ReadSeekMapOutput;
|
|
228
|
+
diagnostics?: ReadSeekCheckOutput;
|
|
229
|
+
identity?: IdentifyOutput;
|
|
230
|
+
}
|
|
231
|
+
export interface ReadSeekFailure {
|
|
232
|
+
code: "readseek-not-installed" | "readseek-execution-error";
|
|
233
|
+
message: string;
|
|
234
|
+
hint?: string;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Classify an error thrown while invoking readseek into the shared failure
|
|
238
|
+
* taxonomy: a missing binary or package (`readseek-not-installed`, with an
|
|
239
|
+
* install hint) versus any other execution error.
|
|
240
|
+
*/
|
|
241
|
+
export declare function classifyReadSeekFailure(err: unknown): ReadSeekFailure;
|
|
242
|
+
export interface ReadSeekRunOptions {
|
|
243
|
+
signal?: AbortSignal;
|
|
244
|
+
stdin?: string;
|
|
245
|
+
timeoutMs?: number;
|
|
246
|
+
cancelable?: boolean;
|
|
247
|
+
/** Set by callers that read a vision payload; the runner may serialize and lengthen timeouts. */
|
|
248
|
+
vision?: boolean;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Host-supplied spawn seam: resolve the binary and run it, returning stdout as
|
|
252
|
+
* text or parsed JSON. The plugin owns binary resolution, cache-dir decoration,
|
|
253
|
+
* cwd, timeout settings, and any vision serialization queue; the client owns
|
|
254
|
+
* argv construction and output parsing.
|
|
255
|
+
*/
|
|
256
|
+
export interface ReadSeekRunner {
|
|
257
|
+
text(args: readonly string[], options?: ReadSeekRunOptions): Promise<string>;
|
|
258
|
+
json(args: readonly string[], options?: ReadSeekRunOptions): Promise<unknown>;
|
|
259
|
+
}
|
|
260
|
+
interface ReadSeekSearchOptions {
|
|
261
|
+
language?: string;
|
|
262
|
+
cached?: boolean;
|
|
263
|
+
others?: boolean;
|
|
264
|
+
ignored?: boolean;
|
|
265
|
+
signal?: AbortSignal;
|
|
266
|
+
}
|
|
267
|
+
interface ReadSeekRefsOptions {
|
|
268
|
+
name?: string;
|
|
269
|
+
scope?: boolean;
|
|
270
|
+
line?: number;
|
|
271
|
+
column?: number;
|
|
272
|
+
language?: string;
|
|
273
|
+
cached?: boolean;
|
|
274
|
+
others?: boolean;
|
|
275
|
+
ignored?: boolean;
|
|
276
|
+
signal?: AbortSignal;
|
|
277
|
+
}
|
|
278
|
+
interface DefOptions {
|
|
279
|
+
name: string;
|
|
280
|
+
language?: string;
|
|
281
|
+
cached?: boolean;
|
|
282
|
+
others?: boolean;
|
|
283
|
+
ignored?: boolean;
|
|
284
|
+
signal?: AbortSignal;
|
|
285
|
+
}
|
|
286
|
+
interface EditOptions {
|
|
287
|
+
apply?: boolean;
|
|
288
|
+
planHash?: string;
|
|
289
|
+
language?: string;
|
|
290
|
+
signal?: AbortSignal;
|
|
291
|
+
timeoutMs?: number;
|
|
292
|
+
cancelable?: boolean;
|
|
293
|
+
}
|
|
294
|
+
interface RenameOptions {
|
|
295
|
+
to: string;
|
|
296
|
+
line: number;
|
|
297
|
+
column?: number;
|
|
298
|
+
workspace?: string;
|
|
299
|
+
apply?: boolean;
|
|
300
|
+
language?: string;
|
|
301
|
+
cached?: boolean;
|
|
302
|
+
others?: boolean;
|
|
303
|
+
ignored?: boolean;
|
|
304
|
+
signal?: AbortSignal;
|
|
305
|
+
}
|
|
306
|
+
interface IdentifyOptions {
|
|
307
|
+
line?: number;
|
|
308
|
+
column?: number;
|
|
309
|
+
language?: string;
|
|
310
|
+
signal?: AbortSignal;
|
|
311
|
+
}
|
|
312
|
+
export interface ReadSeekViewOptions {
|
|
313
|
+
node?: string;
|
|
314
|
+
page?: number;
|
|
315
|
+
kind?: string;
|
|
316
|
+
depth?: number;
|
|
317
|
+
outline?: boolean;
|
|
318
|
+
visionMode?: ReadSeekImageMode;
|
|
319
|
+
visionLevel?: VisionLevel;
|
|
320
|
+
signal?: AbortSignal;
|
|
321
|
+
}
|
|
322
|
+
export interface ReadSeekClient {
|
|
323
|
+
view(filePath: string, options?: ReadSeekViewOptions): Promise<string>;
|
|
324
|
+
digestRaw(target: string, options?: ReadSeekDigestOptions): Promise<unknown>;
|
|
325
|
+
digest(target: string, options?: ReadSeekDigestOptions): Promise<ReadSeekDigestOutput>;
|
|
326
|
+
digestContent(filePath: string, options?: {
|
|
327
|
+
startLine?: number;
|
|
328
|
+
endLine?: number;
|
|
329
|
+
visionMode?: "none" | ReadSeekImageMode;
|
|
330
|
+
signal?: AbortSignal;
|
|
331
|
+
vision?: boolean;
|
|
332
|
+
}): Promise<{
|
|
333
|
+
metadata: ReadSeekDetection;
|
|
334
|
+
cache?: ReadSeekDocumentCache;
|
|
335
|
+
text?: ReadSeekReadOutput;
|
|
336
|
+
image?: ReadSeekImageDetection;
|
|
337
|
+
}>;
|
|
338
|
+
image(filePath: string, modes: ReadSeekImageMode[], options?: {
|
|
339
|
+
signal?: AbortSignal;
|
|
340
|
+
}): Promise<ReadSeekDetection>;
|
|
341
|
+
preparedImage(filePath: string, options?: {
|
|
342
|
+
signal?: AbortSignal;
|
|
343
|
+
}): Promise<ReadSeekPreparedImage>;
|
|
344
|
+
search(target: string, pattern: string, options?: ReadSeekSearchOptions): Promise<ReadSeekSearchFileOutput[]>;
|
|
345
|
+
refs(target: string, options?: ReadSeekRefsOptions): Promise<ReadSeekReference[]>;
|
|
346
|
+
def(target: string, options: DefOptions): Promise<DefLocation[]>;
|
|
347
|
+
check(filePath: string, content: string, options?: {
|
|
348
|
+
signal?: AbortSignal;
|
|
349
|
+
}): Promise<ReadSeekCheckOutput>;
|
|
350
|
+
identify(filePath: string, content: string, options?: IdentifyOptions): Promise<IdentifyOutput>;
|
|
351
|
+
detect(filePath: string, options?: {
|
|
352
|
+
signal?: AbortSignal;
|
|
353
|
+
}): Promise<ReadSeekDetection>;
|
|
354
|
+
edit(filePath: string, edits: unknown[], options?: EditOptions): Promise<EditOutput>;
|
|
355
|
+
rename(filePath: string, options: RenameOptions): Promise<RenameOutput>;
|
|
356
|
+
}
|
|
357
|
+
export declare function createReadSeekClient(runner: ReadSeekRunner): ReadSeekClient;
|
|
358
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ export { DIGEST_FACETS, DOCUMENT_NODE_KINDS, EDIT_VARIANTS, GIT_SELECTION_FLAGS,
|
|
|
2
2
|
export { BUILTIN_FALLBACKS, REPLACEABLE_TOOLS, TOOL_COMPACT_GUIDELINES, fallbackToolDescriptionMap, preferredToolDescriptionMap, renderCompactGuidelines, renderFallbackToolDescription, renderPreferredToolDescription, renderToolRoutingPolicy, resolveToolName, rewriteBacktickedToolNames, type ReplaceableTool, type ToolAliasMap, type ToolRoutingPolicyOptions, } from "./policy.ts";
|
|
3
3
|
export { validateExactlyOneEditVariant, validateGitSelection, validateRefsNameVsScope, validateVisionLevelVsMode, type EditObject, type GitSelectionInput, type RefsScopeInput, type ValidationResult, type VisionInput, } from "./validation.ts";
|
|
4
4
|
export { appendApplyAndPlanHash, appendGitSelectionArgs, buildDefArgs, buildDigestArgs, buildEditArgs, buildLineLocation, buildRefsArgs, buildRenameArgs, buildSearchArgs, buildViewArgs, type ApplyPlanHashInput, type ApplyPlanHashOrder, type DefArgsInput, type DigestArgsInput, type EditArgsInput, type RefsArgsInput, type RenameArgsInput, type SearchArgsInput, type ViewArgsInput, } from "./argv.ts";
|
|
5
|
-
export { READSEEK_PLATFORM_PACKAGES, readSeekBinaryName, readSeekPlatformKey, resolveReadSeekBinaryFromPackages, type ModuleResolver, } from "./platform.ts";
|
|
5
|
+
export { READSEEK_PLATFORM_PACKAGES, readSeekBinaryName, readSeekPlatformKey, resolveReadSeekBinaryFromPackages, resolveReadSeekBinaryFromPath, type ModuleResolver, } from "./platform.ts";
|
|
6
6
|
export { cleanReadSeekErrorText, parseReadSeekJson, } from "./json.ts";
|
|
7
7
|
export { DEFAULT_MAX_OUTPUT_BYTES, DEFAULT_READSEEK_TIMEOUT_MS, ensureSuccessfulStdout, failureFromProcessResult, parseSuccessfulJson, resolveProcessLimits, type ProcessRunOptions, type ProcessRunResult, } from "./process.ts";
|
|
8
8
|
export { runReadSeekNode, runReadSeekNodeJson, runReadSeekNodeText, } from "./process-node.ts";
|
|
9
9
|
export { runReadSeekBun, runReadSeekBunJson, runReadSeekBunText, } from "./process-bun.ts";
|
|
10
|
+
export { classifyReadSeekFailure, createReadSeekClient, type DefLocation, type EditOutput, type IdentifierOutput, type IdentifyOutput, type ReadSeekCheckOutput, type ReadSeekClient, type ReadSeekDetection, type ReadSeekDetectedObject, type ReadSeekDiagnostic, type ReadSeekDigestOptions, type ReadSeekDigestOutput, type ReadSeekDocumentCache, type ReadSeekFailure, type ReadSeekHashline, type ReadSeekImageDetection, type ReadSeekImageMode, type ReadSeekMapOutput, type ReadSeekOcrText, type ReadSeekPreparedImage, type ReadSeekReadOutput, type ReadSeekReference, type ReadSeekRunOptions, type ReadSeekRunner, type RenameConflict, type RenameEdit, type RenameFileOutput, type RenameOutput, type ReadSeekSearchCapture, type ReadSeekSearchFileOutput, type ReadSeekSearchMatch, type ReadSeekSymbol, type ReadSeekViewOptions, } from "./client.ts";
|
package/dist/index.js
CHANGED
|
@@ -410,11 +410,6 @@ function getToolContract(name) {
|
|
|
410
410
|
}
|
|
411
411
|
// src/policy.ts
|
|
412
412
|
var REPLACEABLE_TOOLS = [
|
|
413
|
-
{
|
|
414
|
-
tool: "digest",
|
|
415
|
-
builtIn: "read",
|
|
416
|
-
benefit: "it returns LINE:HASH anchors for safe edits."
|
|
417
|
-
},
|
|
418
413
|
{
|
|
419
414
|
tool: "edit",
|
|
420
415
|
builtIn: "edit",
|
|
@@ -452,7 +447,6 @@ var TOOL_COMPACT_GUIDELINES = {
|
|
|
452
447
|
]
|
|
453
448
|
};
|
|
454
449
|
var BUILTIN_FALLBACKS = {
|
|
455
|
-
read: "digest",
|
|
456
450
|
edit: "edit",
|
|
457
451
|
write: "write",
|
|
458
452
|
grep: "grep",
|
|
@@ -470,11 +464,10 @@ var PREFERENCE_LEADS = {
|
|
|
470
464
|
view: "Preferred for digesting document structure or selected content."
|
|
471
465
|
};
|
|
472
466
|
var FALLBACK_TEMPLATES = {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
apply_patch: "Fallback only. Prefer `edit` for existing text files."
|
|
467
|
+
edit: "Prefer `edit` with fresh LINE:HASH anchors.",
|
|
468
|
+
write: "Prefer `write` so the result returns LINE:HASH anchors.",
|
|
469
|
+
grep: "Prefer `grep` for text/regex search with edit-ready anchors.",
|
|
470
|
+
apply_patch: "Prefer `edit` for existing text files."
|
|
478
471
|
};
|
|
479
472
|
function resolveToolName(name, aliases = {}) {
|
|
480
473
|
return aliases[name] ?? name;
|
|
@@ -732,6 +725,7 @@ function buildRenameArgs(input) {
|
|
|
732
725
|
return appendGitSelectionArgs(args, input);
|
|
733
726
|
}
|
|
734
727
|
// src/platform.ts
|
|
728
|
+
import { accessSync, constants as fsConstants } from "node:fs";
|
|
735
729
|
import { createRequire } from "node:module";
|
|
736
730
|
import path from "node:path";
|
|
737
731
|
var READSEEK_PLATFORM_PACKAGES = {
|
|
@@ -765,6 +759,19 @@ function resolveReadSeekBinaryFromPackages(resolver = resolveFromPackage, option
|
|
|
765
759
|
});
|
|
766
760
|
return path.join(path.dirname(packageJsonPath), "bin", readSeekBinaryName(platform));
|
|
767
761
|
}
|
|
762
|
+
function resolveReadSeekBinaryFromPath(pathEnv = process.env.PATH) {
|
|
763
|
+
const name = readSeekBinaryName();
|
|
764
|
+
for (const dir of (pathEnv ?? "").split(path.delimiter)) {
|
|
765
|
+
if (!dir)
|
|
766
|
+
continue;
|
|
767
|
+
const candidate = path.join(dir, name);
|
|
768
|
+
try {
|
|
769
|
+
accessSync(candidate, fsConstants.X_OK);
|
|
770
|
+
return candidate;
|
|
771
|
+
} catch {}
|
|
772
|
+
}
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
768
775
|
// src/json.ts
|
|
769
776
|
var READSEEK_USAGE_HINT = /\n\s*Run readseek(?: [\w-]+)* --help for more information\.?\s*$/;
|
|
770
777
|
function cleanReadSeekErrorText(stderr) {
|
|
@@ -1015,6 +1022,672 @@ async function runReadSeekBunText(binaryPath, args, options = {}) {
|
|
|
1015
1022
|
async function runReadSeekBunJson(binaryPath, args, options = {}) {
|
|
1016
1023
|
return parseSuccessfulJson(await runReadSeekBun(binaryPath, args, options));
|
|
1017
1024
|
}
|
|
1025
|
+
// src/client.ts
|
|
1026
|
+
function classifyReadSeekFailure(err) {
|
|
1027
|
+
const failure = err;
|
|
1028
|
+
const message = String(failure?.message ?? err);
|
|
1029
|
+
const missing = failure?.code === "ENOENT" || /Cannot find package|Cannot find module|no such file/i.test(message);
|
|
1030
|
+
if (missing) {
|
|
1031
|
+
return { code: "readseek-not-installed", message, hint: "Run npm install to install @jarkkojs/readseek." };
|
|
1032
|
+
}
|
|
1033
|
+
return { code: "readseek-execution-error", message };
|
|
1034
|
+
}
|
|
1035
|
+
function requireNumber(value, field) {
|
|
1036
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value))
|
|
1037
|
+
throw new Error(`invalid readseek ${field}: expected safe integer`);
|
|
1038
|
+
return value;
|
|
1039
|
+
}
|
|
1040
|
+
function requireString(value, field) {
|
|
1041
|
+
if (typeof value !== "string")
|
|
1042
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1043
|
+
return value;
|
|
1044
|
+
}
|
|
1045
|
+
function requireBoolean(value, field) {
|
|
1046
|
+
if (typeof value !== "boolean")
|
|
1047
|
+
throw new Error(`invalid readseek ${field}: expected boolean`);
|
|
1048
|
+
return value;
|
|
1049
|
+
}
|
|
1050
|
+
function optionalString(value, field) {
|
|
1051
|
+
if (value === undefined || value === null)
|
|
1052
|
+
return;
|
|
1053
|
+
return requireString(value, field);
|
|
1054
|
+
}
|
|
1055
|
+
function parseHashline(value, field) {
|
|
1056
|
+
if (!value || typeof value !== "object")
|
|
1057
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1058
|
+
const item = value;
|
|
1059
|
+
return {
|
|
1060
|
+
line: requireNumber(item.line, `${field}.line`),
|
|
1061
|
+
hash: requireString(item.hash, `${field}.hash`),
|
|
1062
|
+
text: requireString(item.text, `${field}.text`)
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
function parseSearchHashlines(value, field) {
|
|
1066
|
+
if (!Array.isArray(value))
|
|
1067
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1068
|
+
return value.map((line) => parseHashline(line, field));
|
|
1069
|
+
}
|
|
1070
|
+
function parseReadOutput(value) {
|
|
1071
|
+
if (!value || typeof value !== "object")
|
|
1072
|
+
throw new Error("invalid readseek read output");
|
|
1073
|
+
const output = value;
|
|
1074
|
+
const hashlines = output.hashlines;
|
|
1075
|
+
if (!Array.isArray(hashlines))
|
|
1076
|
+
throw new Error("invalid readseek hashlines");
|
|
1077
|
+
return {
|
|
1078
|
+
file: requireString(output.file, "file"),
|
|
1079
|
+
language: requireString(output.language, "language"),
|
|
1080
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1081
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1082
|
+
start_line: requireNumber(output.start_line, "start_line"),
|
|
1083
|
+
end_line: requireNumber(output.end_line, "end_line"),
|
|
1084
|
+
hashlines: hashlines.map((line) => parseHashline(line, "hashline"))
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
function parseMapOutput(value) {
|
|
1088
|
+
if (!value || typeof value !== "object")
|
|
1089
|
+
throw new Error("invalid readseek map output");
|
|
1090
|
+
const output = value;
|
|
1091
|
+
const symbols = output.symbols;
|
|
1092
|
+
if (!Array.isArray(symbols))
|
|
1093
|
+
throw new Error("invalid readseek symbols");
|
|
1094
|
+
return {
|
|
1095
|
+
file: requireString(output.file, "file"),
|
|
1096
|
+
language: requireString(output.language, "language"),
|
|
1097
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1098
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1099
|
+
symbols: symbols.map((symbol) => {
|
|
1100
|
+
if (!symbol || typeof symbol !== "object")
|
|
1101
|
+
throw new Error("invalid readseek symbol");
|
|
1102
|
+
const item = symbol;
|
|
1103
|
+
return {
|
|
1104
|
+
kind: requireString(item.kind, "symbol.kind"),
|
|
1105
|
+
name: requireString(item.name, "symbol.name"),
|
|
1106
|
+
qualified_name: requireString(item.qualified_name, "symbol.qualified_name"),
|
|
1107
|
+
start_line: requireNumber(item.start_line, "symbol.start_line"),
|
|
1108
|
+
end_line: requireNumber(item.end_line, "symbol.end_line"),
|
|
1109
|
+
start_hash: requireString(item.start_hash, "symbol.start_hash"),
|
|
1110
|
+
end_hash: requireString(item.end_hash, "symbol.end_hash")
|
|
1111
|
+
};
|
|
1112
|
+
})
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
function parseSearchOutput(value) {
|
|
1116
|
+
if (!value || typeof value !== "object")
|
|
1117
|
+
throw new Error("invalid readseek search output");
|
|
1118
|
+
const output = value;
|
|
1119
|
+
if (!Array.isArray(output.results))
|
|
1120
|
+
throw new Error("invalid readseek search results");
|
|
1121
|
+
return output.results.map((result) => {
|
|
1122
|
+
if (!result || typeof result !== "object")
|
|
1123
|
+
throw new Error("invalid readseek search result");
|
|
1124
|
+
const file = result;
|
|
1125
|
+
if (!Array.isArray(file.matches))
|
|
1126
|
+
throw new Error("invalid readseek search matches");
|
|
1127
|
+
return {
|
|
1128
|
+
file: requireString(file.file, "search.file"),
|
|
1129
|
+
language: requireString(file.language, "search.language"),
|
|
1130
|
+
file_hash: requireString(file.file_hash, "search.file_hash"),
|
|
1131
|
+
matches: file.matches.map((match) => {
|
|
1132
|
+
if (!match || typeof match !== "object")
|
|
1133
|
+
throw new Error("invalid readseek search match");
|
|
1134
|
+
const item = match;
|
|
1135
|
+
if (!Array.isArray(item.captures))
|
|
1136
|
+
throw new Error("invalid readseek search captures");
|
|
1137
|
+
return {
|
|
1138
|
+
pattern_index: item.pattern_index === undefined ? 0 : requireNumber(item.pattern_index, "search.match.pattern_index"),
|
|
1139
|
+
start_line: requireNumber(item.start_line, "search.match.start_line"),
|
|
1140
|
+
end_line: requireNumber(item.end_line, "search.match.end_line"),
|
|
1141
|
+
start_hash: requireString(item.start_hash, "search.match.start_hash"),
|
|
1142
|
+
end_hash: requireString(item.end_hash, "search.match.end_hash"),
|
|
1143
|
+
hashlines: parseSearchHashlines(item.hashlines, "search.match.hashlines"),
|
|
1144
|
+
captures: item.captures.map((capture) => {
|
|
1145
|
+
if (!capture || typeof capture !== "object")
|
|
1146
|
+
throw new Error("invalid readseek search capture");
|
|
1147
|
+
const captureItem = capture;
|
|
1148
|
+
return {
|
|
1149
|
+
name: requireString(captureItem.name, "search.capture.name"),
|
|
1150
|
+
start_line: requireNumber(captureItem.start_line, "search.capture.start_line"),
|
|
1151
|
+
end_line: requireNumber(captureItem.end_line, "search.capture.end_line"),
|
|
1152
|
+
start_hash: requireString(captureItem.start_hash, "search.capture.start_hash"),
|
|
1153
|
+
end_hash: requireString(captureItem.end_hash, "search.capture.end_hash"),
|
|
1154
|
+
hashlines: parseSearchHashlines(captureItem.hashlines, "search.capture.hashlines")
|
|
1155
|
+
};
|
|
1156
|
+
})
|
|
1157
|
+
};
|
|
1158
|
+
})
|
|
1159
|
+
};
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
function parseRefsOutput(value) {
|
|
1163
|
+
if (!value || typeof value !== "object")
|
|
1164
|
+
throw new Error("invalid readseek refs output");
|
|
1165
|
+
const output = value;
|
|
1166
|
+
if (!Array.isArray(output.references))
|
|
1167
|
+
throw new Error("invalid readseek references");
|
|
1168
|
+
return output.references.map((reference) => {
|
|
1169
|
+
if (!reference || typeof reference !== "object")
|
|
1170
|
+
throw new Error("invalid readseek reference");
|
|
1171
|
+
const item = reference;
|
|
1172
|
+
const symbol = item.symbol;
|
|
1173
|
+
const enclosing = symbol && typeof symbol === "object" ? optionalString(symbol.qualified_name, "reference.symbol.qualified_name") : undefined;
|
|
1174
|
+
return {
|
|
1175
|
+
file: requireString(item.file, "reference.file"),
|
|
1176
|
+
line: requireNumber(item.line, "reference.line"),
|
|
1177
|
+
column: requireNumber(item.column, "reference.column"),
|
|
1178
|
+
line_hash: requireString(item.line_hash, "reference.line_hash"),
|
|
1179
|
+
text: requireString(item.text, "reference.text"),
|
|
1180
|
+
enclosingSymbol: enclosing
|
|
1181
|
+
};
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
function parseDiagnosticKind(value) {
|
|
1185
|
+
if (value === "error" || value === "missing")
|
|
1186
|
+
return value;
|
|
1187
|
+
throw new Error("invalid readseek diagnostic.kind");
|
|
1188
|
+
}
|
|
1189
|
+
function parseCheckOutput(value) {
|
|
1190
|
+
if (!value || typeof value !== "object")
|
|
1191
|
+
throw new Error("invalid readseek check output");
|
|
1192
|
+
const output = value;
|
|
1193
|
+
if (!Array.isArray(output.diagnostics))
|
|
1194
|
+
throw new Error("invalid readseek diagnostics");
|
|
1195
|
+
return {
|
|
1196
|
+
errorCount: requireNumber(output.error_count, "error_count"),
|
|
1197
|
+
missingCount: requireNumber(output.missing_count, "missing_count"),
|
|
1198
|
+
diagnostics: output.diagnostics.map((diagnostic) => {
|
|
1199
|
+
if (!diagnostic || typeof diagnostic !== "object")
|
|
1200
|
+
throw new Error("invalid readseek diagnostic");
|
|
1201
|
+
const item = diagnostic;
|
|
1202
|
+
return {
|
|
1203
|
+
kind: parseDiagnosticKind(item.kind),
|
|
1204
|
+
start_line: requireNumber(item.start_line, "diagnostic.start_line"),
|
|
1205
|
+
end_line: requireNumber(item.end_line, "diagnostic.end_line")
|
|
1206
|
+
};
|
|
1207
|
+
})
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
function parseDetectedObjects(value) {
|
|
1211
|
+
if (value === undefined || value === null)
|
|
1212
|
+
return;
|
|
1213
|
+
if (!Array.isArray(value))
|
|
1214
|
+
throw new Error("invalid readseek detect objects");
|
|
1215
|
+
return value.map((object) => {
|
|
1216
|
+
if (!object || typeof object !== "object")
|
|
1217
|
+
throw new Error("invalid readseek detect object");
|
|
1218
|
+
const item = object;
|
|
1219
|
+
const bbox = item.bbox;
|
|
1220
|
+
if (!Array.isArray(bbox) || bbox.length !== 4)
|
|
1221
|
+
throw new Error("invalid readseek detect object.bbox");
|
|
1222
|
+
return {
|
|
1223
|
+
label: requireString(item.label, "object.label"),
|
|
1224
|
+
bbox: bbox.map((n, i) => requireNumber(n, `object.bbox[${i}]`))
|
|
1225
|
+
};
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
function parseImageEncoding(value) {
|
|
1229
|
+
if (value === "base64")
|
|
1230
|
+
return value;
|
|
1231
|
+
throw new Error("invalid image encoding");
|
|
1232
|
+
}
|
|
1233
|
+
function parseDetectOutput(value) {
|
|
1234
|
+
if (!value || typeof value !== "object")
|
|
1235
|
+
throw new Error("invalid readseek detect output");
|
|
1236
|
+
const output = value;
|
|
1237
|
+
const type = requireString(output.type, "type");
|
|
1238
|
+
const file = requireString(output.file, "file");
|
|
1239
|
+
const mime = optionalString(output.mime, "mime");
|
|
1240
|
+
if (type === "application/pdf") {
|
|
1241
|
+
if (output.format !== "pdf")
|
|
1242
|
+
throw new Error("invalid readseek PDF format");
|
|
1243
|
+
return {
|
|
1244
|
+
kind: "pdf",
|
|
1245
|
+
type,
|
|
1246
|
+
file,
|
|
1247
|
+
mime,
|
|
1248
|
+
format: output.format,
|
|
1249
|
+
pages: requireNumber(output.pages, "pages")
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
if (output.width !== undefined || output.height !== undefined) {
|
|
1253
|
+
return {
|
|
1254
|
+
kind: "image",
|
|
1255
|
+
type,
|
|
1256
|
+
file,
|
|
1257
|
+
mime,
|
|
1258
|
+
format: requireString(output.format, "format"),
|
|
1259
|
+
width: requireNumber(output.width, "width"),
|
|
1260
|
+
height: requireNumber(output.height, "height"),
|
|
1261
|
+
animated: requireBoolean(output.animated, "animated"),
|
|
1262
|
+
encoding: output.encoding === undefined ? undefined : parseImageEncoding(output.encoding),
|
|
1263
|
+
data: output.data === undefined ? undefined : requireString(output.data, "data"),
|
|
1264
|
+
ocr: optionalString(output.ocr, "ocr"),
|
|
1265
|
+
caption: optionalString(output.caption, "caption"),
|
|
1266
|
+
objects: parseDetectedObjects(output.objects)
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
if (output.language !== undefined) {
|
|
1270
|
+
return {
|
|
1271
|
+
kind: "source",
|
|
1272
|
+
type,
|
|
1273
|
+
file,
|
|
1274
|
+
language: requireString(output.language, "language"),
|
|
1275
|
+
engine: optionalString(output.engine, "engine"),
|
|
1276
|
+
supported: requireBoolean(output.supported, "supported"),
|
|
1277
|
+
mime,
|
|
1278
|
+
syntax: optionalString(output.syntax, "syntax")
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
return { kind: "text", type, file, mime };
|
|
1282
|
+
}
|
|
1283
|
+
function parseDocumentCache(value) {
|
|
1284
|
+
if (!value || typeof value !== "object")
|
|
1285
|
+
throw new Error("invalid readseek document cache");
|
|
1286
|
+
const cache = value;
|
|
1287
|
+
const state = requireString(cache.state, "cache.state");
|
|
1288
|
+
if (state !== "built" && state !== "reused")
|
|
1289
|
+
throw new Error("invalid readseek cache.state");
|
|
1290
|
+
return {
|
|
1291
|
+
content_hash: requireString(cache.content_hash, "cache.content_hash"),
|
|
1292
|
+
state
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
function parseIdentifyOutput(value) {
|
|
1296
|
+
if (!value || typeof value !== "object")
|
|
1297
|
+
throw new Error("invalid readseek identify output");
|
|
1298
|
+
const output = value;
|
|
1299
|
+
const identifier = output.identifier;
|
|
1300
|
+
const symbol = output.symbol;
|
|
1301
|
+
return {
|
|
1302
|
+
file: requireString(output.file, "file"),
|
|
1303
|
+
language: requireString(output.language, "language"),
|
|
1304
|
+
engine: optionalString(output.engine, "engine"),
|
|
1305
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1306
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1307
|
+
line: requireNumber(output.line, "line"),
|
|
1308
|
+
column: requireNumber(output.column, "column"),
|
|
1309
|
+
line_hash: requireString(output.line_hash, "line_hash"),
|
|
1310
|
+
identifier: identifier && typeof identifier === "object" ? {
|
|
1311
|
+
text: requireString(identifier.text, "identifier.text"),
|
|
1312
|
+
start_column: requireNumber(identifier.start_column, "identifier.start_column"),
|
|
1313
|
+
end_column: requireNumber(identifier.end_column, "identifier.end_column"),
|
|
1314
|
+
start_byte: requireNumber(identifier.start_byte, "identifier.start_byte"),
|
|
1315
|
+
end_byte: requireNumber(identifier.end_byte, "identifier.end_byte")
|
|
1316
|
+
} : undefined,
|
|
1317
|
+
symbol: symbol && typeof symbol === "object" ? {
|
|
1318
|
+
name: requireString(symbol.name, "symbol.name"),
|
|
1319
|
+
kind: requireString(symbol.kind, "symbol.kind"),
|
|
1320
|
+
qualified_name: requireString(symbol.qualified_name, "symbol.qualified_name"),
|
|
1321
|
+
start_line: requireNumber(symbol.start_line, "symbol.start_line"),
|
|
1322
|
+
end_line: requireNumber(symbol.end_line, "symbol.end_line")
|
|
1323
|
+
} : undefined
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
function parseImageContent(value) {
|
|
1327
|
+
const detection = parseDetectOutput(value);
|
|
1328
|
+
if (detection.kind !== "image")
|
|
1329
|
+
throw new Error("invalid readseek image content");
|
|
1330
|
+
return detection;
|
|
1331
|
+
}
|
|
1332
|
+
function parseTextContent(value) {
|
|
1333
|
+
if (!value || typeof value !== "object")
|
|
1334
|
+
throw new Error("invalid readseek content");
|
|
1335
|
+
const output = value;
|
|
1336
|
+
if (output.hashlines !== undefined && output.start_line === undefined) {
|
|
1337
|
+
const hashlines = parseSearchHashlines(output.hashlines, "content.hashlines");
|
|
1338
|
+
const first = hashlines[0];
|
|
1339
|
+
const last = hashlines[hashlines.length - 1];
|
|
1340
|
+
return {
|
|
1341
|
+
file: requireString(output.file, "file"),
|
|
1342
|
+
language: requireString(output.language, "language"),
|
|
1343
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1344
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1345
|
+
start_line: first?.line ?? 1,
|
|
1346
|
+
end_line: last?.line ?? 0,
|
|
1347
|
+
hashlines
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
return parseReadOutput(value);
|
|
1351
|
+
}
|
|
1352
|
+
function parseDigestEnvelope(value) {
|
|
1353
|
+
if (!value || typeof value !== "object")
|
|
1354
|
+
throw new Error("invalid readseek digest output");
|
|
1355
|
+
const output = value;
|
|
1356
|
+
if (output.metadata === undefined)
|
|
1357
|
+
throw new Error("invalid readseek digest metadata");
|
|
1358
|
+
const result = {
|
|
1359
|
+
metadata: parseDetectOutput(output.metadata)
|
|
1360
|
+
};
|
|
1361
|
+
if (output.cache !== undefined)
|
|
1362
|
+
result.cache = parseDocumentCache(output.cache);
|
|
1363
|
+
if (output.content !== undefined)
|
|
1364
|
+
result.content = output.content;
|
|
1365
|
+
if (output.map !== undefined)
|
|
1366
|
+
result.map = parseMapOutput(output.map);
|
|
1367
|
+
if (output.diagnostics !== undefined)
|
|
1368
|
+
result.diagnostics = parseCheckOutput(output.diagnostics);
|
|
1369
|
+
if (output.identity !== undefined)
|
|
1370
|
+
result.identity = parseIdentifyOutput(output.identity);
|
|
1371
|
+
return result;
|
|
1372
|
+
}
|
|
1373
|
+
function parseEditOutput(value) {
|
|
1374
|
+
if (!value || typeof value !== "object")
|
|
1375
|
+
throw new Error("invalid readseek edit output");
|
|
1376
|
+
const output = value;
|
|
1377
|
+
return {
|
|
1378
|
+
file: requireString(output.file, "file"),
|
|
1379
|
+
before_hash: requireString(output.before_hash, "before_hash"),
|
|
1380
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1381
|
+
plan_hash: requireString(output.plan_hash, "plan_hash"),
|
|
1382
|
+
applied: requireBoolean(output.applied, "applied"),
|
|
1383
|
+
changed: requireBoolean(output.changed, "changed"),
|
|
1384
|
+
edit_count: requireNumber(output.edit_count, "edit_count"),
|
|
1385
|
+
before_content: optionalString(output.before_content, "before_content"),
|
|
1386
|
+
content: optionalString(output.content, "content")
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
function parseRenameConflicts(value, field) {
|
|
1390
|
+
if (value === undefined)
|
|
1391
|
+
return [];
|
|
1392
|
+
if (!Array.isArray(value))
|
|
1393
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1394
|
+
return value.map((item) => {
|
|
1395
|
+
if (!item || typeof item !== "object")
|
|
1396
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1397
|
+
const c = item;
|
|
1398
|
+
return {
|
|
1399
|
+
line: requireNumber(c.line, `${field}.line`),
|
|
1400
|
+
column: requireNumber(c.column, `${field}.column`),
|
|
1401
|
+
reason: requireString(c.reason, `${field}.reason`)
|
|
1402
|
+
};
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
function parseRenameEdits(value, field) {
|
|
1406
|
+
if (value === undefined)
|
|
1407
|
+
return [];
|
|
1408
|
+
if (!Array.isArray(value))
|
|
1409
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1410
|
+
return value.map((item) => {
|
|
1411
|
+
if (!item || typeof item !== "object")
|
|
1412
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1413
|
+
const e = item;
|
|
1414
|
+
return {
|
|
1415
|
+
line: requireNumber(e.line, `${field}.line`),
|
|
1416
|
+
start_column: requireNumber(e.start_column, `${field}.start_column`),
|
|
1417
|
+
end_column: requireNumber(e.end_column, `${field}.end_column`),
|
|
1418
|
+
start_byte: requireNumber(e.start_byte, `${field}.start_byte`),
|
|
1419
|
+
end_byte: requireNumber(e.end_byte, `${field}.end_byte`),
|
|
1420
|
+
occurrence: requireString(e.occurrence, `${field}.occurrence`),
|
|
1421
|
+
line_hash: requireString(e.line_hash, `${field}.line_hash`),
|
|
1422
|
+
text: requireString(e.text, `${field}.text`)
|
|
1423
|
+
};
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
function parseRenameOutput(value) {
|
|
1427
|
+
if (!value || typeof value !== "object")
|
|
1428
|
+
throw new Error("invalid readseek rename output");
|
|
1429
|
+
const output = value;
|
|
1430
|
+
const others = output.others;
|
|
1431
|
+
if (others !== undefined && !Array.isArray(others))
|
|
1432
|
+
throw new Error("invalid readseek others");
|
|
1433
|
+
return {
|
|
1434
|
+
file: requireString(output.file, "file"),
|
|
1435
|
+
language: requireString(output.language, "language"),
|
|
1436
|
+
engine: optionalString(output.engine, "engine"),
|
|
1437
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1438
|
+
old_name: requireString(output.old_name, "old_name"),
|
|
1439
|
+
new_name: requireString(output.new_name, "new_name"),
|
|
1440
|
+
applied: requireBoolean(output.applied, "applied"),
|
|
1441
|
+
conflicts: parseRenameConflicts(output.conflicts, "conflicts"),
|
|
1442
|
+
edits: parseRenameEdits(output.edits, "edits"),
|
|
1443
|
+
others: others?.map((entry) => {
|
|
1444
|
+
if (!entry || typeof entry !== "object")
|
|
1445
|
+
throw new Error("invalid readseek other");
|
|
1446
|
+
const o = entry;
|
|
1447
|
+
return {
|
|
1448
|
+
file: requireString(o.file, "other.file"),
|
|
1449
|
+
language: requireString(o.language, "other.language"),
|
|
1450
|
+
engine: optionalString(o.engine, "other.engine"),
|
|
1451
|
+
file_hash: requireString(o.file_hash, "other.file_hash"),
|
|
1452
|
+
conflicts: parseRenameConflicts(o.conflicts, "other.conflicts"),
|
|
1453
|
+
edits: parseRenameEdits(o.edits, "other.edits")
|
|
1454
|
+
};
|
|
1455
|
+
}) ?? []
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
function parseDefCompact(value) {
|
|
1459
|
+
if (!value || typeof value !== "object")
|
|
1460
|
+
throw new Error("invalid readseek def output");
|
|
1461
|
+
const output = value;
|
|
1462
|
+
const locations = output.locations;
|
|
1463
|
+
if (!Array.isArray(locations))
|
|
1464
|
+
throw new Error("invalid readseek def locations");
|
|
1465
|
+
return locations.map((loc) => {
|
|
1466
|
+
if (!loc || typeof loc !== "object")
|
|
1467
|
+
throw new Error("invalid readseek def location");
|
|
1468
|
+
const item = loc;
|
|
1469
|
+
return {
|
|
1470
|
+
file: requireString(item.file, "location.file"),
|
|
1471
|
+
line: requireNumber(item.line, "location.line"),
|
|
1472
|
+
column: requireNumber(item.column, "location.column"),
|
|
1473
|
+
line_hash: requireString(item.line_hash, "location.line_hash"),
|
|
1474
|
+
text: requireString(item.text, "location.text"),
|
|
1475
|
+
kind: optionalString(item.kind, "location.kind"),
|
|
1476
|
+
name: optionalString(item.name, "location.name"),
|
|
1477
|
+
qualified_name: optionalString(item.qualified_name, "location.qualified_name")
|
|
1478
|
+
};
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
function createReadSeekClient(runner) {
|
|
1482
|
+
function digestArgs(target, options) {
|
|
1483
|
+
return buildDigestArgs({
|
|
1484
|
+
path: target,
|
|
1485
|
+
select: options.select ?? "content",
|
|
1486
|
+
at: options.at,
|
|
1487
|
+
end: options.end,
|
|
1488
|
+
limit: options.limit,
|
|
1489
|
+
language: options.language,
|
|
1490
|
+
visionMode: options.visionMode,
|
|
1491
|
+
visionLevel: options.visionLevel,
|
|
1492
|
+
stdinName: options.stdin !== undefined && target === "-" ? options.stdinName ?? target : undefined
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
async function runDigestRaw(target, options = {}) {
|
|
1496
|
+
const args = digestArgs(target, options);
|
|
1497
|
+
const runOptions = {
|
|
1498
|
+
signal: options.signal,
|
|
1499
|
+
stdin: options.stdin,
|
|
1500
|
+
timeoutMs: options.timeoutMs,
|
|
1501
|
+
vision: options.vision
|
|
1502
|
+
};
|
|
1503
|
+
return runner.json(args, runOptions);
|
|
1504
|
+
}
|
|
1505
|
+
async function digest(target, options = {}) {
|
|
1506
|
+
return parseDigestEnvelope(await runDigestRaw(target, options));
|
|
1507
|
+
}
|
|
1508
|
+
function requireDigestContent(envelope, field) {
|
|
1509
|
+
if (envelope.content === undefined)
|
|
1510
|
+
throw new Error(`invalid readseek ${field}: missing content`);
|
|
1511
|
+
return envelope.content;
|
|
1512
|
+
}
|
|
1513
|
+
async function digestContent(filePath, options = {}) {
|
|
1514
|
+
const envelope = await digest(filePath, {
|
|
1515
|
+
select: "content",
|
|
1516
|
+
at: options.startLine !== undefined ? buildLineLocation(options.startLine) : undefined,
|
|
1517
|
+
end: options.endLine,
|
|
1518
|
+
visionMode: options.visionMode,
|
|
1519
|
+
signal: options.signal,
|
|
1520
|
+
vision: options.vision
|
|
1521
|
+
});
|
|
1522
|
+
if (envelope.metadata.kind === "pdf") {
|
|
1523
|
+
return { metadata: envelope.metadata, cache: envelope.cache };
|
|
1524
|
+
}
|
|
1525
|
+
const content = requireDigestContent(envelope, "content");
|
|
1526
|
+
if (envelope.metadata.kind === "image") {
|
|
1527
|
+
return { metadata: envelope.metadata, image: parseImageContent(content) };
|
|
1528
|
+
}
|
|
1529
|
+
return { metadata: envelope.metadata, text: parseTextContent(content) };
|
|
1530
|
+
}
|
|
1531
|
+
return {
|
|
1532
|
+
async view(filePath, options = {}) {
|
|
1533
|
+
const args = buildViewArgs({
|
|
1534
|
+
path: filePath,
|
|
1535
|
+
node: options.node,
|
|
1536
|
+
page: options.page,
|
|
1537
|
+
kind: options.kind,
|
|
1538
|
+
depth: options.depth,
|
|
1539
|
+
outline: options.outline,
|
|
1540
|
+
visionMode: options.visionMode,
|
|
1541
|
+
visionLevel: options.visionLevel
|
|
1542
|
+
});
|
|
1543
|
+
return runner.text(args, {
|
|
1544
|
+
signal: options.signal,
|
|
1545
|
+
vision: options.visionMode !== undefined
|
|
1546
|
+
});
|
|
1547
|
+
},
|
|
1548
|
+
digestRaw(target, options = {}) {
|
|
1549
|
+
return runDigestRaw(target, options);
|
|
1550
|
+
},
|
|
1551
|
+
digest,
|
|
1552
|
+
digestContent,
|
|
1553
|
+
async image(filePath, modes, options = {}) {
|
|
1554
|
+
const requestedModes = modes.length > 1 ? ["all"] : modes;
|
|
1555
|
+
const results = await Promise.allSettled(requestedModes.map(async (mode) => {
|
|
1556
|
+
const digested = await digestContent(filePath, {
|
|
1557
|
+
visionMode: mode,
|
|
1558
|
+
signal: options.signal,
|
|
1559
|
+
vision: true
|
|
1560
|
+
});
|
|
1561
|
+
if (!digested.image)
|
|
1562
|
+
throw new Error(`readseek returned no image analysis for ${filePath}`);
|
|
1563
|
+
return digested.image;
|
|
1564
|
+
}));
|
|
1565
|
+
let merged;
|
|
1566
|
+
for (const result of results) {
|
|
1567
|
+
if (result.status !== "fulfilled")
|
|
1568
|
+
continue;
|
|
1569
|
+
const detection = result.value;
|
|
1570
|
+
merged = merged === undefined ? detection : {
|
|
1571
|
+
...merged,
|
|
1572
|
+
ocr: detection.ocr ?? merged.ocr,
|
|
1573
|
+
caption: detection.caption ?? merged.caption,
|
|
1574
|
+
objects: detection.objects ?? merged.objects
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
if (merged !== undefined)
|
|
1578
|
+
return merged;
|
|
1579
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
1580
|
+
if (failure?.status === "rejected")
|
|
1581
|
+
throw failure.reason;
|
|
1582
|
+
throw new Error(`readseek returned no image analysis for ${filePath}`);
|
|
1583
|
+
},
|
|
1584
|
+
async preparedImage(filePath, options = {}) {
|
|
1585
|
+
const digested = await digestContent(filePath, {
|
|
1586
|
+
visionMode: "none",
|
|
1587
|
+
signal: options.signal
|
|
1588
|
+
});
|
|
1589
|
+
const output = digested.image;
|
|
1590
|
+
if (!output || output.encoding !== "base64" || output.data === undefined || output.mime === undefined) {
|
|
1591
|
+
throw new Error(`readseek returned no prepared image for ${filePath}`);
|
|
1592
|
+
}
|
|
1593
|
+
return { mime: output.mime, encoding: output.encoding, data: output.data };
|
|
1594
|
+
},
|
|
1595
|
+
async search(target, pattern, options = {}) {
|
|
1596
|
+
const args = buildSearchArgs({
|
|
1597
|
+
path: target,
|
|
1598
|
+
pattern,
|
|
1599
|
+
language: options.language,
|
|
1600
|
+
cached: options.cached,
|
|
1601
|
+
others: options.others,
|
|
1602
|
+
ignored: options.ignored
|
|
1603
|
+
});
|
|
1604
|
+
return parseSearchOutput(await runner.json(args, { signal: options.signal }));
|
|
1605
|
+
},
|
|
1606
|
+
async refs(target, options = {}) {
|
|
1607
|
+
const args = buildRefsArgs({
|
|
1608
|
+
path: target,
|
|
1609
|
+
name: options.name,
|
|
1610
|
+
scope: options.scope,
|
|
1611
|
+
line: options.line,
|
|
1612
|
+
column: options.column,
|
|
1613
|
+
language: options.language,
|
|
1614
|
+
cached: options.cached,
|
|
1615
|
+
others: options.others,
|
|
1616
|
+
ignored: options.ignored
|
|
1617
|
+
});
|
|
1618
|
+
return parseRefsOutput(await runner.json(args, { signal: options.signal }));
|
|
1619
|
+
},
|
|
1620
|
+
async def(target, options) {
|
|
1621
|
+
const args = buildDefArgs({
|
|
1622
|
+
path: target,
|
|
1623
|
+
name: options.name,
|
|
1624
|
+
format: "plain",
|
|
1625
|
+
language: options.language,
|
|
1626
|
+
cached: options.cached,
|
|
1627
|
+
others: options.others,
|
|
1628
|
+
ignored: options.ignored
|
|
1629
|
+
});
|
|
1630
|
+
return parseDefCompact(await runner.json(args, { signal: options.signal }));
|
|
1631
|
+
},
|
|
1632
|
+
async check(filePath, content, options = {}) {
|
|
1633
|
+
const envelope = await digest("-", {
|
|
1634
|
+
select: "diagnostics",
|
|
1635
|
+
stdin: content,
|
|
1636
|
+
stdinName: filePath,
|
|
1637
|
+
signal: options.signal
|
|
1638
|
+
});
|
|
1639
|
+
if (!envelope.diagnostics)
|
|
1640
|
+
throw new Error("invalid readseek diagnostics: missing diagnostics facet");
|
|
1641
|
+
return envelope.diagnostics;
|
|
1642
|
+
},
|
|
1643
|
+
async identify(filePath, content, options = {}) {
|
|
1644
|
+
const envelope = await digest("-", {
|
|
1645
|
+
select: "identity",
|
|
1646
|
+
stdin: content,
|
|
1647
|
+
stdinName: filePath,
|
|
1648
|
+
at: options.line !== undefined ? buildLineLocation(options.line, options.column) : undefined,
|
|
1649
|
+
language: options.language,
|
|
1650
|
+
signal: options.signal
|
|
1651
|
+
});
|
|
1652
|
+
if (!envelope.identity)
|
|
1653
|
+
throw new Error("invalid readseek identity: missing identity facet");
|
|
1654
|
+
return envelope.identity;
|
|
1655
|
+
},
|
|
1656
|
+
async detect(filePath, options = {}) {
|
|
1657
|
+
const envelope = await digest(filePath, { select: "metadata", signal: options.signal });
|
|
1658
|
+
return envelope.metadata;
|
|
1659
|
+
},
|
|
1660
|
+
async edit(filePath, edits, options = {}) {
|
|
1661
|
+
const args = buildEditArgs({
|
|
1662
|
+
path: filePath,
|
|
1663
|
+
apply: options.apply,
|
|
1664
|
+
planHash: options.planHash,
|
|
1665
|
+
language: options.language
|
|
1666
|
+
});
|
|
1667
|
+
return parseEditOutput(await runner.json(args, {
|
|
1668
|
+
signal: options.signal,
|
|
1669
|
+
stdin: JSON.stringify({ edits }),
|
|
1670
|
+
timeoutMs: options.timeoutMs,
|
|
1671
|
+
cancelable: options.cancelable
|
|
1672
|
+
}));
|
|
1673
|
+
},
|
|
1674
|
+
async rename(filePath, options) {
|
|
1675
|
+
const args = buildRenameArgs({
|
|
1676
|
+
path: filePath,
|
|
1677
|
+
to: options.to,
|
|
1678
|
+
line: options.line,
|
|
1679
|
+
column: options.column,
|
|
1680
|
+
workspace: options.workspace,
|
|
1681
|
+
apply: options.apply,
|
|
1682
|
+
language: options.language,
|
|
1683
|
+
cached: options.cached,
|
|
1684
|
+
others: options.others,
|
|
1685
|
+
ignored: options.ignored
|
|
1686
|
+
});
|
|
1687
|
+
return parseRenameOutput(await runner.json(args, { signal: options.signal }));
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1018
1691
|
export {
|
|
1019
1692
|
validateVisionLevelVsMode,
|
|
1020
1693
|
validateRefsNameVsScope,
|
|
@@ -1028,6 +1701,7 @@ export {
|
|
|
1028
1701
|
runReadSeekBun,
|
|
1029
1702
|
rewriteBacktickedToolNames,
|
|
1030
1703
|
resolveToolName,
|
|
1704
|
+
resolveReadSeekBinaryFromPath,
|
|
1031
1705
|
resolveReadSeekBinaryFromPackages,
|
|
1032
1706
|
resolveProcessLimits,
|
|
1033
1707
|
renderToolRoutingPolicy,
|
|
@@ -1044,7 +1718,9 @@ export {
|
|
|
1044
1718
|
fallbackToolDescriptionMap,
|
|
1045
1719
|
failureFromProcessResult,
|
|
1046
1720
|
ensureSuccessfulStdout,
|
|
1721
|
+
createReadSeekClient,
|
|
1047
1722
|
cleanReadSeekErrorText,
|
|
1723
|
+
classifyReadSeekFailure,
|
|
1048
1724
|
buildViewArgs,
|
|
1049
1725
|
buildSearchArgs,
|
|
1050
1726
|
buildRenameArgs,
|
package/dist/platform.d.ts
CHANGED
|
@@ -11,3 +11,9 @@ export declare function resolveReadSeekBinaryFromPackages(resolver?: ModuleResol
|
|
|
11
11
|
arch?: string;
|
|
12
12
|
metaPackage?: string;
|
|
13
13
|
}): string;
|
|
14
|
+
/**
|
|
15
|
+
* Find an executable readseek on PATH, or null. PATH is the way a user-managed
|
|
16
|
+
* install (package manager, `npm i -g`, cargo) makes itself known; plugins must
|
|
17
|
+
* not grow their own binary-path settings on top of it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveReadSeekBinaryFromPath(pathEnv?: string | undefined): string | null;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarkkojs/readseek-api",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.10",
|
|
4
4
|
"description": "Shared ReadSeek CLI contract, validation, argv builders, and bounded process runners",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"homepage": "https://
|
|
7
|
+
"homepage": "https://gitlab.com/jarkkojs/readseek/-/tree/main/packages/readseek-api#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://
|
|
10
|
+
"url": "git+https://gitlab.com/jarkkojs/readseek.git",
|
|
11
11
|
"directory": "packages/readseek-api"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://
|
|
14
|
+
"url": "https://gitlab.com/jarkkojs/readseek/-/issues"
|
|
15
15
|
},
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"hashline"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@jarkkojs/readseek": "^0.9.
|
|
48
|
+
"@jarkkojs/readseek": "^0.9.10"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^22.0.0",
|