deepline 0.3.57 → 0.3.58

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.
@@ -199,7 +199,7 @@ export const SDK_RELEASE = {
199
199
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
- version: '0.3.57',
202
+ version: '0.3.58',
203
203
  updateSummary:
204
204
  'Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.',
205
205
  packageCapabilities: {
@@ -311,11 +311,16 @@ async function createOneShotDaytonaSandbox(input: {
311
311
  });
312
312
  }
313
313
 
314
+ type TimedOutDaytonaSandboxReconciliation =
315
+ | { kind: 'started'; sandbox: DaytonaSandbox }
316
+ | { kind: 'deleted' }
317
+ | { kind: 'not_found' };
318
+
314
319
  async function reconcileAndDeleteTimedOutDaytonaSandbox(input: {
315
320
  daytona: DaytonaClient;
316
321
  sandboxName: string;
317
- }): Promise<boolean> {
318
- if (!input.daytona.get) return false;
322
+ }): Promise<TimedOutDaytonaSandboxReconciliation> {
323
+ if (!input.daytona.get) return { kind: 'not_found' };
319
324
  let lastDeleteConflict: unknown = null;
320
325
  for (const delayMs of DAYTONA_TIMED_OUT_CREATE_RECONCILE_DELAYS_MS) {
321
326
  if (delayMs > 0) {
@@ -327,6 +332,14 @@ async function reconcileAndDeleteTimedOutDaytonaSandbox(input: {
327
332
  } catch {
328
333
  continue;
329
334
  }
335
+ // `create` waits only a bounded interval, but the named sandbox may finish
336
+ // the same create transition immediately afterwards. It is already the
337
+ // durable identity associated with this provider operation, so reusing it
338
+ // is safer and faster than attempting a conflicting delete or creating a
339
+ // second sandbox.
340
+ if (sandbox.state === 'started') {
341
+ return { kind: 'started', sandbox };
342
+ }
330
343
  try {
331
344
  await sandbox.delete(30);
332
345
  } catch (error) {
@@ -344,7 +357,7 @@ async function reconcileAndDeleteTimedOutDaytonaSandbox(input: {
344
357
  { cause: error },
345
358
  );
346
359
  }
347
- return true;
360
+ return { kind: 'deleted' };
348
361
  }
349
362
  if (lastDeleteConflict) {
350
363
  throw new Error(
@@ -352,7 +365,7 @@ async function reconcileAndDeleteTimedOutDaytonaSandbox(input: {
352
365
  { cause: lastDeleteConflict },
353
366
  );
354
367
  }
355
- return false;
368
+ return { kind: 'not_found' };
356
369
  }
357
370
 
358
371
  async function createRetriedOneShotDaytonaSandbox(input: {
@@ -402,16 +415,14 @@ async function createRetriedOneShotDaytonaSandbox(input: {
402
415
  // A normal rejected create has no durable provider resource. A timeout
403
416
  // can be ambiguous, so retain its lease until the crash TTL rather than
404
417
  // admitting another sandbox against an unknown provider outcome.
405
- if (reservation && !isDaytonaSandboxStartTimeout(String(error))) {
406
- await input.releaseSandboxCapacity?.(reservation.leaseId);
407
- }
408
- await input.observeCreateCall?.({
409
- type: 'daytona_create_call_failed',
410
- occurredAtMs: Date.now(),
411
- providerAttempt: attempt,
412
- errorClass: daytonaCreateErrorClass(error),
413
- });
414
418
  const message = error instanceof Error ? error.message : String(error);
419
+ const recordCreateFailure = () =>
420
+ input.observeCreateCall?.({
421
+ type: 'daytona_create_call_failed',
422
+ occurredAtMs: Date.now(),
423
+ providerAttempt: attempt,
424
+ errorClass: daytonaCreateErrorClass(error),
425
+ });
415
426
  errors.push(message);
416
427
  input.emitStage('create:attempt_failed', {
417
428
  attempt,
@@ -427,18 +438,49 @@ async function createRetriedOneShotDaytonaSandbox(input: {
427
438
  });
428
439
  const immediateFallbackReason =
429
440
  resolveDaytonaSandboxAcquisitionUnavailableReason([message]);
430
- if (immediateFallbackReason === 'daytona_total_cpu_limit_exceeded') {
431
- throw new DaytonaSandboxAcquisitionUnavailableError(
432
- immediateFallbackReason,
433
- `Daytona sandbox create rejected by the organization CPU limit on provider attempt ${attempt}: ${message}`,
434
- );
435
- }
436
441
  if (isDaytonaSandboxStartTimeout(message)) {
437
- const deleted = await reconcileAndDeleteTimedOutDaytonaSandbox({
438
- daytona: input.daytona,
439
- sandboxName,
440
- });
441
- if (deleted) {
442
+ let reconciliation: TimedOutDaytonaSandboxReconciliation;
443
+ try {
444
+ reconciliation = await reconcileAndDeleteTimedOutDaytonaSandbox({
445
+ daytona: input.daytona,
446
+ sandboxName,
447
+ });
448
+ } catch (reconciliationError) {
449
+ await recordCreateFailure();
450
+ throw reconciliationError;
451
+ }
452
+ if (reconciliation.kind === 'started') {
453
+ const acquiredAt = Date.now();
454
+ try {
455
+ await input.observeCreateCall?.({
456
+ type: 'daytona_create_call_succeeded',
457
+ occurredAtMs: acquiredAt,
458
+ providerAttempt: attempt,
459
+ sandboxId: reconciliation.sandbox.id,
460
+ });
461
+ } catch {
462
+ console.error(
463
+ '[play-runner.daytona.create_lifecycle_event_unrecorded]',
464
+ {
465
+ workflowId: input.context.workflowId ?? null,
466
+ runId: input.context.runId ?? null,
467
+ attempt,
468
+ sandboxId: reconciliation.sandbox.id,
469
+ eventType: 'daytona_create_call_succeeded',
470
+ },
471
+ );
472
+ }
473
+ return {
474
+ sandbox: reconciliation.sandbox,
475
+ attempt,
476
+ attemptElapsedMs: acquiredAt - attemptStartedAt,
477
+ ...(reservation
478
+ ? { sandboxCapacityLeaseId: reservation.leaseId }
479
+ : {}),
480
+ };
481
+ }
482
+ await recordCreateFailure();
483
+ if (reconciliation.kind === 'deleted') {
442
484
  // The provider-confirmed reconciliation means this reservation can
443
485
  // no longer represent a live sandbox. Release before returning the
444
486
  // acquisition-unavailable result so Modal fallback is not blocked
@@ -456,6 +498,16 @@ async function createRetriedOneShotDaytonaSandbox(input: {
456
498
  { cause: error },
457
499
  );
458
500
  }
501
+ if (reservation) {
502
+ await input.releaseSandboxCapacity?.(reservation.leaseId);
503
+ }
504
+ await recordCreateFailure();
505
+ if (immediateFallbackReason === 'daytona_total_cpu_limit_exceeded') {
506
+ throw new DaytonaSandboxAcquisitionUnavailableError(
507
+ immediateFallbackReason,
508
+ `Daytona sandbox create rejected by the organization CPU limit on provider attempt ${attempt}: ${message}`,
509
+ );
510
+ }
459
511
  continue;
460
512
  }
461
513
  // The outcome must be attributed immediately after Daytona acknowledges
package/dist/cli/index.js CHANGED
@@ -1075,7 +1075,7 @@ var SDK_RELEASE = {
1075
1075
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1076
1076
  // getters keep their established compatibility behavior.
1077
1077
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1078
- version: "0.3.57",
1078
+ version: "0.3.58",
1079
1079
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1080
1080
  packageCapabilities: {
1081
1081
  updatePreferences: 1
@@ -1060,7 +1060,7 @@ var SDK_RELEASE = {
1060
1060
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1061
1061
  // getters keep their established compatibility behavior.
1062
1062
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1063
- version: "0.3.57",
1063
+ version: "0.3.58",
1064
1064
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1065
1065
  packageCapabilities: {
1066
1066
  updatePreferences: 1
package/dist/index.js CHANGED
@@ -826,7 +826,7 @@ var SDK_RELEASE = {
826
826
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
827
827
  // getters keep their established compatibility behavior.
828
828
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
829
- version: "0.3.57",
829
+ version: "0.3.58",
830
830
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
831
831
  packageCapabilities: {
832
832
  updatePreferences: 1
package/dist/index.mjs CHANGED
@@ -738,7 +738,7 @@ var SDK_RELEASE = {
738
738
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
739
739
  // getters keep their established compatibility behavior.
740
740
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
741
- version: "0.3.57",
741
+ version: "0.3.58",
742
742
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
743
743
  packageCapabilities: {
744
744
  updatePreferences: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.3.57",
3
+ "version": "0.3.58",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",