disk 0.8.11 → 0.8.12

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/cli.js CHANGED
@@ -223,6 +223,31 @@ var Disk = class {
223
223
  })
224
224
  );
225
225
  }
226
+ /**
227
+ * Constant-time parallel grep across files on this disk. Listing and
228
+ * matching are fanned out across ephemeral exec containers; the request
229
+ * finishes within the supplied time budget regardless of dataset size.
230
+ *
231
+ * The returned `stoppedReason` says whether the search ran to completion
232
+ * or short-circuited on `maxResults` / `maxDurationSeconds`. When
233
+ * stopping early, the matches returned are a sample (whichever workers
234
+ * reported first), not the lexicographically first N.
235
+ */
236
+ async grep(opts) {
237
+ return unwrap(
238
+ this._client.POST("/api/disks/{id}/grep", {
239
+ params: { path: { id: this.id } },
240
+ body: {
241
+ directory: opts.directory,
242
+ pattern: opts.pattern,
243
+ recursive: opts.recursive ?? false,
244
+ maxDurationSeconds: opts.maxDurationSeconds ?? 30,
245
+ concurrency: opts.concurrency ?? 50,
246
+ maxResults: opts.maxResults ?? 1e3
247
+ }
248
+ })
249
+ );
250
+ }
226
251
  /**
227
252
  * Connect to this disk's data plane via the native ArchilClient.
228
253
  *
package/dist/index.cjs CHANGED
@@ -266,6 +266,31 @@ var Disk = class {
266
266
  })
267
267
  );
268
268
  }
269
+ /**
270
+ * Constant-time parallel grep across files on this disk. Listing and
271
+ * matching are fanned out across ephemeral exec containers; the request
272
+ * finishes within the supplied time budget regardless of dataset size.
273
+ *
274
+ * The returned `stoppedReason` says whether the search ran to completion
275
+ * or short-circuited on `maxResults` / `maxDurationSeconds`. When
276
+ * stopping early, the matches returned are a sample (whichever workers
277
+ * reported first), not the lexicographically first N.
278
+ */
279
+ async grep(opts) {
280
+ return unwrap(
281
+ this._client.POST("/api/disks/{id}/grep", {
282
+ params: { path: { id: this.id } },
283
+ body: {
284
+ directory: opts.directory,
285
+ pattern: opts.pattern,
286
+ recursive: opts.recursive ?? false,
287
+ maxDurationSeconds: opts.maxDurationSeconds ?? 30,
288
+ concurrency: opts.concurrency ?? 50,
289
+ maxResults: opts.maxResults ?? 1e3
290
+ }
291
+ })
292
+ );
293
+ }
269
294
  /**
270
295
  * Connect to this disk's data plane via the native ArchilClient.
271
296
  *
package/dist/index.d.cts CHANGED
@@ -148,6 +148,48 @@ interface paths {
148
148
  patch?: never;
149
149
  trace?: never;
150
150
  };
151
+ "/api/disks/{id}/grep": {
152
+ parameters: {
153
+ query?: never;
154
+ header?: never;
155
+ path?: never;
156
+ cookie?: never;
157
+ };
158
+ get?: never;
159
+ put?: never;
160
+ /**
161
+ * Constant-time parallel grep over a directory on a disk
162
+ * @description Searches files under a directory on the disk for lines matching a
163
+ * regular expression. Listing and matching are fanned out across
164
+ * ephemeral exec containers, so the request finishes within the user's
165
+ * time budget regardless of the size of the directory.
166
+ *
167
+ * The user controls cost and latency with three knobs:
168
+ *
169
+ * - `maxDurationSeconds` is the wall-clock deadline.
170
+ * - `concurrency` is the maximum number of parallel grep workers.
171
+ * Higher concurrency finishes larger datasets within the deadline;
172
+ * the controlplane clamps to the runtime fleet's current capacity.
173
+ * - `maxResults` causes the search to short-circuit after the
174
+ * aggregator has collected this many matches.
175
+ *
176
+ * With `recursive: false` only files directly under `directory` are
177
+ * searched. With `recursive: true` subdirectories are walked
178
+ * breadth-first and grep workers are dispatched as soon as each level
179
+ * finishes listing — listing and matching overlap.
180
+ *
181
+ * The matches returned when stopping early on `maxResults` are a sample
182
+ * of whichever workers reported first, not the lexicographically first
183
+ * N. The response surfaces `stoppedReason` so callers can distinguish
184
+ * completion from early termination.
185
+ */
186
+ post: operations["grepDisk"];
187
+ delete?: never;
188
+ options?: never;
189
+ head?: never;
190
+ patch?: never;
191
+ trace?: never;
192
+ };
151
193
  "/api/exec": {
152
194
  parameters: {
153
195
  query?: never;
@@ -758,6 +800,108 @@ interface components {
758
800
  success: boolean;
759
801
  data: components["schemas"]["ExecDiskResult"];
760
802
  };
803
+ GrepDiskRequest: {
804
+ /**
805
+ * @description Directory on the disk to search, relative to the disk root.
806
+ * An empty string or "/" means the disk root.
807
+ * @example data/logs
808
+ */
809
+ directory: string;
810
+ /**
811
+ * @description Extended regular expression (passed to `grep -E`)
812
+ * @example ERROR|FATAL
813
+ */
814
+ pattern: string;
815
+ /**
816
+ * @description When true, walks subdirectories breadth-first.
817
+ * @default false
818
+ */
819
+ recursive: boolean;
820
+ /**
821
+ * @description Wall-clock deadline for the entire request. Capped at 30
822
+ * seconds because the runtime exec container itself is bounded
823
+ * at ~30s; longer requests would have their workers killed
824
+ * mid-scan.
825
+ * @default 30
826
+ */
827
+ maxDurationSeconds: number;
828
+ /**
829
+ * @description Maximum number of parallel grep workers. Higher values finish
830
+ * larger datasets within the deadline but consume more runtime
831
+ * capacity. The controlplane clamps this to the fleet's
832
+ * currently-available capacity.
833
+ * @default 50
834
+ */
835
+ concurrency: number;
836
+ /**
837
+ * @description Stop scanning once the aggregator has this many matches.
838
+ * Returned matches are a sample of whichever workers reported
839
+ * first, not the lexicographically first N.
840
+ * @default 1000
841
+ */
842
+ maxResults: number;
843
+ };
844
+ GrepMatch: {
845
+ /**
846
+ * @description Path to the file (relative to the disk root).
847
+ * @example data/logs/2026-05-03.log
848
+ */
849
+ file: string;
850
+ /**
851
+ * @description 1-based line number where the match occurred.
852
+ * @example 142
853
+ */
854
+ line: number;
855
+ /** @description The matching line. */
856
+ text: string;
857
+ };
858
+ /**
859
+ * @description Why the search stopped.
860
+ * - `completed`: every file under the directory was scanned successfully.
861
+ * - `incomplete`: pipeline ran to its natural end but one or more
862
+ * batches errored (invalid regex, unreadable file, runtime issue).
863
+ * Results may be partial or wrong; do not rely on completeness.
864
+ * - `max_results`: hit `maxResults` before scanning everything.
865
+ * - `deadline`: hit `maxDurationSeconds`.
866
+ * - `list_failed`: directory listing failed; partial results
867
+ * may be present.
868
+ * @enum {string}
869
+ */
870
+ GrepStoppedReason: "completed" | "incomplete" | "max_results" | "deadline" | "list_failed";
871
+ GrepDiskResult: {
872
+ matches: components["schemas"]["GrepMatch"][];
873
+ stoppedReason: components["schemas"]["GrepStoppedReason"];
874
+ /** @description Files actually fed to a grep container. */
875
+ filesScanned: number;
876
+ /** @description Number of grep containers started for this request. */
877
+ containersDispatched: number;
878
+ /**
879
+ * Format: double
880
+ * @description Sum of per-container execution time in seconds, measured by the
881
+ * runtime. Approximates billable container-seconds.
882
+ */
883
+ computeSecondsUsed: number;
884
+ /** @description End-to-end wall clock measured by the server. */
885
+ durationMs: number;
886
+ /**
887
+ * @description Wall-clock time spent enumerating files via listObjects, from
888
+ * the request's start to the moment listing fully drained (or
889
+ * was canceled). Listing and matching overlap, so listingMs +
890
+ * grepMs typically exceeds durationMs.
891
+ */
892
+ listingMs: number;
893
+ /**
894
+ * @description Wall-clock time spent matching, from the first grep container
895
+ * being dispatched to the last container reporting results. 0 if
896
+ * no batches ran.
897
+ */
898
+ grepMs: number;
899
+ };
900
+ ApiResponse_GrepDisk: {
901
+ /** @example true */
902
+ success: boolean;
903
+ data: components["schemas"]["GrepDiskResult"];
904
+ };
761
905
  };
762
906
  responses: {
763
907
  /** @description Invalid or missing authentication credentials */
@@ -1119,6 +1263,37 @@ interface operations {
1119
1263
  };
1120
1264
  };
1121
1265
  };
1266
+ grepDisk: {
1267
+ parameters: {
1268
+ query?: never;
1269
+ header?: never;
1270
+ path: {
1271
+ /** @description Disk ID (format `dsk-{16 hex chars}`) */
1272
+ id: components["parameters"]["DiskId"];
1273
+ };
1274
+ cookie?: never;
1275
+ };
1276
+ requestBody: {
1277
+ content: {
1278
+ "application/json": components["schemas"]["GrepDiskRequest"];
1279
+ };
1280
+ };
1281
+ responses: {
1282
+ /** @description Grep completed (possibly stopped early) */
1283
+ 200: {
1284
+ headers: {
1285
+ [name: string]: unknown;
1286
+ };
1287
+ content: {
1288
+ "application/json": components["schemas"]["ApiResponse_GrepDisk"];
1289
+ };
1290
+ };
1291
+ 400: components["responses"]["ValidationError"];
1292
+ 401: components["responses"]["Unauthorized"];
1293
+ 404: components["responses"]["NotFound"];
1294
+ 500: components["responses"]["InternalError"];
1295
+ };
1296
+ };
1122
1297
  exec: {
1123
1298
  parameters: {
1124
1299
  query?: never;
@@ -1260,6 +1435,9 @@ type CreateApiTokenRequest = components["schemas"]["CreateApiTokenRequest"];
1260
1435
  type ApiTokenResponse = components["schemas"]["ApiTokenResponse"];
1261
1436
  type ExecDiskResult = components["schemas"]["ExecDiskResult"];
1262
1437
  type ExecRequest = components["schemas"]["ExecRequest"];
1438
+ type GrepDiskResult = components["schemas"]["GrepDiskResult"];
1439
+ type GrepMatch = components["schemas"]["GrepMatch"];
1440
+ type GrepStoppedReason = components["schemas"]["GrepStoppedReason"];
1263
1441
  type DiskStatus = DiskResponse["status"];
1264
1442
 
1265
1443
  interface MountOptions {
@@ -1269,6 +1447,34 @@ interface MountOptions {
1269
1447
  insecure?: boolean;
1270
1448
  }
1271
1449
  type ExecResult = ExecDiskResult;
1450
+ type GrepResult = GrepDiskResult;
1451
+
1452
+ interface GrepOptions {
1453
+ /**
1454
+ * Directory on the disk to search, relative to the disk root. An empty
1455
+ * string or "/" means the disk root.
1456
+ */
1457
+ directory: string;
1458
+ /** Extended regular expression (passed to `grep -E`). */
1459
+ pattern: string;
1460
+ /** Walk subdirectories breadth-first. Defaults to false. */
1461
+ recursive?: boolean;
1462
+ /** Wall-clock deadline for the entire request. Defaults to 30s. */
1463
+ maxDurationSeconds?: number;
1464
+ /**
1465
+ * Maximum number of parallel grep workers. Higher values finish larger
1466
+ * datasets within the deadline but consume more runtime capacity. The
1467
+ * controlplane clamps this to the fleet's currently-available capacity.
1468
+ * Defaults to 50.
1469
+ */
1470
+ concurrency?: number;
1471
+ /**
1472
+ * Stop scanning once the aggregator has this many matches. Returned
1473
+ * matches are a sample of whichever workers reported first, not the
1474
+ * lexicographically first N. Defaults to 1000.
1475
+ */
1476
+ maxResults?: number;
1477
+ }
1272
1478
  declare class Disk {
1273
1479
  readonly id: string;
1274
1480
  readonly name: string;
@@ -1310,6 +1516,17 @@ declare class Disk {
1310
1516
  * Blocks until the command completes and returns stdout, stderr, and exit code.
1311
1517
  */
1312
1518
  exec(command: string): Promise<ExecResult>;
1519
+ /**
1520
+ * Constant-time parallel grep across files on this disk. Listing and
1521
+ * matching are fanned out across ephemeral exec containers; the request
1522
+ * finishes within the supplied time budget regardless of dataset size.
1523
+ *
1524
+ * The returned `stoppedReason` says whether the search ran to completion
1525
+ * or short-circuited on `maxResults` / `maxDurationSeconds`. When
1526
+ * stopping early, the matches returned are a sample (whichever workers
1527
+ * reported first), not the lexicographically first N.
1528
+ */
1529
+ grep(opts: GrepOptions): Promise<GrepResult>;
1313
1530
  /**
1314
1531
  * Connect to this disk's data plane via the native ArchilClient.
1315
1532
  *
@@ -1446,4 +1663,4 @@ declare function deleteApiKey(id: string): Promise<void>;
1446
1663
  */
1447
1664
  declare function exec(opts: ExecOptions): Promise<ExecDiskResult>;
1448
1665
 
1449
- export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type ExecMount, type ExecMountSpec, type ExecOptions, type ExecRequest, type ExecResult, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens, configure, createApiKey, createDisk, deleteApiKey, exec, getDisk, listApiKeys, listDisks };
1666
+ export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type ExecMount, type ExecMountSpec, type ExecOptions, type ExecRequest, type ExecResult, type GCSMount, type GrepMatch, type GrepOptions, type GrepResult, type GrepStoppedReason, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens, configure, createApiKey, createDisk, deleteApiKey, exec, getDisk, listApiKeys, listDisks };
package/dist/index.d.ts CHANGED
@@ -148,6 +148,48 @@ interface paths {
148
148
  patch?: never;
149
149
  trace?: never;
150
150
  };
151
+ "/api/disks/{id}/grep": {
152
+ parameters: {
153
+ query?: never;
154
+ header?: never;
155
+ path?: never;
156
+ cookie?: never;
157
+ };
158
+ get?: never;
159
+ put?: never;
160
+ /**
161
+ * Constant-time parallel grep over a directory on a disk
162
+ * @description Searches files under a directory on the disk for lines matching a
163
+ * regular expression. Listing and matching are fanned out across
164
+ * ephemeral exec containers, so the request finishes within the user's
165
+ * time budget regardless of the size of the directory.
166
+ *
167
+ * The user controls cost and latency with three knobs:
168
+ *
169
+ * - `maxDurationSeconds` is the wall-clock deadline.
170
+ * - `concurrency` is the maximum number of parallel grep workers.
171
+ * Higher concurrency finishes larger datasets within the deadline;
172
+ * the controlplane clamps to the runtime fleet's current capacity.
173
+ * - `maxResults` causes the search to short-circuit after the
174
+ * aggregator has collected this many matches.
175
+ *
176
+ * With `recursive: false` only files directly under `directory` are
177
+ * searched. With `recursive: true` subdirectories are walked
178
+ * breadth-first and grep workers are dispatched as soon as each level
179
+ * finishes listing — listing and matching overlap.
180
+ *
181
+ * The matches returned when stopping early on `maxResults` are a sample
182
+ * of whichever workers reported first, not the lexicographically first
183
+ * N. The response surfaces `stoppedReason` so callers can distinguish
184
+ * completion from early termination.
185
+ */
186
+ post: operations["grepDisk"];
187
+ delete?: never;
188
+ options?: never;
189
+ head?: never;
190
+ patch?: never;
191
+ trace?: never;
192
+ };
151
193
  "/api/exec": {
152
194
  parameters: {
153
195
  query?: never;
@@ -758,6 +800,108 @@ interface components {
758
800
  success: boolean;
759
801
  data: components["schemas"]["ExecDiskResult"];
760
802
  };
803
+ GrepDiskRequest: {
804
+ /**
805
+ * @description Directory on the disk to search, relative to the disk root.
806
+ * An empty string or "/" means the disk root.
807
+ * @example data/logs
808
+ */
809
+ directory: string;
810
+ /**
811
+ * @description Extended regular expression (passed to `grep -E`)
812
+ * @example ERROR|FATAL
813
+ */
814
+ pattern: string;
815
+ /**
816
+ * @description When true, walks subdirectories breadth-first.
817
+ * @default false
818
+ */
819
+ recursive: boolean;
820
+ /**
821
+ * @description Wall-clock deadline for the entire request. Capped at 30
822
+ * seconds because the runtime exec container itself is bounded
823
+ * at ~30s; longer requests would have their workers killed
824
+ * mid-scan.
825
+ * @default 30
826
+ */
827
+ maxDurationSeconds: number;
828
+ /**
829
+ * @description Maximum number of parallel grep workers. Higher values finish
830
+ * larger datasets within the deadline but consume more runtime
831
+ * capacity. The controlplane clamps this to the fleet's
832
+ * currently-available capacity.
833
+ * @default 50
834
+ */
835
+ concurrency: number;
836
+ /**
837
+ * @description Stop scanning once the aggregator has this many matches.
838
+ * Returned matches are a sample of whichever workers reported
839
+ * first, not the lexicographically first N.
840
+ * @default 1000
841
+ */
842
+ maxResults: number;
843
+ };
844
+ GrepMatch: {
845
+ /**
846
+ * @description Path to the file (relative to the disk root).
847
+ * @example data/logs/2026-05-03.log
848
+ */
849
+ file: string;
850
+ /**
851
+ * @description 1-based line number where the match occurred.
852
+ * @example 142
853
+ */
854
+ line: number;
855
+ /** @description The matching line. */
856
+ text: string;
857
+ };
858
+ /**
859
+ * @description Why the search stopped.
860
+ * - `completed`: every file under the directory was scanned successfully.
861
+ * - `incomplete`: pipeline ran to its natural end but one or more
862
+ * batches errored (invalid regex, unreadable file, runtime issue).
863
+ * Results may be partial or wrong; do not rely on completeness.
864
+ * - `max_results`: hit `maxResults` before scanning everything.
865
+ * - `deadline`: hit `maxDurationSeconds`.
866
+ * - `list_failed`: directory listing failed; partial results
867
+ * may be present.
868
+ * @enum {string}
869
+ */
870
+ GrepStoppedReason: "completed" | "incomplete" | "max_results" | "deadline" | "list_failed";
871
+ GrepDiskResult: {
872
+ matches: components["schemas"]["GrepMatch"][];
873
+ stoppedReason: components["schemas"]["GrepStoppedReason"];
874
+ /** @description Files actually fed to a grep container. */
875
+ filesScanned: number;
876
+ /** @description Number of grep containers started for this request. */
877
+ containersDispatched: number;
878
+ /**
879
+ * Format: double
880
+ * @description Sum of per-container execution time in seconds, measured by the
881
+ * runtime. Approximates billable container-seconds.
882
+ */
883
+ computeSecondsUsed: number;
884
+ /** @description End-to-end wall clock measured by the server. */
885
+ durationMs: number;
886
+ /**
887
+ * @description Wall-clock time spent enumerating files via listObjects, from
888
+ * the request's start to the moment listing fully drained (or
889
+ * was canceled). Listing and matching overlap, so listingMs +
890
+ * grepMs typically exceeds durationMs.
891
+ */
892
+ listingMs: number;
893
+ /**
894
+ * @description Wall-clock time spent matching, from the first grep container
895
+ * being dispatched to the last container reporting results. 0 if
896
+ * no batches ran.
897
+ */
898
+ grepMs: number;
899
+ };
900
+ ApiResponse_GrepDisk: {
901
+ /** @example true */
902
+ success: boolean;
903
+ data: components["schemas"]["GrepDiskResult"];
904
+ };
761
905
  };
762
906
  responses: {
763
907
  /** @description Invalid or missing authentication credentials */
@@ -1119,6 +1263,37 @@ interface operations {
1119
1263
  };
1120
1264
  };
1121
1265
  };
1266
+ grepDisk: {
1267
+ parameters: {
1268
+ query?: never;
1269
+ header?: never;
1270
+ path: {
1271
+ /** @description Disk ID (format `dsk-{16 hex chars}`) */
1272
+ id: components["parameters"]["DiskId"];
1273
+ };
1274
+ cookie?: never;
1275
+ };
1276
+ requestBody: {
1277
+ content: {
1278
+ "application/json": components["schemas"]["GrepDiskRequest"];
1279
+ };
1280
+ };
1281
+ responses: {
1282
+ /** @description Grep completed (possibly stopped early) */
1283
+ 200: {
1284
+ headers: {
1285
+ [name: string]: unknown;
1286
+ };
1287
+ content: {
1288
+ "application/json": components["schemas"]["ApiResponse_GrepDisk"];
1289
+ };
1290
+ };
1291
+ 400: components["responses"]["ValidationError"];
1292
+ 401: components["responses"]["Unauthorized"];
1293
+ 404: components["responses"]["NotFound"];
1294
+ 500: components["responses"]["InternalError"];
1295
+ };
1296
+ };
1122
1297
  exec: {
1123
1298
  parameters: {
1124
1299
  query?: never;
@@ -1260,6 +1435,9 @@ type CreateApiTokenRequest = components["schemas"]["CreateApiTokenRequest"];
1260
1435
  type ApiTokenResponse = components["schemas"]["ApiTokenResponse"];
1261
1436
  type ExecDiskResult = components["schemas"]["ExecDiskResult"];
1262
1437
  type ExecRequest = components["schemas"]["ExecRequest"];
1438
+ type GrepDiskResult = components["schemas"]["GrepDiskResult"];
1439
+ type GrepMatch = components["schemas"]["GrepMatch"];
1440
+ type GrepStoppedReason = components["schemas"]["GrepStoppedReason"];
1263
1441
  type DiskStatus = DiskResponse["status"];
1264
1442
 
1265
1443
  interface MountOptions {
@@ -1269,6 +1447,34 @@ interface MountOptions {
1269
1447
  insecure?: boolean;
1270
1448
  }
1271
1449
  type ExecResult = ExecDiskResult;
1450
+ type GrepResult = GrepDiskResult;
1451
+
1452
+ interface GrepOptions {
1453
+ /**
1454
+ * Directory on the disk to search, relative to the disk root. An empty
1455
+ * string or "/" means the disk root.
1456
+ */
1457
+ directory: string;
1458
+ /** Extended regular expression (passed to `grep -E`). */
1459
+ pattern: string;
1460
+ /** Walk subdirectories breadth-first. Defaults to false. */
1461
+ recursive?: boolean;
1462
+ /** Wall-clock deadline for the entire request. Defaults to 30s. */
1463
+ maxDurationSeconds?: number;
1464
+ /**
1465
+ * Maximum number of parallel grep workers. Higher values finish larger
1466
+ * datasets within the deadline but consume more runtime capacity. The
1467
+ * controlplane clamps this to the fleet's currently-available capacity.
1468
+ * Defaults to 50.
1469
+ */
1470
+ concurrency?: number;
1471
+ /**
1472
+ * Stop scanning once the aggregator has this many matches. Returned
1473
+ * matches are a sample of whichever workers reported first, not the
1474
+ * lexicographically first N. Defaults to 1000.
1475
+ */
1476
+ maxResults?: number;
1477
+ }
1272
1478
  declare class Disk {
1273
1479
  readonly id: string;
1274
1480
  readonly name: string;
@@ -1310,6 +1516,17 @@ declare class Disk {
1310
1516
  * Blocks until the command completes and returns stdout, stderr, and exit code.
1311
1517
  */
1312
1518
  exec(command: string): Promise<ExecResult>;
1519
+ /**
1520
+ * Constant-time parallel grep across files on this disk. Listing and
1521
+ * matching are fanned out across ephemeral exec containers; the request
1522
+ * finishes within the supplied time budget regardless of dataset size.
1523
+ *
1524
+ * The returned `stoppedReason` says whether the search ran to completion
1525
+ * or short-circuited on `maxResults` / `maxDurationSeconds`. When
1526
+ * stopping early, the matches returned are a sample (whichever workers
1527
+ * reported first), not the lexicographically first N.
1528
+ */
1529
+ grep(opts: GrepOptions): Promise<GrepResult>;
1313
1530
  /**
1314
1531
  * Connect to this disk's data plane via the native ArchilClient.
1315
1532
  *
@@ -1446,4 +1663,4 @@ declare function deleteApiKey(id: string): Promise<void>;
1446
1663
  */
1447
1664
  declare function exec(opts: ExecOptions): Promise<ExecDiskResult>;
1448
1665
 
1449
- export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type ExecMount, type ExecMountSpec, type ExecOptions, type ExecRequest, type ExecResult, type GCSMount, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens, configure, createApiKey, createDisk, deleteApiKey, exec, getDisk, listApiKeys, listDisks };
1666
+ export { type ApiTokenResponse, Archil, ArchilApiError, type ArchilOptions, type AuthorizedUser, type AwsStsUser, type AzureBlobMount, type ConnectedClient, type CreateApiTokenRequest, type CreateDiskRequest, type CreateDiskResult, Disk, type DiskMetrics, type DiskResponse, type DiskStatus, type DiskUser, Disks, type ExecMount, type ExecMountSpec, type ExecOptions, type ExecRequest, type ExecResult, type GCSMount, type GrepMatch, type GrepOptions, type GrepResult, type GrepStoppedReason, type ListDisksOptions, type ListTokensOptions, type MountConfig, type MountConfigResponse, type MountOptions, type MountResponse, type R2Mount, type S3CompatibleMount, type S3Mount, type TokenUser, Tokens, configure, createApiKey, createDisk, deleteApiKey, exec, getDisk, listApiKeys, listDisks };
package/dist/index.js CHANGED
@@ -217,6 +217,31 @@ var Disk = class {
217
217
  })
218
218
  );
219
219
  }
220
+ /**
221
+ * Constant-time parallel grep across files on this disk. Listing and
222
+ * matching are fanned out across ephemeral exec containers; the request
223
+ * finishes within the supplied time budget regardless of dataset size.
224
+ *
225
+ * The returned `stoppedReason` says whether the search ran to completion
226
+ * or short-circuited on `maxResults` / `maxDurationSeconds`. When
227
+ * stopping early, the matches returned are a sample (whichever workers
228
+ * reported first), not the lexicographically first N.
229
+ */
230
+ async grep(opts) {
231
+ return unwrap(
232
+ this._client.POST("/api/disks/{id}/grep", {
233
+ params: { path: { id: this.id } },
234
+ body: {
235
+ directory: opts.directory,
236
+ pattern: opts.pattern,
237
+ recursive: opts.recursive ?? false,
238
+ maxDurationSeconds: opts.maxDurationSeconds ?? 30,
239
+ concurrency: opts.concurrency ?? 50,
240
+ maxResults: opts.maxResults ?? 1e3
241
+ }
242
+ })
243
+ );
244
+ }
220
245
  /**
221
246
  * Connect to this disk's data plane via the native ArchilClient.
222
247
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "disk",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "description": "Pure-JS client and CLI for Archil disks",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",