deepline 0.3.246 → 0.3.248

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 +37 -1
  10. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +1 -0
  11. package/dist/bundling-sources/shared_libs/play-data-plane/column-names.ts +17 -3
  12. package/dist/bundling-sources/shared_libs/play-data-plane/sheet-contract.ts +40 -8
  13. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +26 -1
  14. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +150 -19
  15. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -1
  16. package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +6 -3
  17. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-janitor.ts +26 -21
  18. package/dist/bundling-sources/shared_libs/play-runtime/daytona-sandbox-reaper.ts +23 -21
  19. package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +17 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/log-context.ts +105 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +8 -1
  22. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +9 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +40 -4
  24. package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +50 -5
  25. package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +3 -1
  26. package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +28 -1
  27. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +14 -1
  28. package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +56 -16
  29. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-control-transport.ts +184 -0
  30. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +327 -0
  31. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +87 -30
  32. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +24 -13
  33. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-start-admission.ts +23 -6
  34. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +76 -33
  35. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +90 -35
  36. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +16 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +62 -21
  38. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +368 -66
  39. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +22 -4
  40. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +106 -81
  41. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +1347 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-queue-health.ts +16 -19
  43. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-value-storage.ts +14 -6
  44. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +16 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +40 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +3 -2
  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 starts a bounded wave; 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,6 +125,7 @@ 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;
@@ -162,7 +163,10 @@ export function startRunLedgerOutboxRecovery(
162
163
  requested = true;
163
164
  if (cooldownUntilMs !== null && now() < cooldownUntilMs) return;
164
165
  clearWakeTimer();
165
- if (drainPromise) return;
166
+ if (drainPromise) {
167
+ wakeActiveDrain?.();
168
+ return;
169
+ }
166
170
  drainPromise = drain(reason)
167
171
  .catch((error) => {
168
172
  // drain() handles expected database/projection faults itself. This is a
@@ -179,7 +183,6 @@ export function startRunLedgerOutboxRecovery(
179
183
  };
180
184
 
181
185
  const recordProjectionRetry = (retrying: number) => {
182
- failureCount += 1;
183
186
  logger.warn('[run-ledger-outbox.recovery_retry]', {
184
187
  stage: 'projection',
185
188
  retrying,
@@ -205,6 +208,7 @@ export function startRunLedgerOutboxRecovery(
205
208
  delayMs,
206
209
  error: error instanceof Error ? error.message : String(error),
207
210
  });
211
+ if (closed) return;
208
212
  clearWakeTimer();
209
213
  cooldownUntilMs = now() + delayMs;
210
214
  timer = setTimer(() => {
@@ -216,6 +220,7 @@ export function startRunLedgerOutboxRecovery(
216
220
  };
217
221
 
218
222
  const scheduleNextDue = async (): Promise<void> => {
223
+ if (closed) return;
219
224
  let dueAt: Date | null;
220
225
  try {
221
226
  dueAt = await deps.readNextDueAt();
@@ -247,79 +252,26 @@ export function startRunLedgerOutboxRecovery(
247
252
  };
248
253
 
249
254
  const drain = async (reason: string): Promise<void> => {
250
- while (requested && !closed) {
251
- requested = false;
252
- // Probe first so an idle projector issues one small indexed read per
253
- // wake rather than `parallelism` identical empty scans. Once the probe
254
- // claims a row, the remaining slots can safely lease unrelated runs;
255
- // each dispatcher releases its database client before gateway I/O.
256
- let first: PostgresSchedulerOutboxProjectionResult;
257
- try {
258
- first = await deps.dispatchOnce();
259
- } catch (error) {
260
- scheduleFailureRetry('dispatch', error);
261
- return;
262
- }
263
- const settled = [
264
- {
265
- status: 'fulfilled' as const,
266
- value: first,
267
- },
268
- ...(first.attempted === 0
269
- ? []
270
- : await Promise.allSettled(
271
- Array.from({ length: parallelism - 1 }, () =>
272
- deps.dispatchOnce(),
273
- ),
274
- )),
275
- ];
276
- const rejected = settled.find(
277
- (result): result is PromiseRejectedResult =>
278
- result.status === 'rejected',
279
- );
280
- if (rejected) {
281
- scheduleFailureRetry('dispatch', rejected.reason);
282
- return;
283
- }
284
-
285
- const results = settled.map(
286
- (result) =>
287
- (
288
- result as PromiseFulfilledResult<PostgresSchedulerOutboxProjectionResult>
289
- ).value,
290
- );
291
- const retrying = results.reduce(
292
- (total, result) => total + result.retrying,
293
- 0,
294
- );
295
- const attempted = results.reduce(
296
- (total, result) => total + result.attempted,
297
- 0,
298
- );
299
- const projected = results.reduce(
300
- (total, result) => total + result.projected,
301
- 0,
302
- );
303
- const blocked = results.reduce(
304
- (total, result) => total + result.failed,
305
- 0,
306
- );
307
-
308
- if (retrying > 0) {
309
- // The failed row owns its own durable retry clock. Do NOT stop this
310
- // drain: the claim query preserves causal order within a run, while
311
- // independent runs are safe to project now. Returning here turns one
312
- // transient projection failure into global head-of-line blocking when
313
- // this is the only healthy projector replica.
314
- recordProjectionRetry(retrying);
315
- } else {
316
- failureCount = 0;
317
- }
255
+ type Delivery = {
256
+ id: symbol;
257
+ result: PromiseSettledResult<PostgresSchedulerOutboxProjectionResult> | { status: 'skipped' };
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;
318
268
 
269
+ const reportDeliveries = () => {
270
+ if (retrying > 0) recordProjectionRetry(retrying);
271
+ else if (!dispatchFailed) failureCount = 0;
319
272
  if (attempted > 0) {
320
- // This is the durable queue's high-signal throughput event. It makes
321
- // a delayed public Run observable as a projector/outbox problem,
322
- // without emitting one noisy log line per normal database checkout.
273
+ // Retain the existing throughput event, aggregated over at most one
274
+ // slot-set of completions without making that set a delivery barrier.
323
275
  logger.info('[run-ledger-outbox.recovery_wave]', {
324
276
  reason,
325
277
  parallelism,
@@ -329,16 +281,88 @@ export function startRunLedgerOutboxRecovery(
329
281
  blocked,
330
282
  });
331
283
  }
284
+ completed = attempted = projected = retrying = blocked = 0;
285
+ };
332
286
 
333
- // Continue until no event was claimable. A transient failure schedules
334
- // its own durable retry, so the next pass naturally skips that run while
335
- // moving unrelated runs forward. A permanent failure is settled once and
336
- // likewise cannot block another run's causal prefix.
337
- if (attempted > 0) {
338
- requested = true;
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);
294
+ }
295
+ deliveries.push({ id, result });
296
+ wakeActiveDrain?.();
297
+ };
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;
304
+ }
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) {
319
+ requested = false;
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;
327
+ }
328
+ }
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.
339
354
  continue;
340
355
  }
341
- await scheduleNextDue();
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;
342
366
  }
343
367
  };
344
368
 
@@ -353,6 +377,7 @@ export function startRunLedgerOutboxRecovery(
353
377
  close: async () => {
354
378
  if (closed) return;
355
379
  closed = true;
380
+ wakeActiveDrain?.();
356
381
  clearWakeTimer();
357
382
  cooldownUntilMs = null;
358
383
  unsubscribeNotify?.();