@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.
Files changed (34) hide show
  1. package/dist/services/coder/client.d.ts +13 -1
  2. package/dist/services/coder/client.d.ts.map +1 -1
  3. package/dist/services/coder/client.js +22 -1
  4. package/dist/services/coder/client.js.map +1 -1
  5. package/dist/services/coder/types.d.ts +73 -0
  6. package/dist/services/coder/types.d.ts.map +1 -1
  7. package/dist/services/coder/types.js +83 -1
  8. package/dist/services/coder/types.js.map +1 -1
  9. package/dist/services/coder/workspaces.d.ts +11 -1
  10. package/dist/services/coder/workspaces.d.ts.map +1 -1
  11. package/dist/services/coder/workspaces.js +34 -1
  12. package/dist/services/coder/workspaces.js.map +1 -1
  13. package/dist/services/sandbox/api-reference.js +1 -1
  14. package/dist/services/sandbox/api-reference.js.map +1 -1
  15. package/dist/services/sandbox/getStatus.d.ts +1 -0
  16. package/dist/services/sandbox/getStatus.d.ts.map +1 -1
  17. package/dist/services/sandbox/getStatus.js +3 -2
  18. package/dist/services/sandbox/getStatus.js.map +1 -1
  19. package/dist/services/sandbox/run.d.ts +2 -2
  20. package/dist/services/sandbox/run.d.ts.map +1 -1
  21. package/dist/services/sandbox/run.js +103 -3
  22. package/dist/services/sandbox/run.js.map +1 -1
  23. package/dist/services/sandbox/types.d.ts +3 -2
  24. package/dist/services/sandbox/types.d.ts.map +1 -1
  25. package/dist/services/sandbox/types.js +2 -0
  26. package/dist/services/sandbox/types.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/services/coder/client.ts +34 -0
  29. package/src/services/coder/types.ts +94 -1
  30. package/src/services/coder/workspaces.ts +74 -0
  31. package/src/services/sandbox/api-reference.ts +1 -1
  32. package/src/services/sandbox/getStatus.ts +4 -2
  33. package/src/services/sandbox/run.ts +156 -3
  34. 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 executionPromise = waitForExecutionCompletion(
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(executionPromise, signal, abortController, sandboxId)
221
- : await executionPromise;
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