@arnilo/prism-coding-agent 0.2.4 → 0.2.6

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 (50) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +10 -0
  3. package/dist/coding-checkpoint.js +4 -0
  4. package/dist/diagnostics.d.ts +83 -0
  5. package/dist/diagnostics.js +179 -0
  6. package/dist/git.d.ts +27 -6
  7. package/dist/git.js +58 -1
  8. package/dist/index.d.ts +13 -4
  9. package/dist/index.js +13 -2
  10. package/dist/language/client.d.ts +25 -0
  11. package/dist/language/client.js +54 -0
  12. package/dist/language/framing.d.ts +9 -1
  13. package/dist/language/framing.js +89 -17
  14. package/dist/language/index.d.ts +1 -1
  15. package/dist/language/intelligence.js +58 -0
  16. package/dist/language/types.d.ts +32 -0
  17. package/dist/limits.d.ts +59 -0
  18. package/dist/limits.js +59 -0
  19. package/dist/process/index.d.ts +4 -1
  20. package/dist/process/index.js +1 -0
  21. package/dist/process/recovery.d.ts +174 -0
  22. package/dist/process/recovery.js +320 -0
  23. package/dist/process/sessions.js +714 -25
  24. package/dist/process/types.d.ts +128 -4
  25. package/dist/process/types.js +7 -1
  26. package/dist/repository/glob.d.ts +4 -0
  27. package/dist/repository/glob.js +143 -0
  28. package/dist/repository/indexed-search.d.ts +121 -0
  29. package/dist/repository/indexed-search.js +313 -0
  30. package/dist/repository/list.d.ts +3 -0
  31. package/dist/repository/list.js +119 -0
  32. package/dist/repository/operations.d.ts +5 -0
  33. package/dist/repository/operations.js +14 -0
  34. package/dist/repository/path.d.ts +18 -0
  35. package/dist/repository/path.js +91 -0
  36. package/dist/repository/search.d.ts +9 -0
  37. package/dist/repository/search.js +284 -0
  38. package/dist/repository/types.d.ts +138 -0
  39. package/dist/repository/types.js +31 -0
  40. package/dist/repository/walk.d.ts +22 -0
  41. package/dist/repository/walk.js +99 -0
  42. package/dist/repository.d.ts +11 -172
  43. package/dist/repository.js +11 -748
  44. package/dist/review.d.ts +150 -0
  45. package/dist/review.js +222 -0
  46. package/dist/search.d.ts +3 -1
  47. package/dist/search.js +42 -7
  48. package/dist/workspace-lifecycle.d.ts +153 -0
  49. package/dist/workspace-lifecycle.js +629 -0
  50. package/package.json +3 -3
@@ -11,6 +11,8 @@ export interface ProcessSandboxHandle {
11
11
  }): Promise<{
12
12
  exitCode: number | null;
13
13
  }>;
14
+ /** Opaque non-secret reattachment ref for durable process recovery (plan 026 Task 5). */
15
+ readonly ref?: string;
14
16
  }
15
17
  export interface ProcessSandboxStartRequest {
16
18
  readonly file: string;
@@ -21,8 +23,7 @@ export interface ProcessSandboxStartRequest {
21
23
  readonly signal?: AbortSignal;
22
24
  readonly timeout?: number;
23
25
  }
24
- /**
25
- * Optional sandbox backend for ProcessSessions.
26
+ /** Optional sandbox backend for ProcessSessions.
26
27
  * Presence of `startProcess` = long-running capable; absence fails closed.
27
28
  */
28
29
  export interface ProcessSandboxBackend {
@@ -31,8 +32,67 @@ export interface ProcessSandboxBackend {
31
32
  readonly state: string;
32
33
  }>;
33
34
  }
35
+ /** Bounded terminal geometry + TERM for interactive PTY sessions (frozen caps in limits.ts). */
36
+ export interface ProcessTerminalRequest {
37
+ /** 1..maxTerminalColumns (default 120; host-configured max wins when smaller). */
38
+ readonly columns?: number;
39
+ /** 1..maxTerminalRows (default 40; host-configured max wins when smaller). */
40
+ readonly rows?: number;
41
+ /** TERM string, UTF-8 bytes <= maxTerminalTermBytes (default "xterm-256color"). */
42
+ readonly term?: string;
43
+ }
44
+ /** Bounded resize dimensions for an interactive PTY session. */
45
+ export interface ProcessTerminalResize {
46
+ readonly columns: number;
47
+ readonly rows: number;
48
+ }
49
+ /**
50
+ * Host PTY handle (mirrors ProcessSandboxHandle) plus optional bounded resize
51
+ * and backend metadata. Capability is explicit: the session handle exposes
52
+ * `resize` only when the backend declared `capabilities.resize`.
53
+ */
54
+ export interface ProcessPtyHandle {
55
+ write(data: Uint8Array): Promise<void>;
56
+ signal(name: string): Promise<void>;
57
+ kill(): Promise<void>;
58
+ release(): Promise<void>;
59
+ resize?(dimensions: ProcessTerminalResize): Promise<void>;
60
+ /** Bounded host metadata (UTF-8 JSON bytes <= maxPtyBackendMetadataBytes), surfaced via session metadata(). */
61
+ readonly metadata?: Readonly<Record<string, string>>;
62
+ /** Opaque non-secret reattachment ref for durable process recovery (plan 026 Task 5). */
63
+ readonly ref?: string;
64
+ wait(options?: {
65
+ timeoutMs?: number;
66
+ signal?: AbortSignal;
67
+ }): Promise<{
68
+ exitCode: number | null;
69
+ }>;
70
+ }
71
+ export interface ProcessPtyStartRequest {
72
+ readonly file: string;
73
+ readonly args: readonly string[];
74
+ readonly cwd: string;
75
+ readonly env?: Readonly<Record<string, string>>;
76
+ readonly columns: number;
77
+ readonly rows: number;
78
+ readonly term: string;
79
+ readonly onData?: (data: Buffer) => void;
80
+ readonly signal?: AbortSignal;
81
+ }
82
+ /**
83
+ * Host-selected PTY backend. Capability and metadata are explicit, never
84
+ * duck-typed: `pty: true` requires a backend whose `startPty` is present
85
+ * (otherwise `ERR_PRISM_PROCESS_PTY_UNSUPPORTED` before process creation) and
86
+ * `capabilities.resize` must be true for the session handle to expose resize.
87
+ */
88
+ export interface ProcessPtyBackend {
89
+ startPty?(request: ProcessPtyStartRequest): Promise<ProcessPtyHandle>;
90
+ readonly capabilities?: {
91
+ readonly resize: boolean;
92
+ };
93
+ }
34
94
  export type ProcessSessionState = "starting" | "running" | "exited" | "killed" | "released" | "expired" | "unknown";
35
- export type ProcessSessionErrorCode = "ERR_PRISM_PROCESS_POLICY" | "ERR_PRISM_PROCESS_OWNERSHIP" | "ERR_PRISM_PROCESS_STATE" | "ERR_PRISM_PROCESS_LIMIT" | "ERR_PRISM_PROCESS_PTY_UNSUPPORTED" | "ERR_PRISM_PROCESS_UNSUPPORTED";
95
+ export type ProcessSessionErrorCode = "ERR_PRISM_PROCESS_POLICY" | "ERR_PRISM_PROCESS_OWNERSHIP" | "ERR_PRISM_PROCESS_STATE" | "ERR_PRISM_PROCESS_LIMIT" | "ERR_PRISM_PROCESS_PTY_UNSUPPORTED" | "ERR_PRISM_PROCESS_PTY_BACKEND" | "ERR_PRISM_PROCESS_PTY_LIMIT" | "ERR_PRISM_PROCESS_UNSUPPORTED";
36
96
  export declare class ProcessSessionError extends Error {
37
97
  readonly code: ProcessSessionErrorCode;
38
98
  constructor(code: ProcessSessionErrorCode, message: string);
@@ -43,6 +103,13 @@ export interface ProcessSessionLimits {
43
103
  readonly maxLifetimeMs?: number;
44
104
  readonly maxOutputChunkBytes?: number;
45
105
  readonly maxTotalOutputBytes?: number;
106
+ /** Phase 26: PTY terminal bounds (defaults/hard caps frozen in limits.ts). */
107
+ readonly maxTerminalColumns?: number;
108
+ readonly maxTerminalRows?: number;
109
+ readonly maxTerminalTermBytes?: number;
110
+ readonly maxTerminalResizesPerMinute?: number;
111
+ readonly maxPtyAttachTimeoutMs?: number;
112
+ readonly maxPtyBackendMetadataBytes?: number;
46
113
  }
47
114
  export interface ResolvedProcessSessionLimits {
48
115
  readonly maxSessions: number;
@@ -50,6 +117,12 @@ export interface ResolvedProcessSessionLimits {
50
117
  readonly maxLifetimeMs: number;
51
118
  readonly maxOutputChunkBytes: number;
52
119
  readonly maxTotalOutputBytes: number;
120
+ readonly maxTerminalColumns: number;
121
+ readonly maxTerminalRows: number;
122
+ readonly maxTerminalTermBytes: number;
123
+ readonly maxTerminalResizesPerMinute: number;
124
+ readonly maxPtyAttachTimeoutMs: number;
125
+ readonly maxPtyBackendMetadataBytes: number;
53
126
  }
54
127
  export declare function resolveProcessSessionLimits(limits?: ProcessSessionLimits): ResolvedProcessSessionLimits;
55
128
  export interface ProcessStartRequest {
@@ -57,13 +130,22 @@ export interface ProcessStartRequest {
57
130
  readonly args?: readonly string[];
58
131
  readonly cwd?: string;
59
132
  readonly env?: Readonly<Record<string, string>>;
60
- /** Default false. true on unsupported platform → ERR_PRISM_PROCESS_PTY_UNSUPPORTED. */
133
+ /**
134
+ * Default false. true without a host ptyBackend.startPty →
135
+ * ERR_PRISM_PROCESS_PTY_UNSUPPORTED before process creation; backend
136
+ * failures → ERR_PRISM_PROCESS_PTY_BACKEND; terminal/resize/attach bounds →
137
+ * ERR_PRISM_PROCESS_PTY_LIMIT.
138
+ */
61
139
  readonly pty?: boolean;
140
+ /** Bounded terminal geometry + TERM for pty: true sessions. */
141
+ readonly terminal?: ProcessTerminalRequest;
62
142
  readonly lifetimeMs?: number;
63
143
  /** Owner string for this session; defaults to registry ownership key. */
64
144
  readonly owner?: string;
65
145
  /** When true, run cancel releases instead of killing (default kill). */
66
146
  readonly releaseOnCancel?: boolean;
147
+ /** Abortable start: an aborted signal fails the start before spawn persists. */
148
+ readonly signal?: AbortSignal;
67
149
  }
68
150
  export interface ProcessOutputChunk {
69
151
  readonly data: string;
@@ -85,6 +167,16 @@ export interface ProcessSessionMetadata {
85
167
  readonly exitedAt?: string;
86
168
  readonly state: ProcessSessionState;
87
169
  readonly releaseOnCancel: boolean;
170
+ /** True when the session runs through the host ptyBackend. */
171
+ readonly pty: boolean;
172
+ /** Resolved terminal geometry + TERM for PTY sessions (bounded at start). */
173
+ readonly terminal?: {
174
+ readonly columns: number;
175
+ readonly rows: number;
176
+ readonly term: string;
177
+ };
178
+ /** Bounded backend metadata (validated <= maxPtyBackendMetadataBytes at start). */
179
+ readonly ptyBackendMetadata?: Readonly<Record<string, string>>;
88
180
  }
89
181
  export interface ProcessSession {
90
182
  readonly id: string;
@@ -103,6 +195,8 @@ export interface ProcessSession {
103
195
  signal(name: "SIGTERM" | "SIGINT" | "SIGHUP"): Promise<void>;
104
196
  kill(): Promise<void>;
105
197
  release(): Promise<void>;
198
+ /** Present only when the host backend declared `capabilities.resize` (PTY sessions). */
199
+ resize?(dimensions: ProcessTerminalResize): Promise<void>;
106
200
  }
107
201
  export type CodingProcessEvent = {
108
202
  readonly type: "process_started" | "process_exited" | "process_killed" | "process_released" | "process_expired" | "process_unknown";
@@ -128,6 +222,17 @@ export interface ProcessSessions {
128
222
  reconcile(): Promise<{
129
223
  readonly markedUnknown: number;
130
224
  }>;
225
+ /**
226
+ * Durable process recovery (plan 026 Task 5): reconcile durable recovery
227
+ * records against the live registry — attach-if-attested via the host
228
+ * recovery backend, otherwise `starting|running` records atomically become
229
+ * `unknown`. Never fabricates an exit code and never probes PIDs. Requires
230
+ * `checkpoints` + `leases` + `ownerId` at construction, else
231
+ * ERR_PRISM_RECOVERY_UNSUPPORTED. O(owned records).
232
+ */
233
+ recover(options?: {
234
+ signal?: AbortSignal;
235
+ }): Promise<import("./recovery.js").ProcessRecoveryReport>;
131
236
  dispose(): Promise<void>;
132
237
  }
133
238
  export interface CreateProcessSessionsOptions {
@@ -143,4 +248,23 @@ export interface CreateProcessSessionsOptions {
143
248
  * (`ERR_PRISM_PROCESS_UNSUPPORTED`). Native spawn only when sandbox omitted.
144
249
  */
145
250
  readonly sandbox?: ProcessSandboxBackend;
251
+ /**
252
+ * Phase 26: optional host-selected PTY backend. `pty: true` delegates only
253
+ * to this backend; absent backend or missing startPty fails closed with
254
+ * `ERR_PRISM_PROCESS_PTY_UNSUPPORTED` before process creation.
255
+ */
256
+ readonly ptyBackend?: ProcessPtyBackend;
257
+ /**
258
+ * Phase 26 durable process recovery: intent is persisted before spawn and
259
+ * lifecycle transitions are CAS-written under LeaseStore fencing. All three
260
+ * of `checkpoints`, `leases`, and `ownerId` must be present together — a
261
+ * partial recovery configuration fails closed at construction. `recover()`
262
+ * is attach-if-attested via `recoveryBackend`; otherwise starting/running
263
+ * records atomically become unknown (no fabricated exit, no PID probing).
264
+ */
265
+ readonly checkpoints?: import("@arnilo/prism").CheckpointStore;
266
+ readonly leases?: import("@arnilo/prism").LeaseStore;
267
+ readonly ownerId?: string;
268
+ readonly recoveryBackend?: import("./recovery.js").ProcessRecoveryBackend;
269
+ readonly recoveryLimits?: import("./recovery.js").ProcessRecoveryLimits;
146
270
  }
@@ -1,4 +1,4 @@
1
- import { DEFAULT_MAX_PROCESS_INPUT_BYTES, DEFAULT_MAX_PROCESS_LIFETIME_MS, DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, DEFAULT_MAX_PROCESS_SESSIONS, DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_BYTES, HARD_MAX_PROCESS_INPUT_BYTES, HARD_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_SESSIONS, HARD_MAX_PROCESS_TOTAL_OUTPUT_BYTES, validateCodingLimit, } from "../limits.js";
1
+ import { DEFAULT_MAX_PROCESS_INPUT_BYTES, DEFAULT_MAX_PROCESS_LIFETIME_MS, DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, DEFAULT_MAX_PROCESS_SESSIONS, DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_BYTES, DEFAULT_MAX_PTY_ATTACH_TIMEOUT_MS, DEFAULT_MAX_PTY_BACKEND_METADATA_BYTES, DEFAULT_MAX_TERMINAL_COLUMNS, DEFAULT_MAX_TERMINAL_RESIZES_PER_MINUTE, DEFAULT_MAX_TERMINAL_ROWS, DEFAULT_MAX_TERMINAL_TERM_BYTES, HARD_MAX_PROCESS_INPUT_BYTES, HARD_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_SESSIONS, HARD_MAX_PROCESS_TOTAL_OUTPUT_BYTES, HARD_MAX_PTY_ATTACH_TIMEOUT_MS, HARD_MAX_PTY_BACKEND_METADATA_BYTES, HARD_MAX_TERMINAL_COLUMNS, HARD_MAX_TERMINAL_RESIZES_PER_MINUTE, HARD_MAX_TERMINAL_ROWS, HARD_MAX_TERMINAL_TERM_BYTES, validateCodingLimit, } from "../limits.js";
2
2
  export class ProcessSessionError extends Error {
3
3
  code;
4
4
  constructor(code, message) {
@@ -14,6 +14,12 @@ export function resolveProcessSessionLimits(limits) {
14
14
  maxLifetimeMs: validateCodingLimit("maxLifetimeMs", limits?.maxLifetimeMs ?? DEFAULT_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_LIFETIME_MS),
15
15
  maxOutputChunkBytes: validateCodingLimit("maxOutputChunkBytes", limits?.maxOutputChunkBytes ?? DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES),
16
16
  maxTotalOutputBytes: validateCodingLimit("maxTotalOutputBytes", limits?.maxTotalOutputBytes ?? DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_BYTES, HARD_MAX_PROCESS_TOTAL_OUTPUT_BYTES),
17
+ maxTerminalColumns: validateCodingLimit("maxTerminalColumns", limits?.maxTerminalColumns ?? DEFAULT_MAX_TERMINAL_COLUMNS, HARD_MAX_TERMINAL_COLUMNS),
18
+ maxTerminalRows: validateCodingLimit("maxTerminalRows", limits?.maxTerminalRows ?? DEFAULT_MAX_TERMINAL_ROWS, HARD_MAX_TERMINAL_ROWS),
19
+ maxTerminalTermBytes: validateCodingLimit("maxTerminalTermBytes", limits?.maxTerminalTermBytes ?? DEFAULT_MAX_TERMINAL_TERM_BYTES, HARD_MAX_TERMINAL_TERM_BYTES),
20
+ maxTerminalResizesPerMinute: validateCodingLimit("maxTerminalResizesPerMinute", limits?.maxTerminalResizesPerMinute ?? DEFAULT_MAX_TERMINAL_RESIZES_PER_MINUTE, HARD_MAX_TERMINAL_RESIZES_PER_MINUTE),
21
+ maxPtyAttachTimeoutMs: validateCodingLimit("maxPtyAttachTimeoutMs", limits?.maxPtyAttachTimeoutMs ?? DEFAULT_MAX_PTY_ATTACH_TIMEOUT_MS, HARD_MAX_PTY_ATTACH_TIMEOUT_MS),
22
+ maxPtyBackendMetadataBytes: validateCodingLimit("maxPtyBackendMetadataBytes", limits?.maxPtyBackendMetadataBytes ?? DEFAULT_MAX_PTY_BACKEND_METADATA_BYTES, HARD_MAX_PTY_BACKEND_METADATA_BYTES),
17
23
  };
18
24
  }
19
25
  //# sourceMappingURL=types.js.map
@@ -0,0 +1,4 @@
1
+ import type { RepositoryGlobRequest, RepositoryGlobResult, ResolvedRepositoryLimits } from "./types.js";
2
+ import type { RepositoryWalk } from "./walk.js";
3
+ export declare function globLocal(request: RepositoryGlobRequest, defaults: ResolvedRepositoryLimits, walk: RepositoryWalk): Promise<RepositoryGlobResult>;
4
+ /** Local filesystem repository operations (default backend). */
@@ -0,0 +1,143 @@
1
+ /** Repository glob family (0.2.5 plan 025 Task 1 split).
2
+ * Moved verbatim from repository.ts; public surface unchanged behind the barrel. */
3
+ import { HARD_MAX_REPO_DEPTH, HARD_MAX_REPO_ENTRIES, HARD_MAX_REPO_RESULTS, validateCodingLimit, validateCodingLimitAllowZero, } from "../limits.js";
4
+ import { expandGlobBraces, matchGlobPattern, validateGlobPattern } from "../glob-match.js";
5
+ import { lstat } from "node:fs/promises";
6
+ import { RepositoryError } from "./types.js";
7
+ import { resolveRepoPath } from "./path.js";
8
+ export async function globLocal(request, defaults, walk) {
9
+ try {
10
+ validateGlobPattern(request.pattern, defaults.maxPatternBytes, { braceExpansion: request.braceExpansion === true });
11
+ }
12
+ catch (error) {
13
+ throw new RepositoryError(error instanceof Error ? error.message : String(error));
14
+ }
15
+ // Opt-in bounded brace expansion: textual alternatives only (never touches the
16
+ // filesystem); bounds enforced by expandGlobBraces (max alternatives / bytes).
17
+ const patterns = request.braceExpansion === true ? expandGlobBraces(request.pattern) : [request.pattern];
18
+ const resolved = await resolveRepoPath(request.root, request.path);
19
+ const maxResults = validateCodingLimit("maxResults", request.maxResults ?? defaults.maxResults, HARD_MAX_REPO_RESULTS);
20
+ const offset = validateCodingLimitAllowZero("offset", request.offset ?? 0, HARD_MAX_REPO_ENTRIES);
21
+ const maxDepth = validateCodingLimit("maxDepth", request.maxDepth ?? defaults.maxDepth, HARD_MAX_REPO_DEPTH);
22
+ const exclude = new Set(request.exclude ?? defaults.exclude);
23
+ const deadlineAt = request.deadlineMs !== undefined ? Date.now() + request.deadlineMs : Date.now() + defaults.maxTimeMs;
24
+ const collected = [];
25
+ let scannedEntries = 0;
26
+ let scannedFiles = 0;
27
+ let seen = 0;
28
+ let truncated = false;
29
+ let truncatedBy = null;
30
+ const matchesAnyPattern = (relativePath) => {
31
+ for (const p of patterns) {
32
+ if (matchGlobPattern(p, relativePath))
33
+ return true;
34
+ }
35
+ return false;
36
+ };
37
+ const maybeCollect = (relativePath) => {
38
+ if (!matchesAnyPattern(relativePath))
39
+ return false;
40
+ if (seen < offset) {
41
+ seen++;
42
+ return false;
43
+ }
44
+ if (collected.length >= maxResults) {
45
+ truncated = true;
46
+ truncatedBy = "results";
47
+ return true;
48
+ }
49
+ collected.push(relativePath);
50
+ seen++;
51
+ return truncated;
52
+ };
53
+ try {
54
+ const startStat = await lstat(resolved.absolute);
55
+ if (!startStat.isDirectory()) {
56
+ scannedEntries = 1;
57
+ if (startStat.isFile()) {
58
+ scannedFiles = 1;
59
+ if (matchesAnyPattern(resolved.relative)) {
60
+ if (offset === 0 && maxResults > 0)
61
+ collected.push(resolved.relative);
62
+ else if (offset === 0 && maxResults === 0) {
63
+ truncated = true;
64
+ truncatedBy = "results";
65
+ }
66
+ }
67
+ }
68
+ return {
69
+ paths: collected,
70
+ truncated,
71
+ truncatedBy,
72
+ scannedEntries,
73
+ scannedFiles,
74
+ offset,
75
+ nextOffset: undefined,
76
+ };
77
+ }
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : String(error);
81
+ throw new RepositoryError(`cannot open path: ${message}`);
82
+ }
83
+ try {
84
+ for await (const event of walk(resolved.rootReal, resolved.absolute, {
85
+ maxDepth,
86
+ maxEntries: defaults.maxEntries,
87
+ maxFiles: defaults.maxFiles,
88
+ exclude,
89
+ includeHidden: request.includeHidden === true,
90
+ signal: request.signal,
91
+ deadlineAt,
92
+ })) {
93
+ if (event.type === "limit") {
94
+ truncated = true;
95
+ truncatedBy = event.truncatedBy;
96
+ break;
97
+ }
98
+ scannedEntries++;
99
+ if (event.entry.kind === "file")
100
+ scannedFiles++;
101
+ if (event.entry.kind !== "file")
102
+ continue;
103
+ if (maybeCollect(event.entry.path))
104
+ break;
105
+ }
106
+ }
107
+ catch (error) {
108
+ if (error instanceof RepositoryError && error.message === "Operation aborted") {
109
+ return {
110
+ paths: collected,
111
+ truncated: true,
112
+ truncatedBy: "abort",
113
+ scannedEntries,
114
+ scannedFiles,
115
+ offset,
116
+ nextOffset: collected.length > 0 || offset > 0 ? offset + collected.length : undefined,
117
+ };
118
+ }
119
+ if (error instanceof RepositoryError && error.message === "Repository operation exceeded time limit") {
120
+ return {
121
+ paths: collected,
122
+ truncated: true,
123
+ truncatedBy: "time",
124
+ scannedEntries,
125
+ scannedFiles,
126
+ offset,
127
+ nextOffset: offset + collected.length,
128
+ };
129
+ }
130
+ throw error;
131
+ }
132
+ return {
133
+ paths: collected,
134
+ truncated,
135
+ truncatedBy,
136
+ scannedEntries,
137
+ scannedFiles,
138
+ offset,
139
+ nextOffset: truncated ? offset + collected.length : undefined,
140
+ };
141
+ }
142
+ /** Local filesystem repository operations (default backend). */
143
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1,121 @@
1
+ import type { RepositoryOperations } from "./types.js";
2
+ /** Frozen index state machine: empty | building | ready | stale | failed. */
3
+ export type IndexState = "empty" | "building" | "ready" | "stale" | "failed";
4
+ export declare const INDEX_STATES: readonly IndexState[];
5
+ export interface IndexResourceDiagnostics {
6
+ readonly entries: number;
7
+ readonly bytes: number;
8
+ readonly lastUpdatedAt?: number;
9
+ }
10
+ export interface RepositoryIndexStatus {
11
+ readonly state: IndexState;
12
+ /** Source revision the index was built from; required when `requireSourceRevision`. */
13
+ readonly sourceRevision?: string;
14
+ /** Indexed-at timestamp (epoch ms); used for the staleness age check. */
15
+ readonly updatedAt?: number;
16
+ readonly diagnostics?: IndexResourceDiagnostics;
17
+ }
18
+ export type IndexFileChangeKind = "add" | "edit" | "delete" | "rename";
19
+ export interface IndexFileChange {
20
+ /** Repository-relative path (forward slashes, no leading slash, no `..`). */
21
+ readonly path: string;
22
+ readonly kind: IndexFileChangeKind;
23
+ /** Rename source path (repository-relative). */
24
+ readonly oldPath?: string;
25
+ readonly bytes?: number;
26
+ }
27
+ export interface RepositoryIndexUpdateRequest {
28
+ /** Optional host identity scoping (bounded; never credential-bearing). */
29
+ readonly repositoryId?: string;
30
+ readonly worktreeId?: string;
31
+ /** Revision the changes apply on top of. */
32
+ readonly sourceRevision: string;
33
+ readonly changes: readonly IndexFileChange[];
34
+ }
35
+ export interface RepositoryIndexRemoveRequest {
36
+ /** Repository-relative paths to drop from the index. */
37
+ readonly paths: readonly string[];
38
+ }
39
+ export interface IndexSearchHit {
40
+ /** Repository-relative path (validated for containment). */
41
+ readonly path: string;
42
+ /** Relevance in [0,1]; non-finite or out-of-range scores fail closed. */
43
+ readonly score: number;
44
+ /** Snippet text (bounded; treated as untrusted prompt-injection surface). */
45
+ readonly snippet: string;
46
+ }
47
+ export interface RepositoryIndexQueryRequest {
48
+ readonly query: string;
49
+ readonly mode: "indexed_literal" | "semantic";
50
+ /** Optional repository-relative scope filter. */
51
+ readonly path?: string;
52
+ readonly maxResults: number;
53
+ readonly signal?: AbortSignal;
54
+ readonly deadlineMs?: number;
55
+ }
56
+ export interface RepositoryIndexQueryResult {
57
+ readonly hits: readonly IndexSearchHit[];
58
+ readonly truncated: boolean;
59
+ }
60
+ export interface RepositoryIndexBackend {
61
+ /** Explicit capability declaration; semantic mode is never duck-typed. */
62
+ readonly capabilities: {
63
+ readonly semantic: boolean;
64
+ };
65
+ update(request: RepositoryIndexUpdateRequest): Promise<void>;
66
+ remove(request: RepositoryIndexRemoveRequest): Promise<void>;
67
+ search(request: RepositoryIndexQueryRequest): Promise<RepositoryIndexQueryResult>;
68
+ status(): Promise<RepositoryIndexStatus>;
69
+ dispose(): Promise<void>;
70
+ }
71
+ export interface ResolvedIndexLimits {
72
+ readonly maxUpdateFiles: number;
73
+ readonly maxUpdateBytes: number;
74
+ readonly maxResults: number;
75
+ readonly maxSnippetBytes: number;
76
+ readonly staleMaxAgeMs: number;
77
+ readonly queryTimeoutMs: number;
78
+ }
79
+ export interface IndexLimitOptions {
80
+ readonly maxUpdateFiles?: number;
81
+ readonly maxUpdateBytes?: number;
82
+ readonly maxResults?: number;
83
+ readonly maxSnippetBytes?: number;
84
+ readonly staleMaxAgeMs?: number;
85
+ readonly queryTimeoutMs?: number;
86
+ }
87
+ export declare function resolveIndexLimits(options?: IndexLimitOptions): ResolvedIndexLimits;
88
+ export declare class IndexError extends Error {
89
+ readonly code: "ERR_PRISM_INDEX_UNSUPPORTED" | "ERR_PRISM_INDEX_STALE" | "ERR_PRISM_INDEX_FAILED" | "ERR_PRISM_INDEX_LIMIT" | "ERR_PRISM_INDEX_TIMEOUT" | "ERR_PRISM_INDEX_UNTRUSTED";
90
+ constructor(code: "ERR_PRISM_INDEX_UNSUPPORTED" | "ERR_PRISM_INDEX_STALE" | "ERR_PRISM_INDEX_FAILED" | "ERR_PRISM_INDEX_LIMIT" | "ERR_PRISM_INDEX_TIMEOUT" | "ERR_PRISM_INDEX_UNTRUSTED", message: string);
91
+ }
92
+ export interface IndexedRepositoryOptions {
93
+ /** Host-owned incremental index backend (never started or built implicitly). */
94
+ readonly index: RepositoryIndexBackend;
95
+ /** Literal fallback (e.g. createGitAwareRepositoryOperations) for mode "literal". */
96
+ readonly fallback: RepositoryOperations;
97
+ /** Modes this composite accepts; default literal only. `indexed_literal`/`semantic` must be listed explicitly. */
98
+ readonly allowedModes?: readonly ("literal" | "indexed_literal" | "semantic")[];
99
+ readonly stale?: {
100
+ readonly maxAgeMs?: number;
101
+ /** Require the index to attest a sourceRevision before serving queries. */
102
+ readonly requireSourceRevision?: boolean;
103
+ };
104
+ readonly limits?: IndexLimitOptions;
105
+ }
106
+ export interface IndexFacade {
107
+ update(request: RepositoryIndexUpdateRequest): Promise<void>;
108
+ remove(request: RepositoryIndexRemoveRequest): Promise<void>;
109
+ status(): Promise<RepositoryIndexStatus>;
110
+ dispose(): Promise<void>;
111
+ }
112
+ /**
113
+ * Compose a host index with a literal fallback. Mode "literal" is routed to
114
+ * `fallback` unchanged; indexed modes are served only by the host backend with
115
+ * freshness checks, result validation, and no silent fallback.
116
+ */
117
+ export declare function createIndexedRepositoryOperations(cwd: string, options: IndexedRepositoryOptions): RepositoryOperations & {
118
+ readonly index: IndexFacade;
119
+ };
120
+ /** Stable repo-relative label used in errors; kept for tests and docs. */
121
+ export declare function indexErrorCode(error: unknown): string | undefined;