@agentuity/runtime 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.
@@ -1,13 +1,21 @@
1
1
  import {
2
2
  APIClient,
3
+ executionGet,
3
4
  sandboxCreate,
4
5
  sandboxDestroy,
5
6
  sandboxExecute,
6
7
  sandboxGet,
7
8
  sandboxList,
9
+ sandboxListFiles,
10
+ sandboxMkDir,
11
+ sandboxPause,
12
+ sandboxReadFile,
13
+ sandboxResume,
14
+ sandboxRmDir,
15
+ sandboxRmFile,
8
16
  sandboxRun,
17
+ sandboxSetEnv,
9
18
  sandboxWriteFiles,
10
- sandboxReadFile,
11
19
  snapshotCreate,
12
20
  snapshotGet,
13
21
  snapshotList,
@@ -17,6 +25,7 @@ import {
17
25
  import type {
18
26
  SandboxService,
19
27
  Sandbox,
28
+ SandboxFileInfo,
20
29
  SandboxInfo,
21
30
  SandboxCreateOptions,
22
31
  SandboxRunOptions,
@@ -62,12 +71,9 @@ async function withSpan<T>(
62
71
  }
63
72
  }
64
73
 
65
- function createStreamReader(id: string | undefined, baseUrl: string): StreamReader {
66
- const streamId = id ?? '';
67
- const url = streamId ? `${baseUrl}/${streamId}` : '';
68
-
74
+ function buildStreamReader(id: string, url: string): StreamReader {
69
75
  return {
70
- id: streamId,
76
+ id,
71
77
  url,
72
78
  readonly: true as const,
73
79
  getReader(): ReadableStream<Uint8Array> {
@@ -102,24 +108,30 @@ function createStreamReader(id: string | undefined, baseUrl: string): StreamRead
102
108
  };
103
109
  }
104
110
 
105
- function createSandboxInstance(
106
- client: APIClient,
107
- sandboxId: string,
108
- status: SandboxStatus,
109
- streamBaseUrl: string,
110
- stdoutStreamId?: string,
111
- stderrStreamId?: string,
112
- auditStreamId?: string
113
- ): Sandbox {
114
- const interleaved = !!(stdoutStreamId && stderrStreamId && stdoutStreamId === stderrStreamId);
115
- return {
116
- id: sandboxId,
117
- status,
118
- stdout: createStreamReader(stdoutStreamId, streamBaseUrl),
119
- stderr: createStreamReader(stderrStreamId, streamBaseUrl),
120
- interleaved,
121
- auditStreamId,
111
+ function createStreamReader(id: string | undefined, baseUrl: string): StreamReader {
112
+ const streamId = id ?? '';
113
+ const url = streamId ? `${baseUrl}/${streamId}` : '';
114
+ return buildStreamReader(streamId, url);
115
+ }
122
116
 
117
+ function createStreamReaderFromUrl(streamUrl: string | undefined): StreamReader {
118
+ const url = streamUrl ?? '';
119
+ if (!url) return buildStreamReader('', '');
120
+ try {
121
+ const pathname = new URL(url).pathname.replace(/\/+$/, '');
122
+ const id = pathname.split('/').pop() ?? '';
123
+ return buildStreamReader(id, url);
124
+ } catch {
125
+ const id = url.split('/').pop() ?? '';
126
+ return buildStreamReader(id, url);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Creates the method implementations shared by all Sandbox instances.
132
+ */
133
+ function createSandboxMethods(client: APIClient, sandboxId: string) {
134
+ return {
123
135
  async execute(options: ExecuteOptions): Promise<Execution> {
124
136
  return withSpan(
125
137
  'agentuity.sandbox.execute',
@@ -127,7 +139,26 @@ function createSandboxInstance(
127
139
  'sandbox.id': sandboxId,
128
140
  'sandbox.command': options.command?.join(' ') ?? '',
129
141
  },
130
- () => sandboxExecute(client, { sandboxId, options, signal: options.signal })
142
+ async () => {
143
+ const initial = await sandboxExecute(client, {
144
+ sandboxId,
145
+ options,
146
+ signal: options.signal,
147
+ });
148
+ // Wait for execution to reach a terminal state via long-polling
149
+ const final = await executionGet(client, {
150
+ executionId: initial.executionId,
151
+ wait: '60s',
152
+ });
153
+ return {
154
+ executionId: final.executionId,
155
+ status: final.status,
156
+ exitCode: final.exitCode,
157
+ durationMs: final.durationMs,
158
+ stdoutStreamUrl: initial.stdoutStreamUrl,
159
+ stderrStreamUrl: initial.stderrStreamUrl,
160
+ };
161
+ }
131
162
  );
132
163
  },
133
164
 
@@ -153,6 +184,72 @@ function createSandboxInstance(
153
184
  );
154
185
  },
155
186
 
187
+ async listFiles(path?: string): Promise<SandboxFileInfo[]> {
188
+ return withSpan(
189
+ 'agentuity.sandbox.listFiles',
190
+ {
191
+ 'sandbox.id': sandboxId,
192
+ 'sandbox.dir.path': path ?? '',
193
+ },
194
+ async () => {
195
+ const result = await sandboxListFiles(client, { sandboxId, path });
196
+ return result.files;
197
+ }
198
+ );
199
+ },
200
+
201
+ async mkDir(path: string, recursive?: boolean): Promise<void> {
202
+ await withSpan(
203
+ 'agentuity.sandbox.mkDir',
204
+ {
205
+ 'sandbox.id': sandboxId,
206
+ 'sandbox.dir.path': path,
207
+ },
208
+ () => sandboxMkDir(client, { sandboxId, path, recursive })
209
+ );
210
+ },
211
+
212
+ async rmFile(path: string): Promise<void> {
213
+ await withSpan(
214
+ 'agentuity.sandbox.rmFile',
215
+ {
216
+ 'sandbox.id': sandboxId,
217
+ 'sandbox.file.path': path,
218
+ },
219
+ () => sandboxRmFile(client, { sandboxId, path })
220
+ );
221
+ },
222
+
223
+ async rmDir(path: string, recursive?: boolean): Promise<void> {
224
+ await withSpan(
225
+ 'agentuity.sandbox.rmDir',
226
+ {
227
+ 'sandbox.id': sandboxId,
228
+ 'sandbox.dir.path': path,
229
+ },
230
+ () => sandboxRmDir(client, { sandboxId, path, recursive })
231
+ );
232
+ },
233
+
234
+ async setEnv(env: Record<string, string | null>): Promise<Record<string, string>> {
235
+ return withSpan('agentuity.sandbox.setEnv', { 'sandbox.id': sandboxId }, async () => {
236
+ const result = await sandboxSetEnv(client, { sandboxId, env });
237
+ return result.env;
238
+ });
239
+ },
240
+
241
+ async pause(): Promise<void> {
242
+ await withSpan('agentuity.sandbox.pause', { 'sandbox.id': sandboxId }, () =>
243
+ sandboxPause(client, { sandboxId })
244
+ );
245
+ },
246
+
247
+ async resume(): Promise<void> {
248
+ await withSpan('agentuity.sandbox.resume', { 'sandbox.id': sandboxId }, () =>
249
+ sandboxResume(client, { sandboxId })
250
+ );
251
+ },
252
+
156
253
  async destroy(): Promise<void> {
157
254
  await withSpan('agentuity.sandbox.destroy', { 'sandbox.id': sandboxId }, () =>
158
255
  sandboxDestroy(client, { sandboxId })
@@ -161,6 +258,49 @@ function createSandboxInstance(
161
258
  };
162
259
  }
163
260
 
261
+ function createSandboxInstance(
262
+ client: APIClient,
263
+ sandboxId: string,
264
+ status: SandboxStatus,
265
+ streamBaseUrl: string,
266
+ stdoutStreamId?: string,
267
+ stderrStreamId?: string,
268
+ auditStreamId?: string
269
+ ): Sandbox {
270
+ const interleaved = !!(stdoutStreamId && stderrStreamId && stdoutStreamId === stderrStreamId);
271
+ return {
272
+ id: sandboxId,
273
+ status,
274
+ stdout: createStreamReader(stdoutStreamId, streamBaseUrl),
275
+ stderr: createStreamReader(stderrStreamId, streamBaseUrl),
276
+ interleaved,
277
+ auditStreamId,
278
+ ...createSandboxMethods(client, sandboxId),
279
+ };
280
+ }
281
+
282
+ function createSandboxInstanceFromInfo(client: APIClient, info: SandboxInfo): Sandbox {
283
+ const stdoutReader = createStreamReaderFromUrl(info.stdoutStreamUrl);
284
+ const stderrReader = createStreamReaderFromUrl(info.stderrStreamUrl);
285
+ const interleaved = !!(
286
+ stdoutReader.id &&
287
+ stderrReader.id &&
288
+ stdoutReader.id === stderrReader.id
289
+ );
290
+ return {
291
+ id: info.sandboxId,
292
+ status: info.status,
293
+ name: info.name,
294
+ description: info.description,
295
+ runtime: info.runtime,
296
+ stdout: stdoutReader,
297
+ stderr: stderrReader,
298
+ interleaved,
299
+ auditStreamId: info.auditStreamId,
300
+ ...createSandboxMethods(client, info.sandboxId),
301
+ };
302
+ }
303
+
164
304
  /**
165
305
  * HTTP implementation of the SnapshotService interface
166
306
  */
@@ -298,9 +438,28 @@ export class HTTPSandboxService implements SandboxService {
298
438
  );
299
439
  }
300
440
 
441
+ async connect(sandboxId: string): Promise<Sandbox> {
442
+ return withSpan('agentuity.sandbox.connect', { 'sandbox.id': sandboxId }, async () => {
443
+ const info = await sandboxGet(this.client, { sandboxId });
444
+ return createSandboxInstanceFromInfo(this.client, info);
445
+ });
446
+ }
447
+
301
448
  async destroy(sandboxId: string): Promise<void> {
302
449
  return withSpan('agentuity.sandbox.destroy', { 'sandbox.id': sandboxId }, () =>
303
450
  sandboxDestroy(this.client, { sandboxId })
304
451
  );
305
452
  }
453
+
454
+ async pause(sandboxId: string): Promise<void> {
455
+ return withSpan('agentuity.sandbox.pause', { 'sandbox.id': sandboxId }, () =>
456
+ sandboxPause(this.client, { sandboxId })
457
+ );
458
+ }
459
+
460
+ async resume(sandboxId: string): Promise<void> {
461
+ return withSpan('agentuity.sandbox.resume', { 'sandbox.id': sandboxId }, () =>
462
+ sandboxResume(this.client, { sandboxId })
463
+ );
464
+ }
306
465
  }