deepline 0.1.0 → 0.1.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 (97) hide show
  1. package/dist/cli/index.js +212 -54
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/cli/index.mjs +198 -40
  4. package/dist/cli/index.mjs.map +1 -1
  5. package/dist/index.d.mts +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/index.mjs +1 -1
  9. package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +3256 -0
  10. package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +710 -0
  11. package/dist/repo/apps/play-runner-workers/src/entry.ts +5070 -0
  12. package/dist/repo/apps/play-runner-workers/src/runtime/README.md +21 -0
  13. package/dist/repo/apps/play-runner-workers/src/runtime/batching.ts +177 -0
  14. package/dist/repo/apps/play-runner-workers/src/runtime/execution-plan.ts +52 -0
  15. package/dist/repo/apps/play-runner-workers/src/runtime/tool-batch.ts +100 -0
  16. package/dist/repo/apps/play-runner-workers/src/runtime/tool-result.ts +184 -0
  17. package/dist/repo/sdk/src/cli/commands/auth.ts +482 -0
  18. package/dist/repo/sdk/src/cli/commands/billing.ts +188 -0
  19. package/dist/repo/sdk/src/cli/commands/csv.ts +123 -0
  20. package/dist/repo/sdk/src/cli/commands/db.ts +119 -0
  21. package/dist/repo/sdk/src/cli/commands/feedback.ts +40 -0
  22. package/dist/repo/sdk/src/cli/commands/org.ts +117 -0
  23. package/dist/repo/sdk/src/cli/commands/play.ts +3200 -0
  24. package/dist/repo/sdk/src/cli/commands/tools.ts +687 -0
  25. package/dist/repo/sdk/src/cli/dataset-stats.ts +341 -0
  26. package/dist/repo/sdk/src/cli/index.ts +138 -0
  27. package/dist/repo/sdk/src/cli/progress.ts +135 -0
  28. package/dist/repo/sdk/src/cli/trace.ts +61 -0
  29. package/dist/repo/sdk/src/cli/utils.ts +145 -0
  30. package/dist/repo/sdk/src/client.ts +1188 -0
  31. package/dist/repo/sdk/src/compat.ts +77 -0
  32. package/dist/repo/sdk/src/config.ts +285 -0
  33. package/dist/repo/sdk/src/errors.ts +125 -0
  34. package/dist/repo/sdk/src/http.ts +391 -0
  35. package/dist/repo/sdk/src/index.ts +139 -0
  36. package/dist/repo/sdk/src/play.ts +1330 -0
  37. package/dist/repo/sdk/src/plays/bundle-play-file.ts +133 -0
  38. package/dist/repo/sdk/src/plays/harness-stub.ts +210 -0
  39. package/dist/repo/sdk/src/plays/local-file-discovery.ts +326 -0
  40. package/dist/repo/sdk/src/tool-output.ts +489 -0
  41. package/dist/repo/sdk/src/types.ts +669 -0
  42. package/dist/repo/sdk/src/version.ts +2 -0
  43. package/dist/repo/sdk/src/worker-play-entry.ts +286 -0
  44. package/dist/repo/shared_libs/observability/node-tracing.ts +129 -0
  45. package/dist/repo/shared_libs/observability/tracing.ts +98 -0
  46. package/dist/repo/shared_libs/play-runtime/backend.ts +139 -0
  47. package/dist/repo/shared_libs/play-runtime/batch-runtime.ts +182 -0
  48. package/dist/repo/shared_libs/play-runtime/batching-types.ts +91 -0
  49. package/dist/repo/shared_libs/play-runtime/context.ts +3999 -0
  50. package/dist/repo/shared_libs/play-runtime/coordinator-headers.ts +78 -0
  51. package/dist/repo/shared_libs/play-runtime/ctx-contract.ts +250 -0
  52. package/dist/repo/shared_libs/play-runtime/ctx-types.ts +713 -0
  53. package/dist/repo/shared_libs/play-runtime/dataset-id.ts +10 -0
  54. package/dist/repo/shared_libs/play-runtime/db-session-crypto.ts +304 -0
  55. package/dist/repo/shared_libs/play-runtime/db-session.ts +462 -0
  56. package/dist/repo/shared_libs/play-runtime/dedup-backend.ts +0 -0
  57. package/dist/repo/shared_libs/play-runtime/default-batch-strategies.ts +124 -0
  58. package/dist/repo/shared_libs/play-runtime/execution-plan.ts +262 -0
  59. package/dist/repo/shared_libs/play-runtime/live-events.ts +214 -0
  60. package/dist/repo/shared_libs/play-runtime/live-state-contract.ts +50 -0
  61. package/dist/repo/shared_libs/play-runtime/map-execution-frame.ts +114 -0
  62. package/dist/repo/shared_libs/play-runtime/map-row-identity.ts +158 -0
  63. package/dist/repo/shared_libs/play-runtime/profiles.ts +90 -0
  64. package/dist/repo/shared_libs/play-runtime/progress-emitter.ts +172 -0
  65. package/dist/repo/shared_libs/play-runtime/protocol.ts +121 -0
  66. package/dist/repo/shared_libs/play-runtime/public-play-contract.ts +42 -0
  67. package/dist/repo/shared_libs/play-runtime/result-normalization.ts +33 -0
  68. package/dist/repo/shared_libs/play-runtime/runtime-actions.ts +208 -0
  69. package/dist/repo/shared_libs/play-runtime/runtime-api.ts +1873 -0
  70. package/dist/repo/shared_libs/play-runtime/runtime-constraints.ts +2 -0
  71. package/dist/repo/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +201 -0
  72. package/dist/repo/shared_libs/play-runtime/runtime-pg-driver-pg.ts +48 -0
  73. package/dist/repo/shared_libs/play-runtime/runtime-pg-driver.ts +84 -0
  74. package/dist/repo/shared_libs/play-runtime/scheduler-backend.ts +174 -0
  75. package/dist/repo/shared_libs/play-runtime/static-pipeline-types.ts +147 -0
  76. package/dist/repo/shared_libs/play-runtime/suspension.ts +68 -0
  77. package/dist/repo/shared_libs/play-runtime/tool-batch-executor.ts +146 -0
  78. package/dist/repo/shared_libs/play-runtime/tool-result.ts +387 -0
  79. package/dist/repo/shared_libs/play-runtime/tracing.ts +31 -0
  80. package/dist/repo/shared_libs/play-runtime/waterfall-replay.ts +75 -0
  81. package/dist/repo/shared_libs/play-runtime/worker-api-types.ts +140 -0
  82. package/dist/repo/shared_libs/plays/artifact-transport.ts +14 -0
  83. package/dist/repo/shared_libs/plays/artifact-types.ts +49 -0
  84. package/dist/repo/shared_libs/plays/bundling/index.ts +1346 -0
  85. package/dist/repo/shared_libs/plays/compiler-manifest.ts +186 -0
  86. package/dist/repo/shared_libs/plays/contracts.ts +51 -0
  87. package/dist/repo/shared_libs/plays/dataset.ts +308 -0
  88. package/dist/repo/shared_libs/plays/definition.ts +264 -0
  89. package/dist/repo/shared_libs/plays/file-refs.ts +11 -0
  90. package/dist/repo/shared_libs/plays/rate-limit-scheduler.ts +206 -0
  91. package/dist/repo/shared_libs/plays/resolve-static-pipeline.ts +164 -0
  92. package/dist/repo/shared_libs/plays/row-identity.ts +302 -0
  93. package/dist/repo/shared_libs/plays/runtime-validation.ts +415 -0
  94. package/dist/repo/shared_libs/plays/static-pipeline.ts +560 -0
  95. package/dist/repo/shared_libs/temporal/constants.ts +39 -0
  96. package/dist/repo/shared_libs/temporal/preview-config.ts +153 -0
  97. package/package.json +4 -4
@@ -0,0 +1,713 @@
1
+ // Core types for PlayContext — cloud-only execution via Temporal
2
+ import type { PlayBundleArtifact } from '../plays/artifact-types';
3
+ import type { PlayRunContractSnapshot } from '../plays/contracts';
4
+ import type { PlayStructuredDefinition } from '../plays/definition';
5
+ import type { PlayStaticPipeline } from '../plays/static-pipeline';
6
+ import type { PlayDataset, PlayDatasetInput } from '../plays/dataset';
7
+ import type { PlayQueueHint } from '../plays/rate-limit-scheduler';
8
+ import type { AnyBatchOperationStrategy } from './batching-types';
9
+ import type { ToolResultMetadataInput } from './tool-result';
10
+
11
+ export interface RowState {
12
+ id: number;
13
+ input: unknown;
14
+ status: 'pending' | 'waiting' | 'complete' | 'failed';
15
+ waterfalls: Map<string, WaterfallState>;
16
+ toolCalls: Map<string, ToolCallState>;
17
+ results: Map<string, unknown>;
18
+ }
19
+
20
+ export interface WaterfallState {
21
+ status: 'pending' | 'complete' | 'failed';
22
+ providerIndex: number;
23
+ result?: unknown;
24
+ error?: string;
25
+ }
26
+
27
+ export interface ToolCallState {
28
+ status: 'pending' | 'complete' | 'failed';
29
+ result?: unknown;
30
+ error?: string;
31
+ }
32
+
33
+ export interface WaterfallRequest {
34
+ rowId: number;
35
+ fieldName?: string;
36
+ tableNamespace?: string;
37
+ rowKey?: string | null;
38
+ key: string;
39
+ toolName: string;
40
+ input: Record<string, unknown>;
41
+ providerIndex: number;
42
+ opts?: WaterfallOptions;
43
+ spec?: InlineWaterfallSpec;
44
+ description?: string;
45
+ }
46
+
47
+ export interface ToolCallRequest {
48
+ callId: string;
49
+ rowId: number;
50
+ fieldName?: string;
51
+ toolId: string;
52
+ input: Record<string, unknown>;
53
+ tableNamespace?: string;
54
+ rowKey?: string | null;
55
+ description?: string;
56
+ }
57
+
58
+ export interface ToolBatchResult {
59
+ done: true;
60
+ result: unknown | null;
61
+ }
62
+
63
+ export interface RuntimeStepReceipt {
64
+ key: string;
65
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
66
+ output?: unknown;
67
+ error?: string;
68
+ runId?: string | null;
69
+ }
70
+
71
+ export interface GetRuntimeStepReceiptInput {
72
+ key: string;
73
+ }
74
+
75
+ export interface ClaimRuntimeStepReceiptInput {
76
+ key: string;
77
+ runId: string;
78
+ }
79
+
80
+ export interface CompleteRuntimeStepReceiptInput {
81
+ key: string;
82
+ runId: string;
83
+ output: unknown | null;
84
+ }
85
+
86
+ export interface FailRuntimeStepReceiptInput {
87
+ key: string;
88
+ runId: string;
89
+ error: string;
90
+ }
91
+
92
+ export interface SkipRuntimeStepReceiptInput {
93
+ key: string;
94
+ runId: string;
95
+ output?: unknown | null;
96
+ }
97
+
98
+ export interface WaterfallOptions {
99
+ providers?: string[];
100
+ timeout?: number;
101
+ description?: string;
102
+ }
103
+
104
+ export interface CsvOptions {
105
+ description?: string;
106
+ }
107
+
108
+ export interface MapOptions<TItem = Record<string, unknown>> {
109
+ description?: string;
110
+ /**
111
+ * Optional relative cache window for intentional reruns.
112
+ *
113
+ * By default, ctx.map is durable by play + map key + row identity forever.
114
+ * Set staleAfterSeconds to rerun after that many seconds while retries/replays
115
+ * inside the same window still hit the cache. Daily refreshes use 86400.
116
+ */
117
+ staleAfterSeconds?: number;
118
+ /**
119
+ * Optional stable key per row. When provided, row identity is derived from
120
+ * the selected input field(s) or returned value instead of hashing the full
121
+ * row. Use this to pin identity to primary columns (e.g. `{ key: "email" }`
122
+ * or `{ key: ["first_name", "last_name", "domain"] }`) so harmless
123
+ * mutations to other columns don't invalidate the cache.
124
+ *
125
+ * Must return a non-empty string (numbers are coerced) and must be unique
126
+ * across rows in this ctx.map() call. Empty or duplicate keys throw loudly
127
+ * before any provider work runs. The key function should reference *input*
128
+ * columns only — values produced by this map's field resolvers are stripped
129
+ * before identity is computed.
130
+ */
131
+ key?:
132
+ | (keyof TItem & string)
133
+ | readonly (keyof TItem & string)[]
134
+ | ((row: TItem, index: number) => string | number | readonly unknown[]);
135
+ }
136
+
137
+ export type MapDefinitionOptions<TItem = Record<string, unknown>> = Omit<
138
+ MapOptions<TItem>,
139
+ 'description'
140
+ >;
141
+
142
+ export type MapRunOptions = Pick<MapOptions, 'description'>;
143
+
144
+ export interface ToolCallOptions {
145
+ description?: string;
146
+ }
147
+
148
+ export interface ToolExecutionRequest {
149
+ id: string;
150
+ tool: string;
151
+ input: Record<string, unknown>;
152
+ description?: string;
153
+ }
154
+
155
+ export interface PlayCallOptions {
156
+ description?: string;
157
+ }
158
+
159
+ export interface InlineWaterfallToolStep {
160
+ id: string;
161
+ kind?: 'tool';
162
+ toolId: string;
163
+ mapInput: (input: Record<string, unknown>) => Record<string, unknown>;
164
+ }
165
+
166
+ export interface InlineWaterfallCodeStepContext {
167
+ tools: {
168
+ execute(request: ToolExecutionRequest): Promise<unknown>;
169
+ };
170
+ }
171
+
172
+ export interface InlineWaterfallCodeStep {
173
+ id: string;
174
+ kind: 'code';
175
+ run: (
176
+ input: Record<string, unknown>,
177
+ ctx: InlineWaterfallCodeStepContext,
178
+ ) => unknown | Promise<unknown>;
179
+ }
180
+
181
+ export type InlineWaterfallStep =
182
+ | InlineWaterfallToolStep
183
+ | InlineWaterfallCodeStep;
184
+
185
+ export interface InlineWaterfallSpec {
186
+ id: string;
187
+ output: string;
188
+ minResults: number;
189
+ steps: InlineWaterfallStep[];
190
+ }
191
+
192
+ export interface ResolvedPlayExecution {
193
+ playId: string;
194
+ code?: string | null;
195
+ sourceCode?: string | null;
196
+ codeFormat?: 'function' | 'cjs_module' | 'esm_module';
197
+ artifact?: PlayBundleArtifact | null;
198
+ compressedArtifact?: string | null;
199
+ definition?: PlayStructuredDefinition | null;
200
+ staticPipeline?: PlayStaticPipeline | null;
201
+ contractSnapshot?: PlayRunContractSnapshot | null;
202
+ }
203
+
204
+ export interface PlayExecutionGovernanceLimits {
205
+ maxPlayCallDepth: number;
206
+ maxPlayCallCount: number;
207
+ maxToolCallCount: number;
208
+ maxWaterfallStepExecutions: number | null;
209
+ maxRetryCount: number;
210
+ maxDescendants: number;
211
+ maxChildPlayCallsPerParent: number;
212
+ maxConcurrentPlayCalls: number;
213
+ maxConcurrentToolCalls: number;
214
+ }
215
+
216
+ export interface PlayExecutionGovernanceState {
217
+ rootPlayId: string;
218
+ rootRunId: string;
219
+ currentPlayId: string;
220
+ currentRunId: string;
221
+ ancestryPlayIds: string[];
222
+ ancestryRunIds: string[];
223
+ callDepth: number;
224
+ playCallCount: number;
225
+ toolCallCount: number;
226
+ waterfallStepExecutions: number;
227
+ retryCount: number;
228
+ descendantCount: number;
229
+ parentChildCalls: Record<string, number>;
230
+ inFlightPlayCalls: number;
231
+ inFlightPlayCallsByPlayId?: Record<string, number>;
232
+ inFlightToolCalls: number;
233
+ limits: PlayExecutionGovernanceLimits;
234
+ }
235
+
236
+ export interface BatchRequest {
237
+ provider: string;
238
+ toolName: string;
239
+ inputs: Record<string, unknown>[];
240
+ rowIds: number[];
241
+ }
242
+
243
+ export interface MapStartResult {
244
+ /** Rows that need processing (not yet completed in a prior run). */
245
+ pendingRows: Record<string, unknown>[];
246
+ /** Rows already completed in a prior run (cached results). */
247
+ completedRows: Record<string, unknown>[];
248
+ /** Resolved table namespace. */
249
+ tableNamespace: string;
250
+ }
251
+
252
+ export interface MapExecutionFrame {
253
+ mapInvocationId: string;
254
+ mapNodeId?: string | null;
255
+ logicalNamespace: string;
256
+ artifactTableNamespace: string;
257
+ status: 'running' | 'suspended' | 'completed' | 'failed';
258
+ totalRows: number;
259
+ completedRowKeys: string[];
260
+ pendingRowKeys: string[];
261
+ activeBoundaryId?: string | null;
262
+ startedAt: number;
263
+ updatedAt: number;
264
+ }
265
+
266
+ export interface MapExecutionScope {
267
+ mapInvocationId: string;
268
+ mapNodeId?: string | null;
269
+ logicalNamespace: string;
270
+ artifactTableNamespace: string;
271
+ rowIdentity: (row: Record<string, unknown>, index?: number) => string;
272
+ }
273
+
274
+ export type PlayExecutionEvent =
275
+ | {
276
+ type: 'map.preparing';
277
+ mapInvocationId: string;
278
+ mapNodeId?: string | null;
279
+ logicalNamespace: string;
280
+ artifactTableNamespace: string;
281
+ totalRows: number;
282
+ completedRows: number;
283
+ pendingRows: number;
284
+ at: number;
285
+ }
286
+ | {
287
+ type: 'map.started';
288
+ mapInvocationId: string;
289
+ mapNodeId?: string | null;
290
+ logicalNamespace: string;
291
+ artifactTableNamespace: string;
292
+ totalRows: number;
293
+ completedRows: number;
294
+ pendingRows: number;
295
+ at: number;
296
+ }
297
+ | {
298
+ type: 'map.progress';
299
+ mapInvocationId: string;
300
+ mapNodeId?: string | null;
301
+ logicalNamespace: string;
302
+ artifactTableNamespace: string;
303
+ completedRows: number;
304
+ failedRows: number;
305
+ totalRows?: number;
306
+ at: number;
307
+ }
308
+ | {
309
+ type: 'map.row.updated';
310
+ mapInvocationId: string;
311
+ mapNodeId?: string | null;
312
+ logicalNamespace: string;
313
+ artifactTableNamespace: string;
314
+ rowKey: string;
315
+ rowStatus?: PlayRowUpdate['status'];
316
+ fieldName?: string | null;
317
+ stage?: string | null;
318
+ provider?: string | null;
319
+ at: number;
320
+ }
321
+ | {
322
+ type: 'map.completed' | 'map.suspended' | 'map.resumed' | 'map.failed';
323
+ mapInvocationId: string;
324
+ mapNodeId?: string | null;
325
+ logicalNamespace: string;
326
+ artifactTableNamespace: string;
327
+ completedRows: number;
328
+ failedRows: number;
329
+ totalRows?: number;
330
+ at: number;
331
+ };
332
+
333
+ export type IntegrationEventWaitRuntimeContext = {
334
+ playId?: string;
335
+ runId?: string;
336
+ workflowId?: string;
337
+ orgId?: string;
338
+ executorToken?: string;
339
+ };
340
+
341
+ export type IntegrationEventWaitBoundary = {
342
+ boundaryId: string;
343
+ eventKey: string;
344
+ timeoutMs: number;
345
+ provider: string;
346
+ toolId: string;
347
+ messageRef?: {
348
+ channel: string;
349
+ ts: string;
350
+ };
351
+ };
352
+
353
+ export type IntegrationEventWaitHandler = {
354
+ provider: string;
355
+ toolId: string;
356
+ prepare: (input: {
357
+ payload: Record<string, unknown>;
358
+ context: IntegrationEventWaitRuntimeContext;
359
+ }) => IntegrationEventWaitBoundary | Promise<IntegrationEventWaitBoundary>;
360
+ arm: (input: {
361
+ payload: Record<string, unknown>;
362
+ context: IntegrationEventWaitRuntimeContext;
363
+ boundary: IntegrationEventWaitBoundary;
364
+ }) => Promise<IntegrationEventWaitBoundary>;
365
+ };
366
+
367
+ export interface ContextOptions {
368
+ /** Short-lived HMAC-signed internal token for tool callbacks. Required for cloud execution. */
369
+ executorToken?: string;
370
+ baseUrl?: string;
371
+ orgId?: string;
372
+ userEmail?: string;
373
+ playName?: string;
374
+ convexUrl?: string;
375
+ staticPipeline?: PlayStaticPipeline | null;
376
+ workflowId?: string;
377
+ sessionId?: string;
378
+ verbose?: boolean;
379
+ /** Heartbeat checkpoint from a previous Temporal activity attempt. */
380
+ checkpoint?: PlayCheckpoint;
381
+ /** Enables durable boundary replay such as ctx.sleep() resumptions. */
382
+ durableBoundaries?: boolean;
383
+ /** Called after each durable batch completes — for Temporal heartbeating. */
384
+ onBatchComplete?: (checkpoint: PlayCheckpoint) => void;
385
+ /** Called when the runtime emits a new execution log line. */
386
+ onLog?: (line: string) => void;
387
+ /** Called when a row gains new partial data or stage info. */
388
+ onRowUpdate?: (update: PlayRowUpdate) => void | Promise<void>;
389
+ /** Structured execution events emitted from explicit map scopes. */
390
+ onExecutionEvent?: (event: PlayExecutionEvent) => void | Promise<void>;
391
+ /**
392
+ * Called when ctx.map() starts — inserts items into the sheet and returns
393
+ * the pending/completed split. If not provided, all items are processed.
394
+ */
395
+ onMapStart?: (
396
+ items: Record<string, unknown>[],
397
+ tableNamespace: string,
398
+ context: {
399
+ playName?: string;
400
+ playId?: string;
401
+ runId?: string;
402
+ staticPipeline?: PlayStaticPipeline | null;
403
+ },
404
+ ) => Promise<MapStartResult>;
405
+ playId?: string;
406
+ runId?: string;
407
+ resolvePlay?: (playRef: string) => Promise<ResolvedPlayExecution | null>;
408
+ getToolQueueHints?: (toolId: string) => Promise<readonly PlayQueueHint[]>;
409
+ getToolResultIdentityGetters?: (
410
+ toolId: string,
411
+ output: string,
412
+ ) => Promise<readonly string[]>;
413
+ getToolResultMetadata?: (
414
+ toolId: string,
415
+ ) => Promise<ToolResultMetadataInput | null> | ToolResultMetadataInput | null;
416
+ getIntegrationEventWaitHandler?: (
417
+ toolId: string,
418
+ ) =>
419
+ | IntegrationEventWaitHandler
420
+ | null
421
+ | Promise<IntegrationEventWaitHandler | null>;
422
+ getBatchOperationStrategy?: (
423
+ operation: string,
424
+ ) => AnyBatchOperationStrategy | null;
425
+ executeStructuredPlayDefinition?: (input: {
426
+ definition: PlayStructuredDefinition;
427
+ ctx: unknown;
428
+ rows: Record<string, unknown>[];
429
+ playInput: Record<string, unknown>;
430
+ }) => Promise<unknown>;
431
+ getRuntimeStepReceipt?: (
432
+ input: GetRuntimeStepReceiptInput,
433
+ ) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
434
+ claimRuntimeStepReceipt?: (
435
+ input: ClaimRuntimeStepReceiptInput,
436
+ ) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
437
+ completeRuntimeStepReceipt?: (
438
+ input: CompleteRuntimeStepReceiptInput,
439
+ ) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
440
+ failRuntimeStepReceipt?: (
441
+ input: FailRuntimeStepReceiptInput,
442
+ ) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
443
+ skipRuntimeStepReceipt?: (
444
+ input: SkipRuntimeStepReceiptInput,
445
+ ) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
446
+ governance?: PlayExecutionGovernanceState;
447
+ }
448
+
449
+ export interface PlayCheckpoint {
450
+ /** Waterfall batches that have completed: key = `${toolName}:${provider}`, value = results array. */
451
+ completedBatches: Record<string, BatchResult[]>;
452
+ /** Tool call batches that have completed: key = toolId, value = sparse row-cache-key -> result map. */
453
+ completedToolBatches: Record<string, Record<string, ToolBatchResult>>;
454
+ /** Row states resolved from completed batches. */
455
+ resolvedWaterfalls: Record<string, Record<string, unknown>>;
456
+ /** Durable boundary completions keyed by boundary id. */
457
+ resolvedBoundaries?: Record<
458
+ string,
459
+ | {
460
+ kind: 'sleep';
461
+ delayMs: number;
462
+ completedAt?: number;
463
+ scope?: {
464
+ type: 'workflow' | 'map_row';
465
+ tableNamespace?: string;
466
+ rowKey?: string;
467
+ rowIndex?: number;
468
+ fieldName?: string;
469
+ };
470
+ }
471
+ | {
472
+ kind: 'integration_event';
473
+ eventKey: string;
474
+ timeoutMs: number;
475
+ provider?: string;
476
+ toolId?: string;
477
+ messageRef?: {
478
+ channel: string;
479
+ ts: string;
480
+ };
481
+ output?: unknown;
482
+ completedAt?: number;
483
+ }
484
+ | {
485
+ kind: 'fetch';
486
+ url: string;
487
+ method: string;
488
+ output?: unknown;
489
+ completedAt?: number;
490
+ }
491
+ | {
492
+ kind: 'step';
493
+ stepId: string;
494
+ output?: unknown;
495
+ completedAt?: number;
496
+ }
497
+ >;
498
+ /** Per-map execution frames keyed by invocation id. */
499
+ mapFrames?: Record<string, MapExecutionFrame>;
500
+ }
501
+
502
+ export type PlayFetchResponse = {
503
+ ok: boolean;
504
+ status: number;
505
+ statusText: string;
506
+ url: string;
507
+ headers: Record<string, string>;
508
+ bodyText: string;
509
+ json: unknown | null;
510
+ };
511
+
512
+ export interface BatchResult {
513
+ rowId: number;
514
+ rowKey?: string | null;
515
+ result: unknown | null;
516
+ }
517
+
518
+ export interface ToolDefinition {
519
+ toolId: string;
520
+ provider: string;
521
+ providers?: string[]; // For waterfalls
522
+ supportsBatch?: boolean;
523
+ }
524
+
525
+ type AwaitedMapValue<T> = T extends Promise<infer U> ? AwaitedMapValue<U> : T;
526
+
527
+ export type MapResolvedFields<TColumns extends Record<string, unknown>> = {
528
+ [K in keyof TColumns]: AwaitedMapValue<TColumns[K]>;
529
+ };
530
+
531
+ export type MapAvailableFields<
532
+ TItem,
533
+ TColumns extends Record<string, unknown>,
534
+ > = TItem & Partial<MapResolvedFields<NoInfer<TColumns>>>;
535
+
536
+ export type MapFieldResolver<
537
+ TItem,
538
+ TFields = Record<string, unknown>,
539
+ TValue = unknown,
540
+ > =
541
+ | TValue
542
+ | ((
543
+ row: TItem,
544
+ ctx: unknown,
545
+ fields: TFields,
546
+ index: number,
547
+ ) => TValue | Promise<TValue>);
548
+
549
+ export type MapFieldDefinition<
550
+ TItem,
551
+ TColumns extends Record<string, unknown> = Record<string, unknown>,
552
+ > = {
553
+ [K in keyof TColumns]: MapFieldResolver<
554
+ TItem,
555
+ MapAvailableFields<TItem, TColumns>,
556
+ TColumns[K]
557
+ >;
558
+ };
559
+
560
+ export type RuntimeStepResolver<
561
+ Row = Record<string, unknown>,
562
+ Value = unknown,
563
+ > = (row: Row, ctx: unknown, index: number) => Value | Promise<Value>;
564
+
565
+ export type RuntimeConditionalStepResolver<
566
+ Row = Record<string, unknown>,
567
+ Value = unknown,
568
+ > = {
569
+ kind: 'conditional';
570
+ when: (row: Row, index: number) => boolean | Promise<boolean>;
571
+ run: RuntimeStepResolver<Row, Value>;
572
+ elseValue?: unknown;
573
+ };
574
+
575
+ export type RuntimeStepProgramStep = {
576
+ name: string;
577
+ resolver:
578
+ | RuntimeStepResolver
579
+ | RuntimeConditionalStepResolver
580
+ | RuntimeStepProgram;
581
+ };
582
+
583
+ export type RuntimeStepProgram = {
584
+ kind: 'steps';
585
+ steps: readonly RuntimeStepProgramStep[];
586
+ returnResolver?: RuntimeStepResolver;
587
+ };
588
+
589
+ export type { PlayDataset, PlayDatasetInput };
590
+
591
+ // Structured step data for UI visualization
592
+ // csv_load is NOT a step — it's part of the run metadata, not the pipeline
593
+ export type PlayStep =
594
+ | { type: 'start'; trigger?: string; description?: string }
595
+ | { type: 'csv_load'; arg?: string; rows?: number; description?: string }
596
+ | {
597
+ type: 'map';
598
+ items: number;
599
+ fields?: string[];
600
+ substeps: PlayMapSubstep[];
601
+ description?: string;
602
+ }
603
+ | {
604
+ type: 'waterfall';
605
+ tool?: string;
606
+ providers?: string[];
607
+ id?: string;
608
+ output?: string;
609
+ minResults?: number;
610
+ steps?: Array<{
611
+ id: string;
612
+ kind?: 'tool' | 'code';
613
+ toolId?: string;
614
+ results: PlayStepRowResult[];
615
+ }>;
616
+ results: PlayStepRowResult[];
617
+ description?: string;
618
+ }
619
+ | {
620
+ type: 'tool';
621
+ toolId: string;
622
+ results: PlayStepRowResult[];
623
+ description?: string;
624
+ }
625
+ | {
626
+ type: 'play_call';
627
+ playId: string;
628
+ results?: PlayStepRowResult[];
629
+ nestedSteps: PlayStep[];
630
+ description?: string;
631
+ }
632
+ | {
633
+ type: 'run_javascript';
634
+ alias: string;
635
+ results: PlayStepRowResult[];
636
+ description?: string;
637
+ }
638
+ | { type: 'return'; outputRows: number; description?: string };
639
+
640
+ /** Steps that happen INSIDE a ctx.map() — tool/waterfall calls from field resolvers. */
641
+ export type PlayMapSubstep =
642
+ | {
643
+ type: 'waterfall';
644
+ tool?: string;
645
+ providers?: string[];
646
+ id?: string;
647
+ output?: string;
648
+ minResults?: number;
649
+ steps?: Array<{
650
+ id: string;
651
+ kind?: 'tool' | 'code';
652
+ toolId?: string;
653
+ results: PlayStepRowResult[];
654
+ }>;
655
+ results: PlayStepRowResult[];
656
+ description?: string;
657
+ }
658
+ | {
659
+ type: 'tool';
660
+ toolId: string;
661
+ results: PlayStepRowResult[];
662
+ description?: string;
663
+ }
664
+ | {
665
+ type: 'play_call';
666
+ playId: string;
667
+ results?: PlayStepRowResult[];
668
+ nestedSteps: PlayStep[];
669
+ description?: string;
670
+ }
671
+ | {
672
+ type: 'run_javascript';
673
+ alias: string;
674
+ results: PlayStepRowResult[];
675
+ description?: string;
676
+ };
677
+
678
+ export interface PlayStepRowResult {
679
+ rowId: number;
680
+ status: 'completed' | 'failed' | 'missed' | 'skipped';
681
+ success: boolean;
682
+ provider?: string;
683
+ value?: unknown;
684
+ error?: string | null;
685
+ }
686
+
687
+ export interface PlayRowUpdate {
688
+ key: string;
689
+ rowId: number;
690
+ tableNamespace?: string | null;
691
+ status?: 'running' | 'completed' | 'failed';
692
+ stage?: string | null;
693
+ provider?: string | null;
694
+ error?: string | null;
695
+ dataPatch?: Record<string, unknown>;
696
+ cellMetaPatch?: Record<
697
+ string,
698
+ {
699
+ status:
700
+ | 'queued'
701
+ | 'running'
702
+ | 'completed'
703
+ | 'failed'
704
+ | 'cached'
705
+ | 'missed'
706
+ | 'skipped';
707
+ stage?: string | null;
708
+ provider?: string | null;
709
+ error?: string | null;
710
+ reused?: boolean;
711
+ }
712
+ >;
713
+ }
@@ -0,0 +1,10 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ export function createRuntimeDatasetId(
4
+ playName: string,
5
+ tableNamespace: string,
6
+ ): string {
7
+ return createHash('sha1')
8
+ .update(`${playName}:${tableNamespace}`)
9
+ .digest('hex');
10
+ }