deepline 0.1.163 → 0.1.165
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/bundling-sources/apps/play-runner-workers/src/entry.ts +13 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +302 -119
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/sdk/src/types.ts +9 -0
- package/dist/cli/index.js +213 -22
- package/dist/cli/index.mjs +213 -22
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
|
@@ -3559,6 +3559,18 @@ function resolveSheetContractFromReq(
|
|
|
3559
3559
|
}
|
|
3560
3560
|
}
|
|
3561
3561
|
|
|
3562
|
+
function staticPipelineFromReq(req: RunRequest): PlayStaticPipeline | null {
|
|
3563
|
+
const snapshot = req.contractSnapshot as
|
|
3564
|
+
| { staticPipeline?: unknown }
|
|
3565
|
+
| undefined
|
|
3566
|
+
| null;
|
|
3567
|
+
const pipeline = snapshot?.staticPipeline;
|
|
3568
|
+
if (!pipeline || typeof pipeline !== 'object' || Array.isArray(pipeline)) {
|
|
3569
|
+
return null;
|
|
3570
|
+
}
|
|
3571
|
+
return pipeline as PlayStaticPipeline;
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3562
3574
|
/**
|
|
3563
3575
|
* Direct-Neon writes from the shared harness Worker. Resolves the org runtime
|
|
3564
3576
|
* Postgres URL via `create_db_session` inside that long-lived Worker, then
|
|
@@ -4290,6 +4302,7 @@ function createMinimalWorkerCtx(
|
|
|
4290
4302
|
mapName: name,
|
|
4291
4303
|
rowCountHint,
|
|
4292
4304
|
executionPlan: plan,
|
|
4305
|
+
staticPipeline: staticPipelineFromReq(req),
|
|
4293
4306
|
});
|
|
4294
4307
|
const outputFields = fieldEntries.map(([field]) => field);
|
|
4295
4308
|
const updateMapProgress = (
|
|
@@ -1,83 +1,319 @@
|
|
|
1
1
|
import {
|
|
2
2
|
chooseMapChunkSize,
|
|
3
|
-
EXECUTION_PLAN_DEFAULTS,
|
|
4
3
|
type ExecutionPlan,
|
|
5
4
|
} from '../../../../shared_libs/play-runtime/execution-plan';
|
|
5
|
+
import { getPlayRuntimeBatchStrategy } from '../../../../shared_libs/play-runtime/play-runtime-batching-registry';
|
|
6
6
|
import { TOOL_CALLING_MAP_CHUNK_SIZE } from '../../../../shared_libs/play-runtime/map-chunk-limits';
|
|
7
|
+
import {
|
|
8
|
+
flattenStaticSubsteps,
|
|
9
|
+
getTopLevelPipelineSubsteps,
|
|
10
|
+
type PlayStaticColumnProducer,
|
|
11
|
+
type PlayStaticPipeline,
|
|
12
|
+
type PlayStaticSubstep,
|
|
13
|
+
} from '../../../../shared_libs/plays/static-pipeline';
|
|
7
14
|
|
|
8
15
|
export const CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE = 10_000;
|
|
9
16
|
export { TOOL_CALLING_MAP_CHUNK_SIZE };
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
// Cloudflare preview Workers enforce the 50-subrequest invocation limit. Leave
|
|
18
|
+
// headroom for coordinator/storage calls around row-level unbatched tool RPCs.
|
|
19
|
+
export const UNBATCHED_TOOL_SUBREQUESTS_PER_CHUNK_BUDGET = 40;
|
|
20
|
+
// Fresh unbatched tool calls use one RUNTIME_API integration execute RPC and
|
|
21
|
+
// one HARNESS durable-receipt completion RPC. Batch-cap rows by both.
|
|
22
|
+
export const SUBREQUESTS_PER_UNBATCHED_TOOL_CALL = 2;
|
|
12
23
|
|
|
13
24
|
export type WorkerMapChunkPlanInput = {
|
|
14
25
|
mapName: string;
|
|
15
26
|
rowCountHint: number | null;
|
|
16
27
|
executionPlan?: ExecutionPlan | null;
|
|
28
|
+
staticPipeline?: PlayStaticPipeline | null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type PlanMap = ExecutionPlan['maps'][number];
|
|
32
|
+
type ChunkSizingMap = Pick<
|
|
33
|
+
PlanMap,
|
|
34
|
+
| 'mapName'
|
|
35
|
+
| 'tableNamespace'
|
|
36
|
+
| 'outputFields'
|
|
37
|
+
| 'defaultChunkSize'
|
|
38
|
+
| 'stepsPerChunk'
|
|
39
|
+
> &
|
|
40
|
+
Partial<Pick<PlanMap, 'externalStepFields'>>;
|
|
41
|
+
type ChunkSizingPlan = {
|
|
42
|
+
maps: ChunkSizingMap[];
|
|
43
|
+
toolDeclarations?: ExecutionPlan['toolDeclarations'];
|
|
44
|
+
softWorkflowStepBudget?: number | null;
|
|
17
45
|
};
|
|
18
46
|
|
|
47
|
+
type MapToolStats = [totalToolCount: number, unbatchedToolCount: number];
|
|
48
|
+
|
|
49
|
+
function declarationBelongsToMapOutput(
|
|
50
|
+
declaration: { field?: string | null },
|
|
51
|
+
outputFields: readonly string[],
|
|
52
|
+
externalStepFields: readonly string[] = [],
|
|
53
|
+
): boolean {
|
|
54
|
+
const fieldName = declaration.field;
|
|
55
|
+
if (fieldName == null) return true;
|
|
56
|
+
if (
|
|
57
|
+
outputFields.some(
|
|
58
|
+
(field) => fieldName === field || fieldName.startsWith(`${field}.`),
|
|
59
|
+
)
|
|
60
|
+
) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return externalStepFields.some(
|
|
64
|
+
(field) => fieldName === field || fieldName.endsWith(`.${field}`),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isUnbatchedTool(toolId: string): boolean {
|
|
69
|
+
return getPlayRuntimeBatchStrategy(toolId) === null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function countToolSubsteps(
|
|
73
|
+
substeps: readonly PlayStaticSubstep[],
|
|
74
|
+
): MapToolStats {
|
|
75
|
+
let totalToolCount = 0;
|
|
76
|
+
let unbatchedToolCount = 0;
|
|
77
|
+
|
|
78
|
+
for (const substep of substeps) {
|
|
79
|
+
if (substep.type === 'tool') {
|
|
80
|
+
totalToolCount += 1;
|
|
81
|
+
if (isUnbatchedTool(substep.toolId)) {
|
|
82
|
+
unbatchedToolCount += 1;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (substep.type === 'waterfall') {
|
|
88
|
+
for (const step of substep.steps ?? []) {
|
|
89
|
+
if (!step.toolId) continue;
|
|
90
|
+
totalToolCount += 1;
|
|
91
|
+
if (isUnbatchedTool(step.toolId)) {
|
|
92
|
+
unbatchedToolCount += 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (
|
|
99
|
+
substep.type === 'step_suite' ||
|
|
100
|
+
substep.type === 'control_flow' ||
|
|
101
|
+
substep.type === 'dataset'
|
|
102
|
+
) {
|
|
103
|
+
const [nestedTotal, nestedUnbatched] = countToolSubsteps(
|
|
104
|
+
substep.steps ?? [],
|
|
105
|
+
);
|
|
106
|
+
totalToolCount += nestedTotal;
|
|
107
|
+
unbatchedToolCount += nestedUnbatched;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return [totalToolCount, unbatchedToolCount];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function countProducerTools(
|
|
115
|
+
producers: readonly PlayStaticColumnProducer[],
|
|
116
|
+
): MapToolStats {
|
|
117
|
+
let totalToolCount = 0;
|
|
118
|
+
let unbatchedToolCount = 0;
|
|
119
|
+
|
|
120
|
+
for (const producer of producers) {
|
|
121
|
+
if (producer.kind === 'tool' && producer.toolId) {
|
|
122
|
+
totalToolCount += 1;
|
|
123
|
+
if (isUnbatchedTool(producer.toolId)) {
|
|
124
|
+
unbatchedToolCount += 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (producer.substep.type === 'waterfall') {
|
|
128
|
+
for (const step of producer.substep.steps ?? []) {
|
|
129
|
+
if (!step.toolId) continue;
|
|
130
|
+
totalToolCount += 1;
|
|
131
|
+
if (isUnbatchedTool(step.toolId)) {
|
|
132
|
+
unbatchedToolCount += 1;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (producer.steps?.length) {
|
|
137
|
+
const [nestedTotal, nestedUnbatched] = countProducerTools(producer.steps);
|
|
138
|
+
totalToolCount += nestedTotal;
|
|
139
|
+
unbatchedToolCount += nestedUnbatched;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return [totalToolCount, unbatchedToolCount];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function datasetBelongsToPlanMap(
|
|
147
|
+
dataset: Extract<PlayStaticSubstep, { type: 'dataset' }>,
|
|
148
|
+
planMap: ChunkSizingMap,
|
|
149
|
+
mapName: string,
|
|
150
|
+
): boolean {
|
|
151
|
+
return [dataset.name, dataset.tableNamespace, dataset.field].some(
|
|
152
|
+
(datasetName) =>
|
|
153
|
+
typeof datasetName === 'string' &&
|
|
154
|
+
datasetName.length > 0 &&
|
|
155
|
+
(datasetName === planMap.mapName ||
|
|
156
|
+
datasetName === planMap.tableNamespace ||
|
|
157
|
+
datasetName === mapName),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function countMapLocalTools(input: {
|
|
162
|
+
staticPipeline: PlayStaticPipeline | null | undefined;
|
|
163
|
+
planMap: ChunkSizingMap | null | undefined;
|
|
164
|
+
mapName: string;
|
|
165
|
+
}): MapToolStats | null {
|
|
166
|
+
if (!input.staticPipeline || !input.planMap) return null;
|
|
167
|
+
const planMap = input.planMap;
|
|
168
|
+
const dataset = flattenStaticSubsteps(
|
|
169
|
+
getTopLevelPipelineSubsteps(input.staticPipeline),
|
|
170
|
+
).find(
|
|
171
|
+
(substep): substep is Extract<PlayStaticSubstep, { type: 'dataset' }> =>
|
|
172
|
+
substep.type === 'dataset' &&
|
|
173
|
+
datasetBelongsToPlanMap(substep, planMap, input.mapName),
|
|
174
|
+
);
|
|
175
|
+
if (!dataset) return null;
|
|
176
|
+
|
|
177
|
+
if (dataset.steps?.length) {
|
|
178
|
+
return countToolSubsteps(dataset.steps);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (dataset.columns?.length) {
|
|
182
|
+
return countProducerTools(
|
|
183
|
+
dataset.columns.flatMap((column) => column.producers),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return [0, 0];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function countFallbackDeclarationTools(input: {
|
|
191
|
+
declarations: readonly { toolId: string; field?: string | null }[];
|
|
192
|
+
outputFields: readonly string[];
|
|
193
|
+
externalStepFields?: readonly string[];
|
|
194
|
+
}): MapToolStats {
|
|
195
|
+
let totalToolCount = 0;
|
|
196
|
+
let unbatchedToolCount = 0;
|
|
197
|
+
|
|
198
|
+
for (const declaration of input.declarations) {
|
|
199
|
+
if (
|
|
200
|
+
!declarationBelongsToMapOutput(
|
|
201
|
+
declaration,
|
|
202
|
+
input.outputFields,
|
|
203
|
+
input.externalStepFields ?? [],
|
|
204
|
+
)
|
|
205
|
+
) {
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
totalToolCount += 1;
|
|
209
|
+
if (isUnbatchedTool(declaration.toolId)) {
|
|
210
|
+
unbatchedToolCount += 1;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return [totalToolCount, unbatchedToolCount];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function countDeclarationTools(
|
|
218
|
+
declarations: readonly { toolId: string; field?: string | null }[],
|
|
219
|
+
): MapToolStats {
|
|
220
|
+
return [
|
|
221
|
+
declarations.length,
|
|
222
|
+
declarations.filter((declaration) => isUnbatchedTool(declaration.toolId))
|
|
223
|
+
.length,
|
|
224
|
+
];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function countNestedExecutionSteps(
|
|
228
|
+
substeps: readonly PlayStaticSubstep[] | undefined,
|
|
229
|
+
): number {
|
|
230
|
+
let stepsPerChunk = 1;
|
|
231
|
+
for (const substep of substeps ?? []) {
|
|
232
|
+
if (substep.type === 'waterfall') {
|
|
233
|
+
stepsPerChunk = Math.max(stepsPerChunk, substep.steps?.length ?? 1);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (substep.type === 'step_suite') {
|
|
237
|
+
stepsPerChunk = Math.max(stepsPerChunk, substep.steps.length);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (substep.type === 'control_flow' || substep.type === 'dataset') {
|
|
241
|
+
stepsPerChunk = Math.max(
|
|
242
|
+
stepsPerChunk,
|
|
243
|
+
countNestedExecutionSteps(substep.steps),
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return stepsPerChunk;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function buildStaticChunkSizingPlan(
|
|
251
|
+
staticPipeline: PlayStaticPipeline | null,
|
|
252
|
+
): ChunkSizingPlan | null {
|
|
253
|
+
if (!staticPipeline) return null;
|
|
254
|
+
const datasets = flattenStaticSubsteps(
|
|
255
|
+
getTopLevelPipelineSubsteps(staticPipeline),
|
|
256
|
+
).filter(
|
|
257
|
+
(substep): substep is Extract<PlayStaticSubstep, { type: 'dataset' }> =>
|
|
258
|
+
substep.type === 'dataset',
|
|
259
|
+
);
|
|
260
|
+
if (datasets.length === 0) return null;
|
|
261
|
+
return {
|
|
262
|
+
maps: datasets.map((dataset) => {
|
|
263
|
+
const stepsPerChunk = countNestedExecutionSteps(dataset.steps);
|
|
264
|
+
return {
|
|
265
|
+
mapName: dataset.name ?? dataset.field,
|
|
266
|
+
tableNamespace: dataset.tableNamespace ?? dataset.field,
|
|
267
|
+
outputFields: dataset.outputFields ?? [],
|
|
268
|
+
defaultChunkSize: stepsPerChunk > 1 ? 1_000 : 5_000,
|
|
269
|
+
stepsPerChunk,
|
|
270
|
+
};
|
|
271
|
+
}),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
19
275
|
export function chooseWorkerMapRowsPerChunk(
|
|
20
276
|
input: WorkerMapChunkPlanInput,
|
|
21
277
|
): number {
|
|
22
|
-
const plan = input.executionPlan
|
|
278
|
+
const plan: ChunkSizingPlan | null = input.executionPlan
|
|
279
|
+
? {
|
|
280
|
+
maps: input.executionPlan.maps,
|
|
281
|
+
toolDeclarations: input.executionPlan.toolDeclarations,
|
|
282
|
+
softWorkflowStepBudget:
|
|
283
|
+
input.executionPlan.chunkPlan.softWorkflowStepBudget,
|
|
284
|
+
}
|
|
285
|
+
: buildStaticChunkSizingPlan(input.staticPipeline ?? null);
|
|
23
286
|
const planMap = plan?.maps.find(
|
|
24
287
|
(candidate) =>
|
|
25
288
|
candidate.mapName === input.mapName ||
|
|
26
289
|
candidate.tableNamespace === input.mapName,
|
|
27
290
|
);
|
|
291
|
+
const staticMapToolStats = countMapLocalTools({
|
|
292
|
+
staticPipeline: input.staticPipeline,
|
|
293
|
+
planMap,
|
|
294
|
+
mapName: input.mapName,
|
|
295
|
+
});
|
|
296
|
+
const mapToolStats =
|
|
297
|
+
staticMapToolStats ??
|
|
298
|
+
(plan && planMap
|
|
299
|
+
? countFallbackDeclarationTools({
|
|
300
|
+
declarations: plan.toolDeclarations ?? [],
|
|
301
|
+
outputFields: planMap.outputFields,
|
|
302
|
+
externalStepFields: planMap.externalStepFields ?? [],
|
|
303
|
+
})
|
|
304
|
+
: plan
|
|
305
|
+
? countDeclarationTools(plan.toolDeclarations ?? [])
|
|
306
|
+
: [0, 0]);
|
|
28
307
|
const rowsPerChunk = chooseMapChunkSize({
|
|
29
308
|
totalRows: input.rowCountHint,
|
|
30
309
|
mapCount: Math.max(1, plan?.maps.length ?? 1),
|
|
31
310
|
stepsPerChunk: planMap?.stepsPerChunk ?? 1,
|
|
32
311
|
preferredChunkSize: planMap?.defaultChunkSize,
|
|
33
|
-
softWorkflowStepBudget: plan?.
|
|
312
|
+
softWorkflowStepBudget: plan?.softWorkflowStepBudget,
|
|
34
313
|
});
|
|
35
|
-
const estimatedSubrequestProducingSteps =
|
|
36
|
-
estimateSubrequestProducingStepsForMap(plan, planMap);
|
|
37
|
-
if (estimatedSubrequestProducingSteps > 0) {
|
|
38
|
-
const subrequestSafeRows = Math.max(
|
|
39
|
-
1,
|
|
40
|
-
Math.floor(
|
|
41
|
-
WORKER_SUBREQUEST_SAFE_TOOL_CALLS_PER_CHUNK /
|
|
42
|
-
estimatedSubrequestProducingSteps,
|
|
43
|
-
),
|
|
44
|
-
);
|
|
45
|
-
if (subrequestSafeRows < rowsPerChunk) {
|
|
46
|
-
if (input.rowCountHint === null || !Number.isFinite(input.rowCountHint)) {
|
|
47
|
-
return subrequestSafeRows;
|
|
48
|
-
}
|
|
49
|
-
const totalRows = Math.max(0, Math.floor(input.rowCountHint));
|
|
50
|
-
const mapCount = Math.max(1, plan?.maps.length ?? 1);
|
|
51
|
-
const softBudget =
|
|
52
|
-
plan?.chunkPlan.softWorkflowStepBudget ??
|
|
53
|
-
EXECUTION_PLAN_DEFAULTS.workflowSoftStepBudget;
|
|
54
|
-
const maxChunksPerMap = Math.max(
|
|
55
|
-
1,
|
|
56
|
-
Math.floor(
|
|
57
|
-
Math.max(
|
|
58
|
-
mapCount,
|
|
59
|
-
Math.floor(
|
|
60
|
-
(softBudget -
|
|
61
|
-
EXECUTION_PLAN_DEFAULTS.ingestStepCount -
|
|
62
|
-
EXECUTION_PLAN_DEFAULTS.finalizationStepCount) /
|
|
63
|
-
estimatedSubrequestProducingSteps,
|
|
64
|
-
),
|
|
65
|
-
) / mapCount,
|
|
66
|
-
),
|
|
67
|
-
);
|
|
68
|
-
const requiredChunks = Math.ceil(totalRows / subrequestSafeRows);
|
|
69
|
-
if (requiredChunks <= maxChunksPerMap) return subrequestSafeRows;
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Worker budget exceeded for map "${input.mapName}": ${requiredChunks}/${maxChunksPerMap} chunks.`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
return rowsPerChunk;
|
|
75
|
-
}
|
|
76
314
|
|
|
77
315
|
const toolFreeSimpleMap =
|
|
78
|
-
!!planMap &&
|
|
79
|
-
planMap.stepsPerChunk === 1 &&
|
|
80
|
-
estimateSubrequestProducingStepsForMap(plan, planMap) === 0;
|
|
316
|
+
!!planMap && planMap.stepsPerChunk === 1 && mapToolStats[0] === 0;
|
|
81
317
|
if (
|
|
82
318
|
toolFreeSimpleMap &&
|
|
83
319
|
(input.rowCountHint === null ||
|
|
@@ -86,75 +322,22 @@ export function chooseWorkerMapRowsPerChunk(
|
|
|
86
322
|
return Math.max(rowsPerChunk, CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE);
|
|
87
323
|
}
|
|
88
324
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
explicitExternalSteps > 0
|
|
105
|
-
? 0
|
|
106
|
-
: (planMap.stepsPerChunk ?? 1) > 1
|
|
107
|
-
? (planMap.stepsPerChunk ?? 1)
|
|
108
|
-
: 0;
|
|
109
|
-
if (toolDeclarations.length === 0) {
|
|
110
|
-
return Math.max(mapStepsPerChunk, explicitExternalSteps);
|
|
111
|
-
}
|
|
112
|
-
const outputFields = new Set(
|
|
113
|
-
planMap.outputFields.map((field) => field.trim()).filter(Boolean),
|
|
114
|
-
);
|
|
115
|
-
const explicitExternalStepFields = new Set(
|
|
116
|
-
(planMap.externalStepFields ?? [])
|
|
117
|
-
.map((field) => field.trim())
|
|
118
|
-
.filter(Boolean),
|
|
119
|
-
);
|
|
120
|
-
const hasModernStepMetadata =
|
|
121
|
-
Array.isArray(planMap.stepFields) ||
|
|
122
|
-
Array.isArray(planMap.externalStepFields);
|
|
123
|
-
const mapFields = new Set([
|
|
124
|
-
planMap.mapName,
|
|
125
|
-
planMap.tableNamespace,
|
|
126
|
-
...planMap.outputFields,
|
|
127
|
-
...(planMap.externalStepFields ?? []),
|
|
128
|
-
...(hasModernStepMetadata ? [] : (planMap.stepFields ?? [])),
|
|
129
|
-
...planMap.waterfallStages.flatMap((stage) => [
|
|
130
|
-
stage.waterfallId,
|
|
131
|
-
...stage.stageIds,
|
|
132
|
-
]),
|
|
133
|
-
]);
|
|
134
|
-
let scopedToolDeclarations = 0;
|
|
135
|
-
for (const declaration of toolDeclarations) {
|
|
136
|
-
const field = declaration.field?.trim();
|
|
137
|
-
if (!field) continue;
|
|
138
|
-
if (mapFields.has(field)) {
|
|
139
|
-
scopedToolDeclarations += 1;
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (!field.includes('.')) {
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
const firstSegment = field.slice(0, field.indexOf('.'));
|
|
146
|
-
const lastSegment = field.slice(field.lastIndexOf('.') + 1);
|
|
147
|
-
if (
|
|
148
|
-
outputFields.has(firstSegment) ||
|
|
149
|
-
explicitExternalStepFields.has(lastSegment) ||
|
|
150
|
-
(!hasModernStepMetadata && outputFields.has(lastSegment))
|
|
151
|
-
) {
|
|
152
|
-
scopedToolDeclarations += 1;
|
|
153
|
-
}
|
|
325
|
+
if (mapToolStats[1] > 0) {
|
|
326
|
+
const unbatchedToolCallsPerRow =
|
|
327
|
+
staticMapToolStats !== null
|
|
328
|
+
? mapToolStats[1]
|
|
329
|
+
: Math.max(planMap?.stepsPerChunk ?? 1, mapToolStats[1]);
|
|
330
|
+
const unbatchedSubrequestsPerRow =
|
|
331
|
+
unbatchedToolCallsPerRow * SUBREQUESTS_PER_UNBATCHED_TOOL_CALL;
|
|
332
|
+
const unbatchedToolRowsPerChunk = Math.max(
|
|
333
|
+
1,
|
|
334
|
+
Math.floor(
|
|
335
|
+
UNBATCHED_TOOL_SUBREQUESTS_PER_CHUNK_BUDGET /
|
|
336
|
+
unbatchedSubrequestsPerRow,
|
|
337
|
+
),
|
|
338
|
+
);
|
|
339
|
+
return Math.min(rowsPerChunk, unbatchedToolRowsPerChunk);
|
|
154
340
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
explicitExternalSteps,
|
|
158
|
-
scopedToolDeclarations,
|
|
159
|
-
);
|
|
341
|
+
|
|
342
|
+
return rowsPerChunk;
|
|
160
343
|
}
|
|
@@ -104,10 +104,10 @@ export const SDK_RELEASE = {
|
|
|
104
104
|
// 0.1.111 ships dataset-native tool list getters and result row datasets.
|
|
105
105
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
106
106
|
// fields shipped in 0.1.153.
|
|
107
|
-
version: '0.1.
|
|
107
|
+
version: '0.1.165',
|
|
108
108
|
apiContract: '2026-06-dataset-handle-results-hard-cutover',
|
|
109
109
|
supportPolicy: {
|
|
110
|
-
latest: '0.1.
|
|
110
|
+
latest: '0.1.165',
|
|
111
111
|
minimumSupported: '0.1.53',
|
|
112
112
|
deprecatedBelow: '0.1.53',
|
|
113
113
|
commandMinimumSupported: [
|
|
@@ -319,6 +319,15 @@ export interface ToolSearchResult {
|
|
|
319
319
|
search_mode?: 'v1' | 'v2';
|
|
320
320
|
/** Whether search fell back to category matching. */
|
|
321
321
|
search_fallback_to_category?: boolean;
|
|
322
|
+
/** Explanation and next commands when filters/search succeed but match zero tools. */
|
|
323
|
+
emptyResult?: {
|
|
324
|
+
reason: string;
|
|
325
|
+
message: string;
|
|
326
|
+
suggestions: Array<{
|
|
327
|
+
label: string;
|
|
328
|
+
command: string;
|
|
329
|
+
}>;
|
|
330
|
+
};
|
|
322
331
|
/** Hint explaining omitted play results when searching tools only. */
|
|
323
332
|
omitted_plays_hint?: string;
|
|
324
333
|
/** Copyable CLI command templates for follow-up discovery/execution. */
|