deepline 0.2.0 → 0.2.2

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 (32) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +17 -3
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/observability/scheduled-job-errors.ts +95 -0
  4. package/dist/bundling-sources/shared_libs/play-runtime/backend.ts +19 -0
  5. package/dist/bundling-sources/shared_libs/play-runtime/modal-runtime-config.ts +104 -0
  6. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +4 -1
  7. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +177 -10
  8. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-modal-fallback.ts +218 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +26 -7
  10. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +34 -0
  11. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +380 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/index.ts +28 -3
  13. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +240 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +28 -1
  15. package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +17 -2
  16. package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-placement-policy.ts +188 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +77 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +7 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +10 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +39 -0
  21. package/dist/cli/index.js +50 -26
  22. package/dist/cli/index.mjs +50 -26
  23. package/dist/index.d.mts +5 -3
  24. package/dist/index.d.ts +5 -3
  25. package/dist/index.js +50 -5
  26. package/dist/index.mjs +50 -5
  27. package/dist/plays/bundle-play-file.d.mts +2 -2
  28. package/dist/plays/bundle-play-file.d.ts +2 -2
  29. package/dist/plays/bundle-play-file.mjs +7 -1
  30. package/dist/{tool-execution-error-YDz7UMl-.d.mts → tool-execution-error-4-rhemLQ.d.mts} +7 -1
  31. package/dist/{tool-execution-error-YDz7UMl-.d.ts → tool-execution-error-4-rhemLQ.d.ts} +7 -1
  32. package/package.json +1 -1
@@ -0,0 +1,218 @@
1
+ import type {
2
+ PlayRunnerBackend,
3
+ PlayRunnerCallbacks,
4
+ PlayRunnerPreparedExecution,
5
+ PlayRunnerPrepareInput,
6
+ } from '../types';
7
+ import type {
8
+ PlayRunnerExecutionConfig,
9
+ PlayRunnerResult,
10
+ } from '@shared_libs/play-runtime/protocol';
11
+ import { daytonaPlayRunnerBackend } from './daytona';
12
+ import { DaytonaSandboxAcquisitionUnavailableError } from './daytona-lifecycle';
13
+ import { modalPlayRunnerBackend } from './modal';
14
+ import {
15
+ canTransitionRuntimeSandboxPlacement,
16
+ resolveRuntimeSandboxPlacementPolicy,
17
+ RUNTIME_SANDBOX_PLACEMENT_POLICIES,
18
+ type RuntimeSandboxPlacementPolicyId,
19
+ type RuntimeSandboxPlacementFailureReason,
20
+ type RuntimeSandboxPlacementPolicy,
21
+ type RuntimeSandboxProvider,
22
+ } from '@shared_libs/play-runtime/runtime-sandbox-placement-policy';
23
+
24
+ type DaytonaFallbackPreparedExecution = PlayRunnerPreparedExecution & {
25
+ kind: 'runtime_sandbox_placement';
26
+ policyId: string;
27
+ provider: RuntimeSandboxProvider;
28
+ providerPrepared: PlayRunnerPreparedExecution | undefined;
29
+ };
30
+
31
+ function isPrepared(
32
+ prepared: PlayRunnerPreparedExecution | undefined,
33
+ ): prepared is DaytonaFallbackPreparedExecution {
34
+ return prepared?.kind === 'runtime_sandbox_placement';
35
+ }
36
+
37
+ type RuntimeSandboxProviderAdapter = {
38
+ backend: PlayRunnerBackend;
39
+ classifyAcquisitionFailure: (
40
+ error: unknown,
41
+ ) => RuntimeSandboxPlacementFailureReason | null;
42
+ };
43
+
44
+ function classifyDaytonaAcquisitionFailure(
45
+ error: unknown,
46
+ ): RuntimeSandboxPlacementFailureReason | null {
47
+ if (!(error instanceof DaytonaSandboxAcquisitionUnavailableError)) {
48
+ return null;
49
+ }
50
+ if (error.reason === 'daytona_total_cpu_limit_exceeded') {
51
+ return 'provider_capacity_exhausted';
52
+ }
53
+ if (error.reason === 'daytona_sandbox_start_timeout') {
54
+ return 'provider_start_timeout_before_execution';
55
+ }
56
+ return null;
57
+ }
58
+
59
+ /**
60
+ * Deep placement Implementation. Provider order alone never permits a retry:
61
+ * the policy must also name the exact pre-execution transition and the source
62
+ * Adapter must classify the thrown failure into that provider-neutral reason.
63
+ */
64
+ export function createRuntimeSandboxPlacementBackend(input: {
65
+ policy: RuntimeSandboxPlacementPolicy;
66
+ adapters: Readonly<
67
+ Partial<Record<RuntimeSandboxProvider, RuntimeSandboxProviderAdapter>>
68
+ >;
69
+ }): PlayRunnerBackend {
70
+ const primaryProvider = input.policy.providers[0];
71
+ const primaryAdapter = input.adapters[primaryProvider];
72
+ if (!primaryAdapter) {
73
+ throw new Error(
74
+ `Runtime sandbox placement policy ${input.policy.id} has no Adapter for ${primaryProvider}.`,
75
+ );
76
+ }
77
+ return {
78
+ async prepare(
79
+ prepareInput: PlayRunnerPrepareInput,
80
+ callbacks?: PlayRunnerCallbacks,
81
+ ): Promise<PlayRunnerPreparedExecution> {
82
+ const providerPrepared = await primaryAdapter.backend.prepare?.(
83
+ prepareInput,
84
+ callbacks,
85
+ );
86
+ const prepared: DaytonaFallbackPreparedExecution = {
87
+ kind: 'runtime_sandbox_placement',
88
+ policyId: input.policy.id,
89
+ provider: primaryProvider,
90
+ providerPrepared,
91
+ dispose: async () => await providerPrepared?.dispose?.(),
92
+ };
93
+ return prepared;
94
+ },
95
+
96
+ async execute(
97
+ config: PlayRunnerExecutionConfig,
98
+ callbacks?: PlayRunnerCallbacks,
99
+ prepared?: PlayRunnerPreparedExecution,
100
+ ): Promise<PlayRunnerResult> {
101
+ const policyPrepared =
102
+ isPrepared(prepared) && prepared.policyId === input.policy.id
103
+ ? prepared
104
+ : null;
105
+ for (const [index, provider] of input.policy.providers.entries()) {
106
+ const adapter = input.adapters[provider];
107
+ if (!adapter) {
108
+ throw new Error(
109
+ `Runtime sandbox placement policy ${input.policy.id} has no Adapter for ${provider}.`,
110
+ );
111
+ }
112
+ try {
113
+ return await adapter.backend.execute(
114
+ config,
115
+ callbacks,
116
+ index === 0 && policyPrepared?.provider === provider
117
+ ? policyPrepared.providerPrepared
118
+ : undefined,
119
+ );
120
+ } catch (error) {
121
+ const nextProvider = input.policy.providers[index + 1];
122
+ const reason = adapter.classifyAcquisitionFailure(error);
123
+ if (
124
+ !nextProvider ||
125
+ !reason ||
126
+ callbacks?.cancellationSignal?.aborted ||
127
+ !canTransitionRuntimeSandboxPlacement({
128
+ policy: input.policy,
129
+ from: provider,
130
+ to: nextProvider,
131
+ stage: 'acquisition',
132
+ reason,
133
+ })
134
+ ) {
135
+ throw error;
136
+ }
137
+ console.warn('[play-runner.sandbox_provider_fallback]', {
138
+ runId: config.context.runId ?? null,
139
+ workflowId: config.context.workflowId ?? null,
140
+ policyId: input.policy.id,
141
+ from: provider,
142
+ to: nextProvider,
143
+ stage: 'acquisition',
144
+ reason,
145
+ });
146
+ }
147
+ }
148
+ throw new Error(
149
+ `Runtime sandbox placement policy ${input.policy.id} exhausted without a result.`,
150
+ );
151
+ },
152
+ };
153
+ }
154
+
155
+ export function createRuntimeSandboxPlacementBackendForPolicy(
156
+ policyId: RuntimeSandboxPlacementPolicyId | string,
157
+ overrides: {
158
+ daytona?: PlayRunnerBackend;
159
+ modal?: PlayRunnerBackend;
160
+ } = {},
161
+ ): PlayRunnerBackend {
162
+ return createRuntimeSandboxPlacementBackend({
163
+ policy: resolveRuntimeSandboxPlacementPolicy(policyId),
164
+ adapters: {
165
+ daytona: {
166
+ backend: overrides.daytona ?? daytonaPlayRunnerBackend,
167
+ classifyAcquisitionFailure: classifyDaytonaAcquisitionFailure,
168
+ },
169
+ modal: {
170
+ backend: overrides.modal ?? modalPlayRunnerBackend,
171
+ classifyAcquisitionFailure: () => null,
172
+ },
173
+ },
174
+ });
175
+ }
176
+
177
+ /** Compatibility factory retained for existing imports and tests. */
178
+ export function createDaytonaModalFallbackBackend(
179
+ input: {
180
+ daytona?: PlayRunnerBackend;
181
+ modal?: PlayRunnerBackend;
182
+ } = {},
183
+ ): PlayRunnerBackend {
184
+ return createRuntimeSandboxPlacementBackendForPolicy(
185
+ RUNTIME_SANDBOX_PLACEMENT_POLICIES.daytonaThenModalV1,
186
+ input,
187
+ );
188
+ }
189
+
190
+ export const daytonaModalFallbackPlayRunnerBackend =
191
+ createDaytonaModalFallbackBackend();
192
+
193
+ export const daytonaOnlyPlayRunnerBackend =
194
+ createRuntimeSandboxPlacementBackendForPolicy(
195
+ RUNTIME_SANDBOX_PLACEMENT_POLICIES.daytonaOnlyV1,
196
+ );
197
+
198
+ export const modalOnlyPlayRunnerBackend =
199
+ createRuntimeSandboxPlacementBackendForPolicy(
200
+ RUNTIME_SANDBOX_PLACEMENT_POLICIES.modalOnlyV1,
201
+ );
202
+
203
+ const DEFAULT_POLICY_BACKENDS: Readonly<
204
+ Record<RuntimeSandboxPlacementPolicyId, PlayRunnerBackend>
205
+ > = {
206
+ [RUNTIME_SANDBOX_PLACEMENT_POLICIES.daytonaOnlyV1]:
207
+ daytonaOnlyPlayRunnerBackend,
208
+ [RUNTIME_SANDBOX_PLACEMENT_POLICIES.daytonaThenModalV1]:
209
+ daytonaModalFallbackPlayRunnerBackend,
210
+ [RUNTIME_SANDBOX_PLACEMENT_POLICIES.modalOnlyV1]: modalOnlyPlayRunnerBackend,
211
+ };
212
+
213
+ export function resolveDefaultRuntimeSandboxPlacementBackend(
214
+ policyId: RuntimeSandboxPlacementPolicyId | string,
215
+ ): PlayRunnerBackend {
216
+ const policy = resolveRuntimeSandboxPlacementPolicy(policyId);
217
+ return DEFAULT_POLICY_BACKENDS[policy.id];
218
+ }
@@ -65,6 +65,11 @@ export type StagedDaytonaPayload = {
65
65
  progressEventPath: string;
66
66
  };
67
67
 
68
+ export type RemoteRunnerPayloadSandbox = {
69
+ id: string;
70
+ uploadFile(content: Buffer, path: string): Promise<void>;
71
+ };
72
+
68
73
  function shellQuote(value: string): string {
69
74
  return `'${value.replace(/'/g, `'\\''`)}'`;
70
75
  }
@@ -390,23 +395,23 @@ function remoteRuntimeContextForDaytona(
390
395
  };
391
396
  }
392
397
 
393
- async function timedDaytonaUpload(input: {
394
- sandbox: DaytonaSandbox;
398
+ async function timedRunnerPayloadUpload(input: {
399
+ sandbox: RemoteRunnerPayloadSandbox;
395
400
  emitStage: DaytonaStageEmitter;
396
401
  label: string;
397
402
  path: string;
398
403
  content: Buffer;
399
404
  }) {
400
405
  const startedAt = Date.now();
401
- await input.sandbox.fs.uploadFile(input.content, input.path);
406
+ await input.sandbox.uploadFile(input.content, input.path);
402
407
  input.emitStage(`upload:${input.label}:done`, {
403
408
  bytes: input.content.byteLength,
404
409
  elapsedMs: Date.now() - startedAt,
405
410
  });
406
411
  }
407
412
 
408
- export async function stageDaytonaRunnerPayload(input: {
409
- sandbox: DaytonaSandbox;
413
+ export async function stageRunnerPayload(input: {
414
+ sandbox: RemoteRunnerPayloadSandbox;
410
415
  bundlePromise: Promise<string>;
411
416
  config: PlayRunnerExecutionConfig;
412
417
  workDir: string;
@@ -458,7 +463,7 @@ export async function stageDaytonaRunnerPayload(input: {
458
463
 
459
464
  await Promise.all(
460
465
  [...uniqueLocalPaths.entries()].map(async ([localPath, remotePath]) => {
461
- await timedDaytonaUpload({
466
+ await timedRunnerPayloadUpload({
462
467
  sandbox: input.sandbox,
463
468
  emitStage: input.emitStage,
464
469
  label:
@@ -508,7 +513,7 @@ export async function stageDaytonaRunnerPayload(input: {
508
513
  STANDARD_PLAY_RUNTIME_LIMIT_SECONDS;
509
514
 
510
515
  const envelopeUpload = input.bundlePromise.then((bundle) =>
511
- timedDaytonaUpload({
516
+ timedRunnerPayloadUpload({
512
517
  sandbox: input.sandbox,
513
518
  emitStage: input.emitStage,
514
519
  label: 'payload',
@@ -583,3 +588,17 @@ export async function stageDaytonaRunnerPayload(input: {
583
588
  progressEventPath,
584
589
  };
585
590
  }
591
+
592
+ export async function stageDaytonaRunnerPayload(
593
+ input: Omit<Parameters<typeof stageRunnerPayload>[0], 'sandbox'> & {
594
+ sandbox: DaytonaSandbox;
595
+ },
596
+ ): Promise<StagedDaytonaPayload> {
597
+ return await stageRunnerPayload({
598
+ ...input,
599
+ sandbox: {
600
+ id: input.sandbox.id,
601
+ uploadFile: (content, path) => input.sandbox.fs.uploadFile(content, path),
602
+ },
603
+ });
604
+ }
@@ -24,6 +24,7 @@ import {
24
24
  } from '@shared_libs/play-runtime/daytona-runtime-config';
25
25
  import {
26
26
  DAYTONA_CANCELLED_ERROR,
27
+ DaytonaSandboxAcquisitionUnavailableError,
27
28
  createDaytonaSandboxCleanupManager,
28
29
  createOneShotDaytonaSandboxLifecycle,
29
30
  type DaytonaClient,
@@ -290,12 +291,29 @@ export async function inspectDetachedDaytonaRunner(input: {
290
291
  export async function readDetachedDaytonaRuntimeCompletion(input: {
291
292
  sandboxId: string;
292
293
  runtimeCompletedPath: string;
294
+ expectedOrganizationId?: string | null;
293
295
  }): Promise<number | null> {
294
296
  try {
295
297
  const { clientOptions } = loadDaytonaRequiredConfig();
296
298
  const sandbox = (await daytonaSdkClientFactory
297
299
  .createFull(clientOptions)
298
300
  .get(input.sandboxId)) as DaytonaSandbox;
301
+ const expectedOrganizationId = input.expectedOrganizationId?.trim() || null;
302
+ const observedOrganizationId = sandbox.organizationId?.trim() || null;
303
+ if (
304
+ expectedOrganizationId &&
305
+ observedOrganizationId !== expectedOrganizationId
306
+ ) {
307
+ console.warn(
308
+ '[play-runner.daytona.runtime_completion_wrong_routing_domain]',
309
+ {
310
+ sandboxId: input.sandboxId,
311
+ expectedOrganizationId,
312
+ observedOrganizationId,
313
+ },
314
+ );
315
+ return null;
316
+ }
299
317
  const marker = JSON.parse(
300
318
  (await sandbox.fs.downloadFile(input.runtimeCompletedPath, 5)).toString(
301
319
  'utf-8',
@@ -652,6 +670,7 @@ function prepareDaytonaExecution(
652
670
  context: input.context,
653
671
  emitStage: (stage, extra) =>
654
672
  emitDaytonaStage(callbacks, input.context, stage, extra),
673
+ observeCreateCall: callbacks?.onRuntimeLifecycleEvent,
655
674
  });
656
675
  return {
657
676
  kind: 'daytona',
@@ -790,6 +809,10 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
790
809
  await callbacks?.onRuntimeResourceAcquired?.({
791
810
  kind: 'daytona_sandbox',
792
811
  sandboxId: sandbox.id,
812
+ runtimeEnvironment:
813
+ process.env.DEEPLINE_RUNTIME_ENVIRONMENT === 'preview'
814
+ ? 'preview'
815
+ : 'production',
793
816
  daytonaEnvironment:
794
817
  process.env.DEEPLINE_RUNTIME_ENVIRONMENT === 'preview'
795
818
  ? 'preview'
@@ -1031,6 +1054,14 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
1031
1054
  kind: 'detached_runner',
1032
1055
  boundaryId: `detached-runner:${push.runId}:${runnerAttempt}`,
1033
1056
  runnerAttempt,
1057
+ sandboxProvider: 'daytona',
1058
+ runtimeSandboxRef: {
1059
+ schemaVersion: 1,
1060
+ provider: 'daytona',
1061
+ resourceId: sandbox.id,
1062
+ routingDomain:
1063
+ activeAcquiredResource?.daytonaOrganizationId ?? null,
1064
+ },
1034
1065
  sandboxId: sandbox.id,
1035
1066
  sessionId: start.sessionId,
1036
1067
  cmdId: start.cmdId,
@@ -1121,6 +1152,9 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
1121
1152
  }
1122
1153
  throw error;
1123
1154
  }
1155
+ if (error instanceof DaytonaSandboxAcquisitionUnavailableError) {
1156
+ throw error;
1157
+ }
1124
1158
  emitDaytonaStage(callbacks, config.context, 'execute:error', {
1125
1159
  sandboxId: sandboxCleanup.currentSandbox()?.id ?? null,
1126
1160
  error: formatDaytonaError(error),