@agentuity/core 2.0.12 → 2.0.14
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/coder/client.d.ts +13 -1
- package/dist/services/coder/client.d.ts.map +1 -1
- package/dist/services/coder/client.js +22 -1
- package/dist/services/coder/client.js.map +1 -1
- package/dist/services/coder/types.d.ts +73 -0
- package/dist/services/coder/types.d.ts.map +1 -1
- package/dist/services/coder/types.js +83 -1
- package/dist/services/coder/types.js.map +1 -1
- package/dist/services/coder/workspaces.d.ts +11 -1
- package/dist/services/coder/workspaces.d.ts.map +1 -1
- package/dist/services/coder/workspaces.js +34 -1
- package/dist/services/coder/workspaces.js.map +1 -1
- package/dist/services/sandbox/api-reference.js +1 -1
- package/dist/services/sandbox/api-reference.js.map +1 -1
- package/dist/services/sandbox/getStatus.d.ts +1 -0
- package/dist/services/sandbox/getStatus.d.ts.map +1 -1
- package/dist/services/sandbox/getStatus.js +3 -2
- package/dist/services/sandbox/getStatus.js.map +1 -1
- package/dist/services/sandbox/run.d.ts +2 -2
- package/dist/services/sandbox/run.d.ts.map +1 -1
- package/dist/services/sandbox/run.js +103 -3
- package/dist/services/sandbox/run.js.map +1 -1
- package/dist/services/sandbox/types.d.ts +3 -2
- package/dist/services/sandbox/types.d.ts.map +1 -1
- package/dist/services/sandbox/types.js +2 -0
- package/dist/services/sandbox/types.js.map +1 -1
- package/package.json +2 -2
- package/src/services/coder/client.ts +34 -0
- package/src/services/coder/types.ts +94 -1
- package/src/services/coder/workspaces.ts +74 -0
- package/src/services/sandbox/api-reference.ts +1 -1
- package/src/services/sandbox/getStatus.ts +4 -2
- package/src/services/sandbox/run.ts +156 -3
- package/src/services/sandbox/types.ts +2 -0
|
@@ -14,6 +14,7 @@ import { getServiceUrls } from '../config.ts';
|
|
|
14
14
|
|
|
15
15
|
const timingLogsEnabled = false;
|
|
16
16
|
const EXECUTION_WAIT_DURATION = '5m';
|
|
17
|
+
const EXIT_CODE_FAST_WAIT_DURATION = '250ms';
|
|
17
18
|
const TERMINAL_EXECUTION_STATUSES = new Set(['completed', 'failed', 'timeout', 'cancelled']);
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -207,8 +208,9 @@ export async function sandboxRun(
|
|
|
207
208
|
createResponse.executionId,
|
|
208
209
|
streamPromises.length
|
|
209
210
|
);
|
|
210
|
-
const
|
|
211
|
+
const completionPromise = waitForRunCompletion(
|
|
211
212
|
client,
|
|
213
|
+
sandboxId,
|
|
212
214
|
createResponse.executionId,
|
|
213
215
|
orgId,
|
|
214
216
|
signal,
|
|
@@ -217,8 +219,8 @@ export async function sandboxRun(
|
|
|
217
219
|
);
|
|
218
220
|
|
|
219
221
|
finalExecution = signal
|
|
220
|
-
? await raceWithAbort(
|
|
221
|
-
: await
|
|
222
|
+
? await raceWithAbort(completionPromise, signal, abortController, sandboxId)
|
|
223
|
+
: await completionPromise;
|
|
222
224
|
await waitForStreamsToDrain(streamPromises, signal, abortController, sandboxId);
|
|
223
225
|
} else {
|
|
224
226
|
logger?.debug(
|
|
@@ -244,7 +246,39 @@ export async function sandboxRun(
|
|
|
244
246
|
// drain + lifecycle propagation delay.
|
|
245
247
|
let exitCode = finalExecution?.exitCode ?? 0;
|
|
246
248
|
const statusPollStart = Date.now();
|
|
249
|
+
let shouldWaitForSandboxStatus = finalExecution?.exitCode == null;
|
|
250
|
+
let sandboxStatusReconciled = false;
|
|
247
251
|
if (finalExecution?.exitCode == null) {
|
|
252
|
+
if (createResponse.executionId && finalExecution?.status === 'completed') {
|
|
253
|
+
try {
|
|
254
|
+
const execution = await executionGet(client, {
|
|
255
|
+
executionId: createResponse.executionId,
|
|
256
|
+
orgId,
|
|
257
|
+
wait: EXIT_CODE_FAST_WAIT_DURATION,
|
|
258
|
+
signal,
|
|
259
|
+
});
|
|
260
|
+
if (execution.exitCode != null) {
|
|
261
|
+
exitCode = execution.exitCode;
|
|
262
|
+
finalExecution.exitCode = execution.exitCode;
|
|
263
|
+
shouldWaitForSandboxStatus = false;
|
|
264
|
+
logger?.debug(
|
|
265
|
+
'[run] exit code %d found from fast execution retry (+%dms)',
|
|
266
|
+
exitCode,
|
|
267
|
+
Date.now() - statusPollStart
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
} catch (err) {
|
|
271
|
+
if (!(err instanceof DOMException && err.name === 'AbortError')) {
|
|
272
|
+
logger?.debug(
|
|
273
|
+
'[run] fast execution exit code retry failed (+%dms): %s',
|
|
274
|
+
Date.now() - statusPollStart,
|
|
275
|
+
err
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (shouldWaitForSandboxStatus) {
|
|
248
282
|
try {
|
|
249
283
|
const sandboxStatus = await sandboxGetStatus(client, {
|
|
250
284
|
sandboxId,
|
|
@@ -254,6 +288,7 @@ export async function sandboxRun(
|
|
|
254
288
|
});
|
|
255
289
|
if (sandboxStatus.exitCode != null) {
|
|
256
290
|
exitCode = sandboxStatus.exitCode;
|
|
291
|
+
sandboxStatusReconciled = true;
|
|
257
292
|
logger?.debug(
|
|
258
293
|
'[run] exit code %d found after server-side wait (+%dms)',
|
|
259
294
|
exitCode,
|
|
@@ -261,11 +296,13 @@ export async function sandboxRun(
|
|
|
261
296
|
);
|
|
262
297
|
} else if (sandboxStatus.status === 'failed') {
|
|
263
298
|
exitCode = 1;
|
|
299
|
+
sandboxStatusReconciled = true;
|
|
264
300
|
logger?.debug(
|
|
265
301
|
'[run] sandbox failed after server-side wait (+%dms)',
|
|
266
302
|
Date.now() - statusPollStart
|
|
267
303
|
);
|
|
268
304
|
} else if (sandboxStatus.status === 'terminated') {
|
|
305
|
+
sandboxStatusReconciled = true;
|
|
269
306
|
logger?.debug(
|
|
270
307
|
'[run] sandbox terminated without exit code after server-side wait (+%dms)',
|
|
271
308
|
Date.now() - statusPollStart
|
|
@@ -287,6 +324,18 @@ export async function sandboxRun(
|
|
|
287
324
|
}
|
|
288
325
|
}
|
|
289
326
|
}
|
|
327
|
+
if (
|
|
328
|
+
finalExecution &&
|
|
329
|
+
finalExecution?.exitCode == null &&
|
|
330
|
+
finalExecution?.status !== 'completed' &&
|
|
331
|
+
!sandboxStatusReconciled
|
|
332
|
+
) {
|
|
333
|
+
exitCode = 1;
|
|
334
|
+
logger?.debug(
|
|
335
|
+
'[run] using fallback exit code 1 for terminal status=%s after sandbox status reconciliation failed',
|
|
336
|
+
finalExecution?.status
|
|
337
|
+
);
|
|
338
|
+
}
|
|
290
339
|
if (exitCode === 0) {
|
|
291
340
|
if (finalExecution?.exitCode != null) {
|
|
292
341
|
logger?.debug('[run] using execution exit code 0 from long-poll result');
|
|
@@ -327,6 +376,60 @@ export async function sandboxRun(
|
|
|
327
376
|
}
|
|
328
377
|
}
|
|
329
378
|
|
|
379
|
+
async function waitForRunCompletion(
|
|
380
|
+
client: APIClient,
|
|
381
|
+
sandboxId: string,
|
|
382
|
+
executionId: string,
|
|
383
|
+
orgId: string | undefined,
|
|
384
|
+
signal: AbortSignal | undefined,
|
|
385
|
+
logger: Logger | undefined,
|
|
386
|
+
started: number
|
|
387
|
+
): Promise<{ exitCode?: number; status: string }> {
|
|
388
|
+
const completionAbortController = new AbortController();
|
|
389
|
+
let onAbort: (() => void) | undefined;
|
|
390
|
+
if (signal) {
|
|
391
|
+
onAbort = () => completionAbortController.abort(signal.reason);
|
|
392
|
+
if (signal.aborted) {
|
|
393
|
+
onAbort();
|
|
394
|
+
} else {
|
|
395
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
const completionSignal = completionAbortController.signal;
|
|
401
|
+
const executionPromise = waitForExecutionCompletion(
|
|
402
|
+
client,
|
|
403
|
+
executionId,
|
|
404
|
+
orgId,
|
|
405
|
+
completionSignal,
|
|
406
|
+
logger,
|
|
407
|
+
started
|
|
408
|
+
);
|
|
409
|
+
const statusPromise = waitForSandboxStatusCompletion(
|
|
410
|
+
client,
|
|
411
|
+
sandboxId,
|
|
412
|
+
orgId,
|
|
413
|
+
completionSignal,
|
|
414
|
+
logger,
|
|
415
|
+
started
|
|
416
|
+
).catch((err) => {
|
|
417
|
+
if (completionSignal.aborted) {
|
|
418
|
+
throw err;
|
|
419
|
+
}
|
|
420
|
+
logger?.debug('[run] sandbox status completion wait failed: %s', err);
|
|
421
|
+
return new Promise<never>(() => {});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
const result = await Promise.race([executionPromise, statusPromise]);
|
|
425
|
+
return result;
|
|
426
|
+
} finally {
|
|
427
|
+
if (onAbort && signal) {
|
|
428
|
+
signal.removeEventListener('abort', onAbort);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
330
433
|
async function waitForExecutionCompletion(
|
|
331
434
|
client: APIClient,
|
|
332
435
|
executionId: string,
|
|
@@ -363,6 +466,56 @@ async function waitForExecutionCompletion(
|
|
|
363
466
|
}
|
|
364
467
|
}
|
|
365
468
|
|
|
469
|
+
async function waitForSandboxStatusCompletion(
|
|
470
|
+
client: APIClient,
|
|
471
|
+
sandboxId: string,
|
|
472
|
+
orgId: string | undefined,
|
|
473
|
+
signal: AbortSignal | undefined,
|
|
474
|
+
logger: Logger | undefined,
|
|
475
|
+
started: number
|
|
476
|
+
): Promise<{ exitCode?: number; status: string }> {
|
|
477
|
+
while (true) {
|
|
478
|
+
if (signal?.aborted) {
|
|
479
|
+
throw new DOMException('Aborted', 'AbortError');
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const result = await sandboxGetStatus(client, {
|
|
483
|
+
sandboxId,
|
|
484
|
+
orgId,
|
|
485
|
+
waitForStatus: ['idle', 'terminated', 'failed'],
|
|
486
|
+
waitMs: 300000,
|
|
487
|
+
signal,
|
|
488
|
+
});
|
|
489
|
+
logger?.debug(
|
|
490
|
+
'[run] sandbox status wait: sandbox=%s status=%s exit=%s +%dms',
|
|
491
|
+
sandboxId,
|
|
492
|
+
result.status,
|
|
493
|
+
result.exitCode ?? 'undefined',
|
|
494
|
+
Date.now() - started
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
if (result.exitCode != null) {
|
|
498
|
+
return {
|
|
499
|
+
exitCode: result.exitCode,
|
|
500
|
+
status: 'completed',
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
if (result.status === 'failed') {
|
|
504
|
+
return {
|
|
505
|
+
exitCode: 1,
|
|
506
|
+
status: 'failed',
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
if (result.status === 'terminated') {
|
|
510
|
+
return {
|
|
511
|
+
status: 'completed',
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
366
519
|
async function waitForStreamsToDrain(
|
|
367
520
|
streamPromises: Promise<void>[],
|
|
368
521
|
signal: AbortSignal | undefined,
|
|
@@ -843,6 +843,8 @@ export const SnapshotCreateOptionsSchema = z.object({
|
|
|
843
843
|
tag: z.string().optional().describe('Tag for the snapshot (defaults to "latest")'),
|
|
844
844
|
/** Make the snapshot publicly accessible */
|
|
845
845
|
public: z.boolean().optional().describe('Make the snapshot publicly accessible'),
|
|
846
|
+
/** Organization ID to use for CLI-authenticated requests */
|
|
847
|
+
orgId: z.string().optional().describe('Organization ID for CLI-authenticated requests'),
|
|
846
848
|
});
|
|
847
849
|
export type SnapshotCreateOptions = z.infer<typeof SnapshotCreateOptionsSchema>;
|
|
848
850
|
|