@jarkkojs/readseek-api 0.9.9 → 0.9.11
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 +699 -9
- 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
|
@@ -470,11 +470,11 @@ var PREFERENCE_LEADS = {
|
|
|
470
470
|
view: "Preferred for digesting document structure or selected content."
|
|
471
471
|
};
|
|
472
472
|
var FALLBACK_TEMPLATES = {
|
|
473
|
-
read: "
|
|
474
|
-
edit: "
|
|
475
|
-
write: "
|
|
476
|
-
grep: "
|
|
477
|
-
apply_patch: "
|
|
473
|
+
read: "Prefer `digest` with fresh LINE:HASH anchors.",
|
|
474
|
+
edit: "Prefer `edit` with fresh LINE:HASH anchors.",
|
|
475
|
+
write: "Prefer `write` so the result returns LINE:HASH anchors.",
|
|
476
|
+
grep: "Prefer `grep` for text/regex search with edit-ready anchors.",
|
|
477
|
+
apply_patch: "Prefer `edit` for existing text files."
|
|
478
478
|
};
|
|
479
479
|
function resolveToolName(name, aliases = {}) {
|
|
480
480
|
return aliases[name] ?? name;
|
|
@@ -732,6 +732,7 @@ function buildRenameArgs(input) {
|
|
|
732
732
|
return appendGitSelectionArgs(args, input);
|
|
733
733
|
}
|
|
734
734
|
// src/platform.ts
|
|
735
|
+
import { accessSync, constants as fsConstants } from "node:fs";
|
|
735
736
|
import { createRequire } from "node:module";
|
|
736
737
|
import path from "node:path";
|
|
737
738
|
var READSEEK_PLATFORM_PACKAGES = {
|
|
@@ -760,10 +761,30 @@ function resolveReadSeekBinaryFromPackages(resolver = resolveFromPackage, option
|
|
|
760
761
|
const metaPackage = options.metaPackage ?? "@jarkkojs/readseek";
|
|
761
762
|
const metaPackageJson = resolve(`${metaPackage}/package.json`);
|
|
762
763
|
const metaPackageDir = path.dirname(metaPackageJson);
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
764
|
+
let packageJsonPath;
|
|
765
|
+
try {
|
|
766
|
+
packageJsonPath = resolve(`${platformPackage}/package.json`);
|
|
767
|
+
} catch {
|
|
768
|
+
packageJsonPath = resolve(`${platformPackage}/package.json`, {
|
|
769
|
+
paths: [metaPackageDir]
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), "bin", readSeekBinaryName(platform));
|
|
773
|
+
accessSync(binaryPath, fsConstants.X_OK);
|
|
774
|
+
return binaryPath;
|
|
775
|
+
}
|
|
776
|
+
function resolveReadSeekBinaryFromPath(pathEnv = process.env.PATH) {
|
|
777
|
+
const name = readSeekBinaryName();
|
|
778
|
+
for (const dir of (pathEnv ?? "").split(path.delimiter)) {
|
|
779
|
+
if (!dir)
|
|
780
|
+
continue;
|
|
781
|
+
const candidate = path.join(dir, name);
|
|
782
|
+
try {
|
|
783
|
+
accessSync(candidate, fsConstants.X_OK);
|
|
784
|
+
return candidate;
|
|
785
|
+
} catch {}
|
|
786
|
+
}
|
|
787
|
+
return null;
|
|
767
788
|
}
|
|
768
789
|
// src/json.ts
|
|
769
790
|
var READSEEK_USAGE_HINT = /\n\s*Run readseek(?: [\w-]+)* --help for more information\.?\s*$/;
|
|
@@ -1015,6 +1036,672 @@ async function runReadSeekBunText(binaryPath, args, options = {}) {
|
|
|
1015
1036
|
async function runReadSeekBunJson(binaryPath, args, options = {}) {
|
|
1016
1037
|
return parseSuccessfulJson(await runReadSeekBun(binaryPath, args, options));
|
|
1017
1038
|
}
|
|
1039
|
+
// src/client.ts
|
|
1040
|
+
function classifyReadSeekFailure(err) {
|
|
1041
|
+
const failure = err;
|
|
1042
|
+
const message = String(failure?.message ?? err);
|
|
1043
|
+
const missing = failure?.code === "ENOENT" || /Cannot find package|Cannot find module|no such file/i.test(message);
|
|
1044
|
+
if (missing) {
|
|
1045
|
+
return { code: "readseek-not-installed", message, hint: "Run npm install to install @jarkkojs/readseek." };
|
|
1046
|
+
}
|
|
1047
|
+
return { code: "readseek-execution-error", message };
|
|
1048
|
+
}
|
|
1049
|
+
function requireNumber(value, field) {
|
|
1050
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value))
|
|
1051
|
+
throw new Error(`invalid readseek ${field}: expected safe integer`);
|
|
1052
|
+
return value;
|
|
1053
|
+
}
|
|
1054
|
+
function requireString(value, field) {
|
|
1055
|
+
if (typeof value !== "string")
|
|
1056
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1057
|
+
return value;
|
|
1058
|
+
}
|
|
1059
|
+
function requireBoolean(value, field) {
|
|
1060
|
+
if (typeof value !== "boolean")
|
|
1061
|
+
throw new Error(`invalid readseek ${field}: expected boolean`);
|
|
1062
|
+
return value;
|
|
1063
|
+
}
|
|
1064
|
+
function optionalString(value, field) {
|
|
1065
|
+
if (value === undefined || value === null)
|
|
1066
|
+
return;
|
|
1067
|
+
return requireString(value, field);
|
|
1068
|
+
}
|
|
1069
|
+
function parseHashline(value, field) {
|
|
1070
|
+
if (!value || typeof value !== "object")
|
|
1071
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1072
|
+
const item = value;
|
|
1073
|
+
return {
|
|
1074
|
+
line: requireNumber(item.line, `${field}.line`),
|
|
1075
|
+
hash: requireString(item.hash, `${field}.hash`),
|
|
1076
|
+
text: requireString(item.text, `${field}.text`)
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
function parseSearchHashlines(value, field) {
|
|
1080
|
+
if (!Array.isArray(value))
|
|
1081
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1082
|
+
return value.map((line) => parseHashline(line, field));
|
|
1083
|
+
}
|
|
1084
|
+
function parseReadOutput(value) {
|
|
1085
|
+
if (!value || typeof value !== "object")
|
|
1086
|
+
throw new Error("invalid readseek read output");
|
|
1087
|
+
const output = value;
|
|
1088
|
+
const hashlines = output.hashlines;
|
|
1089
|
+
if (!Array.isArray(hashlines))
|
|
1090
|
+
throw new Error("invalid readseek hashlines");
|
|
1091
|
+
return {
|
|
1092
|
+
file: requireString(output.file, "file"),
|
|
1093
|
+
language: requireString(output.language, "language"),
|
|
1094
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1095
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1096
|
+
start_line: requireNumber(output.start_line, "start_line"),
|
|
1097
|
+
end_line: requireNumber(output.end_line, "end_line"),
|
|
1098
|
+
hashlines: hashlines.map((line) => parseHashline(line, "hashline"))
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
function parseMapOutput(value) {
|
|
1102
|
+
if (!value || typeof value !== "object")
|
|
1103
|
+
throw new Error("invalid readseek map output");
|
|
1104
|
+
const output = value;
|
|
1105
|
+
const symbols = output.symbols;
|
|
1106
|
+
if (!Array.isArray(symbols))
|
|
1107
|
+
throw new Error("invalid readseek symbols");
|
|
1108
|
+
return {
|
|
1109
|
+
file: requireString(output.file, "file"),
|
|
1110
|
+
language: requireString(output.language, "language"),
|
|
1111
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1112
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1113
|
+
symbols: symbols.map((symbol) => {
|
|
1114
|
+
if (!symbol || typeof symbol !== "object")
|
|
1115
|
+
throw new Error("invalid readseek symbol");
|
|
1116
|
+
const item = symbol;
|
|
1117
|
+
return {
|
|
1118
|
+
kind: requireString(item.kind, "symbol.kind"),
|
|
1119
|
+
name: requireString(item.name, "symbol.name"),
|
|
1120
|
+
qualified_name: requireString(item.qualified_name, "symbol.qualified_name"),
|
|
1121
|
+
start_line: requireNumber(item.start_line, "symbol.start_line"),
|
|
1122
|
+
end_line: requireNumber(item.end_line, "symbol.end_line"),
|
|
1123
|
+
start_hash: requireString(item.start_hash, "symbol.start_hash"),
|
|
1124
|
+
end_hash: requireString(item.end_hash, "symbol.end_hash")
|
|
1125
|
+
};
|
|
1126
|
+
})
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
function parseSearchOutput(value) {
|
|
1130
|
+
if (!value || typeof value !== "object")
|
|
1131
|
+
throw new Error("invalid readseek search output");
|
|
1132
|
+
const output = value;
|
|
1133
|
+
if (!Array.isArray(output.results))
|
|
1134
|
+
throw new Error("invalid readseek search results");
|
|
1135
|
+
return output.results.map((result) => {
|
|
1136
|
+
if (!result || typeof result !== "object")
|
|
1137
|
+
throw new Error("invalid readseek search result");
|
|
1138
|
+
const file = result;
|
|
1139
|
+
if (!Array.isArray(file.matches))
|
|
1140
|
+
throw new Error("invalid readseek search matches");
|
|
1141
|
+
return {
|
|
1142
|
+
file: requireString(file.file, "search.file"),
|
|
1143
|
+
language: requireString(file.language, "search.language"),
|
|
1144
|
+
file_hash: requireString(file.file_hash, "search.file_hash"),
|
|
1145
|
+
matches: file.matches.map((match) => {
|
|
1146
|
+
if (!match || typeof match !== "object")
|
|
1147
|
+
throw new Error("invalid readseek search match");
|
|
1148
|
+
const item = match;
|
|
1149
|
+
if (!Array.isArray(item.captures))
|
|
1150
|
+
throw new Error("invalid readseek search captures");
|
|
1151
|
+
return {
|
|
1152
|
+
pattern_index: item.pattern_index === undefined ? 0 : requireNumber(item.pattern_index, "search.match.pattern_index"),
|
|
1153
|
+
start_line: requireNumber(item.start_line, "search.match.start_line"),
|
|
1154
|
+
end_line: requireNumber(item.end_line, "search.match.end_line"),
|
|
1155
|
+
start_hash: requireString(item.start_hash, "search.match.start_hash"),
|
|
1156
|
+
end_hash: requireString(item.end_hash, "search.match.end_hash"),
|
|
1157
|
+
hashlines: parseSearchHashlines(item.hashlines, "search.match.hashlines"),
|
|
1158
|
+
captures: item.captures.map((capture) => {
|
|
1159
|
+
if (!capture || typeof capture !== "object")
|
|
1160
|
+
throw new Error("invalid readseek search capture");
|
|
1161
|
+
const captureItem = capture;
|
|
1162
|
+
return {
|
|
1163
|
+
name: requireString(captureItem.name, "search.capture.name"),
|
|
1164
|
+
start_line: requireNumber(captureItem.start_line, "search.capture.start_line"),
|
|
1165
|
+
end_line: requireNumber(captureItem.end_line, "search.capture.end_line"),
|
|
1166
|
+
start_hash: requireString(captureItem.start_hash, "search.capture.start_hash"),
|
|
1167
|
+
end_hash: requireString(captureItem.end_hash, "search.capture.end_hash"),
|
|
1168
|
+
hashlines: parseSearchHashlines(captureItem.hashlines, "search.capture.hashlines")
|
|
1169
|
+
};
|
|
1170
|
+
})
|
|
1171
|
+
};
|
|
1172
|
+
})
|
|
1173
|
+
};
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
function parseRefsOutput(value) {
|
|
1177
|
+
if (!value || typeof value !== "object")
|
|
1178
|
+
throw new Error("invalid readseek refs output");
|
|
1179
|
+
const output = value;
|
|
1180
|
+
if (!Array.isArray(output.references))
|
|
1181
|
+
throw new Error("invalid readseek references");
|
|
1182
|
+
return output.references.map((reference) => {
|
|
1183
|
+
if (!reference || typeof reference !== "object")
|
|
1184
|
+
throw new Error("invalid readseek reference");
|
|
1185
|
+
const item = reference;
|
|
1186
|
+
const symbol = item.symbol;
|
|
1187
|
+
const enclosing = symbol && typeof symbol === "object" ? optionalString(symbol.qualified_name, "reference.symbol.qualified_name") : undefined;
|
|
1188
|
+
return {
|
|
1189
|
+
file: requireString(item.file, "reference.file"),
|
|
1190
|
+
line: requireNumber(item.line, "reference.line"),
|
|
1191
|
+
column: requireNumber(item.column, "reference.column"),
|
|
1192
|
+
line_hash: requireString(item.line_hash, "reference.line_hash"),
|
|
1193
|
+
text: requireString(item.text, "reference.text"),
|
|
1194
|
+
enclosingSymbol: enclosing
|
|
1195
|
+
};
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
function parseDiagnosticKind(value) {
|
|
1199
|
+
if (value === "error" || value === "missing")
|
|
1200
|
+
return value;
|
|
1201
|
+
throw new Error("invalid readseek diagnostic.kind");
|
|
1202
|
+
}
|
|
1203
|
+
function parseCheckOutput(value) {
|
|
1204
|
+
if (!value || typeof value !== "object")
|
|
1205
|
+
throw new Error("invalid readseek check output");
|
|
1206
|
+
const output = value;
|
|
1207
|
+
if (!Array.isArray(output.diagnostics))
|
|
1208
|
+
throw new Error("invalid readseek diagnostics");
|
|
1209
|
+
return {
|
|
1210
|
+
errorCount: requireNumber(output.error_count, "error_count"),
|
|
1211
|
+
missingCount: requireNumber(output.missing_count, "missing_count"),
|
|
1212
|
+
diagnostics: output.diagnostics.map((diagnostic) => {
|
|
1213
|
+
if (!diagnostic || typeof diagnostic !== "object")
|
|
1214
|
+
throw new Error("invalid readseek diagnostic");
|
|
1215
|
+
const item = diagnostic;
|
|
1216
|
+
return {
|
|
1217
|
+
kind: parseDiagnosticKind(item.kind),
|
|
1218
|
+
start_line: requireNumber(item.start_line, "diagnostic.start_line"),
|
|
1219
|
+
end_line: requireNumber(item.end_line, "diagnostic.end_line")
|
|
1220
|
+
};
|
|
1221
|
+
})
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
function parseDetectedObjects(value) {
|
|
1225
|
+
if (value === undefined || value === null)
|
|
1226
|
+
return;
|
|
1227
|
+
if (!Array.isArray(value))
|
|
1228
|
+
throw new Error("invalid readseek detect objects");
|
|
1229
|
+
return value.map((object) => {
|
|
1230
|
+
if (!object || typeof object !== "object")
|
|
1231
|
+
throw new Error("invalid readseek detect object");
|
|
1232
|
+
const item = object;
|
|
1233
|
+
const bbox = item.bbox;
|
|
1234
|
+
if (!Array.isArray(bbox) || bbox.length !== 4)
|
|
1235
|
+
throw new Error("invalid readseek detect object.bbox");
|
|
1236
|
+
return {
|
|
1237
|
+
label: requireString(item.label, "object.label"),
|
|
1238
|
+
bbox: bbox.map((n, i) => requireNumber(n, `object.bbox[${i}]`))
|
|
1239
|
+
};
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
function parseImageEncoding(value) {
|
|
1243
|
+
if (value === "base64")
|
|
1244
|
+
return value;
|
|
1245
|
+
throw new Error("invalid image encoding");
|
|
1246
|
+
}
|
|
1247
|
+
function parseDetectOutput(value) {
|
|
1248
|
+
if (!value || typeof value !== "object")
|
|
1249
|
+
throw new Error("invalid readseek detect output");
|
|
1250
|
+
const output = value;
|
|
1251
|
+
const type = requireString(output.type, "type");
|
|
1252
|
+
const file = requireString(output.file, "file");
|
|
1253
|
+
const mime = optionalString(output.mime, "mime");
|
|
1254
|
+
if (type === "application/pdf") {
|
|
1255
|
+
if (output.format !== "pdf")
|
|
1256
|
+
throw new Error("invalid readseek PDF format");
|
|
1257
|
+
return {
|
|
1258
|
+
kind: "pdf",
|
|
1259
|
+
type,
|
|
1260
|
+
file,
|
|
1261
|
+
mime,
|
|
1262
|
+
format: output.format,
|
|
1263
|
+
pages: requireNumber(output.pages, "pages")
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
if (output.width !== undefined || output.height !== undefined) {
|
|
1267
|
+
return {
|
|
1268
|
+
kind: "image",
|
|
1269
|
+
type,
|
|
1270
|
+
file,
|
|
1271
|
+
mime,
|
|
1272
|
+
format: requireString(output.format, "format"),
|
|
1273
|
+
width: requireNumber(output.width, "width"),
|
|
1274
|
+
height: requireNumber(output.height, "height"),
|
|
1275
|
+
animated: requireBoolean(output.animated, "animated"),
|
|
1276
|
+
encoding: output.encoding === undefined ? undefined : parseImageEncoding(output.encoding),
|
|
1277
|
+
data: output.data === undefined ? undefined : requireString(output.data, "data"),
|
|
1278
|
+
ocr: optionalString(output.ocr, "ocr"),
|
|
1279
|
+
caption: optionalString(output.caption, "caption"),
|
|
1280
|
+
objects: parseDetectedObjects(output.objects)
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
if (output.language !== undefined) {
|
|
1284
|
+
return {
|
|
1285
|
+
kind: "source",
|
|
1286
|
+
type,
|
|
1287
|
+
file,
|
|
1288
|
+
language: requireString(output.language, "language"),
|
|
1289
|
+
engine: optionalString(output.engine, "engine"),
|
|
1290
|
+
supported: requireBoolean(output.supported, "supported"),
|
|
1291
|
+
mime,
|
|
1292
|
+
syntax: optionalString(output.syntax, "syntax")
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
return { kind: "text", type, file, mime };
|
|
1296
|
+
}
|
|
1297
|
+
function parseDocumentCache(value) {
|
|
1298
|
+
if (!value || typeof value !== "object")
|
|
1299
|
+
throw new Error("invalid readseek document cache");
|
|
1300
|
+
const cache = value;
|
|
1301
|
+
const state = requireString(cache.state, "cache.state");
|
|
1302
|
+
if (state !== "built" && state !== "reused")
|
|
1303
|
+
throw new Error("invalid readseek cache.state");
|
|
1304
|
+
return {
|
|
1305
|
+
content_hash: requireString(cache.content_hash, "cache.content_hash"),
|
|
1306
|
+
state
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
function parseIdentifyOutput(value) {
|
|
1310
|
+
if (!value || typeof value !== "object")
|
|
1311
|
+
throw new Error("invalid readseek identify output");
|
|
1312
|
+
const output = value;
|
|
1313
|
+
const identifier = output.identifier;
|
|
1314
|
+
const symbol = output.symbol;
|
|
1315
|
+
return {
|
|
1316
|
+
file: requireString(output.file, "file"),
|
|
1317
|
+
language: requireString(output.language, "language"),
|
|
1318
|
+
engine: optionalString(output.engine, "engine"),
|
|
1319
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1320
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1321
|
+
line: requireNumber(output.line, "line"),
|
|
1322
|
+
column: requireNumber(output.column, "column"),
|
|
1323
|
+
line_hash: requireString(output.line_hash, "line_hash"),
|
|
1324
|
+
identifier: identifier && typeof identifier === "object" ? {
|
|
1325
|
+
text: requireString(identifier.text, "identifier.text"),
|
|
1326
|
+
start_column: requireNumber(identifier.start_column, "identifier.start_column"),
|
|
1327
|
+
end_column: requireNumber(identifier.end_column, "identifier.end_column"),
|
|
1328
|
+
start_byte: requireNumber(identifier.start_byte, "identifier.start_byte"),
|
|
1329
|
+
end_byte: requireNumber(identifier.end_byte, "identifier.end_byte")
|
|
1330
|
+
} : undefined,
|
|
1331
|
+
symbol: symbol && typeof symbol === "object" ? {
|
|
1332
|
+
name: requireString(symbol.name, "symbol.name"),
|
|
1333
|
+
kind: requireString(symbol.kind, "symbol.kind"),
|
|
1334
|
+
qualified_name: requireString(symbol.qualified_name, "symbol.qualified_name"),
|
|
1335
|
+
start_line: requireNumber(symbol.start_line, "symbol.start_line"),
|
|
1336
|
+
end_line: requireNumber(symbol.end_line, "symbol.end_line")
|
|
1337
|
+
} : undefined
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
function parseImageContent(value) {
|
|
1341
|
+
const detection = parseDetectOutput(value);
|
|
1342
|
+
if (detection.kind !== "image")
|
|
1343
|
+
throw new Error("invalid readseek image content");
|
|
1344
|
+
return detection;
|
|
1345
|
+
}
|
|
1346
|
+
function parseTextContent(value) {
|
|
1347
|
+
if (!value || typeof value !== "object")
|
|
1348
|
+
throw new Error("invalid readseek content");
|
|
1349
|
+
const output = value;
|
|
1350
|
+
if (output.hashlines !== undefined && output.start_line === undefined) {
|
|
1351
|
+
const hashlines = parseSearchHashlines(output.hashlines, "content.hashlines");
|
|
1352
|
+
const first = hashlines[0];
|
|
1353
|
+
const last = hashlines[hashlines.length - 1];
|
|
1354
|
+
return {
|
|
1355
|
+
file: requireString(output.file, "file"),
|
|
1356
|
+
language: requireString(output.language, "language"),
|
|
1357
|
+
line_count: requireNumber(output.line_count, "line_count"),
|
|
1358
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1359
|
+
start_line: first?.line ?? 1,
|
|
1360
|
+
end_line: last?.line ?? 0,
|
|
1361
|
+
hashlines
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
return parseReadOutput(value);
|
|
1365
|
+
}
|
|
1366
|
+
function parseDigestEnvelope(value) {
|
|
1367
|
+
if (!value || typeof value !== "object")
|
|
1368
|
+
throw new Error("invalid readseek digest output");
|
|
1369
|
+
const output = value;
|
|
1370
|
+
if (output.metadata === undefined)
|
|
1371
|
+
throw new Error("invalid readseek digest metadata");
|
|
1372
|
+
const result = {
|
|
1373
|
+
metadata: parseDetectOutput(output.metadata)
|
|
1374
|
+
};
|
|
1375
|
+
if (output.cache !== undefined)
|
|
1376
|
+
result.cache = parseDocumentCache(output.cache);
|
|
1377
|
+
if (output.content !== undefined)
|
|
1378
|
+
result.content = output.content;
|
|
1379
|
+
if (output.map !== undefined)
|
|
1380
|
+
result.map = parseMapOutput(output.map);
|
|
1381
|
+
if (output.diagnostics !== undefined)
|
|
1382
|
+
result.diagnostics = parseCheckOutput(output.diagnostics);
|
|
1383
|
+
if (output.identity !== undefined)
|
|
1384
|
+
result.identity = parseIdentifyOutput(output.identity);
|
|
1385
|
+
return result;
|
|
1386
|
+
}
|
|
1387
|
+
function parseEditOutput(value) {
|
|
1388
|
+
if (!value || typeof value !== "object")
|
|
1389
|
+
throw new Error("invalid readseek edit output");
|
|
1390
|
+
const output = value;
|
|
1391
|
+
return {
|
|
1392
|
+
file: requireString(output.file, "file"),
|
|
1393
|
+
before_hash: requireString(output.before_hash, "before_hash"),
|
|
1394
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1395
|
+
plan_hash: requireString(output.plan_hash, "plan_hash"),
|
|
1396
|
+
applied: requireBoolean(output.applied, "applied"),
|
|
1397
|
+
changed: requireBoolean(output.changed, "changed"),
|
|
1398
|
+
edit_count: requireNumber(output.edit_count, "edit_count"),
|
|
1399
|
+
before_content: optionalString(output.before_content, "before_content"),
|
|
1400
|
+
content: optionalString(output.content, "content")
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
function parseRenameConflicts(value, field) {
|
|
1404
|
+
if (value === undefined)
|
|
1405
|
+
return [];
|
|
1406
|
+
if (!Array.isArray(value))
|
|
1407
|
+
throw new Error(`invalid readseek ${field}`);
|
|
1408
|
+
return value.map((item) => {
|
|
1409
|
+
if (!item || typeof item !== "object")
|
|
1410
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1411
|
+
const c = item;
|
|
1412
|
+
return {
|
|
1413
|
+
line: requireNumber(c.line, `${field}.line`),
|
|
1414
|
+
column: requireNumber(c.column, `${field}.column`),
|
|
1415
|
+
reason: requireString(c.reason, `${field}.reason`)
|
|
1416
|
+
};
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
function parseRenameEdits(value, field) {
|
|
1420
|
+
if (value === undefined)
|
|
1421
|
+
return [];
|
|
1422
|
+
if (!Array.isArray(value))
|
|
1423
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1424
|
+
return value.map((item) => {
|
|
1425
|
+
if (!item || typeof item !== "object")
|
|
1426
|
+
throw new Error(`invalid readseek ${field} entry`);
|
|
1427
|
+
const e = item;
|
|
1428
|
+
return {
|
|
1429
|
+
line: requireNumber(e.line, `${field}.line`),
|
|
1430
|
+
start_column: requireNumber(e.start_column, `${field}.start_column`),
|
|
1431
|
+
end_column: requireNumber(e.end_column, `${field}.end_column`),
|
|
1432
|
+
start_byte: requireNumber(e.start_byte, `${field}.start_byte`),
|
|
1433
|
+
end_byte: requireNumber(e.end_byte, `${field}.end_byte`),
|
|
1434
|
+
occurrence: requireString(e.occurrence, `${field}.occurrence`),
|
|
1435
|
+
line_hash: requireString(e.line_hash, `${field}.line_hash`),
|
|
1436
|
+
text: requireString(e.text, `${field}.text`)
|
|
1437
|
+
};
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
function parseRenameOutput(value) {
|
|
1441
|
+
if (!value || typeof value !== "object")
|
|
1442
|
+
throw new Error("invalid readseek rename output");
|
|
1443
|
+
const output = value;
|
|
1444
|
+
const others = output.others;
|
|
1445
|
+
if (others !== undefined && !Array.isArray(others))
|
|
1446
|
+
throw new Error("invalid readseek others");
|
|
1447
|
+
return {
|
|
1448
|
+
file: requireString(output.file, "file"),
|
|
1449
|
+
language: requireString(output.language, "language"),
|
|
1450
|
+
engine: optionalString(output.engine, "engine"),
|
|
1451
|
+
file_hash: requireString(output.file_hash, "file_hash"),
|
|
1452
|
+
old_name: requireString(output.old_name, "old_name"),
|
|
1453
|
+
new_name: requireString(output.new_name, "new_name"),
|
|
1454
|
+
applied: requireBoolean(output.applied, "applied"),
|
|
1455
|
+
conflicts: parseRenameConflicts(output.conflicts, "conflicts"),
|
|
1456
|
+
edits: parseRenameEdits(output.edits, "edits"),
|
|
1457
|
+
others: others?.map((entry) => {
|
|
1458
|
+
if (!entry || typeof entry !== "object")
|
|
1459
|
+
throw new Error("invalid readseek other");
|
|
1460
|
+
const o = entry;
|
|
1461
|
+
return {
|
|
1462
|
+
file: requireString(o.file, "other.file"),
|
|
1463
|
+
language: requireString(o.language, "other.language"),
|
|
1464
|
+
engine: optionalString(o.engine, "other.engine"),
|
|
1465
|
+
file_hash: requireString(o.file_hash, "other.file_hash"),
|
|
1466
|
+
conflicts: parseRenameConflicts(o.conflicts, "other.conflicts"),
|
|
1467
|
+
edits: parseRenameEdits(o.edits, "other.edits")
|
|
1468
|
+
};
|
|
1469
|
+
}) ?? []
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
function parseDefCompact(value) {
|
|
1473
|
+
if (!value || typeof value !== "object")
|
|
1474
|
+
throw new Error("invalid readseek def output");
|
|
1475
|
+
const output = value;
|
|
1476
|
+
const locations = output.locations;
|
|
1477
|
+
if (!Array.isArray(locations))
|
|
1478
|
+
throw new Error("invalid readseek def locations");
|
|
1479
|
+
return locations.map((loc) => {
|
|
1480
|
+
if (!loc || typeof loc !== "object")
|
|
1481
|
+
throw new Error("invalid readseek def location");
|
|
1482
|
+
const item = loc;
|
|
1483
|
+
return {
|
|
1484
|
+
file: requireString(item.file, "location.file"),
|
|
1485
|
+
line: requireNumber(item.line, "location.line"),
|
|
1486
|
+
column: requireNumber(item.column, "location.column"),
|
|
1487
|
+
line_hash: requireString(item.line_hash, "location.line_hash"),
|
|
1488
|
+
text: requireString(item.text, "location.text"),
|
|
1489
|
+
kind: optionalString(item.kind, "location.kind"),
|
|
1490
|
+
name: optionalString(item.name, "location.name"),
|
|
1491
|
+
qualified_name: optionalString(item.qualified_name, "location.qualified_name")
|
|
1492
|
+
};
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
function createReadSeekClient(runner) {
|
|
1496
|
+
function digestArgs(target, options) {
|
|
1497
|
+
return buildDigestArgs({
|
|
1498
|
+
path: target,
|
|
1499
|
+
select: options.select ?? "content",
|
|
1500
|
+
at: options.at,
|
|
1501
|
+
end: options.end,
|
|
1502
|
+
limit: options.limit,
|
|
1503
|
+
language: options.language,
|
|
1504
|
+
visionMode: options.visionMode,
|
|
1505
|
+
visionLevel: options.visionLevel,
|
|
1506
|
+
stdinName: options.stdin !== undefined && target === "-" ? options.stdinName ?? target : undefined
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
async function runDigestRaw(target, options = {}) {
|
|
1510
|
+
const args = digestArgs(target, options);
|
|
1511
|
+
const runOptions = {
|
|
1512
|
+
signal: options.signal,
|
|
1513
|
+
stdin: options.stdin,
|
|
1514
|
+
timeoutMs: options.timeoutMs,
|
|
1515
|
+
vision: options.vision
|
|
1516
|
+
};
|
|
1517
|
+
return runner.json(args, runOptions);
|
|
1518
|
+
}
|
|
1519
|
+
async function digest(target, options = {}) {
|
|
1520
|
+
return parseDigestEnvelope(await runDigestRaw(target, options));
|
|
1521
|
+
}
|
|
1522
|
+
function requireDigestContent(envelope, field) {
|
|
1523
|
+
if (envelope.content === undefined)
|
|
1524
|
+
throw new Error(`invalid readseek ${field}: missing content`);
|
|
1525
|
+
return envelope.content;
|
|
1526
|
+
}
|
|
1527
|
+
async function digestContent(filePath, options = {}) {
|
|
1528
|
+
const envelope = await digest(filePath, {
|
|
1529
|
+
select: "content",
|
|
1530
|
+
at: options.startLine !== undefined ? buildLineLocation(options.startLine) : undefined,
|
|
1531
|
+
end: options.endLine,
|
|
1532
|
+
visionMode: options.visionMode,
|
|
1533
|
+
signal: options.signal,
|
|
1534
|
+
vision: options.vision
|
|
1535
|
+
});
|
|
1536
|
+
if (envelope.metadata.kind === "pdf") {
|
|
1537
|
+
return { metadata: envelope.metadata, cache: envelope.cache };
|
|
1538
|
+
}
|
|
1539
|
+
const content = requireDigestContent(envelope, "content");
|
|
1540
|
+
if (envelope.metadata.kind === "image") {
|
|
1541
|
+
return { metadata: envelope.metadata, image: parseImageContent(content) };
|
|
1542
|
+
}
|
|
1543
|
+
return { metadata: envelope.metadata, text: parseTextContent(content) };
|
|
1544
|
+
}
|
|
1545
|
+
return {
|
|
1546
|
+
async view(filePath, options = {}) {
|
|
1547
|
+
const args = buildViewArgs({
|
|
1548
|
+
path: filePath,
|
|
1549
|
+
node: options.node,
|
|
1550
|
+
page: options.page,
|
|
1551
|
+
kind: options.kind,
|
|
1552
|
+
depth: options.depth,
|
|
1553
|
+
outline: options.outline,
|
|
1554
|
+
visionMode: options.visionMode,
|
|
1555
|
+
visionLevel: options.visionLevel
|
|
1556
|
+
});
|
|
1557
|
+
return runner.text(args, {
|
|
1558
|
+
signal: options.signal,
|
|
1559
|
+
vision: options.visionMode !== undefined
|
|
1560
|
+
});
|
|
1561
|
+
},
|
|
1562
|
+
digestRaw(target, options = {}) {
|
|
1563
|
+
return runDigestRaw(target, options);
|
|
1564
|
+
},
|
|
1565
|
+
digest,
|
|
1566
|
+
digestContent,
|
|
1567
|
+
async image(filePath, modes, options = {}) {
|
|
1568
|
+
const requestedModes = modes.length > 1 ? ["all"] : modes;
|
|
1569
|
+
const results = await Promise.allSettled(requestedModes.map(async (mode) => {
|
|
1570
|
+
const digested = await digestContent(filePath, {
|
|
1571
|
+
visionMode: mode,
|
|
1572
|
+
signal: options.signal,
|
|
1573
|
+
vision: true
|
|
1574
|
+
});
|
|
1575
|
+
if (!digested.image)
|
|
1576
|
+
throw new Error(`readseek returned no image analysis for ${filePath}`);
|
|
1577
|
+
return digested.image;
|
|
1578
|
+
}));
|
|
1579
|
+
let merged;
|
|
1580
|
+
for (const result of results) {
|
|
1581
|
+
if (result.status !== "fulfilled")
|
|
1582
|
+
continue;
|
|
1583
|
+
const detection = result.value;
|
|
1584
|
+
merged = merged === undefined ? detection : {
|
|
1585
|
+
...merged,
|
|
1586
|
+
ocr: detection.ocr ?? merged.ocr,
|
|
1587
|
+
caption: detection.caption ?? merged.caption,
|
|
1588
|
+
objects: detection.objects ?? merged.objects
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
if (merged !== undefined)
|
|
1592
|
+
return merged;
|
|
1593
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
1594
|
+
if (failure?.status === "rejected")
|
|
1595
|
+
throw failure.reason;
|
|
1596
|
+
throw new Error(`readseek returned no image analysis for ${filePath}`);
|
|
1597
|
+
},
|
|
1598
|
+
async preparedImage(filePath, options = {}) {
|
|
1599
|
+
const digested = await digestContent(filePath, {
|
|
1600
|
+
visionMode: "none",
|
|
1601
|
+
signal: options.signal
|
|
1602
|
+
});
|
|
1603
|
+
const output = digested.image;
|
|
1604
|
+
if (!output || output.encoding !== "base64" || output.data === undefined || output.mime === undefined) {
|
|
1605
|
+
throw new Error(`readseek returned no prepared image for ${filePath}`);
|
|
1606
|
+
}
|
|
1607
|
+
return { mime: output.mime, encoding: output.encoding, data: output.data };
|
|
1608
|
+
},
|
|
1609
|
+
async search(target, pattern, options = {}) {
|
|
1610
|
+
const args = buildSearchArgs({
|
|
1611
|
+
path: target,
|
|
1612
|
+
pattern,
|
|
1613
|
+
language: options.language,
|
|
1614
|
+
cached: options.cached,
|
|
1615
|
+
others: options.others,
|
|
1616
|
+
ignored: options.ignored
|
|
1617
|
+
});
|
|
1618
|
+
return parseSearchOutput(await runner.json(args, { signal: options.signal }));
|
|
1619
|
+
},
|
|
1620
|
+
async refs(target, options = {}) {
|
|
1621
|
+
const args = buildRefsArgs({
|
|
1622
|
+
path: target,
|
|
1623
|
+
name: options.name,
|
|
1624
|
+
scope: options.scope,
|
|
1625
|
+
line: options.line,
|
|
1626
|
+
column: options.column,
|
|
1627
|
+
language: options.language,
|
|
1628
|
+
cached: options.cached,
|
|
1629
|
+
others: options.others,
|
|
1630
|
+
ignored: options.ignored
|
|
1631
|
+
});
|
|
1632
|
+
return parseRefsOutput(await runner.json(args, { signal: options.signal }));
|
|
1633
|
+
},
|
|
1634
|
+
async def(target, options) {
|
|
1635
|
+
const args = buildDefArgs({
|
|
1636
|
+
path: target,
|
|
1637
|
+
name: options.name,
|
|
1638
|
+
format: "plain",
|
|
1639
|
+
language: options.language,
|
|
1640
|
+
cached: options.cached,
|
|
1641
|
+
others: options.others,
|
|
1642
|
+
ignored: options.ignored
|
|
1643
|
+
});
|
|
1644
|
+
return parseDefCompact(await runner.json(args, { signal: options.signal }));
|
|
1645
|
+
},
|
|
1646
|
+
async check(filePath, content, options = {}) {
|
|
1647
|
+
const envelope = await digest("-", {
|
|
1648
|
+
select: "diagnostics",
|
|
1649
|
+
stdin: content,
|
|
1650
|
+
stdinName: filePath,
|
|
1651
|
+
signal: options.signal
|
|
1652
|
+
});
|
|
1653
|
+
if (!envelope.diagnostics)
|
|
1654
|
+
throw new Error("invalid readseek diagnostics: missing diagnostics facet");
|
|
1655
|
+
return envelope.diagnostics;
|
|
1656
|
+
},
|
|
1657
|
+
async identify(filePath, content, options = {}) {
|
|
1658
|
+
const envelope = await digest("-", {
|
|
1659
|
+
select: "identity",
|
|
1660
|
+
stdin: content,
|
|
1661
|
+
stdinName: filePath,
|
|
1662
|
+
at: options.line !== undefined ? buildLineLocation(options.line, options.column) : undefined,
|
|
1663
|
+
language: options.language,
|
|
1664
|
+
signal: options.signal
|
|
1665
|
+
});
|
|
1666
|
+
if (!envelope.identity)
|
|
1667
|
+
throw new Error("invalid readseek identity: missing identity facet");
|
|
1668
|
+
return envelope.identity;
|
|
1669
|
+
},
|
|
1670
|
+
async detect(filePath, options = {}) {
|
|
1671
|
+
const envelope = await digest(filePath, { select: "metadata", signal: options.signal });
|
|
1672
|
+
return envelope.metadata;
|
|
1673
|
+
},
|
|
1674
|
+
async edit(filePath, edits, options = {}) {
|
|
1675
|
+
const args = buildEditArgs({
|
|
1676
|
+
path: filePath,
|
|
1677
|
+
apply: options.apply,
|
|
1678
|
+
planHash: options.planHash,
|
|
1679
|
+
language: options.language
|
|
1680
|
+
});
|
|
1681
|
+
return parseEditOutput(await runner.json(args, {
|
|
1682
|
+
signal: options.signal,
|
|
1683
|
+
stdin: JSON.stringify({ edits }),
|
|
1684
|
+
timeoutMs: options.timeoutMs,
|
|
1685
|
+
cancelable: options.cancelable
|
|
1686
|
+
}));
|
|
1687
|
+
},
|
|
1688
|
+
async rename(filePath, options) {
|
|
1689
|
+
const args = buildRenameArgs({
|
|
1690
|
+
path: filePath,
|
|
1691
|
+
to: options.to,
|
|
1692
|
+
line: options.line,
|
|
1693
|
+
column: options.column,
|
|
1694
|
+
workspace: options.workspace,
|
|
1695
|
+
apply: options.apply,
|
|
1696
|
+
language: options.language,
|
|
1697
|
+
cached: options.cached,
|
|
1698
|
+
others: options.others,
|
|
1699
|
+
ignored: options.ignored
|
|
1700
|
+
});
|
|
1701
|
+
return parseRenameOutput(await runner.json(args, { signal: options.signal }));
|
|
1702
|
+
}
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1018
1705
|
export {
|
|
1019
1706
|
validateVisionLevelVsMode,
|
|
1020
1707
|
validateRefsNameVsScope,
|
|
@@ -1028,6 +1715,7 @@ export {
|
|
|
1028
1715
|
runReadSeekBun,
|
|
1029
1716
|
rewriteBacktickedToolNames,
|
|
1030
1717
|
resolveToolName,
|
|
1718
|
+
resolveReadSeekBinaryFromPath,
|
|
1031
1719
|
resolveReadSeekBinaryFromPackages,
|
|
1032
1720
|
resolveProcessLimits,
|
|
1033
1721
|
renderToolRoutingPolicy,
|
|
@@ -1044,7 +1732,9 @@ export {
|
|
|
1044
1732
|
fallbackToolDescriptionMap,
|
|
1045
1733
|
failureFromProcessResult,
|
|
1046
1734
|
ensureSuccessfulStdout,
|
|
1735
|
+
createReadSeekClient,
|
|
1047
1736
|
cleanReadSeekErrorText,
|
|
1737
|
+
classifyReadSeekFailure,
|
|
1048
1738
|
buildViewArgs,
|
|
1049
1739
|
buildSearchArgs,
|
|
1050
1740
|
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.11",
|
|
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.11"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^22.0.0",
|