scoutline 0.2.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +240 -18
  2. package/dist/capabilities/diagnostics.d.ts +70 -32
  3. package/dist/capabilities/diagnostics.d.ts.map +1 -1
  4. package/dist/capabilities/diagnostics.js +97 -46
  5. package/dist/capabilities/diagnostics.js.map +1 -1
  6. package/dist/capabilities/reader.d.ts +227 -0
  7. package/dist/capabilities/reader.d.ts.map +1 -0
  8. package/dist/capabilities/reader.js +100 -0
  9. package/dist/capabilities/reader.js.map +1 -0
  10. package/dist/capabilities/repository.d.ts +221 -0
  11. package/dist/capabilities/repository.d.ts.map +1 -0
  12. package/dist/capabilities/repository.js +172 -0
  13. package/dist/capabilities/repository.js.map +1 -0
  14. package/dist/commands/cache.d.ts +106 -0
  15. package/dist/commands/cache.d.ts.map +1 -0
  16. package/dist/commands/cache.js +203 -0
  17. package/dist/commands/cache.js.map +1 -0
  18. package/dist/commands/doctor.d.ts +17 -6
  19. package/dist/commands/doctor.d.ts.map +1 -1
  20. package/dist/commands/doctor.js +42 -17
  21. package/dist/commands/doctor.js.map +1 -1
  22. package/dist/commands/read.d.ts +74 -14
  23. package/dist/commands/read.d.ts.map +1 -1
  24. package/dist/commands/read.js +257 -117
  25. package/dist/commands/read.js.map +1 -1
  26. package/dist/commands/repo.d.ts +53 -7
  27. package/dist/commands/repo.d.ts.map +1 -1
  28. package/dist/commands/repo.js +104 -123
  29. package/dist/commands/repo.js.map +1 -1
  30. package/dist/commands/repository-explorer.d.ts +147 -0
  31. package/dist/commands/repository-explorer.d.ts.map +1 -0
  32. package/dist/commands/repository-explorer.js +550 -0
  33. package/dist/commands/repository-explorer.js.map +1 -0
  34. package/dist/index.d.ts +20 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +209 -34
  37. package/dist/index.js.map +1 -1
  38. package/dist/lib/cache.d.ts +123 -18
  39. package/dist/lib/cache.d.ts.map +1 -1
  40. package/dist/lib/cache.js +324 -49
  41. package/dist/lib/cache.js.map +1 -1
  42. package/dist/lib/errors.d.ts +24 -1
  43. package/dist/lib/errors.d.ts.map +1 -1
  44. package/dist/lib/errors.js +33 -2
  45. package/dist/lib/errors.js.map +1 -1
  46. package/dist/lib/execution.d.ts +119 -5
  47. package/dist/lib/execution.d.ts.map +1 -1
  48. package/dist/lib/execution.js +216 -10
  49. package/dist/lib/execution.js.map +1 -1
  50. package/dist/lib/index.d.ts +1 -1
  51. package/dist/lib/index.d.ts.map +1 -1
  52. package/dist/lib/index.js +1 -1
  53. package/dist/lib/index.js.map +1 -1
  54. package/dist/lib/mcp-client.d.ts +29 -5
  55. package/dist/lib/mcp-client.d.ts.map +1 -1
  56. package/dist/lib/mcp-client.js +88 -88
  57. package/dist/lib/mcp-client.js.map +1 -1
  58. package/dist/lib/tool-cache.d.ts +86 -0
  59. package/dist/lib/tool-cache.d.ts.map +1 -0
  60. package/dist/lib/tool-cache.js +123 -0
  61. package/dist/lib/tool-cache.js.map +1 -0
  62. package/dist/providers/minimax/adapter.d.ts +6 -4
  63. package/dist/providers/minimax/adapter.d.ts.map +1 -1
  64. package/dist/providers/minimax/adapter.js +64 -57
  65. package/dist/providers/minimax/adapter.js.map +1 -1
  66. package/dist/providers/minimax/coding-plan-client.d.ts +60 -0
  67. package/dist/providers/minimax/coding-plan-client.d.ts.map +1 -0
  68. package/dist/providers/minimax/coding-plan-client.js +204 -0
  69. package/dist/providers/minimax/coding-plan-client.js.map +1 -0
  70. package/dist/providers/minimax/media.d.ts +60 -6
  71. package/dist/providers/minimax/media.d.ts.map +1 -1
  72. package/dist/providers/minimax/media.js +147 -7
  73. package/dist/providers/minimax/media.js.map +1 -1
  74. package/dist/providers/minimax/quota-client.d.ts +13 -6
  75. package/dist/providers/minimax/quota-client.d.ts.map +1 -1
  76. package/dist/providers/minimax/quota-client.js +5 -0
  77. package/dist/providers/minimax/quota-client.js.map +1 -1
  78. package/dist/providers/minimax/vision-attestations.d.ts +23 -0
  79. package/dist/providers/minimax/vision-attestations.d.ts.map +1 -1
  80. package/dist/providers/minimax/vision-attestations.js +35 -10
  81. package/dist/providers/minimax/vision-attestations.js.map +1 -1
  82. package/dist/providers/minimax/vision-conformance.d.ts +8 -6
  83. package/dist/providers/minimax/vision-conformance.d.ts.map +1 -1
  84. package/dist/providers/minimax/vision-conformance.js +8 -6
  85. package/dist/providers/minimax/vision-conformance.js.map +1 -1
  86. package/dist/providers/minimax/vision-revisions.d.ts +8 -1
  87. package/dist/providers/minimax/vision-revisions.d.ts.map +1 -1
  88. package/dist/providers/minimax/vision-revisions.js +13 -6
  89. package/dist/providers/minimax/vision-revisions.js.map +1 -1
  90. package/dist/providers/selection.d.ts +3 -3
  91. package/dist/providers/selection.js +3 -3
  92. package/dist/providers/types.d.ts +66 -32
  93. package/dist/providers/types.d.ts.map +1 -1
  94. package/dist/providers/types.js.map +1 -1
  95. package/dist/providers/zai/adapter.d.ts.map +1 -1
  96. package/dist/providers/zai/adapter.js +71 -5
  97. package/dist/providers/zai/adapter.js.map +1 -1
  98. package/dist/providers/zai/encoded-error.d.ts +90 -0
  99. package/dist/providers/zai/encoded-error.d.ts.map +1 -0
  100. package/dist/providers/zai/encoded-error.js +169 -0
  101. package/dist/providers/zai/encoded-error.js.map +1 -0
  102. package/dist/providers/zai/reader.d.ts +82 -0
  103. package/dist/providers/zai/reader.d.ts.map +1 -0
  104. package/dist/providers/zai/reader.js +490 -0
  105. package/dist/providers/zai/reader.js.map +1 -0
  106. package/dist/providers/zai/repository.d.ts +76 -0
  107. package/dist/providers/zai/repository.d.ts.map +1 -0
  108. package/dist/providers/zai/repository.js +715 -0
  109. package/dist/providers/zai/repository.js.map +1 -0
  110. package/package.json +3 -3
@@ -0,0 +1,550 @@
1
+ /**
2
+ * Provider-neutral Repository Explorer (P6-05, DESIGN.md §18, §11,
3
+ * PRD FR-081, FR-083–FR-086, FR-088, FR-091; NFR-004, NFR-005, NFR-007).
4
+ *
5
+ * The Explorer is the single non-Adapter consumer of the Repository
6
+ * Capability contract. It owns canonical repository-path handling,
7
+ * deterministic breadth-first traversal, duplicate-directory
8
+ * protection, and local Search/File `--max-chars` projection. It
9
+ * constructs canonical Capability requests, hands them to shared
10
+ * execution, and projects the normalized results.
11
+ *
12
+ * Boundary rules (ARCHITECTURE.md §2, NFR-004):
13
+ * - Imports ONLY provider-neutral Repository Capability types and
14
+ * shared `executeRepositoryOperation` / `ExecutionDependencies`,
15
+ * plus the normalized `ValidationError`.
16
+ * - Imports NO concrete Provider Adapter, MCP/UTCP client, raw tool
17
+ * name, or Provider response type. Provider-specific facts (ZRead
18
+ * grammar, credentials, transports) remain Adapter-internal.
19
+ * - Owns canonicalization, BFS, and projection; never owns
20
+ * transport, credentials, Provider selection, or command
21
+ * presentation.
22
+ *
23
+ * Fixed ordering (DESIGN.md §18):
24
+ * 1. Apply Explorer-level defaults (Search `language`, Tree
25
+ * `depth`) and canonicalize paths.
26
+ * 2. Validate `repository` (at-least-one-slash), `query`
27
+ * (non-whitespace), `language`, and `depth`.
28
+ * 3. Construct the canonical Capability request.
29
+ * 4. Delegate to `executeRepositoryOperation`, which runs
30
+ * `operation.validate`, `operation.cacheIdentity`, the
31
+ * provider-partitioned cache read, ordered legacy candidates,
32
+ * retry-wrapped invoke, and the normalized cache write.
33
+ * 5. Apply post-execution `--max-chars` projection (Search/File
34
+ * only). Tree is never character-limited.
35
+ *
36
+ * `--max-chars` is post-execution projection. It never appears in
37
+ * the canonical request, the cache identity, or the cache itself.
38
+ */
39
+ import { executeRepositoryOperation, } from "../lib/execution.js";
40
+ import { ValidationError } from "../lib/errors.js";
41
+ /**
42
+ * Canonicalize a repository-relative POSIX path.
43
+ *
44
+ * Rules (DESIGN.md §18, technical plan):
45
+ * - Backslashes (`\\`) and ASCII control characters (C0 plus DEL,
46
+ * code points 0–31 and 127) always throw `ValidationError`.
47
+ * - Whole-string root aliases (`undefined`, `""`, `"/"`, `"."`)
48
+ * map to root (`""`). For File (`kind: "file"`), root is
49
+ * invalid and throws.
50
+ * - File accepts a single leading `./` and any leading `/` as
51
+ * convenience; both are stripped. Directory does NOT get the
52
+ * leading `./` convenience (a leading `.` segment is unsafe and
53
+ * is rejected below); leading `/` is naturally stripped by the
54
+ * empty-segment collapse.
55
+ * - Repeated `/` collapses and trailing `/` is removed via the
56
+ * empty-segment skip.
57
+ * - Actual `.` or `..` segments at any position throw.
58
+ * - Percent escapes are never decoded.
59
+ *
60
+ * Returns the canonical repository-relative POSIX path. `""` is the
61
+ * repository root.
62
+ */
63
+ export function canonicalizeRepositoryPath(input, kind) {
64
+ // 1. `undefined` is the canonical "omitted" value. For File this
65
+ // is invalid because File requires a non-root path; for
66
+ // Directory/Tree it is the root.
67
+ if (input === undefined) {
68
+ if (kind === "file") {
69
+ throw new ValidationError("File path is required");
70
+ }
71
+ return "";
72
+ }
73
+ if (typeof input !== "string") {
74
+ throw new ValidationError("Repository path must be a string");
75
+ }
76
+ // 2. Reject backslashes and ASCII control characters (C0 + DEL).
77
+ // Percent escapes are never decoded, so `%2e` and similar are
78
+ // preserved as literal three-character sequences.
79
+ for (let i = 0; i < input.length; i += 1) {
80
+ const code = input.charCodeAt(i);
81
+ if (code === 92 /* backslash */) {
82
+ throw new ValidationError("Repository path must not contain backslashes");
83
+ }
84
+ if (code < 32 || code === 127) {
85
+ throw new ValidationError("Repository path must not contain ASCII control characters");
86
+ }
87
+ }
88
+ // 3. Whole-string root aliases. `""`, `"/"`, and `"."` all map
89
+ // to root. For File, root is invalid.
90
+ if (input === "" || input === "/" || input === ".") {
91
+ if (kind === "file") {
92
+ throw new ValidationError("File path must not be the repository root");
93
+ }
94
+ return "";
95
+ }
96
+ // 4. File-only leading `./` convenience. Directory does not get
97
+ // this: a leading `.` segment is unsafe and is rejected below.
98
+ // Leading `/` is naturally stripped by the empty-segment
99
+ // collapse for both kinds.
100
+ let work = input;
101
+ if (kind === "file" && work.startsWith("./")) {
102
+ work = work.slice(2);
103
+ }
104
+ // 5. Split, collapse empty segments (handles leading/trailing/
105
+ // repeated `/`), and reject any actual `.` or `..` segment.
106
+ const segments = [];
107
+ for (const segment of work.split("/")) {
108
+ if (segment === "")
109
+ continue;
110
+ if (segment === "." || segment === "..") {
111
+ throw new ValidationError(`Repository path must not contain a "${segment}" segment`);
112
+ }
113
+ segments.push(segment);
114
+ }
115
+ const canonical = segments.join("/");
116
+ if (canonical === "") {
117
+ // The input reduced to nothing (e.g., `"///"` or `"./"`). For
118
+ // File, this is root and invalid; for Directory/Tree, this is
119
+ // root.
120
+ if (kind === "file") {
121
+ throw new ValidationError("File path must not be the repository root");
122
+ }
123
+ return "";
124
+ }
125
+ return canonical;
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Defaults and Explorer-level pre-validation.
129
+ //
130
+ // Defaults and canonicalization happen BEFORE
131
+ // `operation.validate` / `operation.cacheIdentity`. The Explorer's
132
+ // pre-validation is provider-neutral (slash in repository,
133
+ // non-whitespace query, language in `{en, zh}`, finite positive
134
+ // integer depth); the Adapter's `operation.validate` runs after,
135
+ // as a defensive backstop with Provider-specific messaging.
136
+ // ---------------------------------------------------------------------------
137
+ /**
138
+ * Normalize a Search language value. `undefined` defaults to `"en"`;
139
+ * `"en"` and `"zh"` are passed through; any other value throws
140
+ * `ValidationError`.
141
+ */
142
+ function normalizeSearchLanguage(language) {
143
+ if (language === undefined)
144
+ return "en";
145
+ if (language === "en" || language === "zh")
146
+ return language;
147
+ throw new ValidationError('Search language must be "en" or "zh"');
148
+ }
149
+ /**
150
+ * Project a Tree depth value. `undefined` defaults to 1. Finite
151
+ * positive values are floored to an integer; non-finite or
152
+ * non-positive values throw `ValidationError`. Matches the
153
+ * existing shipped behaviour.
154
+ */
155
+ function projectTreeDepth(depth) {
156
+ if (depth === undefined)
157
+ return 1;
158
+ const n = Number(depth);
159
+ if (!Number.isFinite(n) || n < 1) {
160
+ throw new ValidationError("Tree depth must be a finite positive integer");
161
+ }
162
+ return Math.floor(n);
163
+ }
164
+ /**
165
+ * Assert that `repository` is a string containing at least one `/`.
166
+ * The check is provider-neutral and preserves the existing
167
+ * at-least-one-slash rule. The exact repository text is preserved.
168
+ */
169
+ function assertRepositoryString(repository) {
170
+ if (typeof repository !== "string") {
171
+ throw new ValidationError("Repository must be a string");
172
+ }
173
+ let hasSlash = false;
174
+ for (let i = 0; i < repository.length; i += 1) {
175
+ if (repository.charCodeAt(i) === 47 /* "/" */) {
176
+ hasSlash = true;
177
+ break;
178
+ }
179
+ }
180
+ if (!hasSlash) {
181
+ throw new ValidationError(`Invalid repository format: "${repository}". Use "owner/repo" format (e.g., "facebook/react")`);
182
+ }
183
+ }
184
+ /**
185
+ * Assert that `query` is a string containing at least one
186
+ * non-whitespace character. The exact query text is preserved.
187
+ */
188
+ function assertSearchQuery(query) {
189
+ if (typeof query !== "string" || query.trim().length === 0) {
190
+ throw new ValidationError("Search query must contain at least one non-whitespace character");
191
+ }
192
+ }
193
+ // ---------------------------------------------------------------------------
194
+ // Provider-derived listing validation (DESIGN.md §18).
195
+ //
196
+ // Every Provider-returned listing and child is validated BEFORE
197
+ // snapshot/enqueue. The validator binds the listing to the exact
198
+ // canonical request and requires every entry to be the immediate
199
+ // child of the listing's path. Unsafe, inconsistent, or
200
+ // non-immediate children fail the whole tree; partial success is
201
+ // never returned. The validation is read-only and never mutates
202
+ // the Adapter result.
203
+ // ---------------------------------------------------------------------------
204
+ function isPlainObject(value) {
205
+ return typeof value === "object" && value !== null && !Array.isArray(value);
206
+ }
207
+ /**
208
+ * Assert that `name` is a valid single path segment: a non-empty
209
+ * string with no `/`, no backslash, no ASCII control characters
210
+ * (C0 + DEL), and not equal to `.` or `..`. Percent escapes remain
211
+ * literal (`%2e` is three characters, not `.`).
212
+ *
213
+ * A directory entry name supplies exactly one path segment, so the
214
+ * segment-level rules are stricter than the full-path rules: a `/`
215
+ * in a name would split it into multiple segments and is therefore
216
+ * rejected here rather than collapsed.
217
+ */
218
+ function assertValidEntryName(name) {
219
+ if (typeof name !== "string" || name.length === 0) {
220
+ throw new ValidationError("Provider-derived directory entry name must be a non-empty string");
221
+ }
222
+ for (let i = 0; i < name.length; i += 1) {
223
+ const code = name.charCodeAt(i);
224
+ if (code === 47 /* "/" */) {
225
+ throw new ValidationError("Provider-derived directory entry name must not contain '/'");
226
+ }
227
+ if (code === 92 /* backslash */) {
228
+ throw new ValidationError("Provider-derived directory entry name must not contain backslashes");
229
+ }
230
+ if (code < 32 || code === 127) {
231
+ throw new ValidationError("Provider-derived directory entry name must not contain ASCII control characters");
232
+ }
233
+ }
234
+ if (name === "." || name === "..") {
235
+ throw new ValidationError(`Provider-derived directory entry name must not be "${name}"`);
236
+ }
237
+ }
238
+ /**
239
+ * Assert that `entry` is a structurally valid
240
+ * {@link RepositoryEntry} that is the IMMEDIATE child of
241
+ * `listingPath` under the canonical request.
242
+ *
243
+ * The entry's `name` must be a valid single segment, and the
244
+ * entry's `path` must equal the immediate-child path constructed
245
+ * from `listingPath` and `name`:
246
+ *
247
+ * expectedPath = listingPath === "" ? name : listingPath + "/" + name
248
+ *
249
+ * `entry.path` MUST equal `expectedPath` exactly. The expectedPath
250
+ * is then canonicalized through the shared canonicalizer under the
251
+ * entry's kind to reject any non-canonical residue. Because
252
+ * `listingPath` arrived canonical (either the Explorer-canonical
253
+ * starting path or a previously validated immediate-child path) and
254
+ * `entry.name` is a validated single segment, the canonical form
255
+ * should equal the expected form; this final canonicalize call is
256
+ * defensive against any future regression.
257
+ *
258
+ * DESIGN §18: `entry.name` is the final path segment and the
259
+ * DirectoryListing holds the requested directory's immediate
260
+ * entries.
261
+ */
262
+ function assertValidRepositoryEntry(entry, listingPath) {
263
+ if (!isPlainObject(entry)) {
264
+ throw new ValidationError("Provider-derived directory entry must be an object");
265
+ }
266
+ assertValidEntryName(entry.name);
267
+ if (entry.kind !== "file" && entry.kind !== "directory") {
268
+ throw new ValidationError("Provider-derived directory entry kind must be 'file' or 'directory'");
269
+ }
270
+ if (typeof entry.path !== "string" || entry.path.length === 0) {
271
+ throw new ValidationError("Provider-derived directory entry path must be a non-empty string");
272
+ }
273
+ // Compute the expected immediate-child path. listingPath is
274
+ // already canonical; entry.name supplies one validated segment.
275
+ const expectedPath = listingPath === "" ? entry.name : `${listingPath}/${entry.name}`;
276
+ if (entry.path !== expectedPath) {
277
+ throw new ValidationError(`Provider-derived directory entry path "${entry.path}" must equal the immediate-child path "${expectedPath}"`);
278
+ }
279
+ // Canonical-safety: canonicalize the expectedPath under the
280
+ // entry's kind to reject any non-canonical residue. Files use the
281
+ // File canonicalizer (root invalid); directories use the
282
+ // Directory canonicalizer (root allowed). A root child is
283
+ // structurally impossible for a non-root listing but is defended
284
+ // against here all the same.
285
+ const canonical = canonicalizeRepositoryPath(expectedPath, entry.kind);
286
+ if (canonical !== expectedPath) {
287
+ throw new ValidationError(`Provider-derived directory entry path is not canonical: "${expectedPath}"`);
288
+ }
289
+ }
290
+ /**
291
+ * Assert that `listing` is a structurally valid
292
+ * {@link RepositoryDirectoryListing} BOUND to the canonical
293
+ * {@link RepositoryDirectoryRequest}. The listing's `repository`
294
+ * MUST equal `request.repository` and the listing's `path` MUST
295
+ * equal `request.path`. Every entry MUST be a valid immediate
296
+ * child of the listing's path.
297
+ *
298
+ * Without this binding a fake or buggy Adapter could return a
299
+ * listing for a different repository or a different directory than
300
+ * the one requested, and the BFS would snapshot or enqueue the
301
+ * wrong subtree. Binding the listing to the request closes that
302
+ * gap.
303
+ */
304
+ function assertValidRepositoryDirectoryListing(listing, request) {
305
+ if (!isPlainObject(listing)) {
306
+ throw new ValidationError("Provider-derived directory listing must be an object");
307
+ }
308
+ if (typeof listing.repository !== "string") {
309
+ throw new ValidationError("Provider-derived directory listing repository must be a string");
310
+ }
311
+ if (listing.repository !== request.repository) {
312
+ throw new ValidationError("Provider-derived directory listing repository must match the request repository");
313
+ }
314
+ if (typeof listing.path !== "string") {
315
+ throw new ValidationError("Provider-derived directory listing path must be a string");
316
+ }
317
+ if (listing.path !== request.path) {
318
+ throw new ValidationError("Provider-derived directory listing path must match the request path");
319
+ }
320
+ if (!Array.isArray(listing.entries)) {
321
+ throw new ValidationError("Provider-derived directory listing entries must be an array");
322
+ }
323
+ for (const entry of listing.entries) {
324
+ assertValidRepositoryEntry(entry, listing.path);
325
+ }
326
+ }
327
+ // ---------------------------------------------------------------------------
328
+ // Local `--max-chars` projection (DESIGN.md §18, technical plan).
329
+ //
330
+ // Projection is post-execution: it runs on the normalized result
331
+ // returned by shared execution. It is the only step that consumes
332
+ // `--max-chars`. `--max-chars` never enters the canonical request,
333
+ // the cache identity, or the cache itself. Tree is never
334
+ // character-limited.
335
+ // ---------------------------------------------------------------------------
336
+ /**
337
+ * Apply the Search `--max-chars` budget. The budget is a single
338
+ * total character count consumed by `excerpts[].text` in Provider
339
+ * order. Absent, `NaN`, zero, or negative means no truncation
340
+ * (matches the shipped `!max || max <= 0` rule). `Infinity` is
341
+ * naturally unlimited (the loop fits every excerpt). Whole
342
+ * excerpts are kept while they fit; the final retained excerpt is
343
+ * truncated with the existing rule
344
+ * `text.slice(0, remaining - 1).trimEnd() + "…"`; later excerpts
345
+ * are omitted. Metadata (`repository`, `query`, `language`,
346
+ * `originalTextLength`) is outside the budget. `originalTextLength`
347
+ * reports the full pre-projection value; `truncated` is set if the
348
+ * projection omitted or truncated any excerpt, OR if the Provider
349
+ * flagged its own truncation.
350
+ *
351
+ * The input result is never mutated.
352
+ */
353
+ function projectSearchResult(result, maxChars) {
354
+ if (!maxChars || maxChars <= 0) {
355
+ return result;
356
+ }
357
+ let remaining = maxChars;
358
+ const projectedExcerpts = [];
359
+ let projectionTruncated = false;
360
+ for (const excerpt of result.excerpts) {
361
+ if (remaining <= 0) {
362
+ projectionTruncated = true;
363
+ break;
364
+ }
365
+ if (excerpt.text.length <= remaining) {
366
+ projectedExcerpts.push({ text: excerpt.text });
367
+ remaining -= excerpt.text.length;
368
+ }
369
+ else {
370
+ const truncatedText = excerpt.text.slice(0, remaining - 1).trimEnd() + "…";
371
+ projectedExcerpts.push({ text: truncatedText });
372
+ remaining = 0;
373
+ projectionTruncated = true;
374
+ }
375
+ }
376
+ if (!projectionTruncated) {
377
+ return result;
378
+ }
379
+ return {
380
+ schemaVersion: 1,
381
+ repository: result.repository,
382
+ query: result.query,
383
+ language: result.language,
384
+ excerpts: projectedExcerpts,
385
+ truncated: true,
386
+ originalTextLength: result.originalTextLength,
387
+ };
388
+ }
389
+ /**
390
+ * Apply the File `--max-chars` budget to `content`. Absent, `NaN`,
391
+ * zero, or negative means no truncation (matches the shipped
392
+ * `!max || max <= 0` rule). `Infinity` is naturally unlimited.
393
+ * Content shorter than or equal to the budget is returned
394
+ * unchanged. Otherwise the content is truncated with the existing
395
+ * rule `content.slice(0, max - 1).trimEnd() + "…"`. `truncated` is
396
+ * set if the projection truncated the content or if the Provider
397
+ * flagged its own truncation. `originalContentLength` reports the
398
+ * full pre-projection value.
399
+ *
400
+ * The input result is never mutated.
401
+ */
402
+ function projectFileResult(result, maxChars) {
403
+ if (!maxChars || maxChars <= 0) {
404
+ return result;
405
+ }
406
+ if (result.content.length <= maxChars) {
407
+ return result;
408
+ }
409
+ const truncatedContent = result.content.slice(0, maxChars - 1).trimEnd() + "…";
410
+ return {
411
+ schemaVersion: 1,
412
+ repository: result.repository,
413
+ path: result.path,
414
+ content: truncatedContent,
415
+ truncated: true,
416
+ originalContentLength: result.originalContentLength,
417
+ };
418
+ }
419
+ // ---------------------------------------------------------------------------
420
+ // Breadth-first traversal (DESIGN.md §18).
421
+ //
422
+ // Deterministic BFS that preserves Provider sibling order,
423
+ // snapshots breadth-first, requests each canonical directory at
424
+ // most once, expands only directories while `level < depth`, and
425
+ // never returns partial success after a directory failure.
426
+ // ---------------------------------------------------------------------------
427
+ /**
428
+ * Collect directory snapshots via deterministic breadth-first
429
+ * traversal.
430
+ *
431
+ * Rules:
432
+ * - BFS starts at level 1 with the canonical starting path. The
433
+ * starting directory is requested exactly once and snapshotted
434
+ * even at depth 1.
435
+ * - Children are snapshot/enqueued in Provider sibling order.
436
+ * Only `kind: "directory"` children are enqueued, and only
437
+ * while `level < depth`.
438
+ * - Each canonical directory path is requested at most once.
439
+ * Duplicate encounters (a directory reachable from multiple
440
+ * parents) preserve first-encounter order and are not
441
+ * re-requested.
442
+ * - Every Provider-derived listing and entry is validated before
443
+ * snapshot/enqueue. Unsafe or inconsistent children fail the
444
+ * whole tree; partial success is never returned.
445
+ *
446
+ * `executeRepositoryOperation` is the single transport-touching
447
+ * call per directory; it owns validate/cache-identity/cache/retry.
448
+ * The Explorer never invokes the Adapter directly.
449
+ */
450
+ async function collectTreeSnapshots(capability, canonicalRequest, depth, options, dependencies) {
451
+ const snapshots = [];
452
+ const visited = new Set();
453
+ // Queue entries: { request, level }. The starting path is
454
+ // enqueued at level 1. The visited set is populated at enqueue
455
+ // time so a directory reachable from multiple parents is
456
+ // requested exactly once and appears in first-encounter order.
457
+ const queue = [
458
+ { request: canonicalRequest, level: 1 },
459
+ ];
460
+ visited.add(canonicalRequest.path);
461
+ while (queue.length > 0) {
462
+ const { request, level } = queue.shift();
463
+ const listing = await executeRepositoryOperation(capability.listDirectory, request, options, dependencies);
464
+ // Validate the Adapter result before snapshot/enqueue. Bind the
465
+ // listing to the canonical request so a fake or buggy Adapter
466
+ // cannot snapshot or enqueue a different repository, a different
467
+ // directory, or non-immediate children.
468
+ assertValidRepositoryDirectoryListing(listing, request);
469
+ snapshots.push(listing);
470
+ if (level >= depth)
471
+ continue;
472
+ for (const entry of listing.entries) {
473
+ if (entry.kind !== "directory")
474
+ continue;
475
+ if (visited.has(entry.path))
476
+ continue;
477
+ visited.add(entry.path);
478
+ queue.push({
479
+ request: { repository: request.repository, path: entry.path },
480
+ level: level + 1,
481
+ });
482
+ }
483
+ }
484
+ return snapshots;
485
+ }
486
+ /**
487
+ * Provider-neutral Repository Search (DESIGN.md §18, PRD FR-081,
488
+ * FR-083). Applies the `language` default, validates `repository`
489
+ * (at-least-one-slash) and `query` (non-whitespace), constructs the
490
+ * canonical request, delegates to shared execution, and applies the
491
+ * `--max-chars` budget to `excerpts[].text` only.
492
+ *
493
+ * Defaults and canonicalization precede `operation.validate` /
494
+ * `operation.cacheIdentity`. The Provider sees the canonical
495
+ * request; the Explorer never widens into Provider-specific fields.
496
+ */
497
+ export async function explorerSearch(capability, request, options, dependencies) {
498
+ assertRepositoryString(request.repository);
499
+ assertSearchQuery(request.query);
500
+ const language = normalizeSearchLanguage(request.language);
501
+ const canonicalRequest = {
502
+ repository: request.repository,
503
+ query: request.query,
504
+ language,
505
+ };
506
+ const result = await executeRepositoryOperation(capability.search, canonicalRequest, { noCache: options.noCache, retryPolicy: options.retryPolicy }, dependencies);
507
+ return projectSearchResult(result, options.maxChars);
508
+ }
509
+ /**
510
+ * Provider-neutral Repository File read (DESIGN.md §18, PRD FR-086).
511
+ * Canonicalizes the File path (root rejected, leading `./` and `/`
512
+ * stripped, unsafe segments throw), delegates to shared execution,
513
+ * and applies the `--max-chars` budget to `content` only.
514
+ */
515
+ export async function explorerReadFile(capability, request, options, dependencies) {
516
+ assertRepositoryString(request.repository);
517
+ const canonicalPath = canonicalizeRepositoryPath(request.path, "file");
518
+ const canonicalRequest = {
519
+ repository: request.repository,
520
+ path: canonicalPath,
521
+ };
522
+ const result = await executeRepositoryOperation(capability.readFile, canonicalRequest, { noCache: options.noCache, retryPolicy: options.retryPolicy }, dependencies);
523
+ return projectFileResult(result, options.maxChars);
524
+ }
525
+ /**
526
+ * Provider-neutral Repository Tree (DESIGN.md §18, PRD FR-088).
527
+ * Canonicalizes the starting path (root allowed), projects depth
528
+ * (default 1, finite positive integer), and drives a deterministic
529
+ * breadth-first traversal that preserves Provider sibling order,
530
+ * requests each canonical directory at most once, and never returns
531
+ * partial success. Tree is never character-limited.
532
+ */
533
+ export async function explorerTree(capability, request, options, dependencies) {
534
+ assertRepositoryString(request.repository);
535
+ const canonicalPath = canonicalizeRepositoryPath(request.path, "directory");
536
+ const depth = projectTreeDepth(request.depth);
537
+ const canonicalRequest = {
538
+ repository: request.repository,
539
+ path: canonicalPath,
540
+ };
541
+ const snapshots = await collectTreeSnapshots(capability, canonicalRequest, depth, { noCache: options.noCache, retryPolicy: options.retryPolicy }, dependencies);
542
+ return {
543
+ schemaVersion: 1,
544
+ repository: request.repository,
545
+ path: canonicalPath,
546
+ depth,
547
+ snapshots,
548
+ };
549
+ }
550
+ //# sourceMappingURL=repository-explorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-explorer.js","sourceRoot":"","sources":["../../src/commands/repository-explorer.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -41,6 +41,26 @@ export interface MainDependencies {
41
41
  readonly searchCache?: ResponseCache;
42
42
  readonly searchSleep?: (ms: number) => Promise<void>;
43
43
  readonly searchRandom?: () => number;
44
+ /**
45
+ * Injectable shared-Repository execution dependencies (P6-07).
46
+ * Production defaults to the same on-disk cache and real sleep/random
47
+ * as Search; tests inject in-memory doubles so Repository dispatch
48
+ * tests stay isolated from Search state. These are NOT a rename of
49
+ * the Search seams.
50
+ */
51
+ readonly repositoryCache?: ResponseCache;
52
+ readonly repositorySleep?: (ms: number) => Promise<void>;
53
+ readonly repositoryRandom?: () => number;
54
+ /**
55
+ * Injectable shared-Reader execution dependencies (Reader Migration
56
+ * Ticket 04). Production defaults to the same on-disk cache and real
57
+ * sleep/random as Search/Repository; tests inject in-memory doubles
58
+ * so Reader dispatch tests stay isolated from Search/Repository
59
+ * state. NOT a rename of either prior seam.
60
+ */
61
+ readonly readerCache?: ResponseCache;
62
+ readonly readerSleep?: (ms: number) => Promise<void>;
63
+ readonly readerRandom?: () => number;
44
64
  }
45
65
  export declare function main(args: readonly string[], dependencies: MainDependencies): Promise<number>;
46
66
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH,OAAO,EAAiB,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI1E,OAAO,KAAK,EAAE,kBAAkB,EAAc,MAAM,sBAAsB,CAAC;AA8X3E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAuBtE;AA6cD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC7D;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAID,wBAAsB,IAAI,CACxB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAuGjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmCH,OAAO,EAAiB,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI1E,OAAO,KAAK,EAAE,kBAAkB,EAAc,MAAM,sBAAsB,CAAC;AA8Z3E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAuBtE;AAuoBD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC7D;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;IACrC;;;;;;OAMG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC;IACzC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IACzC;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAID,wBAAsB,IAAI,CACxB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA4HjB"}