deepline 0.3.247 → 0.3.249

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 (67) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +177 -13
  2. package/dist/bundling-sources/sdk/src/index.ts +8 -0
  3. package/dist/bundling-sources/sdk/src/plays/input-example.ts +40 -0
  4. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  5. package/dist/bundling-sources/sdk/src/runs/overview.ts +457 -0
  6. package/dist/bundling-sources/sdk/src/runs/receipts.ts +23 -0
  7. package/dist/bundling-sources/sdk/src/tool-calls.ts +21 -1
  8. package/dist/bundling-sources/sdk/src/types.ts +16 -1
  9. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +19 -1
  10. package/dist/bundling-sources/shared_libs/play-data-plane/column-names.ts +17 -3
  11. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-contract.ts +40 -8
  12. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +26 -1
  13. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +144 -14
  14. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -1
  15. package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +6 -3
  16. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +26 -21
  17. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +23 -21
  18. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +17 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/log-context.ts +105 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +8 -1
  21. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +1 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +1 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +9 -0
  24. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +40 -4
  25. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +50 -5
  26. package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +3 -1
  27. package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +28 -1
  28. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +14 -1
  29. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +56 -16
  30. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +184 -0
  31. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +327 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +87 -30
  33. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +24 -13
  34. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-start-admission.ts +23 -6
  35. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +76 -33
  36. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +90 -35
  37. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +16 -0
  38. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +112 -50
  39. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +447 -77
  40. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +22 -4
  41. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +105 -121
  42. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +1648 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-queue-health.ts +16 -19
  44. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-value-storage.ts +14 -6
  45. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +16 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +40 -0
  47. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +5 -2
  48. package/dist/bundling-sources/shared_libs/plays/dataset-summary.ts +11 -7
  49. package/dist/bundling-sources/shared_libs/plays/static-pipeline-storage-codec.ts +5 -2
  50. package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +11 -2
  51. package/dist/cli/index.js +3504 -2368
  52. package/dist/cli/index.mjs +3188 -2052
  53. package/dist/{compiler-manifest-n8ZtPv2h.d.mts → compiler-manifest-DavmLa8y.d.mts} +1 -0
  54. package/dist/{compiler-manifest-n8ZtPv2h.d.ts → compiler-manifest-DavmLa8y.d.ts} +1 -0
  55. package/dist/index.d.mts +97 -5
  56. package/dist/index.d.ts +97 -5
  57. package/dist/index.js +135 -15
  58. package/dist/index.mjs +135 -15
  59. package/dist/install-integrity.json +9 -2
  60. package/dist/plays/bundle-play-file.d.mts +2 -2
  61. package/dist/plays/bundle-play-file.d.ts +2 -2
  62. package/dist/plays/bundle-play-file.mjs +1 -1
  63. package/dist/release.d.mts +1 -1
  64. package/dist/release.d.ts +1 -1
  65. package/dist/release.js +1 -1
  66. package/dist/release.mjs +1 -1
  67. package/package.json +1 -1
@@ -361,13 +361,21 @@ function requireReceiptScope(
361
361
  if (!scope.orgId || !scope.playName || !scope.runId) {
362
362
  return receiptGatewayJsonResponse(
363
363
  { error: 'Executor token is missing org/run/play scope.' },
364
- { status: 403 },
364
+ {
365
+ status: 403,
366
+ headers: { 'x-deepline-error-code': 'runtime_receipt_scope_missing' },
367
+ },
365
368
  );
366
369
  }
367
370
  if (body.playName !== scope.playName) {
368
371
  return receiptGatewayJsonResponse(
369
372
  { error: 'Receipt request playName does not match executor token.' },
370
- { status: 403 },
373
+ {
374
+ status: 403,
375
+ headers: {
376
+ 'x-deepline-error-code': 'runtime_receipt_play_scope_mismatch',
377
+ },
378
+ },
371
379
  );
372
380
  }
373
381
  if (body.runId && body.runId !== scope.runId) {
@@ -378,7 +386,12 @@ function requireReceiptScope(
378
386
  });
379
387
  return receiptGatewayJsonResponse(
380
388
  { error: 'Receipt request runId does not match executor token.' },
381
- { status: 403 },
389
+ {
390
+ status: 403,
391
+ headers: {
392
+ 'x-deepline-error-code': 'runtime_receipt_run_scope_mismatch',
393
+ },
394
+ },
382
395
  );
383
396
  }
384
397
  return null;
@@ -403,7 +416,12 @@ function requireSameRunReceipts(
403
416
  return invalid
404
417
  ? receiptGatewayJsonResponse(
405
418
  { error: 'Receipt runId does not match executor token scope.' },
406
- { status: 403 },
419
+ {
420
+ status: 403,
421
+ headers: {
422
+ 'x-deepline-error-code': 'runtime_receipt_run_scope_mismatch',
423
+ },
424
+ },
407
425
  )
408
426
  : null;
409
427
  }
@@ -41,7 +41,7 @@ const MAX_TIMEOUT_MS = 2_147_483_647;
41
41
  * therefore a network/projection concurrency budget, deliberately independent
42
42
  * of the projector's much smaller Postgres pool.
43
43
  *
44
- * A single successful probe opens bounded delivery slots; an idle projector still
44
+ * A single successful probe fills bounded delivery slots; an idle projector still
45
45
  * performs only one indexed head read per safety wake. `SKIP LOCKED` leases
46
46
  * distinct runs, retaining strict causal ordering within every run.
47
47
  */
@@ -125,12 +125,12 @@ export function startRunLedgerOutboxRecovery(
125
125
  let failureCount = 0;
126
126
  let timer: RecoveryTimer | null = null;
127
127
  let drainPromise: Promise<void> | null = null;
128
+ let wakeActiveDrain: (() => void) | null = null;
128
129
  let cooldownUntilMs: number | null = null;
129
130
  let hubLease: PgNotifyHubLease | null = null;
130
131
  let unsubscribeNotify: (() => void) | undefined;
131
132
  let unsubscribeState: (() => void) | undefined;
132
133
  let requestDrain: (reason: string) => void = () => undefined;
133
- let wakeDrainer: (() => void) | null = null;
134
134
 
135
135
  const clearWakeTimer = () => {
136
136
  if (!timer) return;
@@ -164,7 +164,7 @@ export function startRunLedgerOutboxRecovery(
164
164
  if (cooldownUntilMs !== null && now() < cooldownUntilMs) return;
165
165
  clearWakeTimer();
166
166
  if (drainPromise) {
167
- wakeDrainer?.();
167
+ wakeActiveDrain?.();
168
168
  return;
169
169
  }
170
170
  drainPromise = drain(reason)
@@ -251,135 +251,119 @@ export function startRunLedgerOutboxRecovery(
251
251
  timer.unref?.();
252
252
  };
253
253
 
254
- type DeliveryOutcome = {
255
- delivery: Promise<DeliveryOutcome>;
256
- } & (
257
- | { status: 'fulfilled'; value: PostgresSchedulerOutboxProjectionResult }
258
- | { status: 'rejected' | 'skipped' }
259
- );
260
-
261
254
  const drain = async (reason: string): Promise<void> => {
262
- const volume = { attempted: 0, projected: 0, retrying: 0, blocked: 0 };
263
- const reportVolume = () => {
264
- if (volume.attempted === 0) return;
265
- logger.info('[run-ledger-outbox.recovery_wave]', {
266
- reason,
267
- parallelism,
268
- ...volume,
269
- });
270
- volume.attempted = 0;
271
- volume.projected = 0;
272
- volume.retrying = 0;
273
- volume.blocked = 0;
274
- };
275
- const recordResult = (
276
- result: PostgresSchedulerOutboxProjectionResult,
277
- resetFailures = true,
278
- ) => {
279
- volume.attempted += result.attempted;
280
- volume.projected += result.projected;
281
- volume.retrying += result.retrying;
282
- volume.blocked += result.failed;
283
- if (result.retrying > 0) {
284
- // Each retrying run owns its durable retry clock. Independent runs
285
- // remain eligible; this is not a controller-wide delivery cooldown.
286
- recordProjectionRetry(result.retrying);
287
- } else if (resetFailures) {
288
- failureCount = 0;
289
- }
290
- // Streaming delivery has no wave barrier at which to report progress.
291
- // Keep logs bounded per committed volume, and flush at idle/shutdown.
292
- if (volume.attempted >= parallelism) reportVolume();
255
+ type Delivery = {
256
+ id: symbol;
257
+ result: PromiseSettledResult<PostgresSchedulerOutboxProjectionResult> | { status: 'skipped' };
293
258
  };
259
+ const pending = new Set<symbol>();
260
+ const deliveries: Delivery[] = [];
261
+ let refill = false;
262
+ let dispatchFailed = false;
263
+ let completed = 0;
264
+ let attempted = 0;
265
+ let projected = 0;
266
+ let retrying = 0;
267
+ let blocked = 0;
294
268
 
295
- while (requested && !closed) {
296
- requested = false;
297
- // Probe first so an idle projector issues one small indexed read per
298
- // wake rather than `parallelism` identical empty scans. Once the probe
299
- // claims a row, the remaining slots can safely lease unrelated runs;
300
- // each dispatcher releases its database client before gateway I/O.
301
- let first: PostgresSchedulerOutboxProjectionResult;
302
- try {
303
- first = await deps.dispatchOnce();
304
- } catch (error) {
305
- scheduleFailureRetry('dispatch', error);
306
- return;
307
- }
308
- recordResult(first);
309
- if (first.attempted === 0) {
310
- await scheduleNextDue();
311
- continue;
269
+ const reportDeliveries = () => {
270
+ if (retrying > 0) recordProjectionRetry(retrying);
271
+ else if (!dispatchFailed) failureCount = 0;
272
+ if (attempted > 0) {
273
+ // Retain the existing throughput event, aggregated over at most one
274
+ // slot-set of completions without making that set a delivery barrier.
275
+ logger.info('[run-ledger-outbox.recovery_wave]', {
276
+ reason,
277
+ parallelism,
278
+ attempted,
279
+ projected,
280
+ retrying,
281
+ blocked,
282
+ });
312
283
  }
284
+ completed = attempted = projected = retrying = blocked = 0;
285
+ };
313
286
 
314
- const active = new Set<Promise<DeliveryOutcome>>();
315
- let dispatchFailed = false;
316
- const startDelivery = () => {
317
- const delivery: Promise<DeliveryOutcome> = Promise.resolve().then(
318
- async (): Promise<DeliveryOutcome> => {
319
- if (closed || dispatchFailed)
320
- return { delivery, status: 'skipped' };
321
- try {
322
- return {
323
- delivery,
324
- status: 'fulfilled',
325
- value: await deps.dispatchOnce(),
326
- };
327
- } catch (error) {
328
- // Stop refills as soon as this rejection is observed, including
329
- // when another already-completed slot wins Promise.race first.
330
- if (!dispatchFailed) {
331
- dispatchFailed = true;
332
- scheduleFailureRetry('dispatch', error);
333
- }
334
- return { delivery, status: 'rejected' };
335
- }
336
- },
337
- );
338
- active.add(delivery);
339
- };
340
- const fillSlots = () => {
341
- if (closed || dispatchFailed) return;
342
- while (active.size < parallelism) {
343
- startDelivery();
287
+ const launch = () => {
288
+ const id = Symbol();
289
+ pending.add(id);
290
+ const settle = (result: Delivery['result']) => {
291
+ if (result.status === 'rejected' && !dispatchFailed) {
292
+ dispatchFailed = true;
293
+ scheduleFailureRetry('dispatch', result.reason);
344
294
  }
295
+ deliveries.push({ id, result });
296
+ wakeActiveDrain?.();
345
297
  };
346
- fillSlots();
347
- while (active.size > 0) {
348
- const wake = new Promise<null>((resolve) => {
349
- wakeDrainer = () => resolve(null);
350
- });
351
- const outcome = await Promise.race([...active, wake]);
352
- wakeDrainer = null;
353
- if (outcome !== null) {
354
- active.delete(outcome.delivery);
355
- if (outcome.status === 'fulfilled') {
356
- recordResult(outcome.value, !dispatchFailed);
357
- if (outcome.value.attempted > 0 && !closed && !dispatchFailed) {
358
- // Refill this completed slot immediately. A slower independent
359
- // run never owns another run's delivery capacity.
360
- startDelivery();
361
- }
362
- }
298
+ // Subscribe once per delivery. Repeated Promise.race calls would retain
299
+ // a new reaction on a slow callback every time a faster slot completes.
300
+ void Promise.resolve().then(async () => {
301
+ if (closed || dispatchFailed) {
302
+ settle({ status: 'skipped' });
303
+ return;
363
304
  }
364
- if (
365
- requested &&
366
- !closed &&
367
- !dispatchFailed &&
368
- active.size < parallelism
369
- ) {
370
- // A new notification can use slots that previously found no work,
371
- // even while another slot is still awaiting its gateway response.
372
- // Keep the hint while all slots are occupied: an already-started
373
- // empty claim does not establish idle after this notification.
305
+ try {
306
+ settle({ status: 'fulfilled', value: await deps.dispatchOnce() });
307
+ } catch (reason) {
308
+ settle({ status: 'rejected', reason });
309
+ }
310
+ });
311
+ };
312
+
313
+ for (;;) {
314
+ if (!closed && !dispatchFailed) {
315
+ // A wake grants one indexed probe, including when other slots are
316
+ // still delivering. Keep it pending when full so an empty result
317
+ // cannot consume a notification that arrived after its query began.
318
+ if (requested && pending.size < parallelism) {
374
319
  requested = false;
375
- fillSlots();
320
+ launch();
321
+ }
322
+ // Productive completion permits immediate use of every free slot.
323
+ // Empty results grant no refill, so idle work cannot spin on scans.
324
+ if (refill) {
325
+ while (pending.size < parallelism) launch();
326
+ refill = false;
376
327
  }
377
328
  }
378
- reportVolume();
379
- if (dispatchFailed || closed) return;
380
- await scheduleNextDue();
329
+ if (pending.size === 0) {
330
+ reportDeliveries();
331
+ if (!closed && !dispatchFailed) await scheduleNextDue();
332
+ return;
333
+ }
334
+
335
+ await new Promise<void>((resolve) => {
336
+ // Register before checking queued completions and notifications.
337
+ wakeActiveDrain = resolve;
338
+ if (
339
+ deliveries.length > 0 ||
340
+ (requested &&
341
+ !closed &&
342
+ !dispatchFailed &&
343
+ pending.size < parallelism)
344
+ )
345
+ resolve();
346
+ });
347
+ wakeActiveDrain = null;
348
+ const delivery = deliveries.shift();
349
+ if (!delivery) continue;
350
+ pending.delete(delivery.id);
351
+ if (delivery.result.status !== 'fulfilled') {
352
+ // Stop new claims but settle every already-started delivery before
353
+ // cooldown or close can hand ownership to another drain.
354
+ continue;
355
+ }
356
+ const result = delivery.result.value;
357
+ completed += 1;
358
+ attempted += result.attempted;
359
+ projected += result.projected;
360
+ retrying += result.retrying;
361
+ blocked += result.failed;
362
+ if (completed >= parallelism) reportDeliveries();
363
+ // Retryable rows own durable retry clocks. The SQL claim keeps their
364
+ // run ordered while successful slots keep unrelated runs moving.
365
+ refill = result.attempted > 0;
381
366
  }
382
- reportVolume();
383
367
  };
384
368
 
385
369
  // Subscribe first, then scan. Notifications are lossy by design, so every
@@ -393,7 +377,7 @@ export function startRunLedgerOutboxRecovery(
393
377
  close: async () => {
394
378
  if (closed) return;
395
379
  closed = true;
396
- wakeDrainer?.();
380
+ wakeActiveDrain?.();
397
381
  clearWakeTimer();
398
382
  cooldownUntilMs = null;
399
383
  unsubscribeNotify?.();