deepline 0.1.119 → 0.1.121

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 (148) hide show
  1. package/README.md +4 -0
  2. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +21 -0
  3. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +185 -0
  4. package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-batch.ts +107 -0
  5. package/dist/{repo → bundling-sources}/sdk/src/client.ts +116 -12
  6. package/dist/bundling-sources/sdk/src/compat.ts +191 -0
  7. package/dist/bundling-sources/sdk/src/gtm.ts +146 -0
  8. package/dist/bundling-sources/sdk/src/helpers.ts +12 -0
  9. package/dist/{repo → bundling-sources}/sdk/src/index.ts +2 -1
  10. package/dist/{repo → bundling-sources}/sdk/src/play.ts +3 -1
  11. package/dist/{repo → bundling-sources}/sdk/src/plays/bundle-play-file.ts +17 -5
  12. package/dist/{repo → bundling-sources}/sdk/src/release.ts +2 -2
  13. package/dist/{repo → bundling-sources}/sdk/src/runs/observe-transport.ts +2 -3
  14. package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +3 -0
  15. package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +838 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5510 -0
  17. package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +261 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +828 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -0
  20. package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +50 -0
  21. package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +20 -0
  22. package/dist/bundling-sources/shared_libs/play-runtime/event-wait-tools.ts +9 -0
  23. package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +171 -0
  24. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +321 -0
  25. package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +158 -0
  26. package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +34 -0
  27. package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +34 -0
  28. package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +50 -0
  29. package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +119 -0
  30. package/dist/{repo → bundling-sources}/shared_libs/play-runtime/map-row-identity.ts +1 -1
  31. package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +636 -0
  32. package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +9 -0
  33. package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +197 -0
  34. package/dist/bundling-sources/shared_libs/play-runtime/projection.ts +262 -0
  35. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +143 -0
  36. package/dist/bundling-sources/shared_libs/play-runtime/public-play-contract.ts +42 -0
  37. package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +40 -0
  38. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +178 -0
  39. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +4015 -0
  40. package/dist/bundling-sources/shared_libs/play-runtime/runtime-constraints.ts +2 -0
  41. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +238 -0
  42. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +53 -0
  43. package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +149 -0
  44. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +68 -0
  45. package/dist/bundling-sources/shared_libs/play-runtime/tool-batch-executor.ts +149 -0
  46. package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +159 -0
  47. package/dist/bundling-sources/shared_libs/play-runtime/tracing.ts +33 -0
  48. package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +79 -0
  49. package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +139 -0
  50. package/dist/bundling-sources/shared_libs/plays/artifact-transport.ts +14 -0
  51. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +49 -0
  52. package/dist/bundling-sources/shared_libs/plays/compiler-manifest.ts +41 -0
  53. package/dist/bundling-sources/shared_libs/plays/dataset-summary.ts +163 -0
  54. package/dist/bundling-sources/shared_libs/plays/definition.ts +267 -0
  55. package/dist/bundling-sources/shared_libs/plays/file-refs.ts +11 -0
  56. package/dist/bundling-sources/shared_libs/plays/input-contract.ts +146 -0
  57. package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +190 -0
  58. package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +417 -0
  59. package/dist/bundling-sources/shared_libs/plays/tool-codegen.ts +142 -0
  60. package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +274 -0
  61. package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +150 -0
  62. package/dist/cli/index.js +811 -2207
  63. package/dist/cli/index.mjs +847 -2258
  64. package/dist/compiler-manifest-BjoRENv9.d.mts +227 -0
  65. package/dist/compiler-manifest-BjoRENv9.d.ts +227 -0
  66. package/dist/index.d.mts +8 -231
  67. package/dist/index.d.ts +8 -231
  68. package/dist/index.js +101 -15
  69. package/dist/index.mjs +101 -15
  70. package/dist/plays/bundle-play-file.d.mts +120 -0
  71. package/dist/plays/bundle-play-file.d.ts +120 -0
  72. package/dist/plays/bundle-play-file.mjs +1830 -0
  73. package/package.json +4 -9
  74. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-await.ts +0 -0
  75. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-submit.ts +0 -0
  76. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/coordinator-entry.ts +0 -0
  77. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/dedup-do.ts +0 -0
  78. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/entry.ts +0 -0
  79. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/csv-rows.ts +0 -0
  80. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/dataset-handles.ts +0 -0
  81. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +0 -0
  82. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/live-progress.ts +0 -0
  83. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +0 -0
  84. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/receipts.ts +0 -0
  85. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/row-isolation.ts +0 -0
  86. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/tool-http-errors.ts +0 -0
  87. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-instance-create.ts +0 -0
  88. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry-state.ts +0 -0
  89. /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry.ts +0 -0
  90. /package/dist/{repo → bundling-sources}/sdk/src/agent-runtime.ts +0 -0
  91. /package/dist/{repo → bundling-sources}/sdk/src/config.ts +0 -0
  92. /package/dist/{repo → bundling-sources}/sdk/src/errors.ts +0 -0
  93. /package/dist/{repo → bundling-sources}/sdk/src/http.ts +0 -0
  94. /package/dist/{repo → bundling-sources}/sdk/src/plays/harness-stub.ts +0 -0
  95. /package/dist/{repo → bundling-sources}/sdk/src/plays/local-file-discovery.ts +0 -0
  96. /package/dist/{repo → bundling-sources}/sdk/src/stream-reconnect.ts +0 -0
  97. /package/dist/{repo → bundling-sources}/sdk/src/tool-output.ts +0 -0
  98. /package/dist/{repo → bundling-sources}/sdk/src/types.ts +0 -0
  99. /package/dist/{repo → bundling-sources}/sdk/src/version.ts +0 -0
  100. /package/dist/{repo → bundling-sources}/sdk/src/worker-play-entry.ts +0 -0
  101. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/cell-policy.ts +0 -0
  102. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/column-names.ts +0 -0
  103. /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/sheet-contract.ts +0 -0
  104. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/backend.ts +0 -0
  105. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batch-runtime.ts +0 -0
  106. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batching-types.ts +0 -0
  107. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/cell-staleness.ts +0 -0
  108. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/coordinator-headers.ts +0 -0
  109. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/csv-rename.ts +0 -0
  110. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-crypto.ts +0 -0
  111. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-plan.ts +0 -0
  112. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session.ts +0 -0
  113. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/dedup-backend.ts +0 -0
  114. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/default-batch-strategies.ts +0 -0
  115. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/email-status.ts +0 -0
  116. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/execution-plan.ts +0 -0
  117. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/extractor-targets.ts +0 -0
  118. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/fullenrich-batching.ts +0 -0
  119. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/coordinator-rate-state-backend.ts +0 -0
  120. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/governor.ts +0 -0
  121. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/policy.ts +0 -0
  122. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/rate-state-backend.ts +0 -0
  123. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/live-events.ts +0 -0
  124. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/play-runtime-batching-registry.ts +0 -0
  125. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/profiles.ts +0 -0
  126. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/providers.ts +0 -0
  127. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-failure.ts +0 -0
  128. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-ledger.ts +0 -0
  129. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-snapshot-stream.ts +0 -0
  130. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/scheduler-backend.ts +0 -0
  131. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-capability.ts +0 -0
  132. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-redaction.ts +0 -0
  133. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -0
  134. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-program-dataset-builder.ts +0 -0
  135. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/submit-limits.ts +0 -0
  136. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/tool-result.ts +0 -0
  137. /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/work-receipts.ts +0 -0
  138. /package/dist/{repo → bundling-sources}/shared_libs/plays/bootstrap-routes.ts +0 -0
  139. /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/index.ts +0 -0
  140. /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/limits.ts +0 -0
  141. /package/dist/{repo → bundling-sources}/shared_libs/plays/contracts.ts +0 -0
  142. /package/dist/{repo → bundling-sources}/shared_libs/plays/dataset.ts +0 -0
  143. /package/dist/{repo → bundling-sources}/shared_libs/plays/row-identity.ts +0 -0
  144. /package/dist/{repo → bundling-sources}/shared_libs/plays/secret-guardrails.ts +0 -0
  145. /package/dist/{repo → bundling-sources}/shared_libs/plays/static-pipeline.ts +0 -0
  146. /package/dist/{repo → bundling-sources}/shared_libs/security/outbound-url-policy.ts +0 -0
  147. /package/dist/{repo → bundling-sources}/shared_libs/security/safe-fetch.ts +0 -0
  148. /package/dist/{repo → bundling-sources}/shared_libs/temporal/constants.ts +0 -0
@@ -0,0 +1,197 @@
1
+ import { sqlSafePlayColumnName } from '@shared_libs/plays/static-pipeline';
2
+ import type {
3
+ InlineWaterfallSpec,
4
+ MapExecutionScope,
5
+ PlayExecutionEvent,
6
+ PlayRowUpdate,
7
+ } from './ctx-types';
8
+
9
+ type RowContextSnapshot = {
10
+ fieldName?: string;
11
+ mapScope?: MapExecutionScope;
12
+ } | null;
13
+
14
+ type CellStatus =
15
+ | 'queued'
16
+ | 'running'
17
+ | 'completed'
18
+ | 'failed'
19
+ | 'cached'
20
+ | 'missed'
21
+ | 'skipped';
22
+
23
+ export class PlayProgressEmitter {
24
+ constructor(
25
+ private readonly onRowUpdate:
26
+ | ((update: PlayRowUpdate) => void | Promise<void>)
27
+ | undefined,
28
+ private readonly onExecutionEvent:
29
+ | ((event: PlayExecutionEvent) => void | Promise<void>)
30
+ | undefined,
31
+ private readonly getRowContext: () => RowContextSnapshot,
32
+ private readonly isInlineWaterfallToolStep: (
33
+ step: InlineWaterfallSpec['steps'][number],
34
+ ) => boolean,
35
+ ) {}
36
+
37
+ executionEvent(event: PlayExecutionEvent): void {
38
+ if (!this.onExecutionEvent) {
39
+ return;
40
+ }
41
+ void this.onExecutionEvent(event);
42
+ }
43
+
44
+ rowUpdate(
45
+ key: string | null,
46
+ tableNamespace: string | null,
47
+ update: Omit<PlayRowUpdate, 'key'>,
48
+ ): void {
49
+ const rowContext = this.getRowContext();
50
+ const rowScope = rowContext?.mapScope;
51
+ if (rowScope && key) {
52
+ this.executionEvent({
53
+ type: 'map.row.updated',
54
+ mapInvocationId: rowScope.mapInvocationId,
55
+ mapNodeId: rowScope.mapNodeId ?? null,
56
+ logicalNamespace: rowScope.logicalNamespace,
57
+ artifactTableNamespace: rowScope.artifactTableNamespace,
58
+ rowKey: key,
59
+ rowStatus: update.status,
60
+ fieldName: rowContext?.fieldName ?? null,
61
+ stage: update.stage ?? null,
62
+ provider: update.provider ?? null,
63
+ at: Date.now(),
64
+ });
65
+ }
66
+ if (!key || !this.onRowUpdate) {
67
+ return;
68
+ }
69
+ void this.onRowUpdate({
70
+ ...update,
71
+ key,
72
+ tableNamespace,
73
+ });
74
+ }
75
+
76
+ fieldMetaUpdate(input: {
77
+ rowId: number;
78
+ key: string | null;
79
+ tableNamespace: string | null;
80
+ fieldName?: string | null;
81
+ status: CellStatus;
82
+ rowStatus?: PlayRowUpdate['status'];
83
+ stage?: string | null;
84
+ provider?: string | null;
85
+ error?: string | null;
86
+ reused?: boolean;
87
+ dataPatch?: Record<string, unknown>;
88
+ }): void {
89
+ if (!input.fieldName) {
90
+ this.rowUpdate(input.key, input.tableNamespace, {
91
+ rowId: input.rowId,
92
+ status: input.rowStatus,
93
+ stage: input.stage ?? null,
94
+ provider: input.provider ?? null,
95
+ error: input.error ?? null,
96
+ dataPatch: input.dataPatch ?? {},
97
+ });
98
+ return;
99
+ }
100
+
101
+ this.rowUpdate(input.key, input.tableNamespace, {
102
+ rowId: input.rowId,
103
+ status: input.rowStatus,
104
+ stage: input.stage ?? null,
105
+ provider: input.provider ?? null,
106
+ error: input.error ?? null,
107
+ dataPatch: input.dataPatch ?? {},
108
+ cellMetaPatch: {
109
+ [input.fieldName]: {
110
+ status: input.status,
111
+ stage: input.stage ?? null,
112
+ provider: input.provider ?? null,
113
+ error: input.error ?? null,
114
+ ...(input.reused !== undefined ? { reused: input.reused } : {}),
115
+ },
116
+ },
117
+ });
118
+ }
119
+
120
+ cellUpdate(input: {
121
+ rowId: number;
122
+ key: string | null;
123
+ tableNamespace: string | null;
124
+ columnName: string;
125
+ status: CellStatus;
126
+ rowStatus?: PlayRowUpdate['status'];
127
+ stage?: string | null;
128
+ provider?: string | null;
129
+ error?: string | null;
130
+ producer?: {
131
+ kind: 'play' | 'tool' | 'code';
132
+ id?: string | null;
133
+ displayName?: string | null;
134
+ playId?: string | null;
135
+ toolId?: string | null;
136
+ runId?: string | null;
137
+ } | null;
138
+ value?: unknown;
139
+ }): void {
140
+ this.rowUpdate(input.key, input.tableNamespace, {
141
+ rowId: input.rowId,
142
+ status: input.rowStatus,
143
+ stage: input.stage ?? null,
144
+ provider: input.provider ?? null,
145
+ error: input.error ?? null,
146
+ dataPatch:
147
+ input.value === undefined ? {} : { [input.columnName]: input.value },
148
+ cellMetaPatch: {
149
+ [input.columnName]: {
150
+ status: input.status,
151
+ stage: input.stage ?? null,
152
+ provider: input.provider ?? null,
153
+ error: input.error ?? null,
154
+ ...(input.producer !== undefined ? { producer: input.producer } : {}),
155
+ },
156
+ },
157
+ });
158
+ }
159
+
160
+ queuedInlineWaterfallSteps(input: {
161
+ rowId: number;
162
+ key: string | null;
163
+ tableNamespace: string | null;
164
+ spec: InlineWaterfallSpec;
165
+ }): void {
166
+ for (const step of input.spec.steps) {
167
+ this.cellUpdate({
168
+ rowId: input.rowId,
169
+ key: input.key,
170
+ tableNamespace: input.tableNamespace,
171
+ columnName: sqlSafePlayColumnName(`${input.spec.id}.${step.id}`),
172
+ status: 'queued',
173
+ stage: step.id,
174
+ provider: this.isInlineWaterfallToolStep(step)
175
+ ? (
176
+ step as Extract<
177
+ InlineWaterfallSpec['steps'][number],
178
+ { toolId: string }
179
+ >
180
+ ).toolId
181
+ : 'code',
182
+ producer: this.isInlineWaterfallToolStep(step)
183
+ ? {
184
+ kind: 'tool',
185
+ toolId: (
186
+ step as Extract<
187
+ InlineWaterfallSpec['steps'][number],
188
+ { toolId: string }
189
+ >
190
+ ).toolId,
191
+ }
192
+ : { kind: 'code', id: step.id },
193
+ value: null,
194
+ });
195
+ }
196
+ }
197
+ }
@@ -0,0 +1,262 @@
1
+ // The single extractor "projection" interpreter.
2
+ //
3
+ // "Projection" is the step that turns a provider response into the value a
4
+ // target (email, email_status, phone, ...) resolves to. Historically this was
5
+ // reimplemented in three runtimes (the V2 tool-result runtime, the playground
6
+ // waterfall runtime, and the emitted V1-enrich play) with divergent precedence
7
+ // — a latent drift bug class. This module is the one authoritative
8
+ // implementation: callers supply a `ProjectionLookup` that knows how to walk
9
+ // THEIR payload shape, and `project` applies the one fixed precedence.
10
+ //
11
+ // Leaf module: depends only on email-status.ts + extractor-targets.ts, no other
12
+ // runtime code, no Zod — safe inside the size-capped workers-lite bundle.
13
+ //
14
+ // See docs/extractor-projection-unification.md and CONTEXT.md ("Provider Email
15
+ // Status Contract").
16
+
17
+ import { buildEmailStatus } from './email-status';
18
+ import type { EmailStatusExtractorConfig } from './email-status';
19
+ import {
20
+ JOB_CHANGE_STATUS_VALUES,
21
+ type JobChangeGetterValue,
22
+ type JobChangeStatus,
23
+ } from './extractor-targets';
24
+
25
+ /** A located value (value + the concrete path it came from), or null on miss. */
26
+ export type ProjectionHit = { value: unknown; path: string } | null;
27
+
28
+ /**
29
+ * The only seam-crossing dependency. Each runtime supplies an adapter that
30
+ * resolves a list of candidate paths against its own payload shape and returns
31
+ * the first meaningful hit (or null). This absorbs the input-shape difference
32
+ * (V2 `{toolResponse:{raw}}` envelope vs playground raw payload vs the enrich
33
+ * play's pre-projected getters); the interpreter itself is payload-agnostic.
34
+ */
35
+ export type ProjectionLookup = (paths: readonly string[]) => ProjectionHit;
36
+
37
+ export type ProjectionOverrideRule = {
38
+ paths: readonly string[];
39
+ equals?: string | number | boolean | null;
40
+ value: string | number | boolean | null;
41
+ };
42
+
43
+ /** The serializable descriptor shape (a structural subset of
44
+ * ToolResultExtractorDescriptor — descriptors stay plain JSON on the wire). */
45
+ export type ProjectionDescriptor = {
46
+ paths: readonly string[];
47
+ transforms?: readonly string[];
48
+ enum?: readonly string[];
49
+ overrides?: readonly ProjectionOverrideRule[];
50
+ emailStatus?: EmailStatusExtractorConfig;
51
+ };
52
+
53
+ // --- small value helpers (kept local so this module stays a dependency-free leaf) ---
54
+
55
+ function normalizeString(value: unknown): string | null {
56
+ if (typeof value === 'string') {
57
+ const trimmed = value.trim();
58
+ return trimmed ? trimmed : null;
59
+ }
60
+ if (typeof value === 'number' && Number.isFinite(value)) {
61
+ return String(value);
62
+ }
63
+ return null;
64
+ }
65
+
66
+ function isRecord(value: unknown): value is Record<string, unknown> {
67
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
68
+ }
69
+
70
+ // --- typed-signal coercions (one home for every status normalizer) ---
71
+
72
+ function normalizePhoneStatus(value: unknown): unknown {
73
+ if (typeof value === 'boolean') return value ? 'valid' : 'invalid';
74
+ const normalized = normalizeString(value)
75
+ ?.toLowerCase()
76
+ .replace(/[\s-]+/g, '_');
77
+ if (!normalized) return 'unknown';
78
+ if (['verified', 'ok', 'true', 'active'].includes(normalized)) return 'valid';
79
+ if (
80
+ ['bad', 'false', 'failed', 'inactive', 'disconnected'].includes(normalized)
81
+ ) {
82
+ return 'invalid';
83
+ }
84
+ return normalized;
85
+ }
86
+
87
+ function normalizeJobChangeStatus(value: unknown): unknown {
88
+ if (typeof value === 'boolean') return value ? 'moved' : 'no_change';
89
+ const normalized = normalizeString(value)
90
+ ?.toLowerCase()
91
+ .replace(/[\s-]+/g, '_');
92
+ if (!normalized) return 'unknown';
93
+ if (['true', 'yes', 'moved', 'changed', 'new_company'].includes(normalized)) {
94
+ return 'moved';
95
+ }
96
+ if (['false', 'no', 'same', 'no_change'].includes(normalized))
97
+ return 'no_change';
98
+ if (['left', 'left_company'].includes(normalized)) return 'left_company';
99
+ if ((JOB_CHANGE_STATUS_VALUES as readonly string[]).includes(normalized)) {
100
+ return normalized;
101
+ }
102
+ return 'unknown';
103
+ }
104
+
105
+ function firstExperienceDate(value: unknown): string | null {
106
+ if (!Array.isArray(value)) return null;
107
+ for (const entry of value) {
108
+ if (!isRecord(entry)) continue;
109
+ const date = normalizeString(
110
+ entry.start_date ?? entry.started_at ?? entry.startDate,
111
+ );
112
+ if (date) return date;
113
+ }
114
+ return null;
115
+ }
116
+
117
+ function normalizeJobChange(value: unknown): JobChangeGetterValue {
118
+ const record = isRecord(value) ? value : {};
119
+ const nested = isRecord(record.job_change) ? record.job_change : record;
120
+ const output = isRecord(nested.output) ? nested.output : nested;
121
+ const person = isRecord(output.person) ? output.person : {};
122
+ const status = normalizeJobChangeStatus(
123
+ output.status ??
124
+ output.job_change_status ??
125
+ output.job_changed ??
126
+ output.changed,
127
+ ) as JobChangeStatus;
128
+ const moved = status === 'moved';
129
+
130
+ return {
131
+ status,
132
+ date: moved
133
+ ? normalizeString(
134
+ output.date ??
135
+ output.job_change_date ??
136
+ output.change_date ??
137
+ output.changed_at,
138
+ ) ?? firstExperienceDate(person.experiences)
139
+ : null,
140
+ new_company: moved
141
+ ? normalizeString(
142
+ output.new_company ??
143
+ output.current_company ??
144
+ person.company_name ??
145
+ person.current_company,
146
+ )
147
+ : null,
148
+ new_title: moved
149
+ ? normalizeString(
150
+ output.new_title ??
151
+ output.current_title ??
152
+ person.title ??
153
+ person.headline,
154
+ )
155
+ : null,
156
+ };
157
+ }
158
+
159
+ function applyTransforms(
160
+ value: unknown,
161
+ transforms: readonly string[] | undefined,
162
+ ): unknown {
163
+ return (transforms ?? []).reduce((current, transform) => {
164
+ // email_status is materialized by emailStatus (the Provider Email Status
165
+ // Contract), never by a string transform — so an `emailStatus` transform is
166
+ // a no-op and falls through to `return current`.
167
+ if (transform.endsWith('phoneStatus')) return normalizePhoneStatus(current);
168
+ if (transform === 'jobChange') return normalizeJobChange(current);
169
+ if (transform === 'jobChangeStatus')
170
+ return normalizeJobChangeStatus(current);
171
+ return current;
172
+ }, value);
173
+ }
174
+
175
+ function coerceToEnum(
176
+ value: unknown,
177
+ enumValues: readonly string[] | undefined,
178
+ ): unknown {
179
+ if (!enumValues?.length) return value;
180
+ const normalized = normalizeString(value);
181
+ if (!normalized) return value;
182
+ return enumValues.includes(normalized) ? normalized : value;
183
+ }
184
+
185
+ function findOverride(
186
+ overrides: readonly ProjectionOverrideRule[] | undefined,
187
+ lookup: ProjectionLookup,
188
+ ): { value: string | number | boolean | null } | null {
189
+ for (const override of overrides ?? []) {
190
+ const expected = Object.prototype.hasOwnProperty.call(override, 'equals')
191
+ ? override.equals
192
+ : true;
193
+ for (const path of override.paths) {
194
+ const match = lookup([path]);
195
+ if (!match) continue;
196
+ if (match.value === expected) return { value: override.value };
197
+ }
198
+ }
199
+ return null;
200
+ }
201
+
202
+ function projectEmailStatus(
203
+ config: EmailStatusExtractorConfig,
204
+ lookup: ProjectionLookup,
205
+ ): ProjectionHit {
206
+ const values: Record<string, unknown> = {};
207
+ const pathSets: Record<string, readonly string[] | undefined> = {
208
+ rawStatus: config.rawStatus,
209
+ rawScore: config.rawScore,
210
+ valid: config.valid,
211
+ deliverability: config.deliverability,
212
+ catchAll: config.catchAll,
213
+ mxProvider: config.mxProvider,
214
+ mxRecord: config.mxRecord,
215
+ fraudScore: config.fraudScore,
216
+ disposable: config.disposable,
217
+ roleBased: config.roleBased,
218
+ freeEmail: config.freeEmail,
219
+ abuse: config.abuse,
220
+ spamtrap: config.spamtrap,
221
+ suspect: config.suspect,
222
+ };
223
+ let firstPath: string | null = null;
224
+ for (const [name, paths] of Object.entries(pathSets)) {
225
+ if (!paths) continue;
226
+ const match = lookup(paths);
227
+ if (!match) continue;
228
+ values[name] = match.value;
229
+ firstPath ??= match.path;
230
+ }
231
+ if (!firstPath) return null;
232
+ return { path: firstPath, value: buildEmailStatus({ config, values }) };
233
+ }
234
+
235
+ /**
236
+ * Project one extractor descriptor against a payload (via `lookup`).
237
+ *
238
+ * Fixed precedence (identical for every runtime):
239
+ * 1. emailStatus → buildEmailStatus(...) (terminal; never transformed/enum'd)
240
+ * 2. paths → first meaningful hit
241
+ * 3. transforms → phoneStatus | jobChange | jobChangeStatus
242
+ * 4. enum → keep value if not in the set
243
+ * 5. overrides → a matching override wins over the resolved value
244
+ *
245
+ * Returns null when nothing meaningful resolves (caller omits the target).
246
+ */
247
+ export function project(
248
+ descriptor: ProjectionDescriptor,
249
+ lookup: ProjectionLookup,
250
+ ): ProjectionHit {
251
+ if (descriptor.emailStatus) {
252
+ return projectEmailStatus(descriptor.emailStatus, lookup);
253
+ }
254
+ const base = lookup(descriptor.paths);
255
+ if (!base) return null;
256
+ const transformed = coerceToEnum(
257
+ applyTransforms(base.value, descriptor.transforms),
258
+ descriptor.enum,
259
+ );
260
+ const override = findOverride(descriptor.overrides, lookup);
261
+ return { path: base.path, value: override?.value ?? transformed };
262
+ }
@@ -0,0 +1,143 @@
1
+ import type { PlayBundleArtifact } from '../plays/artifact-types';
2
+ import type {
3
+ PlayCheckpoint,
4
+ PlayExecutionEvent,
5
+ PlayRowUpdate,
6
+ PlayStep,
7
+ } from './ctx-types';
8
+ import type { PlayExecutionSuspension } from './suspension';
9
+ import type { PlayStaticPipeline } from '../plays/static-pipeline';
10
+ import type { PlayLiveEventSource } from './live-events';
11
+ import type { PreloadedRuntimeDbSession } from './db-session';
12
+
13
+ export interface PlayRunnerContextConfig {
14
+ executorToken?: string;
15
+ baseUrl?: string;
16
+ vercelProtectionBypassToken?: string | null;
17
+ orgId?: string;
18
+ workflowId?: string;
19
+ playId?: string;
20
+ runId?: string;
21
+ playName?: string;
22
+ userEmail?: string;
23
+ convexUrl?: string;
24
+ staticPipeline?: PlayStaticPipeline | null;
25
+ /**
26
+ * Controls how scoped Postgres sessions enter the runner. `preloaded` means
27
+ * the launch config carries short-lived encrypted sessions minted before
28
+ * dispatch; `sandbox_public_key` means the runner mints missing sessions
29
+ * through the app runtime API with a per-request public key.
30
+ */
31
+ dbSessionStrategy?: 'preloaded' | 'sandbox_public_key';
32
+ /**
33
+ * Short-lived scoped Postgres sessions minted by the worker before the runner
34
+ * starts. They are only an initial fast path: the runner still renews through
35
+ * the app runtime API when a session is absent, too close to expiry, or not an
36
+ * exact-enough match for the requested play/table/operation scope.
37
+ */
38
+ preloadedDbSessions?: PreloadedRuntimeDbSession[];
39
+ }
40
+
41
+ export interface PlayRunnerExecutionConfig {
42
+ artifact: PlayBundleArtifact;
43
+ artifactTransport?: {
44
+ bundledCodePath?: string | null;
45
+ bundledCodeEncoding?: 'utf8' | 'gzip';
46
+ } | null;
47
+ input: Record<string, unknown>;
48
+ checkpoint?: PlayCheckpoint | null;
49
+ csvSourcePath?: string | null;
50
+ csvSourceUrl?: string | null;
51
+ csvSourceContentBase64?: string | null;
52
+ runtimeInputAlias?: string | null;
53
+ materializedFiles: Record<string, string>;
54
+ workspaceRoot: string;
55
+ context: PlayRunnerContextConfig;
56
+ }
57
+
58
+ export type PlayRunnerLogEvent = {
59
+ type: 'log';
60
+ at: string;
61
+ source: PlayLiveEventSource;
62
+ line: string;
63
+ };
64
+
65
+ export type PlayRunnerEvent =
66
+ | PlayRunnerLogEvent
67
+ | {
68
+ type: 'checkpoint';
69
+ checkpoint: PlayCheckpoint;
70
+ }
71
+ | {
72
+ type: 'row_update';
73
+ update: PlayRowUpdate;
74
+ }
75
+ | {
76
+ type: 'execution_event';
77
+ event: PlayExecutionEvent;
78
+ }
79
+ | {
80
+ type: 'result';
81
+ result: PlayRunnerResult;
82
+ };
83
+
84
+ export type PlayRunnerDeferredRuntimeTask = {
85
+ kind: 'daytona_sandbox_cleanup';
86
+ sandboxId: string;
87
+ billingStartedAt: number;
88
+ cpu: number;
89
+ memoryGiB: number;
90
+ diskGiB: number;
91
+ };
92
+
93
+ export type PlayRunnerRuntimeTiming = {
94
+ backend: 'daytona';
95
+ daytonaCreateMs?: number;
96
+ daytonaUploadMs?: number;
97
+ daytonaExecuteMs?: number;
98
+ };
99
+
100
+ export type PlayRunnerResult =
101
+ | {
102
+ status: 'completed';
103
+ output: unknown;
104
+ outputRowCount?: number;
105
+ logs: string[];
106
+ stats: Record<string, unknown>;
107
+ steps: PlayStep[];
108
+ checkpoint: PlayCheckpoint;
109
+ tableNamespace?: string | null;
110
+ totalRows?: number;
111
+ inserted?: number;
112
+ skipped?: number;
113
+ runtimeTiming?: PlayRunnerRuntimeTiming;
114
+ deferredRuntimeTasks?: PlayRunnerDeferredRuntimeTask[];
115
+ }
116
+ | {
117
+ status: 'suspended';
118
+ suspension: PlayExecutionSuspension;
119
+ logs: string[];
120
+ stats: Record<string, unknown>;
121
+ steps: PlayStep[];
122
+ checkpoint: PlayCheckpoint;
123
+ tableNamespace?: string | null;
124
+ totalRows?: number;
125
+ inserted?: number;
126
+ skipped?: number;
127
+ runtimeTiming?: PlayRunnerRuntimeTiming;
128
+ deferredRuntimeTasks?: PlayRunnerDeferredRuntimeTask[];
129
+ }
130
+ | {
131
+ status: 'failed';
132
+ error: string;
133
+ logs: string[];
134
+ stats: Record<string, unknown>;
135
+ steps: PlayStep[];
136
+ checkpoint?: PlayCheckpoint | null;
137
+ tableNamespace?: string | null;
138
+ totalRows?: number;
139
+ inserted?: number;
140
+ skipped?: number;
141
+ runtimeTiming?: PlayRunnerRuntimeTiming;
142
+ deferredRuntimeTasks?: PlayRunnerDeferredRuntimeTask[];
143
+ };
@@ -0,0 +1,42 @@
1
+ export type PublicPlayRunStatus =
2
+ | 'queued'
3
+ | 'running'
4
+ | 'waiting'
5
+ | 'completed'
6
+ | 'failed'
7
+ | 'cancelled';
8
+
9
+ export interface PublicPlayRunResult {
10
+ success: boolean;
11
+ runId: string;
12
+ result?: unknown;
13
+ logs: string[];
14
+ durationMs: number;
15
+ error?: string;
16
+ }
17
+
18
+ export interface PublicPlayProgressStatus {
19
+ status: string;
20
+ totalRows?: number;
21
+ logs: string[];
22
+ error?: string;
23
+ }
24
+
25
+ export interface PublicPlayWaitState {
26
+ kind: 'integration_event' | 'sleep';
27
+ boundaryId?: string;
28
+ eventKey?: string;
29
+ until?: number;
30
+ }
31
+
32
+ export interface PublicPlayStatus {
33
+ runId: string;
34
+ apiVersion?: number;
35
+ status: PublicPlayRunStatus;
36
+ error?: string;
37
+ progress?: PublicPlayProgressStatus;
38
+ result?: unknown;
39
+ resultView?: unknown;
40
+ contract?: Record<string, unknown> | null;
41
+ wait?: PublicPlayWaitState | null;
42
+ }
@@ -0,0 +1,40 @@
1
+ import type { WorkReceiptStatus } from './work-receipts';
2
+
3
+ export const RECEIPT_STATUS_CODE = {
4
+ pending: 0,
5
+ running: 1,
6
+ completed: 2,
7
+ failed: 3,
8
+ skipped: 4,
9
+ } as const satisfies Record<WorkReceiptStatus, number>;
10
+
11
+ export type ReceiptStatusCode =
12
+ (typeof RECEIPT_STATUS_CODE)[keyof typeof RECEIPT_STATUS_CODE];
13
+
14
+ export function receiptStatusFromCode(value: unknown): WorkReceiptStatus {
15
+ switch (Number(value ?? RECEIPT_STATUS_CODE.pending)) {
16
+ case RECEIPT_STATUS_CODE.running:
17
+ return 'running';
18
+ case RECEIPT_STATUS_CODE.completed:
19
+ return 'completed';
20
+ case RECEIPT_STATUS_CODE.failed:
21
+ return 'failed';
22
+ case RECEIPT_STATUS_CODE.skipped:
23
+ return 'skipped';
24
+ case RECEIPT_STATUS_CODE.pending:
25
+ default:
26
+ return 'pending';
27
+ }
28
+ }
29
+
30
+ export function receiptCodeFromStatus(
31
+ status: WorkReceiptStatus,
32
+ ): ReceiptStatusCode {
33
+ return RECEIPT_STATUS_CODE[status];
34
+ }
35
+
36
+ export function receiptStatusCodeFromUnknown(
37
+ value: unknown,
38
+ ): ReceiptStatusCode {
39
+ return receiptCodeFromStatus(receiptStatusFromCode(value));
40
+ }