@agentuity/core 1.0.37 → 1.0.38
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/services/keyvalue/service.d.ts +2 -0
- package/dist/services/keyvalue/service.d.ts.map +1 -1
- package/dist/services/keyvalue/service.js +4 -0
- package/dist/services/keyvalue/service.js.map +1 -1
- package/dist/services/sandbox/client.d.ts +56 -5
- package/dist/services/sandbox/client.d.ts.map +1 -1
- package/dist/services/sandbox/client.js +120 -51
- package/dist/services/sandbox/client.js.map +1 -1
- package/dist/services/sandbox/pause.js +1 -1
- package/dist/services/sandbox/pause.js.map +1 -1
- package/dist/services/sandbox/types.d.ts +30 -0
- package/dist/services/sandbox/types.d.ts.map +1 -1
- package/dist/services/sandbox/types.js +28 -0
- package/dist/services/sandbox/types.js.map +1 -1
- package/dist/services/stream/delete.d.ts +27 -0
- package/dist/services/stream/delete.d.ts.map +1 -0
- package/dist/services/stream/delete.js +58 -0
- package/dist/services/stream/delete.js.map +1 -0
- package/dist/services/stream/index.d.ts +3 -0
- package/dist/services/stream/index.d.ts.map +1 -1
- package/dist/services/stream/index.js +3 -0
- package/dist/services/stream/index.js.map +1 -1
- package/dist/services/stream/namespaces.d.ts +75 -0
- package/dist/services/stream/namespaces.d.ts.map +1 -0
- package/dist/services/stream/namespaces.js +99 -0
- package/dist/services/stream/namespaces.js.map +1 -0
- package/dist/services/stream/search.d.ts +34 -0
- package/dist/services/stream/search.d.ts.map +1 -0
- package/dist/services/stream/search.js +49 -0
- package/dist/services/stream/search.js.map +1 -0
- package/dist/services/task/service.d.ts +152 -18
- package/dist/services/task/service.d.ts.map +1 -1
- package/dist/services/task/service.js +251 -10
- package/dist/services/task/service.js.map +1 -1
- package/dist/services/vector/service.d.ts +3 -0
- package/dist/services/vector/service.d.ts.map +1 -1
- package/dist/services/vector/service.js +7 -0
- package/dist/services/vector/service.js.map +1 -1
- package/package.json +2 -2
- package/src/services/keyvalue/service.ts +4 -0
- package/src/services/sandbox/client.ts +215 -84
- package/src/services/sandbox/pause.ts +1 -1
- package/src/services/sandbox/types.ts +52 -0
- package/src/services/stream/delete.ts +87 -0
- package/src/services/stream/index.ts +3 -0
- package/src/services/stream/namespaces.ts +160 -0
- package/src/services/stream/search.ts +80 -0
- package/src/services/task/service.ts +371 -13
- package/src/services/vector/service.ts +8 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ExecuteOptionsSchema as CoreExecuteOptionsSchema,
|
|
3
3
|
type SandboxCreateOptions,
|
|
4
|
+
type SandboxFileInfo,
|
|
4
5
|
type SandboxInfo,
|
|
6
|
+
type SandboxStatus,
|
|
5
7
|
type Execution,
|
|
6
8
|
type FileToWrite,
|
|
7
9
|
type SandboxRunOptions,
|
|
@@ -12,11 +14,21 @@ import type { Readable, Writable } from 'node:stream';
|
|
|
12
14
|
import { z } from 'zod';
|
|
13
15
|
import { APIClient } from '../api.ts';
|
|
14
16
|
import { getEnv } from '../env.ts';
|
|
15
|
-
import { sandboxCreate
|
|
17
|
+
import { sandboxCreate } from './create.ts';
|
|
16
18
|
import { sandboxDestroy } from './destroy.ts';
|
|
17
19
|
import { sandboxGet } from './get.ts';
|
|
18
20
|
import { sandboxExecute } from './execute.ts';
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
sandboxWriteFiles,
|
|
23
|
+
sandboxReadFile,
|
|
24
|
+
sandboxListFiles,
|
|
25
|
+
sandboxMkDir,
|
|
26
|
+
sandboxRmFile,
|
|
27
|
+
sandboxRmDir,
|
|
28
|
+
sandboxSetEnv,
|
|
29
|
+
} from './files.ts';
|
|
30
|
+
import { sandboxPause } from './pause.ts';
|
|
31
|
+
import { sandboxResume } from './resume.ts';
|
|
20
32
|
import { sandboxRun } from './run.ts';
|
|
21
33
|
import { executionGet, type ExecutionInfo } from './execution.ts';
|
|
22
34
|
import { createMinimalLogger } from '../logger.ts';
|
|
@@ -130,7 +142,7 @@ export const SandboxClientRunIOSchema = z.object({
|
|
|
130
142
|
export type SandboxClientRunIO = z.infer<typeof SandboxClientRunIOSchema>;
|
|
131
143
|
|
|
132
144
|
/**
|
|
133
|
-
* A sandbox instance returned by SandboxClient.create()
|
|
145
|
+
* A sandbox instance returned by SandboxClient.create() or SandboxClient.connect()
|
|
134
146
|
*/
|
|
135
147
|
export interface SandboxInstance {
|
|
136
148
|
/**
|
|
@@ -139,9 +151,9 @@ export interface SandboxInstance {
|
|
|
139
151
|
id: string;
|
|
140
152
|
|
|
141
153
|
/**
|
|
142
|
-
* Sandbox status at creation time
|
|
154
|
+
* Sandbox status at creation or connection time
|
|
143
155
|
*/
|
|
144
|
-
status:
|
|
156
|
+
status: SandboxStatus;
|
|
145
157
|
|
|
146
158
|
/**
|
|
147
159
|
* URL to stream stdout output
|
|
@@ -173,17 +185,171 @@ export interface SandboxInstance {
|
|
|
173
185
|
*/
|
|
174
186
|
readFile(path: string): Promise<ReadableStream<Uint8Array>>;
|
|
175
187
|
|
|
188
|
+
/**
|
|
189
|
+
* List files in the sandbox workspace
|
|
190
|
+
*/
|
|
191
|
+
listFiles(path?: string): Promise<SandboxFileInfo[]>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Create a directory in the sandbox workspace
|
|
195
|
+
*/
|
|
196
|
+
mkDir(path: string, recursive?: boolean): Promise<void>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Remove a file from the sandbox workspace
|
|
200
|
+
*/
|
|
201
|
+
rmFile(path: string): Promise<void>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Remove a directory from the sandbox workspace
|
|
205
|
+
*/
|
|
206
|
+
rmDir(path: string, recursive?: boolean): Promise<void>;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Set environment variables on the sandbox. Pass null to delete a variable.
|
|
210
|
+
*/
|
|
211
|
+
setEnv(env: Record<string, string | null>): Promise<Record<string, string>>;
|
|
212
|
+
|
|
176
213
|
/**
|
|
177
214
|
* Get current sandbox information
|
|
178
215
|
*/
|
|
179
216
|
get(): Promise<SandboxInfo>;
|
|
180
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Pause the sandbox, creating a checkpoint of its current state
|
|
220
|
+
*/
|
|
221
|
+
pause(): Promise<void>;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Resume the sandbox from a paused or evacuated state
|
|
225
|
+
*/
|
|
226
|
+
resume(): Promise<void>;
|
|
227
|
+
|
|
181
228
|
/**
|
|
182
229
|
* Destroy the sandbox and release all resources
|
|
183
230
|
*/
|
|
184
231
|
destroy(): Promise<void>;
|
|
185
232
|
}
|
|
186
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Creates the method implementations shared by both create() and connect().
|
|
236
|
+
* Modelled after the similar helper in packages/runtime/src/services/sandbox/http.ts.
|
|
237
|
+
*/
|
|
238
|
+
function createSandboxInstanceMethods(
|
|
239
|
+
client: APIClient,
|
|
240
|
+
sandboxId: string,
|
|
241
|
+
orgId?: string
|
|
242
|
+
): Omit<
|
|
243
|
+
SandboxInstance,
|
|
244
|
+
'id' | 'status' | 'stdoutStreamUrl' | 'stderrStreamUrl' | 'auditStreamUrl'
|
|
245
|
+
> {
|
|
246
|
+
return {
|
|
247
|
+
async execute(executeOptions: ExecuteOptions): Promise<Execution> {
|
|
248
|
+
const { pipe, ...coreOptions } = executeOptions;
|
|
249
|
+
|
|
250
|
+
const initialResult = await sandboxExecute(client, {
|
|
251
|
+
sandboxId,
|
|
252
|
+
options: coreOptions,
|
|
253
|
+
orgId,
|
|
254
|
+
signal: coreOptions.signal,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// If pipe options provided, stream the output to the writable streams
|
|
258
|
+
if (pipe) {
|
|
259
|
+
const streamPromises: Promise<void>[] = [];
|
|
260
|
+
|
|
261
|
+
if (pipe.stdout && initialResult.stdoutStreamUrl) {
|
|
262
|
+
streamPromises.push(
|
|
263
|
+
pipeStreamToWritable(
|
|
264
|
+
initialResult.stdoutStreamUrl,
|
|
265
|
+
pipe.stdout,
|
|
266
|
+
coreOptions.signal
|
|
267
|
+
)
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
if (pipe.stderr && initialResult.stderrStreamUrl) {
|
|
271
|
+
streamPromises.push(
|
|
272
|
+
pipeStreamToWritable(
|
|
273
|
+
initialResult.stderrStreamUrl,
|
|
274
|
+
pipe.stderr,
|
|
275
|
+
coreOptions.signal
|
|
276
|
+
)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Wait for all streams to complete
|
|
281
|
+
if (streamPromises.length > 0) {
|
|
282
|
+
await Promise.all(streamPromises);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Wait for execution to complete and get final result with exit code
|
|
287
|
+
const finalResult = await waitForExecution(
|
|
288
|
+
client,
|
|
289
|
+
initialResult.executionId,
|
|
290
|
+
orgId,
|
|
291
|
+
coreOptions.signal
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
executionId: finalResult.executionId,
|
|
296
|
+
status: finalResult.status,
|
|
297
|
+
exitCode: finalResult.exitCode,
|
|
298
|
+
durationMs: finalResult.durationMs,
|
|
299
|
+
stdoutStreamUrl: initialResult.stdoutStreamUrl,
|
|
300
|
+
stderrStreamUrl: initialResult.stderrStreamUrl,
|
|
301
|
+
};
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
async writeFiles(files: FileToWrite[]): Promise<number> {
|
|
305
|
+
const result = await sandboxWriteFiles(client, { sandboxId, files, orgId });
|
|
306
|
+
return result.filesWritten;
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
async readFile(path: string): Promise<ReadableStream<Uint8Array>> {
|
|
310
|
+
return sandboxReadFile(client, { sandboxId, path, orgId });
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
async listFiles(path?: string): Promise<SandboxFileInfo[]> {
|
|
314
|
+
const result = await sandboxListFiles(client, { sandboxId, path, orgId });
|
|
315
|
+
return result.files;
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
async mkDir(path: string, recursive?: boolean): Promise<void> {
|
|
319
|
+
await sandboxMkDir(client, { sandboxId, path, recursive, orgId });
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
async rmFile(path: string): Promise<void> {
|
|
323
|
+
await sandboxRmFile(client, { sandboxId, path, orgId });
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
async rmDir(path: string, recursive?: boolean): Promise<void> {
|
|
327
|
+
await sandboxRmDir(client, { sandboxId, path, recursive, orgId });
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
async setEnv(env: Record<string, string | null>): Promise<Record<string, string>> {
|
|
331
|
+
const result = await sandboxSetEnv(client, { sandboxId, env, orgId });
|
|
332
|
+
return result.env;
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
async get(): Promise<SandboxInfo> {
|
|
336
|
+
return sandboxGet(client, { sandboxId, orgId });
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
async pause(): Promise<void> {
|
|
340
|
+
return sandboxPause(client, { sandboxId, orgId });
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
async resume(): Promise<void> {
|
|
344
|
+
return sandboxResume(client, { sandboxId, orgId });
|
|
345
|
+
},
|
|
346
|
+
|
|
347
|
+
async destroy(): Promise<void> {
|
|
348
|
+
return sandboxDestroy(client, { sandboxId, orgId });
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
187
353
|
/**
|
|
188
354
|
* Convenience client for sandbox operations.
|
|
189
355
|
*
|
|
@@ -284,90 +450,13 @@ export class SandboxClient {
|
|
|
284
450
|
orgId: this.#orgId,
|
|
285
451
|
});
|
|
286
452
|
|
|
287
|
-
const sandboxId = response.sandboxId;
|
|
288
|
-
const client = this.#client;
|
|
289
|
-
const orgId = this.#orgId;
|
|
290
|
-
|
|
291
453
|
return {
|
|
292
|
-
id: sandboxId,
|
|
454
|
+
id: response.sandboxId,
|
|
293
455
|
status: response.status,
|
|
294
456
|
stdoutStreamUrl: response.stdoutStreamUrl,
|
|
295
457
|
stderrStreamUrl: response.stderrStreamUrl,
|
|
296
458
|
auditStreamUrl: response.auditStreamUrl,
|
|
297
|
-
|
|
298
|
-
async execute(executeOptions: ExecuteOptions): Promise<Execution> {
|
|
299
|
-
const { pipe, ...coreOptions } = executeOptions;
|
|
300
|
-
|
|
301
|
-
const initialResult = await sandboxExecute(client, {
|
|
302
|
-
sandboxId,
|
|
303
|
-
options: coreOptions,
|
|
304
|
-
orgId,
|
|
305
|
-
signal: coreOptions.signal,
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// If pipe options provided, stream the output to the writable streams
|
|
309
|
-
if (pipe) {
|
|
310
|
-
const streamPromises: Promise<void>[] = [];
|
|
311
|
-
|
|
312
|
-
if (pipe.stdout && initialResult.stdoutStreamUrl) {
|
|
313
|
-
streamPromises.push(
|
|
314
|
-
pipeStreamToWritable(
|
|
315
|
-
initialResult.stdoutStreamUrl,
|
|
316
|
-
pipe.stdout,
|
|
317
|
-
coreOptions.signal
|
|
318
|
-
)
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
if (pipe.stderr && initialResult.stderrStreamUrl) {
|
|
322
|
-
streamPromises.push(
|
|
323
|
-
pipeStreamToWritable(
|
|
324
|
-
initialResult.stderrStreamUrl,
|
|
325
|
-
pipe.stderr,
|
|
326
|
-
coreOptions.signal
|
|
327
|
-
)
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Wait for all streams to complete
|
|
332
|
-
if (streamPromises.length > 0) {
|
|
333
|
-
await Promise.all(streamPromises);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Wait for execution to complete and get final result with exit code
|
|
338
|
-
const finalResult = await waitForExecution(
|
|
339
|
-
client,
|
|
340
|
-
initialResult.executionId,
|
|
341
|
-
orgId,
|
|
342
|
-
coreOptions.signal
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
return {
|
|
346
|
-
executionId: finalResult.executionId,
|
|
347
|
-
status: finalResult.status,
|
|
348
|
-
exitCode: finalResult.exitCode,
|
|
349
|
-
durationMs: finalResult.durationMs,
|
|
350
|
-
stdoutStreamUrl: initialResult.stdoutStreamUrl,
|
|
351
|
-
stderrStreamUrl: initialResult.stderrStreamUrl,
|
|
352
|
-
};
|
|
353
|
-
},
|
|
354
|
-
|
|
355
|
-
async writeFiles(files: FileToWrite[]): Promise<number> {
|
|
356
|
-
const result = await sandboxWriteFiles(client, { sandboxId, files, orgId });
|
|
357
|
-
return result.filesWritten;
|
|
358
|
-
},
|
|
359
|
-
|
|
360
|
-
async readFile(path: string): Promise<ReadableStream<Uint8Array>> {
|
|
361
|
-
return sandboxReadFile(client, { sandboxId, path, orgId });
|
|
362
|
-
},
|
|
363
|
-
|
|
364
|
-
async get(): Promise<SandboxInfo> {
|
|
365
|
-
return sandboxGet(client, { sandboxId, orgId });
|
|
366
|
-
},
|
|
367
|
-
|
|
368
|
-
async destroy(): Promise<void> {
|
|
369
|
-
return sandboxDestroy(client, { sandboxId, orgId });
|
|
370
|
-
},
|
|
459
|
+
...createSandboxInstanceMethods(this.#client, response.sandboxId, this.#orgId),
|
|
371
460
|
};
|
|
372
461
|
}
|
|
373
462
|
|
|
@@ -432,4 +521,46 @@ export class SandboxClient {
|
|
|
432
521
|
signal,
|
|
433
522
|
});
|
|
434
523
|
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Get a full sandbox instance for an existing sandbox by ID.
|
|
527
|
+
*
|
|
528
|
+
* Unlike `get()` which returns read-only metadata, `connect()` returns
|
|
529
|
+
* a `SandboxInstance` with `execute()`, `writeFiles()`, and all other
|
|
530
|
+
* interaction methods — allowing you to resume working with a sandbox
|
|
531
|
+
* using just its ID.
|
|
532
|
+
*
|
|
533
|
+
* @param sandboxId - The sandbox ID to connect to
|
|
534
|
+
* @returns A sandbox instance with all interaction methods
|
|
535
|
+
*/
|
|
536
|
+
async connect(sandboxId: string): Promise<SandboxInstance> {
|
|
537
|
+
const info = await sandboxGet(this.#client, { sandboxId, orgId: this.#orgId });
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
id: info.sandboxId,
|
|
541
|
+
status: info.status,
|
|
542
|
+
stdoutStreamUrl: info.stdoutStreamUrl,
|
|
543
|
+
stderrStreamUrl: info.stderrStreamUrl,
|
|
544
|
+
auditStreamUrl: info.auditStreamUrl,
|
|
545
|
+
...createSandboxInstanceMethods(this.#client, info.sandboxId, this.#orgId),
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Pause a running sandbox, creating a checkpoint of its current state
|
|
551
|
+
*
|
|
552
|
+
* @param sandboxId - The sandbox ID to pause
|
|
553
|
+
*/
|
|
554
|
+
async pause(sandboxId: string): Promise<void> {
|
|
555
|
+
return sandboxPause(this.#client, { sandboxId, orgId: this.#orgId });
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Resume a paused or evacuated sandbox from its checkpoint
|
|
560
|
+
*
|
|
561
|
+
* @param sandboxId - The sandbox ID to resume
|
|
562
|
+
*/
|
|
563
|
+
async resume(sandboxId: string): Promise<void> {
|
|
564
|
+
return sandboxResume(this.#client, { sandboxId, orgId: this.#orgId });
|
|
565
|
+
}
|
|
435
566
|
}
|
|
@@ -25,7 +25,7 @@ export async function sandboxPause(client: APIClient, params: SandboxPauseParams
|
|
|
25
25
|
queryParams.set('orgId', orgId);
|
|
26
26
|
}
|
|
27
27
|
const queryString = queryParams.toString();
|
|
28
|
-
const url = `/sandbox/${sandboxId}/pause${queryString ? `?${queryString}` : ''}`;
|
|
28
|
+
const url = `/sandbox/${encodeURIComponent(sandboxId)}/pause${queryString ? `?${queryString}` : ''}`;
|
|
29
29
|
|
|
30
30
|
const resp = await client.post<z.infer<typeof PauseResponseSchema>>(
|
|
31
31
|
url,
|
|
@@ -339,11 +339,57 @@ export const SandboxSchema = z.object({
|
|
|
339
339
|
readFile: z
|
|
340
340
|
.custom<(path: string) => Promise<ReadableStream<Uint8Array>>>()
|
|
341
341
|
.describe('Read a file from the sandbox workspace.'),
|
|
342
|
+
/** List files in the sandbox workspace. */
|
|
343
|
+
listFiles: z
|
|
344
|
+
.custom<(path?: string) => Promise<SandboxFileInfo[]>>()
|
|
345
|
+
.describe('List files in the sandbox workspace.'),
|
|
346
|
+
/** Create a directory in the sandbox workspace. */
|
|
347
|
+
mkDir: z
|
|
348
|
+
.custom<(path: string, recursive?: boolean) => Promise<void>>()
|
|
349
|
+
.describe('Create a directory in the sandbox workspace.'),
|
|
350
|
+
/** Remove a file from the sandbox workspace. */
|
|
351
|
+
rmFile: z
|
|
352
|
+
.custom<(path: string) => Promise<void>>()
|
|
353
|
+
.describe('Remove a file from the sandbox workspace.'),
|
|
354
|
+
/** Remove a directory from the sandbox workspace. */
|
|
355
|
+
rmDir: z
|
|
356
|
+
.custom<(path: string, recursive?: boolean) => Promise<void>>()
|
|
357
|
+
.describe('Remove a directory from the sandbox workspace.'),
|
|
358
|
+
/** Set environment variables on the sandbox. Pass null to delete a variable. */
|
|
359
|
+
setEnv: z
|
|
360
|
+
.custom<(env: Record<string, string | null>) => Promise<Record<string, string>>>()
|
|
361
|
+
.describe('Set environment variables on the sandbox. Pass null to delete a variable.'),
|
|
362
|
+
/** Pause the sandbox, creating a checkpoint of its current state. */
|
|
363
|
+
pause: z
|
|
364
|
+
.custom<() => Promise<void>>()
|
|
365
|
+
.describe('Pause the sandbox, creating a checkpoint of its current state.'),
|
|
366
|
+
/** Resume the sandbox from a paused or evacuated state. */
|
|
367
|
+
resume: z
|
|
368
|
+
.custom<() => Promise<void>>()
|
|
369
|
+
.describe('Resume the sandbox from a paused or evacuated state.'),
|
|
342
370
|
/** Destroy the sandbox */
|
|
343
371
|
destroy: z.custom<() => Promise<void>>().describe('Destroy the sandbox'),
|
|
344
372
|
});
|
|
345
373
|
export type Sandbox = z.infer<typeof SandboxSchema>;
|
|
346
374
|
|
|
375
|
+
/**
|
|
376
|
+
* File information returned by sandbox file operations.
|
|
377
|
+
* NOTE: This interface is structurally identical to FileInfo in ./files.ts.
|
|
378
|
+
* It is duplicated here to avoid circular type imports. Keep these in sync.
|
|
379
|
+
*/
|
|
380
|
+
export interface SandboxFileInfo {
|
|
381
|
+
/** File path relative to the listed directory */
|
|
382
|
+
path: string;
|
|
383
|
+
/** File size in bytes */
|
|
384
|
+
size: number;
|
|
385
|
+
/** Whether the entry is a directory */
|
|
386
|
+
isDir: boolean;
|
|
387
|
+
/** Unix permissions as octal string (e.g., "0644") */
|
|
388
|
+
mode: string;
|
|
389
|
+
/** Modification time in RFC3339 format */
|
|
390
|
+
modTime: string;
|
|
391
|
+
}
|
|
392
|
+
|
|
347
393
|
/** Information about a user who created the sandbox */
|
|
348
394
|
export const SandboxUserInfoSchema = z.object({
|
|
349
395
|
/** User ID */
|
|
@@ -785,9 +831,15 @@ export type SandboxRunResult = z.infer<typeof SandboxRunResultSchema>;
|
|
|
785
831
|
export interface SandboxService {
|
|
786
832
|
run(options: SandboxRunOptions): Promise<SandboxRunResult>;
|
|
787
833
|
create(options?: SandboxCreateOptions): Promise<Sandbox>;
|
|
834
|
+
/** Get a full Sandbox instance for an existing sandbox by ID. */
|
|
835
|
+
connect(sandboxId: string): Promise<Sandbox>;
|
|
788
836
|
get(sandboxId: string): Promise<SandboxInfo>;
|
|
789
837
|
list(params?: ListSandboxesParams): Promise<ListSandboxesResponse>;
|
|
790
838
|
destroy(sandboxId: string): Promise<void>;
|
|
839
|
+
/** Pause a running sandbox, creating a checkpoint of its current state. */
|
|
840
|
+
pause(sandboxId: string): Promise<void>;
|
|
841
|
+
/** Resume a paused or evacuated sandbox from its checkpoint. */
|
|
842
|
+
resume(sandboxId: string): Promise<void>;
|
|
791
843
|
snapshot: SnapshotService;
|
|
792
844
|
}
|
|
793
845
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type APIClient } from '../api.ts';
|
|
3
|
+
import { StreamResponseError } from './util.ts';
|
|
4
|
+
|
|
5
|
+
// --- Response schemas matching Pulse format ---
|
|
6
|
+
|
|
7
|
+
const DeleteStreamResponseSchema = z.discriminatedUnion('success', [
|
|
8
|
+
z.object({
|
|
9
|
+
success: z.literal<false>(false),
|
|
10
|
+
message: z.string().optional(),
|
|
11
|
+
}),
|
|
12
|
+
z.object({
|
|
13
|
+
success: z.literal<true>(true),
|
|
14
|
+
}),
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
type DeleteStreamResponse = z.infer<typeof DeleteStreamResponseSchema>;
|
|
18
|
+
|
|
19
|
+
const DeleteNamespaceResponseSchema = z.discriminatedUnion('success', [
|
|
20
|
+
z.object({
|
|
21
|
+
success: z.literal<false>(false),
|
|
22
|
+
message: z.string().optional(),
|
|
23
|
+
}),
|
|
24
|
+
z.object({
|
|
25
|
+
success: z.literal<true>(true),
|
|
26
|
+
deleted: z.number(),
|
|
27
|
+
}),
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
type DeleteNamespaceResponse = z.infer<typeof DeleteNamespaceResponseSchema>;
|
|
31
|
+
|
|
32
|
+
// --- Return types ---
|
|
33
|
+
|
|
34
|
+
export interface StreamDeleteNamespaceResult {
|
|
35
|
+
deleted: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// --- Functions ---
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Delete a single stream by ID.
|
|
42
|
+
*
|
|
43
|
+
* @param client - The API client configured for Pulse
|
|
44
|
+
* @param id - The stream ID to delete
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* await streamDelete(client, 'strm_abc123');
|
|
48
|
+
*/
|
|
49
|
+
export async function streamDelete(client: APIClient, id: string): Promise<void> {
|
|
50
|
+
const resp = await client.delete<DeleteStreamResponse>(
|
|
51
|
+
`/${encodeURIComponent(id)}`,
|
|
52
|
+
DeleteStreamResponseSchema
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (resp.success) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
throw new StreamResponseError({ message: resp.message });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Delete all streams in a namespace (soft delete).
|
|
64
|
+
*
|
|
65
|
+
* @param client - The API client configured for Pulse
|
|
66
|
+
* @param name - The namespace name to delete
|
|
67
|
+
* @returns The number of streams that were deleted
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const result = await streamDeleteNamespace(client, 'old-logs');
|
|
71
|
+
* console.log(`Deleted ${result.deleted} streams`);
|
|
72
|
+
*/
|
|
73
|
+
export async function streamDeleteNamespace(
|
|
74
|
+
client: APIClient,
|
|
75
|
+
name: string
|
|
76
|
+
): Promise<StreamDeleteNamespaceResult> {
|
|
77
|
+
const resp = await client.delete<DeleteNamespaceResponse>(
|
|
78
|
+
`/namespace/${encodeURIComponent(name)}`,
|
|
79
|
+
DeleteNamespaceResponseSchema
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
if (resp.success) {
|
|
83
|
+
return { deleted: resp.deleted };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
throw new StreamResponseError({ message: resp.message });
|
|
87
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type APIClient } from '../api.ts';
|
|
3
|
+
import { StreamResponseError } from './util.ts';
|
|
4
|
+
|
|
5
|
+
// --- Schemas ---
|
|
6
|
+
|
|
7
|
+
export const NamespaceInfoSchema = z.object({
|
|
8
|
+
name: z.string().describe('the namespace name'),
|
|
9
|
+
count: z.number().describe('number of streams in this namespace'),
|
|
10
|
+
total_size: z.number().describe('total size in bytes across all streams'),
|
|
11
|
+
created_at: z.string().describe('ISO 8601 timestamp of the earliest stream'),
|
|
12
|
+
last_used_at: z.string().describe('ISO 8601 timestamp of the most recent activity'),
|
|
13
|
+
internal: z.boolean().describe('whether this namespace contains internal/system streams'),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type NamespaceInfo = z.infer<typeof NamespaceInfoSchema>;
|
|
17
|
+
|
|
18
|
+
// Response schema matching Pulse's format (NO data wrapper)
|
|
19
|
+
const ListNamespacesResponseSchema = z.discriminatedUnion('success', [
|
|
20
|
+
z.object({
|
|
21
|
+
success: z.literal<false>(false),
|
|
22
|
+
message: z.string().optional(),
|
|
23
|
+
}),
|
|
24
|
+
z.object({
|
|
25
|
+
success: z.literal<true>(true),
|
|
26
|
+
namespaces: z.array(NamespaceInfoSchema),
|
|
27
|
+
total: z.number(),
|
|
28
|
+
}),
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
type ListNamespacesResponse = z.infer<typeof ListNamespacesResponseSchema>;
|
|
32
|
+
|
|
33
|
+
export const StreamNamespaceEntrySchema = z.object({
|
|
34
|
+
id: z.string().describe('the stream entry id'),
|
|
35
|
+
name: z.string().describe('the stream namespace name'),
|
|
36
|
+
created_at: z.string().nullable().describe('ISO 8601 creation timestamp'),
|
|
37
|
+
updated_at: z.string().nullable().describe('ISO 8601 last update timestamp'),
|
|
38
|
+
org_id: z.string().describe('the organization id'),
|
|
39
|
+
project_id: z.string().nullable().describe('the project id'),
|
|
40
|
+
chunks: z.number().describe('number of chunks'),
|
|
41
|
+
completed: z.boolean().describe('whether the stream upload is completed'),
|
|
42
|
+
size_bytes: z.number().describe('size in bytes'),
|
|
43
|
+
started_at: z.string().nullable().describe('ISO 8601 stream start timestamp'),
|
|
44
|
+
ended_at: z.string().nullable().describe('ISO 8601 stream end timestamp'),
|
|
45
|
+
headers: z.record(z.string(), z.string()).nullable().optional().describe('stream headers'),
|
|
46
|
+
metadata: z.record(z.string(), z.string()).nullable().optional().describe('stream metadata'),
|
|
47
|
+
expires_at: z.string().nullable().describe('ISO 8601 expiration timestamp or null'),
|
|
48
|
+
url: z.string().describe('public URL to access the stream'),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export type StreamNamespaceEntry = z.infer<typeof StreamNamespaceEntrySchema>;
|
|
52
|
+
|
|
53
|
+
const GetNamespaceResponseSchema = z.discriminatedUnion('success', [
|
|
54
|
+
z.object({
|
|
55
|
+
success: z.literal<false>(false),
|
|
56
|
+
message: z.string().optional(),
|
|
57
|
+
}),
|
|
58
|
+
z.object({
|
|
59
|
+
success: z.literal<true>(true),
|
|
60
|
+
name: z.string(),
|
|
61
|
+
entries: z.array(StreamNamespaceEntrySchema),
|
|
62
|
+
total: z.number(),
|
|
63
|
+
total_size: z.number(),
|
|
64
|
+
}),
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
type GetNamespaceResponse = z.infer<typeof GetNamespaceResponseSchema>;
|
|
68
|
+
|
|
69
|
+
// --- Options ---
|
|
70
|
+
|
|
71
|
+
export interface StreamListNamespacesOptions {
|
|
72
|
+
limit?: number;
|
|
73
|
+
offset?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface StreamGetNamespaceOptions {
|
|
77
|
+
limit?: number;
|
|
78
|
+
offset?: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// --- Return types ---
|
|
82
|
+
|
|
83
|
+
export interface StreamNamespacesResult {
|
|
84
|
+
namespaces: NamespaceInfo[];
|
|
85
|
+
total: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface StreamNamespaceResult {
|
|
89
|
+
name: string;
|
|
90
|
+
entries: StreamNamespaceEntry[];
|
|
91
|
+
total: number;
|
|
92
|
+
totalSize: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// --- Functions ---
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* List stream namespaces (aggregated view).
|
|
99
|
+
* Each namespace groups streams by name, showing count, total size, and timestamps.
|
|
100
|
+
*
|
|
101
|
+
* @param client - The API client configured for Pulse
|
|
102
|
+
* @param options - Pagination options
|
|
103
|
+
* @returns Aggregated namespace list with total count
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const result = await streamListNamespaces(client, { limit: 50 });
|
|
107
|
+
* console.log(`Found ${result.total} namespaces`);
|
|
108
|
+
*/
|
|
109
|
+
export async function streamListNamespaces(
|
|
110
|
+
client: APIClient,
|
|
111
|
+
options: StreamListNamespacesOptions = {}
|
|
112
|
+
): Promise<StreamNamespacesResult> {
|
|
113
|
+
const resp = await client.post<ListNamespacesResponse>(
|
|
114
|
+
'/namespaces',
|
|
115
|
+
{ limit: options.limit, offset: options.offset },
|
|
116
|
+
ListNamespacesResponseSchema
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (resp.success) {
|
|
120
|
+
return { namespaces: resp.namespaces, total: resp.total };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
throw new StreamResponseError({ message: resp.message });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get entries within a specific stream namespace.
|
|
128
|
+
* Returns full detail for each stream entry in the namespace.
|
|
129
|
+
*
|
|
130
|
+
* @param client - The API client configured for Pulse
|
|
131
|
+
* @param name - The namespace name
|
|
132
|
+
* @param options - Pagination options
|
|
133
|
+
* @returns Namespace entries with total count and size
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* const result = await streamGetNamespace(client, 'agent-logs', { limit: 100 });
|
|
137
|
+
* console.log(`${result.total} entries, ${result.totalSize} bytes total`);
|
|
138
|
+
*/
|
|
139
|
+
export async function streamGetNamespace(
|
|
140
|
+
client: APIClient,
|
|
141
|
+
name: string,
|
|
142
|
+
options: StreamGetNamespaceOptions = {}
|
|
143
|
+
): Promise<StreamNamespaceResult> {
|
|
144
|
+
const resp = await client.post<GetNamespaceResponse>(
|
|
145
|
+
`/namespace/${encodeURIComponent(name)}/info`,
|
|
146
|
+
{ limit: options.limit, offset: options.offset },
|
|
147
|
+
GetNamespaceResponseSchema
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
if (resp.success) {
|
|
151
|
+
return {
|
|
152
|
+
name: resp.name,
|
|
153
|
+
entries: resp.entries,
|
|
154
|
+
total: resp.total,
|
|
155
|
+
totalSize: resp.total_size,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
throw new StreamResponseError({ message: resp.message });
|
|
160
|
+
}
|