deepline 0.1.88 → 0.1.90
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.
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/index.d.mts +64 -38
- package/dist/index.d.ts +64 -38
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/repo/apps/play-runner-workers/src/entry.ts +92 -181
- package/dist/repo/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +44 -0
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +202 -12
- package/dist/repo/shared_libs/plays/row-identity.ts +14 -8
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -229,10 +229,10 @@ var import_node_path2 = require("path");
|
|
|
229
229
|
|
|
230
230
|
// src/release.ts
|
|
231
231
|
var SDK_RELEASE = {
|
|
232
|
-
version: "0.1.
|
|
232
|
+
version: "0.1.90",
|
|
233
233
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
234
234
|
supportPolicy: {
|
|
235
|
-
latest: "0.1.
|
|
235
|
+
latest: "0.1.90",
|
|
236
236
|
minimumSupported: "0.1.53",
|
|
237
237
|
deprecatedBelow: "0.1.53"
|
|
238
238
|
}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -206,10 +206,10 @@ import { join as join2 } from "path";
|
|
|
206
206
|
|
|
207
207
|
// src/release.ts
|
|
208
208
|
var SDK_RELEASE = {
|
|
209
|
-
version: "0.1.
|
|
209
|
+
version: "0.1.90",
|
|
210
210
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
211
211
|
supportPolicy: {
|
|
212
|
-
latest: "0.1.
|
|
212
|
+
latest: "0.1.90",
|
|
213
213
|
minimumSupported: "0.1.53",
|
|
214
214
|
deprecatedBelow: "0.1.53"
|
|
215
215
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -13,7 +13,17 @@ declare const PLAY_ARTIFACT_KINDS: {
|
|
|
13
13
|
};
|
|
14
14
|
type PlayArtifactKind = (typeof PLAY_ARTIFACT_KINDS)[keyof typeof PLAY_ARTIFACT_KINDS];
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* A top-level key the play's function literally `return`s. Derived from the
|
|
18
|
+
* `return { ... }` object literal — NOT from dataset `.withColumn(...)` names —
|
|
19
|
+
* so the "Returns" graph node mirrors the function's real output shape.
|
|
20
|
+
* `isDataset` is true when the key's value is a `PlayDataset` handle (a table).
|
|
21
|
+
*/
|
|
22
|
+
interface PlayStaticReturnField {
|
|
23
|
+
name: string;
|
|
24
|
+
isDataset: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface PlayStaticPipeline {
|
|
17
27
|
tableNamespace?: string;
|
|
18
28
|
inputFields?: string[];
|
|
19
29
|
rowKeyFields?: string[];
|
|
@@ -22,16 +32,22 @@ interface PlayStaticPipelineSnapshot {
|
|
|
22
32
|
csvDescription?: string;
|
|
23
33
|
datasetDescription?: string;
|
|
24
34
|
fields: string[];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Top-level keys of the play's `return { ... }` object literal, in source
|
|
37
|
+
* order. Undefined when the terminal return isn't a statically-known object
|
|
38
|
+
* literal (bare value, dataset handle, conditional returns, etc.).
|
|
39
|
+
*/
|
|
40
|
+
returnFields?: PlayStaticReturnField[];
|
|
41
|
+
stages?: PlayStaticSubstep[];
|
|
42
|
+
substeps: PlayStaticSubstep[];
|
|
43
|
+
sheetContract?: PlaySheetContract | null;
|
|
28
44
|
sheetContractErrors?: string[];
|
|
29
45
|
}
|
|
30
|
-
type
|
|
31
|
-
interface
|
|
46
|
+
type PlaySheetColumnSource = 'input' | 'datasetColumn' | 'waterfallStep' | 'childPlayColumn';
|
|
47
|
+
interface PlaySheetColumnContract {
|
|
32
48
|
id: string;
|
|
33
49
|
sqlName: string;
|
|
34
|
-
source:
|
|
50
|
+
source: PlaySheetColumnSource;
|
|
35
51
|
field?: string;
|
|
36
52
|
parentField?: string;
|
|
37
53
|
playId?: string;
|
|
@@ -42,44 +58,49 @@ interface PlaySheetColumnContractSnapshot {
|
|
|
42
58
|
toolId?: string;
|
|
43
59
|
isRowKey?: boolean;
|
|
44
60
|
}
|
|
45
|
-
interface
|
|
61
|
+
interface PlaySheetContract {
|
|
46
62
|
tableNamespace: string;
|
|
47
|
-
columns:
|
|
63
|
+
columns: PlaySheetColumnContract[];
|
|
48
64
|
}
|
|
49
|
-
type
|
|
50
|
-
interface
|
|
65
|
+
type PlayStaticColumnProducerKind = 'tool' | 'waterfall' | 'stepProgram' | 'playCall' | 'controlFlow' | 'transform';
|
|
66
|
+
interface PlayStaticColumnProducer {
|
|
51
67
|
id: string;
|
|
52
|
-
kind:
|
|
68
|
+
kind: PlayStaticColumnProducerKind;
|
|
53
69
|
field: string;
|
|
54
70
|
toolId?: string;
|
|
55
71
|
playId?: string;
|
|
72
|
+
dependsOnFields?: string[];
|
|
73
|
+
staleAfterSeconds?: number;
|
|
56
74
|
conditional?: boolean;
|
|
57
|
-
sourceRange?:
|
|
58
|
-
steps?:
|
|
59
|
-
substep:
|
|
75
|
+
sourceRange?: PlayStaticSourceRange;
|
|
76
|
+
steps?: PlayStaticColumnProducer[];
|
|
77
|
+
substep: PlayStaticSubstep;
|
|
60
78
|
}
|
|
61
|
-
interface
|
|
79
|
+
interface PlayStaticDatasetColumn {
|
|
62
80
|
id: string;
|
|
63
|
-
source:
|
|
81
|
+
source: PlaySheetColumnSource;
|
|
64
82
|
sqlName?: string;
|
|
65
|
-
|
|
83
|
+
staleAfterSeconds?: number;
|
|
84
|
+
producers: PlayStaticColumnProducer[];
|
|
66
85
|
}
|
|
67
|
-
interface
|
|
86
|
+
interface PlayStaticSourceRange {
|
|
68
87
|
sourcePath?: string;
|
|
69
88
|
startLine: number;
|
|
70
89
|
endLine: number;
|
|
71
90
|
startColumn: number;
|
|
72
91
|
endColumn: number;
|
|
73
92
|
}
|
|
74
|
-
type
|
|
93
|
+
type PlayStaticSubstepMetadata = {
|
|
75
94
|
conditional?: boolean;
|
|
95
|
+
dependsOnFields?: string[];
|
|
96
|
+
staleAfterSeconds?: number;
|
|
76
97
|
};
|
|
77
|
-
type
|
|
98
|
+
type PlayStaticSubstep = PlayStaticSubstepMetadata & ({
|
|
78
99
|
type: 'csv';
|
|
79
100
|
field: string;
|
|
80
101
|
path?: string;
|
|
81
102
|
description?: string;
|
|
82
|
-
sourceRange?:
|
|
103
|
+
sourceRange?: PlayStaticSourceRange;
|
|
83
104
|
callDepth?: number;
|
|
84
105
|
callPath?: string[];
|
|
85
106
|
} | {
|
|
@@ -90,22 +111,24 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
90
111
|
inputFields?: string[];
|
|
91
112
|
rowKeyFields?: string[];
|
|
92
113
|
outputFields?: string[];
|
|
93
|
-
columns?:
|
|
114
|
+
columns?: PlayStaticDatasetColumn[];
|
|
94
115
|
waterfallIds?: string[];
|
|
95
|
-
steps?:
|
|
96
|
-
sheetContract?:
|
|
116
|
+
steps?: PlayStaticSubstep[];
|
|
117
|
+
sheetContract?: PlaySheetContract | null;
|
|
97
118
|
description?: string;
|
|
98
|
-
sourceRange?:
|
|
119
|
+
sourceRange?: PlayStaticSourceRange;
|
|
99
120
|
callDepth?: number;
|
|
100
121
|
callPath?: string[];
|
|
101
122
|
} | {
|
|
102
123
|
type: 'tool';
|
|
103
124
|
toolId: string;
|
|
104
125
|
field: string;
|
|
126
|
+
paramsSource?: string;
|
|
127
|
+
sourceText?: string;
|
|
105
128
|
description?: string;
|
|
106
129
|
inLoop?: boolean;
|
|
107
130
|
isEventWait?: boolean;
|
|
108
|
-
sourceRange?:
|
|
131
|
+
sourceRange?: PlayStaticSourceRange;
|
|
109
132
|
callDepth?: number;
|
|
110
133
|
callPath?: string[];
|
|
111
134
|
} | {
|
|
@@ -124,16 +147,16 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
124
147
|
paramsSource?: string;
|
|
125
148
|
}>;
|
|
126
149
|
description?: string;
|
|
127
|
-
sourceRange?:
|
|
150
|
+
sourceRange?: PlayStaticSourceRange;
|
|
128
151
|
callDepth?: number;
|
|
129
152
|
callPath?: string[];
|
|
130
153
|
} | {
|
|
131
154
|
type: 'step_suite';
|
|
132
155
|
field: string;
|
|
133
|
-
steps:
|
|
156
|
+
steps: PlayStaticSubstep[];
|
|
134
157
|
returnSource?: string;
|
|
135
158
|
description?: string;
|
|
136
|
-
sourceRange?:
|
|
159
|
+
sourceRange?: PlayStaticSourceRange;
|
|
137
160
|
callDepth?: number;
|
|
138
161
|
callPath?: string[];
|
|
139
162
|
} | {
|
|
@@ -141,37 +164,40 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
141
164
|
playId: string;
|
|
142
165
|
field: string;
|
|
143
166
|
inLoop?: boolean;
|
|
144
|
-
pipeline?:
|
|
167
|
+
pipeline?: PlayStaticPipeline | null;
|
|
145
168
|
cycleDetected?: boolean;
|
|
146
169
|
resolutionError?: string;
|
|
147
170
|
description?: string;
|
|
148
|
-
sourceRange?:
|
|
171
|
+
sourceRange?: PlayStaticSourceRange;
|
|
149
172
|
callDepth?: number;
|
|
150
173
|
callPath?: string[];
|
|
151
174
|
} | {
|
|
152
175
|
type: 'control_flow';
|
|
153
176
|
kind: 'conditional' | 'loop';
|
|
154
177
|
field: string;
|
|
155
|
-
steps:
|
|
178
|
+
steps: PlayStaticSubstep[];
|
|
156
179
|
description?: string;
|
|
157
|
-
sourceRange?:
|
|
180
|
+
sourceRange?: PlayStaticSourceRange;
|
|
158
181
|
callDepth?: number;
|
|
159
182
|
callPath?: string[];
|
|
160
183
|
} | {
|
|
161
184
|
type: 'run_javascript';
|
|
162
185
|
alias: string;
|
|
186
|
+
sourceText?: string;
|
|
163
187
|
description?: string;
|
|
164
|
-
sourceRange?:
|
|
188
|
+
sourceRange?: PlayStaticSourceRange;
|
|
165
189
|
callDepth?: number;
|
|
166
190
|
callPath?: string[];
|
|
167
191
|
} | {
|
|
168
192
|
type: 'code';
|
|
169
193
|
field: string;
|
|
194
|
+
sourceText?: string;
|
|
170
195
|
description?: string;
|
|
171
|
-
sourceRange?:
|
|
196
|
+
sourceRange?: PlayStaticSourceRange;
|
|
172
197
|
callDepth?: number;
|
|
173
198
|
callPath?: string[];
|
|
174
199
|
});
|
|
200
|
+
|
|
175
201
|
type PlayCompilerDependencyManifest = {
|
|
176
202
|
playName: string;
|
|
177
203
|
/** Original source path for direct imported definePlay dependencies. */
|
|
@@ -179,7 +205,7 @@ type PlayCompilerDependencyManifest = {
|
|
|
179
205
|
sourceHash: string;
|
|
180
206
|
graphHash: string;
|
|
181
207
|
artifactHash: string;
|
|
182
|
-
staticPipeline:
|
|
208
|
+
staticPipeline: PlayStaticPipeline;
|
|
183
209
|
};
|
|
184
210
|
type PlayCompilerManifest = {
|
|
185
211
|
compilerVersion: number;
|
|
@@ -188,7 +214,7 @@ type PlayCompilerManifest = {
|
|
|
188
214
|
graphHash: string;
|
|
189
215
|
artifactHash: string;
|
|
190
216
|
artifactKind?: PlayArtifactKind;
|
|
191
|
-
staticPipeline:
|
|
217
|
+
staticPipeline: PlayStaticPipeline;
|
|
192
218
|
importedPlayDependencies: PlayCompilerDependencyManifest[];
|
|
193
219
|
};
|
|
194
220
|
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,17 @@ declare const PLAY_ARTIFACT_KINDS: {
|
|
|
13
13
|
};
|
|
14
14
|
type PlayArtifactKind = (typeof PLAY_ARTIFACT_KINDS)[keyof typeof PLAY_ARTIFACT_KINDS];
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* A top-level key the play's function literally `return`s. Derived from the
|
|
18
|
+
* `return { ... }` object literal — NOT from dataset `.withColumn(...)` names —
|
|
19
|
+
* so the "Returns" graph node mirrors the function's real output shape.
|
|
20
|
+
* `isDataset` is true when the key's value is a `PlayDataset` handle (a table).
|
|
21
|
+
*/
|
|
22
|
+
interface PlayStaticReturnField {
|
|
23
|
+
name: string;
|
|
24
|
+
isDataset: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface PlayStaticPipeline {
|
|
17
27
|
tableNamespace?: string;
|
|
18
28
|
inputFields?: string[];
|
|
19
29
|
rowKeyFields?: string[];
|
|
@@ -22,16 +32,22 @@ interface PlayStaticPipelineSnapshot {
|
|
|
22
32
|
csvDescription?: string;
|
|
23
33
|
datasetDescription?: string;
|
|
24
34
|
fields: string[];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Top-level keys of the play's `return { ... }` object literal, in source
|
|
37
|
+
* order. Undefined when the terminal return isn't a statically-known object
|
|
38
|
+
* literal (bare value, dataset handle, conditional returns, etc.).
|
|
39
|
+
*/
|
|
40
|
+
returnFields?: PlayStaticReturnField[];
|
|
41
|
+
stages?: PlayStaticSubstep[];
|
|
42
|
+
substeps: PlayStaticSubstep[];
|
|
43
|
+
sheetContract?: PlaySheetContract | null;
|
|
28
44
|
sheetContractErrors?: string[];
|
|
29
45
|
}
|
|
30
|
-
type
|
|
31
|
-
interface
|
|
46
|
+
type PlaySheetColumnSource = 'input' | 'datasetColumn' | 'waterfallStep' | 'childPlayColumn';
|
|
47
|
+
interface PlaySheetColumnContract {
|
|
32
48
|
id: string;
|
|
33
49
|
sqlName: string;
|
|
34
|
-
source:
|
|
50
|
+
source: PlaySheetColumnSource;
|
|
35
51
|
field?: string;
|
|
36
52
|
parentField?: string;
|
|
37
53
|
playId?: string;
|
|
@@ -42,44 +58,49 @@ interface PlaySheetColumnContractSnapshot {
|
|
|
42
58
|
toolId?: string;
|
|
43
59
|
isRowKey?: boolean;
|
|
44
60
|
}
|
|
45
|
-
interface
|
|
61
|
+
interface PlaySheetContract {
|
|
46
62
|
tableNamespace: string;
|
|
47
|
-
columns:
|
|
63
|
+
columns: PlaySheetColumnContract[];
|
|
48
64
|
}
|
|
49
|
-
type
|
|
50
|
-
interface
|
|
65
|
+
type PlayStaticColumnProducerKind = 'tool' | 'waterfall' | 'stepProgram' | 'playCall' | 'controlFlow' | 'transform';
|
|
66
|
+
interface PlayStaticColumnProducer {
|
|
51
67
|
id: string;
|
|
52
|
-
kind:
|
|
68
|
+
kind: PlayStaticColumnProducerKind;
|
|
53
69
|
field: string;
|
|
54
70
|
toolId?: string;
|
|
55
71
|
playId?: string;
|
|
72
|
+
dependsOnFields?: string[];
|
|
73
|
+
staleAfterSeconds?: number;
|
|
56
74
|
conditional?: boolean;
|
|
57
|
-
sourceRange?:
|
|
58
|
-
steps?:
|
|
59
|
-
substep:
|
|
75
|
+
sourceRange?: PlayStaticSourceRange;
|
|
76
|
+
steps?: PlayStaticColumnProducer[];
|
|
77
|
+
substep: PlayStaticSubstep;
|
|
60
78
|
}
|
|
61
|
-
interface
|
|
79
|
+
interface PlayStaticDatasetColumn {
|
|
62
80
|
id: string;
|
|
63
|
-
source:
|
|
81
|
+
source: PlaySheetColumnSource;
|
|
64
82
|
sqlName?: string;
|
|
65
|
-
|
|
83
|
+
staleAfterSeconds?: number;
|
|
84
|
+
producers: PlayStaticColumnProducer[];
|
|
66
85
|
}
|
|
67
|
-
interface
|
|
86
|
+
interface PlayStaticSourceRange {
|
|
68
87
|
sourcePath?: string;
|
|
69
88
|
startLine: number;
|
|
70
89
|
endLine: number;
|
|
71
90
|
startColumn: number;
|
|
72
91
|
endColumn: number;
|
|
73
92
|
}
|
|
74
|
-
type
|
|
93
|
+
type PlayStaticSubstepMetadata = {
|
|
75
94
|
conditional?: boolean;
|
|
95
|
+
dependsOnFields?: string[];
|
|
96
|
+
staleAfterSeconds?: number;
|
|
76
97
|
};
|
|
77
|
-
type
|
|
98
|
+
type PlayStaticSubstep = PlayStaticSubstepMetadata & ({
|
|
78
99
|
type: 'csv';
|
|
79
100
|
field: string;
|
|
80
101
|
path?: string;
|
|
81
102
|
description?: string;
|
|
82
|
-
sourceRange?:
|
|
103
|
+
sourceRange?: PlayStaticSourceRange;
|
|
83
104
|
callDepth?: number;
|
|
84
105
|
callPath?: string[];
|
|
85
106
|
} | {
|
|
@@ -90,22 +111,24 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
90
111
|
inputFields?: string[];
|
|
91
112
|
rowKeyFields?: string[];
|
|
92
113
|
outputFields?: string[];
|
|
93
|
-
columns?:
|
|
114
|
+
columns?: PlayStaticDatasetColumn[];
|
|
94
115
|
waterfallIds?: string[];
|
|
95
|
-
steps?:
|
|
96
|
-
sheetContract?:
|
|
116
|
+
steps?: PlayStaticSubstep[];
|
|
117
|
+
sheetContract?: PlaySheetContract | null;
|
|
97
118
|
description?: string;
|
|
98
|
-
sourceRange?:
|
|
119
|
+
sourceRange?: PlayStaticSourceRange;
|
|
99
120
|
callDepth?: number;
|
|
100
121
|
callPath?: string[];
|
|
101
122
|
} | {
|
|
102
123
|
type: 'tool';
|
|
103
124
|
toolId: string;
|
|
104
125
|
field: string;
|
|
126
|
+
paramsSource?: string;
|
|
127
|
+
sourceText?: string;
|
|
105
128
|
description?: string;
|
|
106
129
|
inLoop?: boolean;
|
|
107
130
|
isEventWait?: boolean;
|
|
108
|
-
sourceRange?:
|
|
131
|
+
sourceRange?: PlayStaticSourceRange;
|
|
109
132
|
callDepth?: number;
|
|
110
133
|
callPath?: string[];
|
|
111
134
|
} | {
|
|
@@ -124,16 +147,16 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
124
147
|
paramsSource?: string;
|
|
125
148
|
}>;
|
|
126
149
|
description?: string;
|
|
127
|
-
sourceRange?:
|
|
150
|
+
sourceRange?: PlayStaticSourceRange;
|
|
128
151
|
callDepth?: number;
|
|
129
152
|
callPath?: string[];
|
|
130
153
|
} | {
|
|
131
154
|
type: 'step_suite';
|
|
132
155
|
field: string;
|
|
133
|
-
steps:
|
|
156
|
+
steps: PlayStaticSubstep[];
|
|
134
157
|
returnSource?: string;
|
|
135
158
|
description?: string;
|
|
136
|
-
sourceRange?:
|
|
159
|
+
sourceRange?: PlayStaticSourceRange;
|
|
137
160
|
callDepth?: number;
|
|
138
161
|
callPath?: string[];
|
|
139
162
|
} | {
|
|
@@ -141,37 +164,40 @@ type PlayStaticSubstepSnapshot = PlayStaticSubstepMetadataSnapshot & ({
|
|
|
141
164
|
playId: string;
|
|
142
165
|
field: string;
|
|
143
166
|
inLoop?: boolean;
|
|
144
|
-
pipeline?:
|
|
167
|
+
pipeline?: PlayStaticPipeline | null;
|
|
145
168
|
cycleDetected?: boolean;
|
|
146
169
|
resolutionError?: string;
|
|
147
170
|
description?: string;
|
|
148
|
-
sourceRange?:
|
|
171
|
+
sourceRange?: PlayStaticSourceRange;
|
|
149
172
|
callDepth?: number;
|
|
150
173
|
callPath?: string[];
|
|
151
174
|
} | {
|
|
152
175
|
type: 'control_flow';
|
|
153
176
|
kind: 'conditional' | 'loop';
|
|
154
177
|
field: string;
|
|
155
|
-
steps:
|
|
178
|
+
steps: PlayStaticSubstep[];
|
|
156
179
|
description?: string;
|
|
157
|
-
sourceRange?:
|
|
180
|
+
sourceRange?: PlayStaticSourceRange;
|
|
158
181
|
callDepth?: number;
|
|
159
182
|
callPath?: string[];
|
|
160
183
|
} | {
|
|
161
184
|
type: 'run_javascript';
|
|
162
185
|
alias: string;
|
|
186
|
+
sourceText?: string;
|
|
163
187
|
description?: string;
|
|
164
|
-
sourceRange?:
|
|
188
|
+
sourceRange?: PlayStaticSourceRange;
|
|
165
189
|
callDepth?: number;
|
|
166
190
|
callPath?: string[];
|
|
167
191
|
} | {
|
|
168
192
|
type: 'code';
|
|
169
193
|
field: string;
|
|
194
|
+
sourceText?: string;
|
|
170
195
|
description?: string;
|
|
171
|
-
sourceRange?:
|
|
196
|
+
sourceRange?: PlayStaticSourceRange;
|
|
172
197
|
callDepth?: number;
|
|
173
198
|
callPath?: string[];
|
|
174
199
|
});
|
|
200
|
+
|
|
175
201
|
type PlayCompilerDependencyManifest = {
|
|
176
202
|
playName: string;
|
|
177
203
|
/** Original source path for direct imported definePlay dependencies. */
|
|
@@ -179,7 +205,7 @@ type PlayCompilerDependencyManifest = {
|
|
|
179
205
|
sourceHash: string;
|
|
180
206
|
graphHash: string;
|
|
181
207
|
artifactHash: string;
|
|
182
|
-
staticPipeline:
|
|
208
|
+
staticPipeline: PlayStaticPipeline;
|
|
183
209
|
};
|
|
184
210
|
type PlayCompilerManifest = {
|
|
185
211
|
compilerVersion: number;
|
|
@@ -188,7 +214,7 @@ type PlayCompilerManifest = {
|
|
|
188
214
|
graphHash: string;
|
|
189
215
|
artifactHash: string;
|
|
190
216
|
artifactKind?: PlayArtifactKind;
|
|
191
|
-
staticPipeline:
|
|
217
|
+
staticPipeline: PlayStaticPipeline;
|
|
192
218
|
importedPlayDependencies: PlayCompilerDependencyManifest[];
|
|
193
219
|
};
|
|
194
220
|
|
package/dist/index.js
CHANGED
|
@@ -246,10 +246,10 @@ var import_node_path2 = require("path");
|
|
|
246
246
|
|
|
247
247
|
// src/release.ts
|
|
248
248
|
var SDK_RELEASE = {
|
|
249
|
-
version: "0.1.
|
|
249
|
+
version: "0.1.90",
|
|
250
250
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
251
251
|
supportPolicy: {
|
|
252
|
-
latest: "0.1.
|
|
252
|
+
latest: "0.1.90",
|
|
253
253
|
minimumSupported: "0.1.53",
|
|
254
254
|
deprecatedBelow: "0.1.53"
|
|
255
255
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -179,10 +179,10 @@ import { join as join2 } from "path";
|
|
|
179
179
|
|
|
180
180
|
// src/release.ts
|
|
181
181
|
var SDK_RELEASE = {
|
|
182
|
-
version: "0.1.
|
|
182
|
+
version: "0.1.90",
|
|
183
183
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
184
184
|
supportPolicy: {
|
|
185
|
-
latest: "0.1.
|
|
185
|
+
latest: "0.1.90",
|
|
186
186
|
minimumSupported: "0.1.53",
|
|
187
187
|
deprecatedBelow: "0.1.53"
|
|
188
188
|
}
|
|
@@ -34,7 +34,6 @@ import {
|
|
|
34
34
|
type WorkflowStep,
|
|
35
35
|
} from 'cloudflare:workers';
|
|
36
36
|
import {
|
|
37
|
-
chooseMapChunkSize,
|
|
38
37
|
deterministicMapChunkStepName,
|
|
39
38
|
type ExecutionPlan,
|
|
40
39
|
} from '../../../shared_libs/play-runtime/execution-plan';
|
|
@@ -62,7 +61,7 @@ import {
|
|
|
62
61
|
} from './child-play-await';
|
|
63
62
|
import type { AnyBatchOperationStrategy } from '../../../shared_libs/play-runtime/batching-types';
|
|
64
63
|
import {
|
|
65
|
-
|
|
64
|
+
parseToolExecuteResponse,
|
|
66
65
|
createToolExecuteResult,
|
|
67
66
|
deserializeToolExecuteResult,
|
|
68
67
|
isSerializedToolExecuteResult,
|
|
@@ -131,6 +130,7 @@ import {
|
|
|
131
130
|
setHarnessBinding,
|
|
132
131
|
} from '../../../sdk/src/plays/harness-stub';
|
|
133
132
|
import { createHarnessWorkerReceiptStore } from './runtime/harness-receipt-store';
|
|
133
|
+
import { chooseWorkerMapRowsPerChunk } from './runtime/map-chunk-plan';
|
|
134
134
|
import {
|
|
135
135
|
applyCsvRenameProjection,
|
|
136
136
|
stripCsvProjectionMetadata,
|
|
@@ -1289,18 +1289,12 @@ async function callToolDirect(
|
|
|
1289
1289
|
});
|
|
1290
1290
|
if (res.ok) {
|
|
1291
1291
|
const body = (await res.json()) as Record<string, unknown>;
|
|
1292
|
-
const
|
|
1293
|
-
const status =
|
|
1294
|
-
typeof body.status === 'string'
|
|
1295
|
-
? body.status
|
|
1296
|
-
: result == null
|
|
1297
|
-
? 'no_result'
|
|
1298
|
-
: 'completed';
|
|
1292
|
+
const parsed = parseToolExecuteResponse(toolId, body);
|
|
1299
1293
|
return wrapWorkerToolResult(
|
|
1300
1294
|
toolId,
|
|
1301
|
-
result,
|
|
1302
|
-
|
|
1303
|
-
status,
|
|
1295
|
+
parsed.result,
|
|
1296
|
+
parsed.metadata,
|
|
1297
|
+
parsed.status,
|
|
1304
1298
|
);
|
|
1305
1299
|
}
|
|
1306
1300
|
|
|
@@ -1338,121 +1332,6 @@ async function callToolDirect(
|
|
|
1338
1332
|
throw lastError ?? new Error(`tool ${toolId} failed before execution.`);
|
|
1339
1333
|
}
|
|
1340
1334
|
|
|
1341
|
-
function parseExecuteToolMetadata(
|
|
1342
|
-
toolId: string,
|
|
1343
|
-
data: Record<string, unknown>,
|
|
1344
|
-
): ToolResultMetadataInput | null {
|
|
1345
|
-
const metadata = data._metadata;
|
|
1346
|
-
if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) {
|
|
1347
|
-
return null;
|
|
1348
|
-
}
|
|
1349
|
-
const tool = (metadata as Record<string, unknown>).tool;
|
|
1350
|
-
if (!tool || typeof tool !== 'object' || Array.isArray(tool)) return null;
|
|
1351
|
-
const record = tool as Record<string, unknown>;
|
|
1352
|
-
const metadataToolId =
|
|
1353
|
-
typeof record.toolId === 'string' && record.toolId.trim()
|
|
1354
|
-
? record.toolId.trim()
|
|
1355
|
-
: toolId;
|
|
1356
|
-
return {
|
|
1357
|
-
toolId: metadataToolId,
|
|
1358
|
-
extractors: parseExtractorMetadata(record.extractors),
|
|
1359
|
-
targetGetters: parseGetterMetadata(record.targetGetters),
|
|
1360
|
-
listExtractorPaths: parseStringArray(record.listExtractorPaths),
|
|
1361
|
-
listIdentityGetters: parseGetterMetadata(record.listIdentityGetters),
|
|
1362
|
-
};
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
function parseExtractorMetadata(
|
|
1366
|
-
value: unknown,
|
|
1367
|
-
): ToolResultMetadataInput['extractors'] {
|
|
1368
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1369
|
-
return undefined;
|
|
1370
|
-
}
|
|
1371
|
-
const entries = Object.entries(value as Record<string, unknown>).flatMap(
|
|
1372
|
-
([key, descriptor]) => {
|
|
1373
|
-
if (
|
|
1374
|
-
!descriptor ||
|
|
1375
|
-
typeof descriptor !== 'object' ||
|
|
1376
|
-
Array.isArray(descriptor)
|
|
1377
|
-
) {
|
|
1378
|
-
return [];
|
|
1379
|
-
}
|
|
1380
|
-
const record = descriptor as Record<string, unknown>;
|
|
1381
|
-
const paths = parseStringArray(record.paths);
|
|
1382
|
-
if (paths.length === 0) return [];
|
|
1383
|
-
const transforms = parseStringArray(record.transforms);
|
|
1384
|
-
const enumValues = parseStringArray(record.enum);
|
|
1385
|
-
const overrides = parseExtractorOverrides(record.overrides);
|
|
1386
|
-
return [
|
|
1387
|
-
[
|
|
1388
|
-
key,
|
|
1389
|
-
{
|
|
1390
|
-
paths,
|
|
1391
|
-
...(transforms.length > 0 ? { transforms } : {}),
|
|
1392
|
-
...(enumValues.length > 0 ? { enum: enumValues } : {}),
|
|
1393
|
-
...(overrides.length > 0 ? { overrides } : {}),
|
|
1394
|
-
},
|
|
1395
|
-
],
|
|
1396
|
-
] as const;
|
|
1397
|
-
},
|
|
1398
|
-
);
|
|
1399
|
-
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
function parseExtractorOverrides(
|
|
1403
|
-
value: unknown,
|
|
1404
|
-
): NonNullable<
|
|
1405
|
-
NonNullable<ToolResultMetadataInput['extractors']>[string]['overrides']
|
|
1406
|
-
> {
|
|
1407
|
-
if (!Array.isArray(value)) return [];
|
|
1408
|
-
return value.flatMap((entry) => {
|
|
1409
|
-
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
1410
|
-
return [];
|
|
1411
|
-
}
|
|
1412
|
-
const record = entry as Record<string, unknown>;
|
|
1413
|
-
const paths = parseStringArray(record.paths);
|
|
1414
|
-
if (paths.length === 0) return [];
|
|
1415
|
-
const equals =
|
|
1416
|
-
record.equals === null ||
|
|
1417
|
-
typeof record.equals === 'string' ||
|
|
1418
|
-
typeof record.equals === 'number' ||
|
|
1419
|
-
typeof record.equals === 'boolean'
|
|
1420
|
-
? record.equals
|
|
1421
|
-
: true;
|
|
1422
|
-
const overrideValue = record.value;
|
|
1423
|
-
if (
|
|
1424
|
-
overrideValue !== null &&
|
|
1425
|
-
typeof overrideValue !== 'string' &&
|
|
1426
|
-
typeof overrideValue !== 'number' &&
|
|
1427
|
-
typeof overrideValue !== 'boolean'
|
|
1428
|
-
) {
|
|
1429
|
-
return [];
|
|
1430
|
-
}
|
|
1431
|
-
return [{ paths, equals, value: overrideValue }];
|
|
1432
|
-
});
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
function parseGetterMetadata(
|
|
1436
|
-
value: unknown,
|
|
1437
|
-
): Record<string, readonly string[]> | undefined {
|
|
1438
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1439
|
-
return undefined;
|
|
1440
|
-
}
|
|
1441
|
-
const entries = Object.entries(value as Record<string, unknown>)
|
|
1442
|
-
.map(([key, paths]) => [key, parseStringArray(paths)] as const)
|
|
1443
|
-
.filter(
|
|
1444
|
-
(entry): entry is readonly [string, string[]] => entry[1].length > 0,
|
|
1445
|
-
);
|
|
1446
|
-
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
function parseStringArray(value: unknown): string[] {
|
|
1450
|
-
if (!Array.isArray(value)) return [];
|
|
1451
|
-
return value
|
|
1452
|
-
.map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
|
|
1453
|
-
.filter(Boolean);
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1335
|
function toolMetadataFallback(toolId: string): ToolResultMetadataInput {
|
|
1457
1336
|
if (toolId === 'test_rate_limit') {
|
|
1458
1337
|
return {
|
|
@@ -2956,42 +2835,71 @@ function augmentSheetContractWithDatasetFields(input: {
|
|
|
2956
2835
|
outputFields?: readonly string[];
|
|
2957
2836
|
}): PlaySheetContract {
|
|
2958
2837
|
const outputFields = new Set(input.outputFields ?? []);
|
|
2959
|
-
const existingFields = new Set(
|
|
2960
|
-
input.contract.columns.flatMap((column) =>
|
|
2961
|
-
typeof column.field === 'string' ? [column.field] : [],
|
|
2962
|
-
),
|
|
2963
|
-
);
|
|
2964
|
-
const existingSqlNames = new Set(
|
|
2965
|
-
input.contract.columns.map((column) => column.sqlName),
|
|
2966
|
-
);
|
|
2967
|
-
const columns = [...input.contract.columns];
|
|
2968
2838
|
const candidateFields = new Set<string>();
|
|
2969
2839
|
for (const row of input.rows) {
|
|
2970
2840
|
for (const field of Object.keys(row)) {
|
|
2971
|
-
|
|
2841
|
+
if (isDatasetPayloadField(field)) {
|
|
2842
|
+
candidateFields.add(field);
|
|
2843
|
+
}
|
|
2972
2844
|
}
|
|
2973
2845
|
}
|
|
2974
2846
|
for (const field of outputFields) {
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
for (const field of candidateFields) {
|
|
2978
|
-
if (!isDatasetPayloadField(field) || existingFields.has(field)) {
|
|
2979
|
-
continue;
|
|
2847
|
+
if (isDatasetPayloadField(field)) {
|
|
2848
|
+
candidateFields.add(field);
|
|
2980
2849
|
}
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
const existingFields = new Set<string>();
|
|
2853
|
+
const existingSqlNames = new Set<string>();
|
|
2854
|
+
const inputColumns: PlaySheetContract['columns'] = [];
|
|
2855
|
+
const outputColumns: PlaySheetContract['columns'] = [];
|
|
2856
|
+
const appendColumn = (
|
|
2857
|
+
target: PlaySheetContract['columns'],
|
|
2858
|
+
column: PlaySheetContract['columns'][number],
|
|
2859
|
+
) => {
|
|
2860
|
+
const field = typeof column.field === 'string' ? column.field : column.id;
|
|
2861
|
+
const sqlName = column.sqlName.trim();
|
|
2862
|
+
if (
|
|
2863
|
+
!field ||
|
|
2864
|
+
!sqlName ||
|
|
2865
|
+
existingFields.has(field) ||
|
|
2866
|
+
existingSqlNames.has(sqlName)
|
|
2867
|
+
) {
|
|
2868
|
+
return;
|
|
2984
2869
|
}
|
|
2985
2870
|
existingFields.add(field);
|
|
2986
2871
|
existingSqlNames.add(sqlName);
|
|
2987
|
-
|
|
2872
|
+
target.push(column);
|
|
2873
|
+
};
|
|
2874
|
+
|
|
2875
|
+
for (const column of input.contract.columns) {
|
|
2876
|
+
const field = typeof column.field === 'string' ? column.field : column.id;
|
|
2877
|
+
if (
|
|
2878
|
+
column.source === 'input' &&
|
|
2879
|
+
field === input.contract.tableNamespace &&
|
|
2880
|
+
!candidateFields.has(field)
|
|
2881
|
+
) {
|
|
2882
|
+
continue;
|
|
2883
|
+
}
|
|
2884
|
+
appendColumn(
|
|
2885
|
+
column.source === 'input' ? inputColumns : outputColumns,
|
|
2886
|
+
column,
|
|
2887
|
+
);
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
for (const field of candidateFields) {
|
|
2891
|
+
if (existingFields.has(field)) continue;
|
|
2892
|
+
const sqlName = sqlSafePlayColumnName(field);
|
|
2893
|
+
if (existingSqlNames.has(sqlName)) continue;
|
|
2894
|
+
appendColumn(outputFields.has(field) ? outputColumns : inputColumns, {
|
|
2988
2895
|
id: `runtime:${input.contract.tableNamespace}:${field}`,
|
|
2989
2896
|
sqlName,
|
|
2990
2897
|
source: outputFields.has(field) ? 'datasetColumn' : 'input',
|
|
2991
2898
|
field,
|
|
2992
2899
|
});
|
|
2993
2900
|
}
|
|
2994
|
-
|
|
2901
|
+
|
|
2902
|
+
return { ...input.contract, columns: [...inputColumns, ...outputColumns] };
|
|
2995
2903
|
}
|
|
2996
2904
|
|
|
2997
2905
|
async function persistCompletedMapRows(input: {
|
|
@@ -3031,6 +2939,7 @@ async function prepareMapRows(input: {
|
|
|
3031
2939
|
req: RunRequest;
|
|
3032
2940
|
tableNamespace: string;
|
|
3033
2941
|
rows: Record<string, unknown>[];
|
|
2942
|
+
inputOffset: number;
|
|
3034
2943
|
outputFields: string[];
|
|
3035
2944
|
cellPolicies?: CellStalenessPolicyByField;
|
|
3036
2945
|
}): Promise<{
|
|
@@ -3056,6 +2965,7 @@ async function prepareMapRows(input: {
|
|
|
3056
2965
|
}),
|
|
3057
2966
|
rows: input.rows.map((row) => publicCsvStorageRow(row)),
|
|
3058
2967
|
runId: input.req.runId,
|
|
2968
|
+
inputOffset: input.inputOffset,
|
|
3059
2969
|
userEmail: input.req.userEmail,
|
|
3060
2970
|
cellPolicies: input.cellPolicies,
|
|
3061
2971
|
});
|
|
@@ -3535,16 +3445,10 @@ function createMinimalWorkerCtx(
|
|
|
3535
3445
|
const baseOffset = 0;
|
|
3536
3446
|
const fieldEntries = Object.entries(fieldsDef);
|
|
3537
3447
|
const plan = req.executionPlan;
|
|
3538
|
-
const
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
const rowsPerChunk = chooseMapChunkSize({
|
|
3543
|
-
totalRows: rowCountHint,
|
|
3544
|
-
mapCount: Math.max(1, plan?.maps.length ?? 1),
|
|
3545
|
-
stepsPerChunk: planMap?.stepsPerChunk ?? 1,
|
|
3546
|
-
preferredChunkSize: planMap?.defaultChunkSize,
|
|
3547
|
-
softWorkflowStepBudget: plan?.chunkPlan.softWorkflowStepBudget,
|
|
3448
|
+
const rowsPerChunk = chooseWorkerMapRowsPerChunk({
|
|
3449
|
+
mapName: name,
|
|
3450
|
+
rowCountHint,
|
|
3451
|
+
executionPlan: plan,
|
|
3548
3452
|
});
|
|
3549
3453
|
const outputFields = fieldEntries.map(([field]) => field);
|
|
3550
3454
|
const updateMapProgress = (
|
|
@@ -3719,6 +3623,7 @@ function createMinimalWorkerCtx(
|
|
|
3719
3623
|
...row,
|
|
3720
3624
|
__deeplineRowKey: rowKey,
|
|
3721
3625
|
})),
|
|
3626
|
+
inputOffset: baseOffset + chunkStart,
|
|
3722
3627
|
});
|
|
3723
3628
|
recordRunnerPerfTrace({
|
|
3724
3629
|
req,
|
|
@@ -4458,22 +4363,25 @@ function createMinimalWorkerCtx(
|
|
|
4458
4363
|
program.steps.map((step) => [step.name, step.resolver]),
|
|
4459
4364
|
);
|
|
4460
4365
|
const cellPolicies = Object.fromEntries(
|
|
4461
|
-
program.steps.
|
|
4462
|
-
step.name,
|
|
4366
|
+
program.steps.flatMap((step) =>
|
|
4463
4367
|
step.staleAfterSeconds === undefined
|
|
4464
|
-
?
|
|
4465
|
-
:
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4368
|
+
? []
|
|
4369
|
+
: [
|
|
4370
|
+
[
|
|
4371
|
+
step.name,
|
|
4372
|
+
normalizeCellStalenessPolicy({
|
|
4373
|
+
staleAfterSeconds: step.staleAfterSeconds,
|
|
4374
|
+
}),
|
|
4375
|
+
],
|
|
4376
|
+
],
|
|
4377
|
+
),
|
|
4469
4378
|
) as CellStalenessPolicyByField;
|
|
4470
4379
|
const authoredCellPolicies = Object.fromEntries(
|
|
4471
|
-
program.steps.
|
|
4472
|
-
step.name,
|
|
4380
|
+
program.steps.flatMap((step) =>
|
|
4473
4381
|
step.staleAfterSeconds === undefined
|
|
4474
|
-
?
|
|
4475
|
-
: { staleAfterSeconds: step.staleAfterSeconds },
|
|
4476
|
-
|
|
4382
|
+
? []
|
|
4383
|
+
: [[step.name, { staleAfterSeconds: step.staleAfterSeconds }]],
|
|
4384
|
+
),
|
|
4477
4385
|
) as AuthoredCellStalenessPolicyByField;
|
|
4478
4386
|
return runMap(
|
|
4479
4387
|
this.name,
|
|
@@ -4703,22 +4611,25 @@ function createMinimalWorkerCtx(
|
|
|
4703
4611
|
fieldsDef.steps.map((step) => [step.name, step.resolver]),
|
|
4704
4612
|
);
|
|
4705
4613
|
const cellPolicies = Object.fromEntries(
|
|
4706
|
-
fieldsDef.steps.
|
|
4707
|
-
step.name,
|
|
4614
|
+
fieldsDef.steps.flatMap((step) =>
|
|
4708
4615
|
step.staleAfterSeconds === undefined
|
|
4709
|
-
?
|
|
4710
|
-
:
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4616
|
+
? []
|
|
4617
|
+
: [
|
|
4618
|
+
[
|
|
4619
|
+
step.name,
|
|
4620
|
+
normalizeCellStalenessPolicy({
|
|
4621
|
+
staleAfterSeconds: step.staleAfterSeconds,
|
|
4622
|
+
}),
|
|
4623
|
+
],
|
|
4624
|
+
],
|
|
4625
|
+
),
|
|
4714
4626
|
) as CellStalenessPolicyByField;
|
|
4715
4627
|
const authoredCellPolicies = Object.fromEntries(
|
|
4716
|
-
fieldsDef.steps.
|
|
4717
|
-
step.name,
|
|
4628
|
+
fieldsDef.steps.flatMap((step) =>
|
|
4718
4629
|
step.staleAfterSeconds === undefined
|
|
4719
|
-
?
|
|
4720
|
-
: { staleAfterSeconds: step.staleAfterSeconds },
|
|
4721
|
-
|
|
4630
|
+
? []
|
|
4631
|
+
: [[step.name, { staleAfterSeconds: step.staleAfterSeconds }]],
|
|
4632
|
+
),
|
|
4722
4633
|
) as AuthoredCellStalenessPolicyByField;
|
|
4723
4634
|
return runMap(
|
|
4724
4635
|
name,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chooseMapChunkSize,
|
|
3
|
+
type ExecutionPlan,
|
|
4
|
+
} from '../../../../shared_libs/play-runtime/execution-plan';
|
|
5
|
+
|
|
6
|
+
export const CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE = 10_000;
|
|
7
|
+
|
|
8
|
+
export type WorkerMapChunkPlanInput = {
|
|
9
|
+
mapName: string;
|
|
10
|
+
rowCountHint: number | null;
|
|
11
|
+
executionPlan?: ExecutionPlan | null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function chooseWorkerMapRowsPerChunk(
|
|
15
|
+
input: WorkerMapChunkPlanInput,
|
|
16
|
+
): number {
|
|
17
|
+
const plan = input.executionPlan ?? null;
|
|
18
|
+
const planMap = plan?.maps.find(
|
|
19
|
+
(candidate) =>
|
|
20
|
+
candidate.mapName === input.mapName ||
|
|
21
|
+
candidate.tableNamespace === input.mapName,
|
|
22
|
+
);
|
|
23
|
+
const rowsPerChunk = chooseMapChunkSize({
|
|
24
|
+
totalRows: input.rowCountHint,
|
|
25
|
+
mapCount: Math.max(1, plan?.maps.length ?? 1),
|
|
26
|
+
stepsPerChunk: planMap?.stepsPerChunk ?? 1,
|
|
27
|
+
preferredChunkSize: planMap?.defaultChunkSize,
|
|
28
|
+
softWorkflowStepBudget: plan?.chunkPlan.softWorkflowStepBudget,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const toolFreeSimpleMap =
|
|
32
|
+
!!planMap &&
|
|
33
|
+
planMap.stepsPerChunk === 1 &&
|
|
34
|
+
(plan?.toolDeclarations.length ?? 0) === 0;
|
|
35
|
+
if (
|
|
36
|
+
toolFreeSimpleMap &&
|
|
37
|
+
(input.rowCountHint === null ||
|
|
38
|
+
input.rowCountHint >= CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE)
|
|
39
|
+
) {
|
|
40
|
+
return Math.max(rowsPerChunk, CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return rowsPerChunk;
|
|
44
|
+
}
|
|
@@ -50,10 +50,10 @@ export type SdkRelease = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export const SDK_RELEASE = {
|
|
53
|
-
version: '0.1.
|
|
53
|
+
version: '0.1.90',
|
|
54
54
|
apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
|
|
55
55
|
supportPolicy: {
|
|
56
|
-
latest: '0.1.
|
|
56
|
+
latest: '0.1.90',
|
|
57
57
|
minimumSupported: '0.1.53',
|
|
58
58
|
deprecatedBelow: '0.1.53',
|
|
59
59
|
},
|
|
@@ -17,7 +17,10 @@ export type {
|
|
|
17
17
|
EmailStatusVerdict,
|
|
18
18
|
} from './email-status';
|
|
19
19
|
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
buildEmailStatus,
|
|
22
|
+
type EmailStatusExtractorConfig,
|
|
23
|
+
} from './email-status';
|
|
21
24
|
import {
|
|
22
25
|
JOB_CHANGE_STATUS_VALUES,
|
|
23
26
|
type JobChangeGetterValue,
|
|
@@ -56,12 +59,12 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
56
59
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
|
|
62
|
+
type V2ToolExecuteOutput = {
|
|
60
63
|
raw: unknown;
|
|
61
64
|
meta?: Record<string, unknown>;
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
function parseV2ToolExecuteOutput(
|
|
65
68
|
data: Record<string, unknown>,
|
|
66
69
|
): V2ToolExecuteOutput | null {
|
|
67
70
|
const toolResponse = data.toolResponse;
|
|
@@ -77,9 +80,10 @@ export function parseV2ToolExecuteOutput(
|
|
|
77
80
|
return null;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
function adaptV2ExecuteResponseToToolResult(data: Record<string, unknown>): {
|
|
84
|
+
output?: V2ToolExecuteOutput;
|
|
85
|
+
result: unknown;
|
|
86
|
+
} {
|
|
83
87
|
const output = parseV2ToolExecuteOutput(data);
|
|
84
88
|
if (!output) {
|
|
85
89
|
return { result: data.result ?? data };
|
|
@@ -93,7 +97,195 @@ export function adaptV2ExecuteResponseToToolResult(
|
|
|
93
97
|
};
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Parsed view of a raw `/api/v2/integrations/:toolId/execute` JSON body.
|
|
102
|
+
*
|
|
103
|
+
* This is the single runtime-side seam from a V2 execute response to the
|
|
104
|
+
* inputs of {@link createToolExecuteResult}. Both runner substrates (the
|
|
105
|
+
* in-process cjs runtime in `shared_libs/play-runtime/context.ts` and the
|
|
106
|
+
* Workers runtime in `apps/play-runner-workers`) must go through
|
|
107
|
+
* {@link parseToolExecuteResponse}; the intermediate envelope shapes
|
|
108
|
+
* (`toolResponse` adaptation, `_metadata.tool` parsing, status derivation)
|
|
109
|
+
* are private to this module.
|
|
110
|
+
*
|
|
111
|
+
* Boundary note: provider-specific redaction (wiza/apify/bettercontact billing
|
|
112
|
+
* fields) happens server-side in
|
|
113
|
+
* `src/lib/integrations/execute-result-normalization.ts` BEFORE the response
|
|
114
|
+
* leaves the API. This module only ever sees the already-redacted public
|
|
115
|
+
* response — do not move redaction here, it would leak provider internals
|
|
116
|
+
* into the shared runtime bundles.
|
|
117
|
+
*/
|
|
118
|
+
export type ParsedToolExecuteResponse = {
|
|
119
|
+
status: string;
|
|
120
|
+
jobId?: string;
|
|
121
|
+
meta?: Record<string, unknown>;
|
|
122
|
+
toolResponse?: {
|
|
123
|
+
raw?: unknown;
|
|
124
|
+
meta?: Record<string, unknown>;
|
|
125
|
+
};
|
|
126
|
+
/** Legacy `{ data, meta }` envelope consumed by createToolExecuteResult. */
|
|
127
|
+
result: unknown;
|
|
128
|
+
/** Tool extractor metadata parsed from `_metadata.tool`, if present. */
|
|
129
|
+
metadata: ToolResultMetadataInput | null;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export function parseToolExecuteResponse(
|
|
133
|
+
toolId: string,
|
|
134
|
+
body: Record<string, unknown>,
|
|
135
|
+
): ParsedToolExecuteResponse {
|
|
136
|
+
const { result } = adaptV2ExecuteResponseToToolResult(body);
|
|
137
|
+
const status =
|
|
138
|
+
typeof body.status === 'string'
|
|
139
|
+
? body.status
|
|
140
|
+
: result == null
|
|
141
|
+
? 'no_result'
|
|
142
|
+
: 'completed';
|
|
143
|
+
return {
|
|
144
|
+
status,
|
|
145
|
+
jobId: typeof body.job_id === 'string' ? body.job_id : undefined,
|
|
146
|
+
meta: isRecord(body.meta) ? body.meta : undefined,
|
|
147
|
+
toolResponse: isRecord(body.toolResponse)
|
|
148
|
+
? (body.toolResponse as ParsedToolExecuteResponse['toolResponse'])
|
|
149
|
+
: undefined,
|
|
150
|
+
result,
|
|
151
|
+
metadata: parseExecuteToolMetadata(toolId, body),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function parseExecuteToolMetadata(
|
|
156
|
+
toolId: string,
|
|
157
|
+
data: Record<string, unknown>,
|
|
158
|
+
): ToolResultMetadataInput | null {
|
|
159
|
+
const metadata = data._metadata;
|
|
160
|
+
if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const tool = (metadata as Record<string, unknown>).tool;
|
|
164
|
+
if (!tool || typeof tool !== 'object' || Array.isArray(tool)) return null;
|
|
165
|
+
const record = tool as Record<string, unknown>;
|
|
166
|
+
const metadataToolId =
|
|
167
|
+
typeof record.toolId === 'string' && record.toolId.trim()
|
|
168
|
+
? record.toolId
|
|
169
|
+
: toolId;
|
|
170
|
+
const readGetters = (value: unknown): Record<string, readonly string[]> => {
|
|
171
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
|
172
|
+
return Object.fromEntries(
|
|
173
|
+
Object.entries(value as Record<string, unknown>).flatMap(
|
|
174
|
+
([key, paths]) => {
|
|
175
|
+
if (!Array.isArray(paths)) return [];
|
|
176
|
+
const normalized = paths.filter(
|
|
177
|
+
(path): path is string =>
|
|
178
|
+
typeof path === 'string' && path.trim().length > 0,
|
|
179
|
+
);
|
|
180
|
+
return normalized.length > 0 ? [[key, normalized]] : [];
|
|
181
|
+
},
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
const readExtractors = (
|
|
186
|
+
value: unknown,
|
|
187
|
+
): ToolResultMetadataInput['extractors'] => {
|
|
188
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
|
|
189
|
+
return Object.fromEntries(
|
|
190
|
+
Object.entries(value as Record<string, unknown>).flatMap(
|
|
191
|
+
([key, entry]) => {
|
|
192
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry))
|
|
193
|
+
return [];
|
|
194
|
+
const recordEntry = entry as Record<string, unknown>;
|
|
195
|
+
if (!Array.isArray(recordEntry.paths)) return [];
|
|
196
|
+
const paths = recordEntry.paths.filter(
|
|
197
|
+
(path): path is string =>
|
|
198
|
+
typeof path === 'string' && path.trim().length > 0,
|
|
199
|
+
);
|
|
200
|
+
if (paths.length === 0) return [];
|
|
201
|
+
const overrides = Array.isArray(recordEntry.overrides)
|
|
202
|
+
? recordEntry.overrides.flatMap((override) => {
|
|
203
|
+
if (
|
|
204
|
+
!override ||
|
|
205
|
+
typeof override !== 'object' ||
|
|
206
|
+
Array.isArray(override)
|
|
207
|
+
) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
const overrideRecord = override as Record<string, unknown>;
|
|
211
|
+
const overridePaths = Array.isArray(overrideRecord.paths)
|
|
212
|
+
? overrideRecord.paths.filter(
|
|
213
|
+
(path): path is string =>
|
|
214
|
+
typeof path === 'string' && path.trim().length > 0,
|
|
215
|
+
)
|
|
216
|
+
: [];
|
|
217
|
+
if (overridePaths.length === 0) return [];
|
|
218
|
+
const readOverridePrimitive = (
|
|
219
|
+
candidate: unknown,
|
|
220
|
+
): string | number | boolean | null | undefined => {
|
|
221
|
+
if (candidate === null) return null;
|
|
222
|
+
if (typeof candidate === 'string') return candidate;
|
|
223
|
+
if (typeof candidate === 'number') return candidate;
|
|
224
|
+
if (typeof candidate === 'boolean') return candidate;
|
|
225
|
+
return undefined;
|
|
226
|
+
};
|
|
227
|
+
const value = readOverridePrimitive(overrideRecord.value);
|
|
228
|
+
if (value === undefined) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
const equals: string | number | boolean | null =
|
|
232
|
+
readOverridePrimitive(overrideRecord.equals) ?? true;
|
|
233
|
+
return [{ paths: overridePaths, equals, value }];
|
|
234
|
+
})
|
|
235
|
+
: [];
|
|
236
|
+
const emailStatus =
|
|
237
|
+
recordEntry.emailStatus &&
|
|
238
|
+
typeof recordEntry.emailStatus === 'object' &&
|
|
239
|
+
!Array.isArray(recordEntry.emailStatus)
|
|
240
|
+
? (recordEntry.emailStatus as EmailStatusExtractorConfig)
|
|
241
|
+
: undefined;
|
|
242
|
+
return [
|
|
243
|
+
[
|
|
244
|
+
key,
|
|
245
|
+
{
|
|
246
|
+
paths,
|
|
247
|
+
...(Array.isArray(recordEntry.transforms)
|
|
248
|
+
? {
|
|
249
|
+
transforms: recordEntry.transforms.filter(
|
|
250
|
+
(transform): transform is string =>
|
|
251
|
+
typeof transform === 'string' &&
|
|
252
|
+
transform.trim().length > 0,
|
|
253
|
+
),
|
|
254
|
+
}
|
|
255
|
+
: {}),
|
|
256
|
+
...(Array.isArray(recordEntry.enum)
|
|
257
|
+
? {
|
|
258
|
+
enum: recordEntry.enum.filter(
|
|
259
|
+
(value): value is string =>
|
|
260
|
+
typeof value === 'string' && value.trim().length > 0,
|
|
261
|
+
),
|
|
262
|
+
}
|
|
263
|
+
: {}),
|
|
264
|
+
...(overrides.length > 0 ? { overrides } : {}),
|
|
265
|
+
...(emailStatus ? { emailStatus } : {}),
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
];
|
|
269
|
+
},
|
|
270
|
+
),
|
|
271
|
+
);
|
|
272
|
+
};
|
|
273
|
+
const listExtractorPaths = Array.isArray(record.listExtractorPaths)
|
|
274
|
+
? record.listExtractorPaths.filter(
|
|
275
|
+
(path): path is string =>
|
|
276
|
+
typeof path === 'string' && path.trim().length > 0,
|
|
277
|
+
)
|
|
278
|
+
: [];
|
|
279
|
+
return {
|
|
280
|
+
toolId: metadataToolId,
|
|
281
|
+
extractors: readExtractors(record.extractors),
|
|
282
|
+
targetGetters: readGetters(record.targetGetters),
|
|
283
|
+
listExtractorPaths,
|
|
284
|
+
listIdentityGetters: readGetters(record.listIdentityGetters),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function toV2RawToolOutputPath(path: string): string {
|
|
97
289
|
const normalized = String(path || '')
|
|
98
290
|
.trim()
|
|
99
291
|
.replace(/^\./, '');
|
|
@@ -445,9 +637,7 @@ function normalizeJobChangeStatus(value: unknown): unknown {
|
|
|
445
637
|
if (['false', 'no', 'same', 'no_change'].includes(normalized))
|
|
446
638
|
return 'no_change';
|
|
447
639
|
if (['left', 'left_company'].includes(normalized)) return 'left_company';
|
|
448
|
-
if (
|
|
449
|
-
(JOB_CHANGE_STATUS_VALUES as readonly string[]).includes(normalized)
|
|
450
|
-
) {
|
|
640
|
+
if ((JOB_CHANGE_STATUS_VALUES as readonly string[]).includes(normalized)) {
|
|
451
641
|
return normalized;
|
|
452
642
|
}
|
|
453
643
|
return 'unknown';
|
|
@@ -481,12 +671,12 @@ function normalizeJobChange(value: unknown): JobChangeGetterValue {
|
|
|
481
671
|
return {
|
|
482
672
|
status,
|
|
483
673
|
date: moved
|
|
484
|
-
? normalizeString(
|
|
674
|
+
? (normalizeString(
|
|
485
675
|
output.date ??
|
|
486
676
|
output.job_change_date ??
|
|
487
677
|
output.change_date ??
|
|
488
678
|
output.changed_at,
|
|
489
|
-
) ?? firstExperienceDate(person.experiences)
|
|
679
|
+
) ?? firstExperienceDate(person.experiences))
|
|
490
680
|
: null,
|
|
491
681
|
new_company: moved
|
|
492
682
|
? normalizeString(
|
|
@@ -169,19 +169,25 @@ export function normalizePlayName(value: string): string {
|
|
|
169
169
|
return validateIdentifierPart(value, 'Play name', PLAY_NAME_MAX_LENGTH);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Normalize a play name into the leading segment of a physical sheet table name.
|
|
174
|
+
*
|
|
175
|
+
* A qualified reference like "prebuilt/name-and-domain-to-email-waterfall" folds
|
|
176
|
+
* its namespace separator into a plain identifier
|
|
177
|
+
* ("prebuilt_name_and_domain_to_email_waterfall") so the physical table reads
|
|
178
|
+
* cleanly. `validatePlaySheetTableName` enforces the 63-char Postgres identifier
|
|
179
|
+
* limit on the play + namespace combination and fails loudly when a name is
|
|
180
|
+
* genuinely too long — no opaque content digest is mixed into the table name.
|
|
181
|
+
*/
|
|
172
182
|
export function normalizePlayNameForSheet(value: string): string {
|
|
173
183
|
if (!value.includes('/')) {
|
|
174
184
|
return normalizePlayName(value);
|
|
175
185
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
186
|
+
return validateIdentifierPart(
|
|
187
|
+
value.replace(/\//g, '_'),
|
|
188
|
+
'Play name',
|
|
189
|
+
PLAY_NAME_MAX_LENGTH,
|
|
179
190
|
);
|
|
180
|
-
const prefixLength = Math.max(1, PLAY_NAME_MAX_LENGTH - digest.length - 1);
|
|
181
|
-
const prefix =
|
|
182
|
-
normalizedReference.slice(0, prefixLength).replace(/_+$/g, '') ||
|
|
183
|
-
'qualified_play';
|
|
184
|
-
return `${prefix}_${digest}`;
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
export function normalizeTableNamespace(value: string): string {
|