deepline 0.1.107 → 0.1.108
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 +98 -24
- package/dist/cli/index.mjs +98 -24
- package/dist/index.d.mts +21 -5
- package/dist/index.d.ts +21 -5
- package/dist/index.js +10 -4
- package/dist/index.mjs +10 -4
- package/dist/repo/apps/play-runner-workers/src/entry.ts +55 -44
- package/dist/repo/sdk/src/play.ts +21 -4
- package/dist/repo/sdk/src/release.ts +5 -3
- package/dist/repo/sdk/src/worker-play-entry.ts +4 -0
- package/dist/repo/shared_libs/play-runtime/cell-staleness.ts +64 -5
- package/dist/repo/shared_libs/play-runtime/run-ledger.ts +6 -0
- package/dist/repo/shared_libs/play-runtime/step-program-dataset-builder.ts +8 -0
- package/dist/repo/shared_libs/plays/static-pipeline.ts +87 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -244,16 +244,18 @@ var SDK_RELEASE = {
|
|
|
244
244
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
245
245
|
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
246
246
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
247
|
-
|
|
247
|
+
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
248
|
+
// the SDK enrich generator's one-second stale policy.
|
|
249
|
+
version: "0.1.108",
|
|
248
250
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
249
251
|
supportPolicy: {
|
|
250
|
-
latest: "0.1.
|
|
252
|
+
latest: "0.1.108",
|
|
251
253
|
minimumSupported: "0.1.53",
|
|
252
254
|
deprecatedBelow: "0.1.53",
|
|
253
255
|
commandMinimumSupported: [
|
|
254
256
|
{
|
|
255
257
|
command: "enrich",
|
|
256
|
-
minimumSupported: "0.1.
|
|
258
|
+
minimumSupported: "0.1.108",
|
|
257
259
|
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
258
260
|
}
|
|
259
261
|
],
|
|
@@ -857,6 +859,8 @@ function normalizeStepProgress(value) {
|
|
|
857
859
|
value.artifactTableNamespace
|
|
858
860
|
)
|
|
859
861
|
} : {},
|
|
862
|
+
...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
|
|
863
|
+
...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
|
|
860
864
|
...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {}
|
|
861
865
|
};
|
|
862
866
|
}
|
|
@@ -15491,7 +15495,7 @@ function renderIdiomaticExecuteStep(command, options) {
|
|
|
15491
15495
|
` tool: ${tool},`,
|
|
15492
15496
|
` input: ${input2} as any,`,
|
|
15493
15497
|
` description: ${stringLiteral((command.description ?? "").trim() || `Run ${command.alias} via ${command.tool}.`)},`,
|
|
15494
|
-
...options.force ? [`
|
|
15498
|
+
...options.force ? [` force: true,`] : [],
|
|
15495
15499
|
` });`,
|
|
15496
15500
|
` return ${extraction};`,
|
|
15497
15501
|
`}`
|
|
@@ -15523,17 +15527,13 @@ function renderPlayStep(command, options) {
|
|
|
15523
15527
|
${indent(renderJavascriptBody(command.run_if_js), 6)}
|
|
15524
15528
|
}` : "null";
|
|
15525
15529
|
const runIfLines = command.run_if_js ? [` const __dlRunIf = ${runIfJs};`, ` if (!__dlRunIf(row)) return null;`] : [];
|
|
15526
|
-
const playOptions = [
|
|
15527
|
-
` description: ${stringLiteral(command.description ?? command.alias)}`,
|
|
15528
|
-
...options.force ? [` staleAfterSeconds: 1`] : []
|
|
15529
|
-
].join(",\n");
|
|
15530
15530
|
return [
|
|
15531
15531
|
`async (row, stepCtx) => {`,
|
|
15532
15532
|
...options.precheck ? [` if (${options.precheck}) return null;`] : [],
|
|
15533
15533
|
...runIfLines,
|
|
15534
15534
|
` const payload = __dlTemplate(${payload}, row) as Record<string, unknown>;`,
|
|
15535
15535
|
` const result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
|
|
15536
|
-
|
|
15536
|
+
` description: ${stringLiteral(command.description ?? command.alias)}`,
|
|
15537
15537
|
` });`,
|
|
15538
15538
|
` return __dlPlayResultValue(${alias}, result);`,
|
|
15539
15539
|
`}`
|
|
@@ -15550,12 +15550,17 @@ function renderJavascriptBody(source) {
|
|
|
15550
15550
|
}
|
|
15551
15551
|
return source;
|
|
15552
15552
|
}
|
|
15553
|
-
function renderColumnStep(alias, resolverSource,
|
|
15553
|
+
function renderColumnStep(alias, resolverSource, options = {}) {
|
|
15554
15554
|
const resolver = indent(resolverSource, 8);
|
|
15555
|
+
const optionFields = [
|
|
15556
|
+
...options.recompute === true ? ["recompute: true"] : [],
|
|
15557
|
+
...options.recomputeOnError === true ? ["recomputeOnError: true"] : []
|
|
15558
|
+
];
|
|
15559
|
+
const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
|
|
15555
15560
|
return [
|
|
15556
15561
|
` .withColumn(${stringLiteral(alias)},`,
|
|
15557
|
-
|
|
15558
|
-
...
|
|
15562
|
+
`${resolver}${optionSource ? "," : ""}`,
|
|
15563
|
+
...optionSource ? [` ${optionSource},`] : [],
|
|
15559
15564
|
` )`
|
|
15560
15565
|
].join("\n");
|
|
15561
15566
|
}
|
|
@@ -15604,6 +15609,29 @@ function collectMetadataColumns(commands, waterfallGroupId) {
|
|
|
15604
15609
|
}
|
|
15605
15610
|
return columns;
|
|
15606
15611
|
}
|
|
15612
|
+
function collectGeneratedAliases(commands) {
|
|
15613
|
+
const aliases = [];
|
|
15614
|
+
const addAlias = (alias) => {
|
|
15615
|
+
if (alias && !aliases.includes(alias)) {
|
|
15616
|
+
aliases.push(alias);
|
|
15617
|
+
}
|
|
15618
|
+
};
|
|
15619
|
+
for (const command of commands) {
|
|
15620
|
+
if (isWaterfall(command)) {
|
|
15621
|
+
const before = aliases.length;
|
|
15622
|
+
collectGeneratedAliases(command.commands).forEach(addAlias);
|
|
15623
|
+
if (aliases.length > before) {
|
|
15624
|
+
addAlias(command.with_waterfall);
|
|
15625
|
+
addAlias(`${command.with_waterfall}_source`);
|
|
15626
|
+
}
|
|
15627
|
+
continue;
|
|
15628
|
+
}
|
|
15629
|
+
if (!command.disabled) {
|
|
15630
|
+
addAlias(command.alias);
|
|
15631
|
+
}
|
|
15632
|
+
}
|
|
15633
|
+
return aliases;
|
|
15634
|
+
}
|
|
15607
15635
|
function renderMetadataColumnStep(config) {
|
|
15608
15636
|
const columns = collectMetadataColumns(config.commands);
|
|
15609
15637
|
if (Object.keys(columns).length === 0) {
|
|
@@ -15611,8 +15639,8 @@ function renderMetadataColumnStep(config) {
|
|
|
15611
15639
|
}
|
|
15612
15640
|
return [
|
|
15613
15641
|
` .withColumn('_metadata',`,
|
|
15614
|
-
` (row) => __dlMergeMetadata(row
|
|
15615
|
-
` {
|
|
15642
|
+
` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
|
|
15643
|
+
` { recompute: true },`,
|
|
15616
15644
|
` )`
|
|
15617
15645
|
].join("\n");
|
|
15618
15646
|
}
|
|
@@ -15639,7 +15667,7 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
|
|
|
15639
15667
|
inlineRunJavascript,
|
|
15640
15668
|
idiomaticGetters
|
|
15641
15669
|
}),
|
|
15642
|
-
force
|
|
15670
|
+
{ recompute: force, recomputeOnError: true }
|
|
15643
15671
|
);
|
|
15644
15672
|
}).filter((line) => line !== null);
|
|
15645
15673
|
const aliases = activeChildren.map((nested) => nested.alias);
|
|
@@ -15655,15 +15683,13 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
|
|
|
15655
15683
|
}
|
|
15656
15684
|
return [
|
|
15657
15685
|
...columnSteps,
|
|
15658
|
-
renderColumnStep(
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
forceParent
|
|
15662
|
-
),
|
|
15686
|
+
renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`, {
|
|
15687
|
+
recompute: forceParent
|
|
15688
|
+
}),
|
|
15663
15689
|
renderColumnStep(
|
|
15664
15690
|
`${command.with_waterfall}_source`,
|
|
15665
15691
|
typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`,
|
|
15666
|
-
forceParent
|
|
15692
|
+
{ recompute: forceParent }
|
|
15667
15693
|
)
|
|
15668
15694
|
];
|
|
15669
15695
|
}
|
|
@@ -15700,18 +15726,20 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
|
|
|
15700
15726
|
inlineRunJavascript,
|
|
15701
15727
|
idiomaticGetters
|
|
15702
15728
|
}),
|
|
15703
|
-
force
|
|
15729
|
+
{ recompute: force, recomputeOnError: true }
|
|
15704
15730
|
)
|
|
15705
15731
|
);
|
|
15706
15732
|
});
|
|
15707
15733
|
const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
|
|
15708
15734
|
const metadataColumnSource = renderMetadataColumnStep(config);
|
|
15735
|
+
const generatedAliases = collectGeneratedAliases(config.commands);
|
|
15709
15736
|
const body = [
|
|
15710
15737
|
`export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
|
|
15711
15738
|
` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
|
|
15712
15739
|
` const rowStart = __dlNonNegativeInteger(input.rowStart, 0);`,
|
|
15713
15740
|
` const rowEndExclusive = Number.isFinite(input.rowEnd) ? Math.max(rowStart, __dlWholeNumber(input.rowEnd, rowStart) + 1) : undefined;`,
|
|
15714
|
-
` const
|
|
15741
|
+
` const selectedRows = sourceRows.slice(rowStart, rowEndExclusive, { key: 'deepline_enrich_selected_rows', sourceLabel: 'Selected enrich rows' });`,
|
|
15742
|
+
` const rows = selectedRows.map((row) => __dlStripErroredGeneratedColumns(row, ${stableJson(generatedAliases)}), { key: 'deepline_enrich_repair_rows', sourceLabel: 'Selected enrich rows' });`,
|
|
15715
15743
|
` const enriched = await ctx`,
|
|
15716
15744
|
` .dataset(${stringLiteral(mapName)}, rows)`,
|
|
15717
15745
|
columnStepSource,
|
|
@@ -15797,6 +15825,18 @@ function helperSource() {
|
|
|
15797
15825
|
` return null;`,
|
|
15798
15826
|
`}`,
|
|
15799
15827
|
``,
|
|
15828
|
+
`function __dlMetadataFromRow(row: Record<string, unknown>): unknown {`,
|
|
15829
|
+
` const direct = __dlParseMetadata(row._metadata);`,
|
|
15830
|
+
` if (direct) return direct;`,
|
|
15831
|
+
` const relocated = __dlParseMetadata(row.metadata);`,
|
|
15832
|
+
` if (relocated) return relocated;`,
|
|
15833
|
+
` const dotted = __dlParseMetadata(row['metadata.columns']);`,
|
|
15834
|
+
` if (dotted) return { columns: dotted };`,
|
|
15835
|
+
` const underscored = __dlParseMetadata(row.metadata__columns);`,
|
|
15836
|
+
` if (underscored) return { columns: underscored };`,
|
|
15837
|
+
` return row._metadata;`,
|
|
15838
|
+
`}`,
|
|
15839
|
+
``,
|
|
15800
15840
|
`function __dlMergeMetadata(existing: unknown, patch: Record<string, unknown>): Record<string, unknown> {`,
|
|
15801
15841
|
` const base = __dlParseMetadata(existing) ?? {};`,
|
|
15802
15842
|
` const baseColumns = __dlRecord(base.columns) ? base.columns : {};`,
|
|
@@ -15871,6 +15911,40 @@ function helperSource() {
|
|
|
15871
15911
|
` return status === 'error' || status === 'failed' || (typeof record.error === 'string' && record.error.trim() !== '') || (typeof resultError === 'string' && resultError.trim() !== '');`,
|
|
15872
15912
|
`}`,
|
|
15873
15913
|
``,
|
|
15914
|
+
`function __dlGeneratedCellError(value: unknown): boolean {`,
|
|
15915
|
+
` if (typeof value === 'string') {`,
|
|
15916
|
+
` const lower = value.trim().toLowerCase();`,
|
|
15917
|
+
` if (!lower) return false;`,
|
|
15918
|
+
` if (lower.startsWith('error:') || lower.includes(': error:') || lower.includes('"error"')) return true;`,
|
|
15919
|
+
` try {`,
|
|
15920
|
+
` return __dlGeneratedCellError(JSON.parse(value));`,
|
|
15921
|
+
` } catch {`,
|
|
15922
|
+
` return false;`,
|
|
15923
|
+
` }`,
|
|
15924
|
+
` }`,
|
|
15925
|
+
` if (!__dlRecord(value)) return false;`,
|
|
15926
|
+
` const status = typeof value.status === 'string' ? value.status.toLowerCase() : '';`,
|
|
15927
|
+
` if (status === 'error' || status === 'failed') return true;`,
|
|
15928
|
+
` if (typeof value.error === 'string' && value.error.trim() !== '') return true;`,
|
|
15929
|
+
` const raw = __dlGetByPath(value, 'toolResponse.raw') ?? __dlGetByPath(value, 'toolOutput.raw');`,
|
|
15930
|
+
` if (raw !== undefined && raw !== value && __dlGeneratedCellError(raw)) return true;`,
|
|
15931
|
+
` const result = value.result;`,
|
|
15932
|
+
` return result !== undefined && result !== value && __dlGeneratedCellError(result);`,
|
|
15933
|
+
`}`,
|
|
15934
|
+
``,
|
|
15935
|
+
`function __dlStripErroredGeneratedColumns(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
|
|
15936
|
+
` let next: Record<string, unknown> | null = null;`,
|
|
15937
|
+
` for (const alias of aliases) {`,
|
|
15938
|
+
` for (const key of __dlAliasCandidates(alias)) {`,
|
|
15939
|
+
` if (key in row && __dlGeneratedCellError(row[key])) {`,
|
|
15940
|
+
` if (next === null) next = { ...row };`,
|
|
15941
|
+
` delete next[key];`,
|
|
15942
|
+
` }`,
|
|
15943
|
+
` }`,
|
|
15944
|
+
` }`,
|
|
15945
|
+
` return next ?? row;`,
|
|
15946
|
+
`}`,
|
|
15947
|
+
``,
|
|
15874
15948
|
`function __dlRawToolOutput(result: unknown): unknown {`,
|
|
15875
15949
|
` if (!result || typeof result !== 'object') return result;`,
|
|
15876
15950
|
` const record = result as Record<string, unknown>;`,
|
|
@@ -16281,7 +16355,7 @@ function helperSource() {
|
|
|
16281
16355
|
` tool: input.tool,`,
|
|
16282
16356
|
` input: payload,`,
|
|
16283
16357
|
` ...(input.description ? { description: input.description } : {}),`,
|
|
16284
|
-
` ...(input.force ? {
|
|
16358
|
+
` ...(input.force ? { force: true } : {}),`,
|
|
16285
16359
|
` });`,
|
|
16286
16360
|
` return __dlExtract(input.alias, result, input.row, input.extract, Boolean(input.legacyEnvelope));`,
|
|
16287
16361
|
`}`
|
package/dist/cli/index.mjs
CHANGED
|
@@ -221,16 +221,18 @@ var SDK_RELEASE = {
|
|
|
221
221
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
222
222
|
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
223
223
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
224
|
-
|
|
224
|
+
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
225
|
+
// the SDK enrich generator's one-second stale policy.
|
|
226
|
+
version: "0.1.108",
|
|
225
227
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
226
228
|
supportPolicy: {
|
|
227
|
-
latest: "0.1.
|
|
229
|
+
latest: "0.1.108",
|
|
228
230
|
minimumSupported: "0.1.53",
|
|
229
231
|
deprecatedBelow: "0.1.53",
|
|
230
232
|
commandMinimumSupported: [
|
|
231
233
|
{
|
|
232
234
|
command: "enrich",
|
|
233
|
-
minimumSupported: "0.1.
|
|
235
|
+
minimumSupported: "0.1.108",
|
|
234
236
|
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
235
237
|
}
|
|
236
238
|
],
|
|
@@ -834,6 +836,8 @@ function normalizeStepProgress(value) {
|
|
|
834
836
|
value.artifactTableNamespace
|
|
835
837
|
)
|
|
836
838
|
} : {},
|
|
839
|
+
...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
|
|
840
|
+
...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
|
|
837
841
|
...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {}
|
|
838
842
|
};
|
|
839
843
|
}
|
|
@@ -15508,7 +15512,7 @@ function renderIdiomaticExecuteStep(command, options) {
|
|
|
15508
15512
|
` tool: ${tool},`,
|
|
15509
15513
|
` input: ${input2} as any,`,
|
|
15510
15514
|
` description: ${stringLiteral((command.description ?? "").trim() || `Run ${command.alias} via ${command.tool}.`)},`,
|
|
15511
|
-
...options.force ? [`
|
|
15515
|
+
...options.force ? [` force: true,`] : [],
|
|
15512
15516
|
` });`,
|
|
15513
15517
|
` return ${extraction};`,
|
|
15514
15518
|
`}`
|
|
@@ -15540,17 +15544,13 @@ function renderPlayStep(command, options) {
|
|
|
15540
15544
|
${indent(renderJavascriptBody(command.run_if_js), 6)}
|
|
15541
15545
|
}` : "null";
|
|
15542
15546
|
const runIfLines = command.run_if_js ? [` const __dlRunIf = ${runIfJs};`, ` if (!__dlRunIf(row)) return null;`] : [];
|
|
15543
|
-
const playOptions = [
|
|
15544
|
-
` description: ${stringLiteral(command.description ?? command.alias)}`,
|
|
15545
|
-
...options.force ? [` staleAfterSeconds: 1`] : []
|
|
15546
|
-
].join(",\n");
|
|
15547
15547
|
return [
|
|
15548
15548
|
`async (row, stepCtx) => {`,
|
|
15549
15549
|
...options.precheck ? [` if (${options.precheck}) return null;`] : [],
|
|
15550
15550
|
...runIfLines,
|
|
15551
15551
|
` const payload = __dlTemplate(${payload}, row) as Record<string, unknown>;`,
|
|
15552
15552
|
` const result = await stepCtx.runPlay(${callId}, ${playRef}, payload, {`,
|
|
15553
|
-
|
|
15553
|
+
` description: ${stringLiteral(command.description ?? command.alias)}`,
|
|
15554
15554
|
` });`,
|
|
15555
15555
|
` return __dlPlayResultValue(${alias}, result);`,
|
|
15556
15556
|
`}`
|
|
@@ -15567,12 +15567,17 @@ function renderJavascriptBody(source) {
|
|
|
15567
15567
|
}
|
|
15568
15568
|
return source;
|
|
15569
15569
|
}
|
|
15570
|
-
function renderColumnStep(alias, resolverSource,
|
|
15570
|
+
function renderColumnStep(alias, resolverSource, options = {}) {
|
|
15571
15571
|
const resolver = indent(resolverSource, 8);
|
|
15572
|
+
const optionFields = [
|
|
15573
|
+
...options.recompute === true ? ["recompute: true"] : [],
|
|
15574
|
+
...options.recomputeOnError === true ? ["recomputeOnError: true"] : []
|
|
15575
|
+
];
|
|
15576
|
+
const optionSource = optionFields.length > 0 ? `{ ${optionFields.join(", ")} }` : null;
|
|
15572
15577
|
return [
|
|
15573
15578
|
` .withColumn(${stringLiteral(alias)},`,
|
|
15574
|
-
|
|
15575
|
-
...
|
|
15579
|
+
`${resolver}${optionSource ? "," : ""}`,
|
|
15580
|
+
...optionSource ? [` ${optionSource},`] : [],
|
|
15576
15581
|
` )`
|
|
15577
15582
|
].join("\n");
|
|
15578
15583
|
}
|
|
@@ -15621,6 +15626,29 @@ function collectMetadataColumns(commands, waterfallGroupId) {
|
|
|
15621
15626
|
}
|
|
15622
15627
|
return columns;
|
|
15623
15628
|
}
|
|
15629
|
+
function collectGeneratedAliases(commands) {
|
|
15630
|
+
const aliases = [];
|
|
15631
|
+
const addAlias = (alias) => {
|
|
15632
|
+
if (alias && !aliases.includes(alias)) {
|
|
15633
|
+
aliases.push(alias);
|
|
15634
|
+
}
|
|
15635
|
+
};
|
|
15636
|
+
for (const command of commands) {
|
|
15637
|
+
if (isWaterfall(command)) {
|
|
15638
|
+
const before = aliases.length;
|
|
15639
|
+
collectGeneratedAliases(command.commands).forEach(addAlias);
|
|
15640
|
+
if (aliases.length > before) {
|
|
15641
|
+
addAlias(command.with_waterfall);
|
|
15642
|
+
addAlias(`${command.with_waterfall}_source`);
|
|
15643
|
+
}
|
|
15644
|
+
continue;
|
|
15645
|
+
}
|
|
15646
|
+
if (!command.disabled) {
|
|
15647
|
+
addAlias(command.alias);
|
|
15648
|
+
}
|
|
15649
|
+
}
|
|
15650
|
+
return aliases;
|
|
15651
|
+
}
|
|
15624
15652
|
function renderMetadataColumnStep(config) {
|
|
15625
15653
|
const columns = collectMetadataColumns(config.commands);
|
|
15626
15654
|
if (Object.keys(columns).length === 0) {
|
|
@@ -15628,8 +15656,8 @@ function renderMetadataColumnStep(config) {
|
|
|
15628
15656
|
}
|
|
15629
15657
|
return [
|
|
15630
15658
|
` .withColumn('_metadata',`,
|
|
15631
|
-
` (row) => __dlMergeMetadata(row
|
|
15632
|
-
` {
|
|
15659
|
+
` (row) => __dlMergeMetadata(__dlMetadataFromRow(row), ${stableJson({ columns })}),`,
|
|
15660
|
+
` { recompute: true },`,
|
|
15633
15661
|
` )`
|
|
15634
15662
|
].join("\n");
|
|
15635
15663
|
}
|
|
@@ -15656,7 +15684,7 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
|
|
|
15656
15684
|
inlineRunJavascript,
|
|
15657
15685
|
idiomaticGetters
|
|
15658
15686
|
}),
|
|
15659
|
-
force
|
|
15687
|
+
{ recompute: force, recomputeOnError: true }
|
|
15660
15688
|
);
|
|
15661
15689
|
}).filter((line) => line !== null);
|
|
15662
15690
|
const aliases = activeChildren.map((nested) => nested.alias);
|
|
@@ -15672,15 +15700,13 @@ function renderWaterfallColumns(command, forceAliases, inlineRunJavascript, idio
|
|
|
15672
15700
|
}
|
|
15673
15701
|
return [
|
|
15674
15702
|
...columnSteps,
|
|
15675
|
-
renderColumnStep(
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
forceParent
|
|
15679
|
-
),
|
|
15703
|
+
renderColumnStep(command.with_waterfall, `(row) => ${returnExpr}`, {
|
|
15704
|
+
recompute: forceParent
|
|
15705
|
+
}),
|
|
15680
15706
|
renderColumnStep(
|
|
15681
15707
|
`${command.with_waterfall}_source`,
|
|
15682
15708
|
typeof command.min_results === "number" ? `(row) => __dlContributingAliases(row, ${stableJson(aliases)})` : `(row) => __dlFirstMeaningfulAlias(row, ${stableJson(aliases)})`,
|
|
15683
|
-
forceParent
|
|
15709
|
+
{ recompute: forceParent }
|
|
15684
15710
|
)
|
|
15685
15711
|
];
|
|
15686
15712
|
}
|
|
@@ -15717,18 +15743,20 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
|
|
|
15717
15743
|
inlineRunJavascript,
|
|
15718
15744
|
idiomaticGetters
|
|
15719
15745
|
}),
|
|
15720
|
-
force
|
|
15746
|
+
{ recompute: force, recomputeOnError: true }
|
|
15721
15747
|
)
|
|
15722
15748
|
);
|
|
15723
15749
|
});
|
|
15724
15750
|
const columnStepSource = columnSteps.length > 0 ? columnSteps.join("\n") : ` .withColumn('noop', () => null)`;
|
|
15725
15751
|
const metadataColumnSource = renderMetadataColumnStep(config);
|
|
15752
|
+
const generatedAliases = collectGeneratedAliases(config.commands);
|
|
15726
15753
|
const body = [
|
|
15727
15754
|
`export default definePlay(${stringLiteral(playName)}, async (ctx, input: EnrichInput) => {`,
|
|
15728
15755
|
` const sourceRows = await ctx.csv<Record<string, unknown>>(input.file);`,
|
|
15729
15756
|
` const rowStart = __dlNonNegativeInteger(input.rowStart, 0);`,
|
|
15730
15757
|
` const rowEndExclusive = Number.isFinite(input.rowEnd) ? Math.max(rowStart, __dlWholeNumber(input.rowEnd, rowStart) + 1) : undefined;`,
|
|
15731
|
-
` const
|
|
15758
|
+
` const selectedRows = sourceRows.slice(rowStart, rowEndExclusive, { key: 'deepline_enrich_selected_rows', sourceLabel: 'Selected enrich rows' });`,
|
|
15759
|
+
` const rows = selectedRows.map((row) => __dlStripErroredGeneratedColumns(row, ${stableJson(generatedAliases)}), { key: 'deepline_enrich_repair_rows', sourceLabel: 'Selected enrich rows' });`,
|
|
15732
15760
|
` const enriched = await ctx`,
|
|
15733
15761
|
` .dataset(${stringLiteral(mapName)}, rows)`,
|
|
15734
15762
|
columnStepSource,
|
|
@@ -15814,6 +15842,18 @@ function helperSource() {
|
|
|
15814
15842
|
` return null;`,
|
|
15815
15843
|
`}`,
|
|
15816
15844
|
``,
|
|
15845
|
+
`function __dlMetadataFromRow(row: Record<string, unknown>): unknown {`,
|
|
15846
|
+
` const direct = __dlParseMetadata(row._metadata);`,
|
|
15847
|
+
` if (direct) return direct;`,
|
|
15848
|
+
` const relocated = __dlParseMetadata(row.metadata);`,
|
|
15849
|
+
` if (relocated) return relocated;`,
|
|
15850
|
+
` const dotted = __dlParseMetadata(row['metadata.columns']);`,
|
|
15851
|
+
` if (dotted) return { columns: dotted };`,
|
|
15852
|
+
` const underscored = __dlParseMetadata(row.metadata__columns);`,
|
|
15853
|
+
` if (underscored) return { columns: underscored };`,
|
|
15854
|
+
` return row._metadata;`,
|
|
15855
|
+
`}`,
|
|
15856
|
+
``,
|
|
15817
15857
|
`function __dlMergeMetadata(existing: unknown, patch: Record<string, unknown>): Record<string, unknown> {`,
|
|
15818
15858
|
` const base = __dlParseMetadata(existing) ?? {};`,
|
|
15819
15859
|
` const baseColumns = __dlRecord(base.columns) ? base.columns : {};`,
|
|
@@ -15888,6 +15928,40 @@ function helperSource() {
|
|
|
15888
15928
|
` return status === 'error' || status === 'failed' || (typeof record.error === 'string' && record.error.trim() !== '') || (typeof resultError === 'string' && resultError.trim() !== '');`,
|
|
15889
15929
|
`}`,
|
|
15890
15930
|
``,
|
|
15931
|
+
`function __dlGeneratedCellError(value: unknown): boolean {`,
|
|
15932
|
+
` if (typeof value === 'string') {`,
|
|
15933
|
+
` const lower = value.trim().toLowerCase();`,
|
|
15934
|
+
` if (!lower) return false;`,
|
|
15935
|
+
` if (lower.startsWith('error:') || lower.includes(': error:') || lower.includes('"error"')) return true;`,
|
|
15936
|
+
` try {`,
|
|
15937
|
+
` return __dlGeneratedCellError(JSON.parse(value));`,
|
|
15938
|
+
` } catch {`,
|
|
15939
|
+
` return false;`,
|
|
15940
|
+
` }`,
|
|
15941
|
+
` }`,
|
|
15942
|
+
` if (!__dlRecord(value)) return false;`,
|
|
15943
|
+
` const status = typeof value.status === 'string' ? value.status.toLowerCase() : '';`,
|
|
15944
|
+
` if (status === 'error' || status === 'failed') return true;`,
|
|
15945
|
+
` if (typeof value.error === 'string' && value.error.trim() !== '') return true;`,
|
|
15946
|
+
` const raw = __dlGetByPath(value, 'toolResponse.raw') ?? __dlGetByPath(value, 'toolOutput.raw');`,
|
|
15947
|
+
` if (raw !== undefined && raw !== value && __dlGeneratedCellError(raw)) return true;`,
|
|
15948
|
+
` const result = value.result;`,
|
|
15949
|
+
` return result !== undefined && result !== value && __dlGeneratedCellError(result);`,
|
|
15950
|
+
`}`,
|
|
15951
|
+
``,
|
|
15952
|
+
`function __dlStripErroredGeneratedColumns(row: Record<string, unknown>, aliases: string[]): Record<string, unknown> {`,
|
|
15953
|
+
` let next: Record<string, unknown> | null = null;`,
|
|
15954
|
+
` for (const alias of aliases) {`,
|
|
15955
|
+
` for (const key of __dlAliasCandidates(alias)) {`,
|
|
15956
|
+
` if (key in row && __dlGeneratedCellError(row[key])) {`,
|
|
15957
|
+
` if (next === null) next = { ...row };`,
|
|
15958
|
+
` delete next[key];`,
|
|
15959
|
+
` }`,
|
|
15960
|
+
` }`,
|
|
15961
|
+
` }`,
|
|
15962
|
+
` return next ?? row;`,
|
|
15963
|
+
`}`,
|
|
15964
|
+
``,
|
|
15891
15965
|
`function __dlRawToolOutput(result: unknown): unknown {`,
|
|
15892
15966
|
` if (!result || typeof result !== 'object') return result;`,
|
|
15893
15967
|
` const record = result as Record<string, unknown>;`,
|
|
@@ -16298,7 +16372,7 @@ function helperSource() {
|
|
|
16298
16372
|
` tool: input.tool,`,
|
|
16299
16373
|
` input: payload,`,
|
|
16300
16374
|
` ...(input.description ? { description: input.description } : {}),`,
|
|
16301
|
-
` ...(input.force ? {
|
|
16375
|
+
` ...(input.force ? { force: true } : {}),`,
|
|
16302
16376
|
` });`,
|
|
16303
16377
|
` return __dlExtract(input.alias, result, input.row, input.extract, Boolean(input.legacyEnvelope));`,
|
|
16304
16378
|
`}`
|
package/dist/index.d.mts
CHANGED
|
@@ -70,6 +70,8 @@ interface PlayStaticColumnProducer {
|
|
|
70
70
|
toolId?: string;
|
|
71
71
|
playId?: string;
|
|
72
72
|
dependsOnFields?: string[];
|
|
73
|
+
recompute?: boolean;
|
|
74
|
+
recomputeOnError?: boolean;
|
|
73
75
|
staleAfterSeconds?: number;
|
|
74
76
|
conditional?: boolean;
|
|
75
77
|
sourceRange?: PlayStaticSourceRange;
|
|
@@ -80,6 +82,8 @@ interface PlayStaticDatasetColumn {
|
|
|
80
82
|
id: string;
|
|
81
83
|
source: PlaySheetColumnSource;
|
|
82
84
|
sqlName?: string;
|
|
85
|
+
recompute?: boolean;
|
|
86
|
+
recomputeOnError?: boolean;
|
|
83
87
|
staleAfterSeconds?: number;
|
|
84
88
|
producers: PlayStaticColumnProducer[];
|
|
85
89
|
}
|
|
@@ -93,6 +97,8 @@ interface PlayStaticSourceRange {
|
|
|
93
97
|
type PlayStaticSubstepMetadata = {
|
|
94
98
|
conditional?: boolean;
|
|
95
99
|
dependsOnFields?: string[];
|
|
100
|
+
recompute?: boolean;
|
|
101
|
+
recomputeOnError?: boolean;
|
|
96
102
|
staleAfterSeconds?: number;
|
|
97
103
|
};
|
|
98
104
|
type PlayStaticSubstep = PlayStaticSubstepMetadata & ({
|
|
@@ -2979,6 +2985,8 @@ type ToolExecutionRequest = {
|
|
|
2979
2985
|
input: Record<string, unknown>;
|
|
2980
2986
|
/** Human-readable description for logs and run inspection. */
|
|
2981
2987
|
description?: string;
|
|
2988
|
+
/** Recompute this tool call instead of reusing a durable receipt/checkpoint. */
|
|
2989
|
+
force?: boolean;
|
|
2982
2990
|
/** Numeric TTL in seconds for this tool checkpoint. */
|
|
2983
2991
|
staleAfterSeconds?: number;
|
|
2984
2992
|
};
|
|
@@ -3031,6 +3039,10 @@ type DatasetColumnDefinition<Row, Value> = {
|
|
|
3031
3039
|
run: (input: DatasetColumnRunInput<Row, Value>) => Value | Promise<Value>;
|
|
3032
3040
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
3033
3041
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
3042
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
3043
|
+
readonly recompute?: boolean;
|
|
3044
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
3045
|
+
readonly recomputeOnError?: boolean;
|
|
3034
3046
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
3035
3047
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
3036
3048
|
};
|
|
@@ -3049,6 +3061,10 @@ type ConditionalStepResolver<Row, Value, Else = null> = {
|
|
|
3049
3061
|
type StepOptions<Row, Value = unknown> = {
|
|
3050
3062
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
3051
3063
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
3064
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
3065
|
+
readonly recompute?: boolean;
|
|
3066
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
3067
|
+
readonly recomputeOnError?: boolean;
|
|
3052
3068
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
3053
3069
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
3054
3070
|
};
|
|
@@ -3069,11 +3085,13 @@ type StepProgramResolver<Input, Return> = {
|
|
|
3069
3085
|
};
|
|
3070
3086
|
type PlayStepProgramStep = {
|
|
3071
3087
|
readonly name: string;
|
|
3088
|
+
readonly recompute?: boolean;
|
|
3089
|
+
readonly recomputeOnError?: boolean;
|
|
3072
3090
|
readonly staleAfterSeconds?: StaleAfterSeconds;
|
|
3073
3091
|
readonly resolver: StepResolver<Record<string, unknown>, unknown> | ConditionalStepResolver<Record<string, unknown>, unknown> | StepProgramResolver<Record<string, unknown>, unknown>;
|
|
3074
3092
|
};
|
|
3075
3093
|
type ColumnResolver<Row, Value> = StepResolver<Row, Value> | ConditionalStepResolver<Row, Value> | StepProgramResolver<Row, Value>;
|
|
3076
|
-
type StepProgramOutput<TProgram> = TProgram extends StepProgram<
|
|
3094
|
+
type StepProgramOutput<TProgram> = TProgram extends StepProgram<unknown, infer Output, unknown> ? Output : never;
|
|
3077
3095
|
/**
|
|
3078
3096
|
* Builder returned by `ctx.dataset(...)` for row-level durable columns.
|
|
3079
3097
|
*
|
|
@@ -3315,9 +3333,7 @@ interface DeeplinePlayRuntimeContext {
|
|
|
3315
3333
|
*
|
|
3316
3334
|
* @sdkReference runtime 150 ctx.tools.execute(request)
|
|
3317
3335
|
*/
|
|
3318
|
-
execute<TOutput = LoosePlayObject>(request: ToolExecutionRequest
|
|
3319
|
-
staleAfterSeconds?: number;
|
|
3320
|
-
}): Promise<ToolExecuteResult<TOutput>>;
|
|
3336
|
+
execute<TOutput = LoosePlayObject>(request: ToolExecutionRequest): Promise<ToolExecuteResult<TOutput>>;
|
|
3321
3337
|
};
|
|
3322
3338
|
/**
|
|
3323
3339
|
* Execute a single tool by stable step key and tool ID.
|
|
@@ -3343,7 +3359,7 @@ interface DeeplinePlayRuntimeContext {
|
|
|
3343
3359
|
*
|
|
3344
3360
|
* @sdkReference runtime 180 ctx.runSteps(program, input, options)
|
|
3345
3361
|
*/
|
|
3346
|
-
runSteps<TInput extends Record<string, unknown>, TOutput>(program: StepProgram<TInput,
|
|
3362
|
+
runSteps<TInput extends Record<string, unknown>, TOutput>(program: StepProgram<TInput, unknown, TOutput>, input: TInput, options?: {
|
|
3347
3363
|
description?: string;
|
|
3348
3364
|
}): Promise<TOutput>;
|
|
3349
3365
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ interface PlayStaticColumnProducer {
|
|
|
70
70
|
toolId?: string;
|
|
71
71
|
playId?: string;
|
|
72
72
|
dependsOnFields?: string[];
|
|
73
|
+
recompute?: boolean;
|
|
74
|
+
recomputeOnError?: boolean;
|
|
73
75
|
staleAfterSeconds?: number;
|
|
74
76
|
conditional?: boolean;
|
|
75
77
|
sourceRange?: PlayStaticSourceRange;
|
|
@@ -80,6 +82,8 @@ interface PlayStaticDatasetColumn {
|
|
|
80
82
|
id: string;
|
|
81
83
|
source: PlaySheetColumnSource;
|
|
82
84
|
sqlName?: string;
|
|
85
|
+
recompute?: boolean;
|
|
86
|
+
recomputeOnError?: boolean;
|
|
83
87
|
staleAfterSeconds?: number;
|
|
84
88
|
producers: PlayStaticColumnProducer[];
|
|
85
89
|
}
|
|
@@ -93,6 +97,8 @@ interface PlayStaticSourceRange {
|
|
|
93
97
|
type PlayStaticSubstepMetadata = {
|
|
94
98
|
conditional?: boolean;
|
|
95
99
|
dependsOnFields?: string[];
|
|
100
|
+
recompute?: boolean;
|
|
101
|
+
recomputeOnError?: boolean;
|
|
96
102
|
staleAfterSeconds?: number;
|
|
97
103
|
};
|
|
98
104
|
type PlayStaticSubstep = PlayStaticSubstepMetadata & ({
|
|
@@ -2979,6 +2985,8 @@ type ToolExecutionRequest = {
|
|
|
2979
2985
|
input: Record<string, unknown>;
|
|
2980
2986
|
/** Human-readable description for logs and run inspection. */
|
|
2981
2987
|
description?: string;
|
|
2988
|
+
/** Recompute this tool call instead of reusing a durable receipt/checkpoint. */
|
|
2989
|
+
force?: boolean;
|
|
2982
2990
|
/** Numeric TTL in seconds for this tool checkpoint. */
|
|
2983
2991
|
staleAfterSeconds?: number;
|
|
2984
2992
|
};
|
|
@@ -3031,6 +3039,10 @@ type DatasetColumnDefinition<Row, Value> = {
|
|
|
3031
3039
|
run: (input: DatasetColumnRunInput<Row, Value>) => Value | Promise<Value>;
|
|
3032
3040
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
3033
3041
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
3042
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
3043
|
+
readonly recompute?: boolean;
|
|
3044
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
3045
|
+
readonly recomputeOnError?: boolean;
|
|
3034
3046
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
3035
3047
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
3036
3048
|
};
|
|
@@ -3049,6 +3061,10 @@ type ConditionalStepResolver<Row, Value, Else = null> = {
|
|
|
3049
3061
|
type StepOptions<Row, Value = unknown> = {
|
|
3050
3062
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
3051
3063
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
3064
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
3065
|
+
readonly recompute?: boolean;
|
|
3066
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
3067
|
+
readonly recomputeOnError?: boolean;
|
|
3052
3068
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
3053
3069
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
3054
3070
|
};
|
|
@@ -3069,11 +3085,13 @@ type StepProgramResolver<Input, Return> = {
|
|
|
3069
3085
|
};
|
|
3070
3086
|
type PlayStepProgramStep = {
|
|
3071
3087
|
readonly name: string;
|
|
3088
|
+
readonly recompute?: boolean;
|
|
3089
|
+
readonly recomputeOnError?: boolean;
|
|
3072
3090
|
readonly staleAfterSeconds?: StaleAfterSeconds;
|
|
3073
3091
|
readonly resolver: StepResolver<Record<string, unknown>, unknown> | ConditionalStepResolver<Record<string, unknown>, unknown> | StepProgramResolver<Record<string, unknown>, unknown>;
|
|
3074
3092
|
};
|
|
3075
3093
|
type ColumnResolver<Row, Value> = StepResolver<Row, Value> | ConditionalStepResolver<Row, Value> | StepProgramResolver<Row, Value>;
|
|
3076
|
-
type StepProgramOutput<TProgram> = TProgram extends StepProgram<
|
|
3094
|
+
type StepProgramOutput<TProgram> = TProgram extends StepProgram<unknown, infer Output, unknown> ? Output : never;
|
|
3077
3095
|
/**
|
|
3078
3096
|
* Builder returned by `ctx.dataset(...)` for row-level durable columns.
|
|
3079
3097
|
*
|
|
@@ -3315,9 +3333,7 @@ interface DeeplinePlayRuntimeContext {
|
|
|
3315
3333
|
*
|
|
3316
3334
|
* @sdkReference runtime 150 ctx.tools.execute(request)
|
|
3317
3335
|
*/
|
|
3318
|
-
execute<TOutput = LoosePlayObject>(request: ToolExecutionRequest
|
|
3319
|
-
staleAfterSeconds?: number;
|
|
3320
|
-
}): Promise<ToolExecuteResult<TOutput>>;
|
|
3336
|
+
execute<TOutput = LoosePlayObject>(request: ToolExecutionRequest): Promise<ToolExecuteResult<TOutput>>;
|
|
3321
3337
|
};
|
|
3322
3338
|
/**
|
|
3323
3339
|
* Execute a single tool by stable step key and tool ID.
|
|
@@ -3343,7 +3359,7 @@ interface DeeplinePlayRuntimeContext {
|
|
|
3343
3359
|
*
|
|
3344
3360
|
* @sdkReference runtime 180 ctx.runSteps(program, input, options)
|
|
3345
3361
|
*/
|
|
3346
|
-
runSteps<TInput extends Record<string, unknown>, TOutput>(program: StepProgram<TInput,
|
|
3362
|
+
runSteps<TInput extends Record<string, unknown>, TOutput>(program: StepProgram<TInput, unknown, TOutput>, input: TInput, options?: {
|
|
3347
3363
|
description?: string;
|
|
3348
3364
|
}): Promise<TOutput>;
|
|
3349
3365
|
/**
|
package/dist/index.js
CHANGED
|
@@ -272,16 +272,18 @@ var SDK_RELEASE = {
|
|
|
272
272
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
273
273
|
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
274
274
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
275
|
-
|
|
275
|
+
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
276
|
+
// the SDK enrich generator's one-second stale policy.
|
|
277
|
+
version: "0.1.108",
|
|
276
278
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
277
279
|
supportPolicy: {
|
|
278
|
-
latest: "0.1.
|
|
280
|
+
latest: "0.1.108",
|
|
279
281
|
minimumSupported: "0.1.53",
|
|
280
282
|
deprecatedBelow: "0.1.53",
|
|
281
283
|
commandMinimumSupported: [
|
|
282
284
|
{
|
|
283
285
|
command: "enrich",
|
|
284
|
-
minimumSupported: "0.1.
|
|
286
|
+
minimumSupported: "0.1.108",
|
|
285
287
|
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
286
288
|
}
|
|
287
289
|
],
|
|
@@ -885,6 +887,8 @@ function normalizeStepProgress(value) {
|
|
|
885
887
|
value.artifactTableNamespace
|
|
886
888
|
)
|
|
887
889
|
} : {},
|
|
890
|
+
...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
|
|
891
|
+
...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
|
|
888
892
|
...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {}
|
|
889
893
|
};
|
|
890
894
|
}
|
|
@@ -4075,7 +4079,9 @@ var DeeplineStepProgram = class _DeeplineStepProgram {
|
|
|
4075
4079
|
resolver: stepResolver,
|
|
4076
4080
|
...options?.staleAfterSeconds !== void 0 ? {
|
|
4077
4081
|
staleAfterSeconds: options.staleAfterSeconds
|
|
4078
|
-
} : {}
|
|
4082
|
+
} : {},
|
|
4083
|
+
...options?.recompute === true ? { recompute: true } : {},
|
|
4084
|
+
...options?.recomputeOnError === true ? { recomputeOnError: true } : {}
|
|
4079
4085
|
}
|
|
4080
4086
|
],
|
|
4081
4087
|
this.returnResolver
|
package/dist/index.mjs
CHANGED
|
@@ -194,16 +194,18 @@ var SDK_RELEASE = {
|
|
|
194
194
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
195
195
|
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
196
196
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
197
|
-
|
|
197
|
+
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
198
|
+
// the SDK enrich generator's one-second stale policy.
|
|
199
|
+
version: "0.1.108",
|
|
198
200
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
199
201
|
supportPolicy: {
|
|
200
|
-
latest: "0.1.
|
|
202
|
+
latest: "0.1.108",
|
|
201
203
|
minimumSupported: "0.1.53",
|
|
202
204
|
deprecatedBelow: "0.1.53",
|
|
203
205
|
commandMinimumSupported: [
|
|
204
206
|
{
|
|
205
207
|
command: "enrich",
|
|
206
|
-
minimumSupported: "0.1.
|
|
208
|
+
minimumSupported: "0.1.108",
|
|
207
209
|
reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
|
|
208
210
|
}
|
|
209
211
|
],
|
|
@@ -807,6 +809,8 @@ function normalizeStepProgress(value) {
|
|
|
807
809
|
value.artifactTableNamespace
|
|
808
810
|
)
|
|
809
811
|
} : {},
|
|
812
|
+
...finiteNumber(value.startedAt) !== null ? { startedAt: finiteNumber(value.startedAt) } : {},
|
|
813
|
+
...finiteNumber(value.completedAt) !== null ? { completedAt: finiteNumber(value.completedAt) } : {},
|
|
810
814
|
...finiteNumber(value.updatedAt) !== null ? { updatedAt: finiteNumber(value.updatedAt) } : {}
|
|
811
815
|
};
|
|
812
816
|
}
|
|
@@ -3997,7 +4001,9 @@ var DeeplineStepProgram = class _DeeplineStepProgram {
|
|
|
3997
4001
|
resolver: stepResolver,
|
|
3998
4002
|
...options?.staleAfterSeconds !== void 0 ? {
|
|
3999
4003
|
staleAfterSeconds: options.staleAfterSeconds
|
|
4000
|
-
} : {}
|
|
4004
|
+
} : {},
|
|
4005
|
+
...options?.recompute === true ? { recompute: true } : {},
|
|
4006
|
+
...options?.recomputeOnError === true ? { recomputeOnError: true } : {}
|
|
4001
4007
|
}
|
|
4002
4008
|
],
|
|
4003
4009
|
this.returnResolver
|
|
@@ -1959,6 +1959,8 @@ type WorkerConditionalStepResolver = {
|
|
|
1959
1959
|
|
|
1960
1960
|
type WorkerStepProgramStep = {
|
|
1961
1961
|
name: string;
|
|
1962
|
+
recompute?: boolean;
|
|
1963
|
+
recomputeOnError?: boolean;
|
|
1962
1964
|
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
1963
1965
|
resolver:
|
|
1964
1966
|
| WorkerStepResolver
|
|
@@ -1993,6 +1995,49 @@ type WorkerMapOptions = {
|
|
|
1993
1995
|
onRowError?: 'isolate' | 'fail';
|
|
1994
1996
|
};
|
|
1995
1997
|
|
|
1998
|
+
function authoredCellPolicyForWorkerStep(
|
|
1999
|
+
step: WorkerStepProgramStep,
|
|
2000
|
+
): {
|
|
2001
|
+
recompute?: true;
|
|
2002
|
+
recomputeOnError?: true;
|
|
2003
|
+
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
2004
|
+
} | null {
|
|
2005
|
+
const policy = {
|
|
2006
|
+
...(step.recompute === true ? { recompute: true as const } : {}),
|
|
2007
|
+
...(step.recomputeOnError === true
|
|
2008
|
+
? { recomputeOnError: true as const }
|
|
2009
|
+
: {}),
|
|
2010
|
+
...(step.staleAfterSeconds !== undefined
|
|
2011
|
+
? { staleAfterSeconds: step.staleAfterSeconds }
|
|
2012
|
+
: {}),
|
|
2013
|
+
};
|
|
2014
|
+
return Object.keys(policy).length > 0 ? policy : null;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
function workerCellPoliciesFromSteps(
|
|
2018
|
+
steps: readonly WorkerStepProgramStep[],
|
|
2019
|
+
): CellStalenessPolicyByField {
|
|
2020
|
+
return Object.fromEntries(
|
|
2021
|
+
steps.flatMap((step) => {
|
|
2022
|
+
const policy = authoredCellPolicyForWorkerStep(step);
|
|
2023
|
+
return policy
|
|
2024
|
+
? [[step.name, normalizeCellStalenessPolicy(policy)]]
|
|
2025
|
+
: [];
|
|
2026
|
+
}),
|
|
2027
|
+
) as CellStalenessPolicyByField;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
function authoredWorkerCellPoliciesFromSteps(
|
|
2031
|
+
steps: readonly WorkerStepProgramStep[],
|
|
2032
|
+
): AuthoredCellStalenessPolicyByField {
|
|
2033
|
+
return Object.fromEntries(
|
|
2034
|
+
steps.flatMap((step) => {
|
|
2035
|
+
const policy = authoredCellPolicyForWorkerStep(step);
|
|
2036
|
+
return policy ? [[step.name, policy]] : [];
|
|
2037
|
+
}),
|
|
2038
|
+
) as AuthoredCellStalenessPolicyByField;
|
|
2039
|
+
}
|
|
2040
|
+
|
|
1996
2041
|
/**
|
|
1997
2042
|
* Per-cell terminal state recorded by map row execution and merged into the
|
|
1998
2043
|
* Runtime Sheet row's `_cell_meta`. 'failed' carries the cell's error message;
|
|
@@ -2983,8 +3028,8 @@ function augmentSheetContractWithDatasetFields(input: {
|
|
|
2983
3028
|
const field = typeof column.field === 'string' ? column.field : column.id;
|
|
2984
3029
|
if (
|
|
2985
3030
|
column.source === 'input' &&
|
|
2986
|
-
field === input.contract.tableNamespace &&
|
|
2987
|
-
|
|
3031
|
+
((field === input.contract.tableNamespace && !candidateFields.has(field)) ||
|
|
3032
|
+
outputFields.has(field))
|
|
2988
3033
|
) {
|
|
2989
3034
|
continue;
|
|
2990
3035
|
}
|
|
@@ -4696,27 +4741,10 @@ function createMinimalWorkerCtx(
|
|
|
4696
4741
|
const fields = Object.fromEntries(
|
|
4697
4742
|
program.steps.map((step) => [step.name, step.resolver]),
|
|
4698
4743
|
);
|
|
4699
|
-
const cellPolicies =
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
: [
|
|
4704
|
-
[
|
|
4705
|
-
step.name,
|
|
4706
|
-
normalizeCellStalenessPolicy({
|
|
4707
|
-
staleAfterSeconds: step.staleAfterSeconds,
|
|
4708
|
-
}),
|
|
4709
|
-
],
|
|
4710
|
-
],
|
|
4711
|
-
),
|
|
4712
|
-
) as CellStalenessPolicyByField;
|
|
4713
|
-
const authoredCellPolicies = Object.fromEntries(
|
|
4714
|
-
program.steps.flatMap((step) =>
|
|
4715
|
-
step.staleAfterSeconds === undefined
|
|
4716
|
-
? []
|
|
4717
|
-
: [[step.name, { staleAfterSeconds: step.staleAfterSeconds }]],
|
|
4718
|
-
),
|
|
4719
|
-
) as AuthoredCellStalenessPolicyByField;
|
|
4744
|
+
const cellPolicies = workerCellPoliciesFromSteps(program.steps);
|
|
4745
|
+
const authoredCellPolicies = authoredWorkerCellPoliciesFromSteps(
|
|
4746
|
+
program.steps,
|
|
4747
|
+
);
|
|
4720
4748
|
return runMap(
|
|
4721
4749
|
this.name,
|
|
4722
4750
|
this.rows,
|
|
@@ -4944,27 +4972,10 @@ function createMinimalWorkerCtx(
|
|
|
4944
4972
|
const fields = Object.fromEntries(
|
|
4945
4973
|
fieldsDef.steps.map((step) => [step.name, step.resolver]),
|
|
4946
4974
|
);
|
|
4947
|
-
const cellPolicies =
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
: [
|
|
4952
|
-
[
|
|
4953
|
-
step.name,
|
|
4954
|
-
normalizeCellStalenessPolicy({
|
|
4955
|
-
staleAfterSeconds: step.staleAfterSeconds,
|
|
4956
|
-
}),
|
|
4957
|
-
],
|
|
4958
|
-
],
|
|
4959
|
-
),
|
|
4960
|
-
) as CellStalenessPolicyByField;
|
|
4961
|
-
const authoredCellPolicies = Object.fromEntries(
|
|
4962
|
-
fieldsDef.steps.flatMap((step) =>
|
|
4963
|
-
step.staleAfterSeconds === undefined
|
|
4964
|
-
? []
|
|
4965
|
-
: [[step.name, { staleAfterSeconds: step.staleAfterSeconds }]],
|
|
4966
|
-
),
|
|
4967
|
-
) as AuthoredCellStalenessPolicyByField;
|
|
4975
|
+
const cellPolicies = workerCellPoliciesFromSteps(fieldsDef.steps);
|
|
4976
|
+
const authoredCellPolicies = authoredWorkerCellPoliciesFromSteps(
|
|
4977
|
+
fieldsDef.steps,
|
|
4978
|
+
);
|
|
4968
4979
|
return runMap(
|
|
4969
4980
|
name,
|
|
4970
4981
|
rows,
|
|
@@ -231,6 +231,8 @@ export type ToolExecutionRequest = {
|
|
|
231
231
|
input: Record<string, unknown>;
|
|
232
232
|
/** Human-readable description for logs and run inspection. */
|
|
233
233
|
description?: string;
|
|
234
|
+
/** Recompute this tool call instead of reusing a durable receipt/checkpoint. */
|
|
235
|
+
force?: boolean;
|
|
234
236
|
/** Numeric TTL in seconds for this tool checkpoint. */
|
|
235
237
|
staleAfterSeconds?: number;
|
|
236
238
|
};
|
|
@@ -294,6 +296,10 @@ export type DatasetColumnDefinition<Row, Value> = {
|
|
|
294
296
|
run: (input: DatasetColumnRunInput<Row, Value>) => Value | Promise<Value>;
|
|
295
297
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
296
298
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
299
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
300
|
+
readonly recompute?: boolean;
|
|
301
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
302
|
+
readonly recomputeOnError?: boolean;
|
|
297
303
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
298
304
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
299
305
|
};
|
|
@@ -316,6 +322,10 @@ export type ConditionalStepResolver<Row, Value, Else = null> = {
|
|
|
316
322
|
export type StepOptions<Row, Value = unknown> = {
|
|
317
323
|
/** Optional row-level gate. Skipped rows produce `null` for this column. */
|
|
318
324
|
readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
|
|
325
|
+
/** Recompute this cell on each run instead of reusing its durable value. */
|
|
326
|
+
readonly recompute?: boolean;
|
|
327
|
+
/** Recompute this cell when its durable value is an error-shaped object. */
|
|
328
|
+
readonly recomputeOnError?: boolean;
|
|
319
329
|
/** Fixed or value-dependent freshness policy for this cell. */
|
|
320
330
|
readonly staleAfterSeconds?: StaleAfterSeconds<Value>;
|
|
321
331
|
};
|
|
@@ -351,6 +361,8 @@ export type StepProgramResolver<Input, Return> = {
|
|
|
351
361
|
|
|
352
362
|
export type PlayStepProgramStep = {
|
|
353
363
|
readonly name: string;
|
|
364
|
+
readonly recompute?: boolean;
|
|
365
|
+
readonly recomputeOnError?: boolean;
|
|
354
366
|
readonly staleAfterSeconds?: StaleAfterSeconds;
|
|
355
367
|
readonly resolver:
|
|
356
368
|
| StepResolver<Record<string, unknown>, unknown>
|
|
@@ -364,7 +376,7 @@ export type ColumnResolver<Row, Value> =
|
|
|
364
376
|
| StepProgramResolver<Row, Value>;
|
|
365
377
|
|
|
366
378
|
export type StepProgramOutput<TProgram> =
|
|
367
|
-
TProgram extends StepProgram<
|
|
379
|
+
TProgram extends StepProgram<unknown, infer Output, unknown> ? Output : never;
|
|
368
380
|
|
|
369
381
|
/**
|
|
370
382
|
* Builder returned by `ctx.dataset(...)` for row-level durable columns.
|
|
@@ -663,7 +675,7 @@ export interface DeeplinePlayRuntimeContext {
|
|
|
663
675
|
* @sdkReference runtime 150 ctx.tools.execute(request)
|
|
664
676
|
*/
|
|
665
677
|
execute<TOutput = LoosePlayObject>(
|
|
666
|
-
request: ToolExecutionRequest
|
|
678
|
+
request: ToolExecutionRequest,
|
|
667
679
|
): Promise<ToolExecuteResult<TOutput>>;
|
|
668
680
|
};
|
|
669
681
|
/**
|
|
@@ -694,7 +706,7 @@ export interface DeeplinePlayRuntimeContext {
|
|
|
694
706
|
* @sdkReference runtime 180 ctx.runSteps(program, input, options)
|
|
695
707
|
*/
|
|
696
708
|
runSteps<TInput extends Record<string, unknown>, TOutput>(
|
|
697
|
-
program: StepProgram<TInput,
|
|
709
|
+
program: StepProgram<TInput, unknown, TOutput>,
|
|
698
710
|
input: TInput,
|
|
699
711
|
options?: { description?: string },
|
|
700
712
|
): Promise<TOutput>;
|
|
@@ -1128,6 +1140,10 @@ class DeeplineStepProgram<Input, Output, ReturnValue> implements StepProgram<
|
|
|
1128
1140
|
options.staleAfterSeconds as PlayStepProgramStep['staleAfterSeconds'],
|
|
1129
1141
|
}
|
|
1130
1142
|
: {}),
|
|
1143
|
+
...(options?.recompute === true ? { recompute: true } : {}),
|
|
1144
|
+
...(options?.recomputeOnError === true
|
|
1145
|
+
? { recomputeOnError: true }
|
|
1146
|
+
: {}),
|
|
1131
1147
|
},
|
|
1132
1148
|
],
|
|
1133
1149
|
this.returnResolver as StepResolver<
|
|
@@ -1598,7 +1614,8 @@ function emailStatusExtractorConfig(
|
|
|
1598
1614
|
if (paths) config[key] = paths;
|
|
1599
1615
|
}
|
|
1600
1616
|
if (isRecord(value.statusMap)) {
|
|
1601
|
-
config.statusMap =
|
|
1617
|
+
config.statusMap =
|
|
1618
|
+
value.statusMap as EmailStatusExtractorConfig['statusMap'];
|
|
1602
1619
|
}
|
|
1603
1620
|
if (Array.isArray(value.rules)) {
|
|
1604
1621
|
config.rules = value.rules as EmailStatusExtractorConfig['rules'];
|
|
@@ -94,16 +94,18 @@ export const SDK_RELEASE = {
|
|
|
94
94
|
// 0.1.106 ships play cell provenance metadata and v2 preview retry hardening.
|
|
95
95
|
// 0.1.107 ships the v2 quickstart command, the deepline-plays-quickstart
|
|
96
96
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
97
|
-
|
|
97
|
+
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
98
|
+
// the SDK enrich generator's one-second stale policy.
|
|
99
|
+
version: '0.1.108',
|
|
98
100
|
apiContract: '2026-06-dataset-column-cell-stale-hard-cutover',
|
|
99
101
|
supportPolicy: {
|
|
100
|
-
latest: '0.1.
|
|
102
|
+
latest: '0.1.108',
|
|
101
103
|
minimumSupported: '0.1.53',
|
|
102
104
|
deprecatedBelow: '0.1.53',
|
|
103
105
|
commandMinimumSupported: [
|
|
104
106
|
{
|
|
105
107
|
command: 'enrich',
|
|
106
|
-
minimumSupported: '0.1.
|
|
108
|
+
minimumSupported: '0.1.108',
|
|
107
109
|
reason:
|
|
108
110
|
'Older SDK CLI enrich generated stale play source for the current dataset API.',
|
|
109
111
|
},
|
|
@@ -134,6 +134,10 @@ class WorkerStepProgram<Input, Output, ReturnValue> implements StepProgram<
|
|
|
134
134
|
options.staleAfterSeconds as PlayStepProgramStep['staleAfterSeconds'],
|
|
135
135
|
}
|
|
136
136
|
: {}),
|
|
137
|
+
...(options?.recompute === true ? { recompute: true } : {}),
|
|
138
|
+
...(options?.recomputeOnError === true
|
|
139
|
+
? { recomputeOnError: true }
|
|
140
|
+
: {}),
|
|
137
141
|
},
|
|
138
142
|
],
|
|
139
143
|
this.returnResolver as StepResolver<
|
|
@@ -15,11 +15,15 @@ export type AuthoredStaleAfterSeconds<Value = unknown> =
|
|
|
15
15
|
|
|
16
16
|
/** Freshness policy as written by play authors before runtime normalization. */
|
|
17
17
|
export type AuthoredCellStalenessPolicy<Value = unknown> = {
|
|
18
|
+
recompute?: boolean;
|
|
19
|
+
recomputeOnError?: boolean;
|
|
18
20
|
staleAfterSeconds?: AuthoredStaleAfterSeconds<Value>;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
/** Runtime-normalized freshness policy stored in execution plans. */
|
|
22
24
|
export type CellStalenessPolicy = {
|
|
25
|
+
recompute?: boolean;
|
|
26
|
+
recomputeOnError?: boolean;
|
|
23
27
|
staleAfterSeconds?: number;
|
|
24
28
|
dynamicStaleAfterSeconds?: boolean;
|
|
25
29
|
};
|
|
@@ -53,7 +57,10 @@ export type PreviousCell<Value = unknown> = {
|
|
|
53
57
|
};
|
|
54
58
|
|
|
55
59
|
export type CellStalenessDecision =
|
|
56
|
-
| {
|
|
60
|
+
| {
|
|
61
|
+
action: 'recompute';
|
|
62
|
+
reason: 'missing' | 'failed' | 'forced' | 'stale';
|
|
63
|
+
}
|
|
57
64
|
| { action: 'reuse'; reason: 'fresh' | 'no_policy' | 'no_expiry' };
|
|
58
65
|
|
|
59
66
|
export type CellStalenessPolicyByField = Record<string, CellStalenessPolicy>;
|
|
@@ -83,15 +90,36 @@ export function validateStaleAfterSeconds(
|
|
|
83
90
|
export function normalizeCellStalenessPolicy(
|
|
84
91
|
policy: AuthoredCellStalenessPolicy | undefined,
|
|
85
92
|
): CellStalenessPolicy {
|
|
93
|
+
if (
|
|
94
|
+
policy?.recompute !== undefined &&
|
|
95
|
+
typeof policy.recompute !== 'boolean'
|
|
96
|
+
) {
|
|
97
|
+
throw new Error('recompute must be a boolean.');
|
|
98
|
+
}
|
|
99
|
+
if (
|
|
100
|
+
policy?.recomputeOnError !== undefined &&
|
|
101
|
+
typeof policy.recomputeOnError !== 'boolean'
|
|
102
|
+
) {
|
|
103
|
+
throw new Error('recomputeOnError must be a boolean.');
|
|
104
|
+
}
|
|
105
|
+
const recompute = policy?.recompute === true;
|
|
106
|
+
const recomputeOnError = policy?.recomputeOnError === true;
|
|
107
|
+
const flags = {
|
|
108
|
+
...(recompute ? { recompute: true } : {}),
|
|
109
|
+
...(recomputeOnError ? { recomputeOnError: true } : {}),
|
|
110
|
+
};
|
|
86
111
|
const staleAfterSeconds = policy?.staleAfterSeconds;
|
|
87
112
|
if (staleAfterSeconds === undefined) {
|
|
88
|
-
return
|
|
113
|
+
return flags;
|
|
89
114
|
}
|
|
90
115
|
if (typeof staleAfterSeconds === 'function') {
|
|
91
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
...flags,
|
|
118
|
+
dynamicStaleAfterSeconds: true,
|
|
119
|
+
};
|
|
92
120
|
}
|
|
93
121
|
validateStaleAfterSeconds(staleAfterSeconds);
|
|
94
|
-
return { staleAfterSeconds };
|
|
122
|
+
return { ...flags, staleAfterSeconds };
|
|
95
123
|
}
|
|
96
124
|
|
|
97
125
|
export function resolveCompletedCellStalenessMeta<Value>(input: {
|
|
@@ -162,6 +190,7 @@ export function previousCellFromValue<Value>(input: {
|
|
|
162
190
|
|
|
163
191
|
export function shouldRecomputeCell(input: {
|
|
164
192
|
hasValue: boolean;
|
|
193
|
+
value?: unknown;
|
|
165
194
|
meta?: CellStalenessMeta | null;
|
|
166
195
|
policy?: CellStalenessPolicy;
|
|
167
196
|
nowMs?: number;
|
|
@@ -175,6 +204,17 @@ export function shouldRecomputeCell(input: {
|
|
|
175
204
|
return { action: 'recompute', reason: 'failed' };
|
|
176
205
|
}
|
|
177
206
|
|
|
207
|
+
if (input.policy?.recompute === true) {
|
|
208
|
+
return { action: 'recompute', reason: 'forced' };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (
|
|
212
|
+
input.policy?.recomputeOnError === true &&
|
|
213
|
+
isErrorLikeCellValue(input.value)
|
|
214
|
+
) {
|
|
215
|
+
return { action: 'recompute', reason: 'failed' };
|
|
216
|
+
}
|
|
217
|
+
|
|
178
218
|
const staleAt =
|
|
179
219
|
input.meta && Object.prototype.hasOwnProperty.call(input.meta, 'staleAt')
|
|
180
220
|
? input.meta.staleAt
|
|
@@ -254,7 +294,26 @@ export function cellPolicyFields(
|
|
|
254
294
|
.filter(
|
|
255
295
|
([, policy]) =>
|
|
256
296
|
policy.staleAfterSeconds !== undefined ||
|
|
257
|
-
policy.dynamicStaleAfterSeconds === true
|
|
297
|
+
policy.dynamicStaleAfterSeconds === true ||
|
|
298
|
+
policy.recompute === true ||
|
|
299
|
+
policy.recomputeOnError === true,
|
|
258
300
|
)
|
|
259
301
|
.map(([field]) => field);
|
|
260
302
|
}
|
|
303
|
+
|
|
304
|
+
function isErrorLikeCellValue(value: unknown): boolean {
|
|
305
|
+
if (typeof value === 'string') {
|
|
306
|
+
return /(^|: )error(:|$)/i.test(value.trim());
|
|
307
|
+
}
|
|
308
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
const record = value as Record<string, unknown>;
|
|
312
|
+
const raw = (record.toolResponse as { raw?: unknown } | undefined)?.raw;
|
|
313
|
+
return (
|
|
314
|
+
(raw !== undefined && isErrorLikeCellValue(raw)) ||
|
|
315
|
+
(typeof record.error === 'string' && record.error.trim().length > 0) ||
|
|
316
|
+
record.status === 'failed' ||
|
|
317
|
+
record.status === 'error'
|
|
318
|
+
);
|
|
319
|
+
}
|
|
@@ -438,6 +438,12 @@ function normalizeStepProgress(
|
|
|
438
438
|
),
|
|
439
439
|
}
|
|
440
440
|
: {}),
|
|
441
|
+
...(finiteNumber(value.startedAt) !== null
|
|
442
|
+
? { startedAt: finiteNumber(value.startedAt) }
|
|
443
|
+
: {}),
|
|
444
|
+
...(finiteNumber(value.completedAt) !== null
|
|
445
|
+
? { completedAt: finiteNumber(value.completedAt) }
|
|
446
|
+
: {}),
|
|
441
447
|
...(finiteNumber(value.updatedAt) !== null
|
|
442
448
|
? { updatedAt: finiteNumber(value.updatedAt) }
|
|
443
449
|
: {}),
|
|
@@ -5,6 +5,8 @@ export type StepProgramDatasetOptions = {
|
|
|
5
5
|
row: Record<string, unknown>,
|
|
6
6
|
index: number,
|
|
7
7
|
) => boolean | Promise<boolean>;
|
|
8
|
+
recompute?: boolean;
|
|
9
|
+
recomputeOnError?: boolean;
|
|
8
10
|
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
9
11
|
};
|
|
10
12
|
|
|
@@ -48,6 +50,8 @@ function isPreviousCell(value: unknown): value is PreviousCell {
|
|
|
48
50
|
|
|
49
51
|
export type StepProgramDatasetStep<TResolver> = {
|
|
50
52
|
name: string;
|
|
53
|
+
recompute?: boolean;
|
|
54
|
+
recomputeOnError?: boolean;
|
|
51
55
|
resolver: TResolver;
|
|
52
56
|
staleAfterSeconds?: AuthoredStaleAfterSeconds;
|
|
53
57
|
};
|
|
@@ -133,6 +137,10 @@ export class StepProgramDatasetBuilder<
|
|
|
133
137
|
...(normalized.options?.staleAfterSeconds !== undefined
|
|
134
138
|
? { staleAfterSeconds: normalized.options.staleAfterSeconds }
|
|
135
139
|
: {}),
|
|
140
|
+
...(normalized.options?.recompute === true ? { recompute: true } : {}),
|
|
141
|
+
...(normalized.options?.recomputeOnError === true
|
|
142
|
+
? { recomputeOnError: true }
|
|
143
|
+
: {}),
|
|
136
144
|
} as TStep,
|
|
137
145
|
];
|
|
138
146
|
return this;
|
|
@@ -32,6 +32,61 @@ export interface PlayStaticPipeline {
|
|
|
32
32
|
sheetContractErrors?: string[];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function dedupeStaticFieldNames(
|
|
36
|
+
fields: Array<string | null | undefined>,
|
|
37
|
+
): string[] {
|
|
38
|
+
const seen = new Set<string>();
|
|
39
|
+
const out: string[] = [];
|
|
40
|
+
for (const field of fields) {
|
|
41
|
+
const trimmed = typeof field === 'string' ? field.trim() : '';
|
|
42
|
+
if (!trimmed || seen.has(trimmed)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
seen.add(trimmed);
|
|
46
|
+
out.push(trimmed);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function inputFieldFromStaticCsvArg(csvArg: unknown): string | null {
|
|
52
|
+
if (typeof csvArg !== 'string') return null;
|
|
53
|
+
const match = /^input\.([A-Za-z_$][\w$]*)$/.exec(csvArg.trim());
|
|
54
|
+
return match?.[1] ?? null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function deriveStaticPipelineFileInputFields(
|
|
58
|
+
pipeline: PlayStaticPipeline | null | undefined,
|
|
59
|
+
): string[] {
|
|
60
|
+
if (!pipeline) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const explicitCsvFields = getCompiledPipelineSubsteps(pipeline)
|
|
64
|
+
.filter((substep) => substep.type === 'csv')
|
|
65
|
+
.map((substep) =>
|
|
66
|
+
substep.type === 'csv'
|
|
67
|
+
? (inputFieldFromStaticCsvArg(substep.path) ?? substep.field)
|
|
68
|
+
: null,
|
|
69
|
+
);
|
|
70
|
+
const inferredCsvField =
|
|
71
|
+
explicitCsvFields.length > 0
|
|
72
|
+
? null
|
|
73
|
+
: (inputFieldFromStaticCsvArg(pipeline.csvArg) ??
|
|
74
|
+
(pipeline.csvArg ? 'csv' : null));
|
|
75
|
+
return dedupeStaticFieldNames([...explicitCsvFields, inferredCsvField]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function deriveStaticPipelineEntryInputFields(
|
|
79
|
+
pipeline: PlayStaticPipeline | null | undefined,
|
|
80
|
+
): string[] {
|
|
81
|
+
if (!pipeline) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const fileInputs = deriveStaticPipelineFileInputFields(pipeline);
|
|
85
|
+
return fileInputs.length > 0
|
|
86
|
+
? fileInputs
|
|
87
|
+
: dedupeStaticFieldNames(pipeline.inputFields ?? []);
|
|
88
|
+
}
|
|
89
|
+
|
|
35
90
|
export type PlaySheetColumnSource =
|
|
36
91
|
| 'input'
|
|
37
92
|
| 'datasetColumn'
|
|
@@ -73,6 +128,8 @@ export interface PlayStaticColumnProducer {
|
|
|
73
128
|
toolId?: string;
|
|
74
129
|
playId?: string;
|
|
75
130
|
dependsOnFields?: string[];
|
|
131
|
+
recompute?: boolean;
|
|
132
|
+
recomputeOnError?: boolean;
|
|
76
133
|
staleAfterSeconds?: number;
|
|
77
134
|
conditional?: boolean;
|
|
78
135
|
sourceRange?: PlayStaticSourceRange;
|
|
@@ -84,6 +141,8 @@ export interface PlayStaticDatasetColumn {
|
|
|
84
141
|
id: string;
|
|
85
142
|
source: PlaySheetColumnSource;
|
|
86
143
|
sqlName?: string;
|
|
144
|
+
recompute?: boolean;
|
|
145
|
+
recomputeOnError?: boolean;
|
|
87
146
|
staleAfterSeconds?: number;
|
|
88
147
|
producers: PlayStaticColumnProducer[];
|
|
89
148
|
}
|
|
@@ -275,6 +334,8 @@ export interface PlayStaticSourceRange {
|
|
|
275
334
|
type PlayStaticSubstepMetadata = {
|
|
276
335
|
conditional?: boolean;
|
|
277
336
|
dependsOnFields?: string[];
|
|
337
|
+
recompute?: boolean;
|
|
338
|
+
recomputeOnError?: boolean;
|
|
278
339
|
staleAfterSeconds?: number;
|
|
279
340
|
};
|
|
280
341
|
|
|
@@ -600,13 +661,18 @@ function compileDatasetColumns(
|
|
|
600
661
|
);
|
|
601
662
|
if (!column) continue;
|
|
602
663
|
const pipelineSubstep =
|
|
603
|
-
substep.staleAfterSeconds === undefined
|
|
664
|
+
substep.staleAfterSeconds === undefined &&
|
|
665
|
+
substep.recompute !== true &&
|
|
666
|
+
substep.recomputeOnError !== true
|
|
604
667
|
? pipelineSubsteps.find(
|
|
605
668
|
(candidate) => fieldForColumnProducer(candidate) === field,
|
|
606
669
|
)
|
|
607
670
|
: undefined;
|
|
608
671
|
const producer = columnProducerFromSubstep(
|
|
609
|
-
pipelineSubstep &&
|
|
672
|
+
pipelineSubstep &&
|
|
673
|
+
(pipelineSubstep.staleAfterSeconds !== undefined ||
|
|
674
|
+
pipelineSubstep.recompute === true ||
|
|
675
|
+
pipelineSubstep.recomputeOnError === true)
|
|
610
676
|
? pipelineSubstep
|
|
611
677
|
: substep,
|
|
612
678
|
field,
|
|
@@ -618,6 +684,15 @@ function compileDatasetColumns(
|
|
|
618
684
|
) {
|
|
619
685
|
column.staleAfterSeconds = producer.staleAfterSeconds;
|
|
620
686
|
}
|
|
687
|
+
if (column.recompute !== true && producer.recompute === true) {
|
|
688
|
+
column.recompute = true;
|
|
689
|
+
}
|
|
690
|
+
if (
|
|
691
|
+
column.recomputeOnError !== true &&
|
|
692
|
+
producer.recomputeOnError === true
|
|
693
|
+
) {
|
|
694
|
+
column.recomputeOnError = true;
|
|
695
|
+
}
|
|
621
696
|
}
|
|
622
697
|
|
|
623
698
|
return [...columnsById.values()];
|
|
@@ -667,6 +742,8 @@ function columnProducerFromSubstep(
|
|
|
667
742
|
...(substep.dependsOnFields?.length
|
|
668
743
|
? { dependsOnFields: [...substep.dependsOnFields] }
|
|
669
744
|
: {}),
|
|
745
|
+
...(substep.recompute === true ? { recompute: true } : {}),
|
|
746
|
+
...(substep.recomputeOnError === true ? { recomputeOnError: true } : {}),
|
|
670
747
|
...(substep.staleAfterSeconds !== undefined
|
|
671
748
|
? { staleAfterSeconds: substep.staleAfterSeconds }
|
|
672
749
|
: {}),
|
|
@@ -828,7 +905,14 @@ export function compileSheetContract(pipeline: PlayStaticPipeline): {
|
|
|
828
905
|
errors.push('Sheet contract produced an empty column id.');
|
|
829
906
|
return;
|
|
830
907
|
}
|
|
831
|
-
|
|
908
|
+
const existing = columns.find((candidate) => candidate.id === column.id);
|
|
909
|
+
if (existing) {
|
|
910
|
+
if (existing.source === 'input' && column.source === 'datasetColumn') {
|
|
911
|
+
existing.source = 'datasetColumn';
|
|
912
|
+
existing.field = column.field;
|
|
913
|
+
}
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
832
916
|
columns.push({
|
|
833
917
|
...column,
|
|
834
918
|
sqlName: sqlSafePlayColumnName(column.id),
|