deepline 0.1.213 → 0.1.215

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/apps/play-runner-workers/src/child-manifest-resolver.ts +107 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +85 -10
  3. package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-runtime-proxy.ts +34 -0
  4. package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +50 -36
  5. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +12 -0
  6. package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry.ts +4 -0
  7. package/dist/bundling-sources/sdk/src/client.ts +1 -2
  8. package/dist/bundling-sources/sdk/src/release.ts +2 -2
  9. package/dist/bundling-sources/sdk/src/types.ts +2 -3
  10. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +21 -3
  11. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +73 -28
  12. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +14 -3
  13. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +19 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/profiles.ts +22 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +33 -1
  16. package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +13 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +5 -2
  18. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +66 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +18 -55
  20. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +57 -25
  21. package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +17 -1
  22. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +3 -2
  23. package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +11 -1
  24. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
  25. package/dist/cli/index.js +80 -443
  26. package/dist/cli/index.mjs +80 -443
  27. package/dist/index.d.mts +2 -3
  28. package/dist/index.d.ts +2 -3
  29. package/dist/index.js +7 -6
  30. package/dist/index.mjs +7 -6
  31. package/dist/plays/bundle-play-file.mjs +1 -1
  32. package/package.json +1 -1
@@ -95,7 +95,7 @@ import {
95
95
  PLAY_RUNTIME_CONTRACT,
96
96
  PLAY_RUNTIME_CONTRACT_HEADER,
97
97
  } from './runtime-contract';
98
- import { PLAY_RUNTIME_API_COMPAT_PATH } from './runtime-api-paths';
98
+ import { PLAY_RUNTIME_API_CURRENT_PATH } from './runtime-api-paths';
99
99
  import {
100
100
  PLAY_RUNTIME_SHEET_ATTEMPT_LEASE_TTL_MS,
101
101
  PLAY_RUNTIME_WORK_RECEIPT_LEASE_TTL_MS,
@@ -298,6 +298,7 @@ const RUNTIME_WORK_RECEIPT_LEASE_COLUMNS = [
298
298
  'lease_expires_at',
299
299
  ] as const;
300
300
  const RUNTIME_WORK_RECEIPT_FAILURE_KIND_COLUMN = 'failure_kind';
301
+ const RUNTIME_WORK_RECEIPT_KEY_INDEX = 'idx_deepline_step_receipts_k_unique';
301
302
  const RUNTIME_WORK_RECEIPT_SELF_HEAL_COLUMNS = [
302
303
  ...RUNTIME_WORK_RECEIPT_LEASE_COLUMNS,
303
304
  RUNTIME_WORK_RECEIPT_FAILURE_KIND_COLUMN,
@@ -504,7 +505,7 @@ function resolveRuntimeApiUrl(context: RuntimeApiContext): string {
504
505
  if (!baseUrl) {
505
506
  throw new Error('Runner runtime API requires a baseUrl.');
506
507
  }
507
- return `${baseUrl.replace(/\/$/, '')}${PLAY_RUNTIME_API_COMPAT_PATH}`;
508
+ return `${baseUrl.replace(/\/$/, '')}${PLAY_RUNTIME_API_CURRENT_PATH}`;
508
509
  }
509
510
 
510
511
  function resolveRuntimeApiHeaders(
@@ -588,9 +589,11 @@ async function postRuntimeApi<TResponse>(
588
589
  const details =
589
590
  typeof parsed?.details === 'string'
590
591
  ? parsed.details
591
- : typeof parsed?.debug_error === 'string'
592
- ? parsed.debug_error
593
- : null;
592
+ : typeof parsed?.detail === 'string'
593
+ ? parsed.detail
594
+ : typeof parsed?.debug_error === 'string'
595
+ ? parsed.debug_error
596
+ : null;
594
597
  const shouldRetryRuntimeResponse =
595
598
  (response.status === 503 &&
596
599
  parsed?.code === 'ingestion_plane_not_ready') ||
@@ -2040,6 +2043,22 @@ function isMissingRuntimeWorkReceiptSelfHealColumnError(
2040
2043
  );
2041
2044
  }
2042
2045
 
2046
+ function isMissingRuntimeWorkReceiptKeyConstraintError(
2047
+ error: unknown,
2048
+ ): boolean {
2049
+ if (!error || typeof error !== 'object') {
2050
+ return false;
2051
+ }
2052
+ const code = 'code' in error ? String(error.code) : '';
2053
+ const message = 'message' in error ? String(error.message) : '';
2054
+ return (
2055
+ code === '42P10' ||
2056
+ /no unique or exclusion constraint matching the ON CONFLICT specification/i.test(
2057
+ message,
2058
+ )
2059
+ );
2060
+ }
2061
+
2043
2062
  function runtimeWorkReceiptEnsureCacheKey(
2044
2063
  session: RuntimePostgresSession,
2045
2064
  ): string {
@@ -2119,22 +2138,29 @@ async function ensureRuntimeWorkReceiptTable(
2119
2138
  session,
2120
2139
  client,
2121
2140
  );
2122
- if (missingColumns.length === 0) return;
2141
+ if (missingColumns.length > 0) {
2142
+ await client.query(`
2143
+ ALTER TABLE ${workReceiptTable(session)}
2144
+ ${missingColumns
2145
+ .map((column) => {
2146
+ const type =
2147
+ column === 'lease_expires_at'
2148
+ ? 'timestamptz'
2149
+ : column === 'lease_owner_attempt'
2150
+ ? 'integer'
2151
+ : column === RUNTIME_WORK_RECEIPT_FAILURE_KIND_COLUMN
2152
+ ? 'smallint NOT NULL DEFAULT 0'
2153
+ : 'text';
2154
+ return `ADD COLUMN IF NOT EXISTS ${column} ${type}`;
2155
+ })
2156
+ .join(',\n ')}
2157
+ `);
2158
+ }
2123
2159
  await client.query(`
2124
- ALTER TABLE ${workReceiptTable(session)}
2125
- ${missingColumns
2126
- .map((column) => {
2127
- const type =
2128
- column === 'lease_expires_at'
2129
- ? 'timestamptz'
2130
- : column === 'lease_owner_attempt'
2131
- ? 'integer'
2132
- : column === RUNTIME_WORK_RECEIPT_FAILURE_KIND_COLUMN
2133
- ? 'smallint NOT NULL DEFAULT 0'
2134
- : 'text';
2135
- return `ADD COLUMN IF NOT EXISTS ${column} ${type}`;
2136
- })
2137
- .join(',\n ')}
2160
+ CREATE UNIQUE INDEX IF NOT EXISTS ${quoteIdentifier(
2161
+ RUNTIME_WORK_RECEIPT_KEY_INDEX,
2162
+ )}
2163
+ ON ${workReceiptTable(session)} (k)
2138
2164
  `);
2139
2165
  })
2140
2166
  .then(() => undefined);
@@ -2238,7 +2264,8 @@ async function withRuntimeWorkReceiptClient<T>(
2238
2264
  } catch (error) {
2239
2265
  if (
2240
2266
  isMissingRelationError(error) ||
2241
- isMissingRuntimeWorkReceiptSelfHealColumnError(error)
2267
+ isMissingRuntimeWorkReceiptSelfHealColumnError(error) ||
2268
+ isMissingRuntimeWorkReceiptKeyConstraintError(error)
2242
2269
  ) {
2243
2270
  runtimeWorkReceiptEnsureCache.delete(
2244
2271
  runtimeWorkReceiptEnsureCacheKey(session),
@@ -4636,6 +4663,7 @@ export async function completeRuntimeWorkReceipt(
4636
4663
  runAttempt?: number | null;
4637
4664
  leaseId?: string | null;
4638
4665
  output: unknown;
4666
+ returnOutput?: boolean;
4639
4667
  },
4640
4668
  ): Promise<WorkReceipt | null> {
4641
4669
  if (
@@ -4741,7 +4769,7 @@ export async function completeRuntimeWorkReceipt(
4741
4769
  })}
4742
4770
  RETURNING convert_from(k, 'UTF8') AS k,
4743
4771
  status,
4744
- output,
4772
+ CASE WHEN $7::boolean THEN output ELSE NULL::jsonb END AS output,
4745
4773
  error,
4746
4774
  failure_kind,
4747
4775
  run_id,
@@ -4754,7 +4782,7 @@ export async function completeRuntimeWorkReceipt(
4754
4782
  replay AS (
4755
4783
  SELECT convert_from(k, 'UTF8') AS k,
4756
4784
  status,
4757
- output,
4785
+ CASE WHEN $7::boolean THEN output ELSE NULL::jsonb END AS output,
4758
4786
  error,
4759
4787
  failure_kind,
4760
4788
  run_id,
@@ -4783,6 +4811,7 @@ export async function completeRuntimeWorkReceipt(
4783
4811
  input.runId,
4784
4812
  leaseId,
4785
4813
  runAttempt,
4814
+ input.returnOutput !== false,
4786
4815
  ],
4787
4816
  );
4788
4817
  return rows[0] ? mapRuntimeWorkReceiptRow(rows[0]) : null;
@@ -4801,6 +4830,7 @@ export async function completeRuntimeWorkReceipts(
4801
4830
  leaseId?: string | null;
4802
4831
  runAttempt?: number | null;
4803
4832
  }>;
4833
+ returnOutput?: boolean;
4804
4834
  },
4805
4835
  ): Promise<Array<WorkReceipt | null>> {
4806
4836
  const receipts = input.receipts.filter((receipt) => receipt.key.trim());
@@ -4819,6 +4849,7 @@ export async function completeRuntimeWorkReceipts(
4819
4849
  await completeRuntimeWorkReceipts(context, {
4820
4850
  playName: input.playName,
4821
4851
  receipts: siblingReceipts,
4852
+ returnOutput: input.returnOutput,
4822
4853
  });
4823
4854
  } catch (error) {
4824
4855
  siblingError = error;
@@ -4938,7 +4969,7 @@ export async function completeRuntimeWorkReceipts(
4938
4969
  })}
4939
4970
  RETURNING target.k,
4940
4971
  target.status,
4941
- target.output,
4972
+ CASE WHEN $7::boolean THEN target.output ELSE NULL::jsonb END AS output,
4942
4973
  target.error,
4943
4974
  target.failure_kind,
4944
4975
  target.run_id,
@@ -4952,7 +4983,7 @@ export async function completeRuntimeWorkReceipts(
4952
4983
  replay AS (
4953
4984
  SELECT target.k,
4954
4985
  target.status,
4955
- target.output,
4986
+ CASE WHEN $7::boolean THEN target.output ELSE NULL::jsonb END AS output,
4956
4987
  target.error,
4957
4988
  target.failure_kind,
4958
4989
  target.run_id,
@@ -5020,6 +5051,7 @@ export async function completeRuntimeWorkReceipts(
5020
5051
  ),
5021
5052
  ),
5022
5053
  RECEIPT_STATUS_COMPLETED,
5054
+ input.returnOutput !== false,
5023
5055
  ],
5024
5056
  );
5025
5057
  return rows.map((row) =>
@@ -1,8 +1,15 @@
1
- export const PLAY_RUNTIME_CONTRACT = 2;
1
+ export const PLAY_RUNTIME_CONTRACT = 3;
2
2
  export const PLAY_RUNTIME_CONTRACT_MIN_SUPPORTED = 1;
3
3
  export const PLAY_RUNTIME_CONTRACT_HEADER = 'x-deepline-runtime-contract';
4
4
 
5
5
  export const RUNTIME_CONTRACT_CHANGELOG = [
6
+ {
7
+ contract: 3,
8
+ changed:
9
+ 'Runtime receipt completion responses are compact acknowledgements; receipt reads remain the payload replay path.',
10
+ compatOwner: 'runtime',
11
+ compatRemoval: 'contract 2 support window closure',
12
+ },
6
13
  {
7
14
  contract: 2,
8
15
  changed:
@@ -12,6 +19,15 @@ export const RUNTIME_CONTRACT_CHANGELOG = [
12
19
  },
13
20
  ] as const;
14
21
 
22
+ export function runtimeReceiptCompletionResponse<
23
+ T extends { output?: unknown },
24
+ >(runtimeContract: number | null | undefined, receipt: T | null): T | null {
25
+ if (!receipt || (runtimeContract ?? 1) < 3) return receipt;
26
+ const { output, ...ack } = receipt;
27
+ void output;
28
+ return ack as T;
29
+ }
30
+
15
31
  export type RuntimeContractResolution =
16
32
  | { ok: true; contract: number }
17
33
  | {
@@ -4,8 +4,9 @@
4
4
  * One of three pluggable axes (alongside runner-backends and dedup-backends).
5
5
  * Selected per-run via PlayExecutionProfile.
6
6
  *
7
- * Cloudflare Workflows is the default production scheduler through the
8
- * workers_edge profile. Absurd is the durable Daytona-backed scheduler.
7
+ * Absurd is the enabled production scheduler. The Cloudflare Workflows
8
+ * adapter is retained for historical run interpretation while workers_edge
9
+ * launch admission is disabled.
9
10
  *
10
11
  * Customer plays are unaffected — this is purely the orchestration layer.
11
12
  */
@@ -5,10 +5,18 @@ const JWT_RE =
5
5
  /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
6
6
  const PRIVATE_KEY_RE =
7
7
  /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
8
+ // Only redact self-identifying credential prefixes here. Generic words such as
9
+ // `key`, `token`, and `secret` are common in harmless play/run slugs (for
10
+ // example `absurd-key-rotation-check`) and need an assignment context before
11
+ // they are sensitive; HIGH_ENTROPY_ASSIGNMENT_RE handles that case below.
8
12
  const COMMON_SECRET_RE =
9
- /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]|key|token|secret|api[_-]?key)[A-Za-z0-9_./+=:-]{12,}\b/gi;
13
+ /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs])[A-Za-z0-9_./+=:-]{12,}\b/gi;
14
+ const GENERIC_PREFIXED_SECRET_RE =
15
+ /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
10
16
  const URL_SECRET_VALUE_RE =
11
17
  /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
18
+ const GENERIC_SECRET_ASSIGNMENT_RE =
19
+ /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
12
20
  const HIGH_ENTROPY_ASSIGNMENT_RE =
13
21
  /\b(?:api[_-]?key|token|secret|password|authorization|access[_-]?token|refresh[_-]?token)\b\s*[:=]\s*["']?[^"',\s]{16,}["']?/gi;
14
22
  const SENSITIVE_URL_PARAM_RE =
@@ -39,6 +47,8 @@ export function redactSecretLikeString(value: string): string {
39
47
  .replace(BEARER_TOKEN_RE, `Bearer ${SECRET_REDACTION_PLACEHOLDER}`)
40
48
  .replace(JWT_RE, SECRET_REDACTION_PLACEHOLDER)
41
49
  .replace(COMMON_SECRET_RE, SECRET_REDACTION_PLACEHOLDER)
50
+ .replace(GENERIC_PREFIXED_SECRET_RE, SECRET_REDACTION_PLACEHOLDER)
51
+ .replace(GENERIC_SECRET_ASSIGNMENT_RE, SECRET_REDACTION_PLACEHOLDER)
42
52
  .replace(HIGH_ENTROPY_ASSIGNMENT_RE, (match) => {
43
53
  const separator = match.includes('=') ? '=' : ':';
44
54
  const [key] = match.split(separator, 1);
@@ -0,0 +1,10 @@
1
+ export function transientServiceUnavailableDetail(
2
+ error: unknown,
3
+ ): string | null {
4
+ const detail = error instanceof Error ? error.message : String(error);
5
+ return /ServiceUnavailable|Service temporarily unavailable|temporarily unavailable \(Code:\s*\d+\)/i.test(
6
+ detail,
7
+ )
8
+ ? detail
9
+ : null;
10
+ }