deepline 0.1.157 → 0.1.159

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.
@@ -1,11 +1,14 @@
1
1
  import {
2
2
  chooseMapChunkSize,
3
+ EXECUTION_PLAN_DEFAULTS,
3
4
  type ExecutionPlan,
4
5
  } from '../../../../shared_libs/play-runtime/execution-plan';
5
6
  import { TOOL_CALLING_MAP_CHUNK_SIZE } from '../../../../shared_libs/play-runtime/map-chunk-limits';
6
7
 
7
8
  export const CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE = 10_000;
8
9
  export { TOOL_CALLING_MAP_CHUNK_SIZE };
10
+ export const WORKER_SUBREQUEST_SAFE_TOOL_CALLS_PER_CHUNK =
11
+ TOOL_CALLING_MAP_CHUNK_SIZE;
9
12
 
10
13
  export type WorkerMapChunkPlanInput = {
11
14
  mapName: string;
@@ -29,11 +32,52 @@ export function chooseWorkerMapRowsPerChunk(
29
32
  preferredChunkSize: planMap?.defaultChunkSize,
30
33
  softWorkflowStepBudget: plan?.chunkPlan.softWorkflowStepBudget,
31
34
  });
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
+ }
32
76
 
33
77
  const toolFreeSimpleMap =
34
78
  !!planMap &&
35
79
  planMap.stepsPerChunk === 1 &&
36
- !mapDoesExternalWork(planMap, plan);
80
+ estimateSubrequestProducingStepsForMap(plan, planMap) === 0;
37
81
  if (
38
82
  toolFreeSimpleMap &&
39
83
  (input.rowCountHint === null ||
@@ -42,55 +86,75 @@ export function chooseWorkerMapRowsPerChunk(
42
86
  return Math.max(rowsPerChunk, CACHE_ENABLED_SIMPLE_MAP_CHUNK_SIZE);
43
87
  }
44
88
 
45
- if (
46
- mapDoesExternalWork(planMap, plan) &&
47
- input.rowCountHint !== null &&
48
- input.rowCountHint <= rowsPerChunk
49
- ) {
50
- return Math.min(rowsPerChunk, TOOL_CALLING_MAP_CHUNK_SIZE);
51
- }
52
-
53
89
  return rowsPerChunk;
54
90
  }
55
91
 
56
- function mapDoesExternalWork(
57
- planMap: ExecutionPlan['maps'][number] | undefined,
92
+ function estimateSubrequestProducingStepsForMap(
58
93
  plan: ExecutionPlan | null,
59
- ): boolean {
60
- if (Array.isArray(planMap?.externalStepFields)) {
61
- return planMap.externalStepFields.length > 0;
62
- }
63
- if (!plan?.toolDeclarations.length) {
64
- return false;
65
- }
94
+ planMap: ExecutionPlan['maps'][number] | undefined,
95
+ ): number {
96
+ const toolDeclarations = plan?.toolDeclarations ?? [];
66
97
  if (!planMap) {
67
- return true;
98
+ return toolDeclarations.length;
99
+ }
100
+ const explicitExternalSteps = Array.isArray(planMap.externalStepFields)
101
+ ? planMap.externalStepFields.length
102
+ : 0;
103
+ const mapStepsPerChunk =
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);
68
111
  }
69
- const outputFields = new Set(planMap.outputFields);
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);
70
123
  const mapFields = new Set([
71
124
  planMap.mapName,
72
125
  planMap.tableNamespace,
73
126
  ...planMap.outputFields,
74
- ...(planMap.stepFields ?? []),
75
127
  ...(planMap.externalStepFields ?? []),
128
+ ...(hasModernStepMetadata ? [] : (planMap.stepFields ?? [])),
76
129
  ...planMap.waterfallStages.flatMap((stage) => [
77
130
  stage.waterfallId,
78
131
  ...stage.stageIds,
79
132
  ]),
80
133
  ]);
81
- return plan.toolDeclarations.some((tool) => {
82
- const field = tool.field?.trim();
83
- if (!field) {
84
- return false;
85
- }
134
+ let scopedToolDeclarations = 0;
135
+ for (const declaration of toolDeclarations) {
136
+ const field = declaration.field?.trim();
137
+ if (!field) continue;
86
138
  if (mapFields.has(field)) {
87
- return true;
139
+ scopedToolDeclarations += 1;
140
+ continue;
88
141
  }
89
142
  if (!field.includes('.')) {
90
- return false;
143
+ continue;
91
144
  }
92
145
  const firstSegment = field.slice(0, field.indexOf('.'));
93
146
  const lastSegment = field.slice(field.lastIndexOf('.') + 1);
94
- return outputFields.has(firstSegment) || outputFields.has(lastSegment);
95
- });
147
+ if (
148
+ outputFields.has(firstSegment) ||
149
+ explicitExternalStepFields.has(lastSegment) ||
150
+ (!hasModernStepMetadata && outputFields.has(lastSegment))
151
+ ) {
152
+ scopedToolDeclarations += 1;
153
+ }
154
+ }
155
+ return Math.max(
156
+ mapStepsPerChunk,
157
+ explicitExternalSteps,
158
+ scopedToolDeclarations,
159
+ );
96
160
  }
@@ -362,6 +362,17 @@ export type ConditionalStepResolver<Row, Value, Else = null> = {
362
362
  export type StepOptions<Row, Value = unknown> = {
363
363
  /** Optional row-level gate. Skipped rows produce `null` for this column. */
364
364
  readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
365
+ /**
366
+ * Legacy dataset-column recompute flag accepted for older authored plays.
367
+ *
368
+ * Prefer putting freshness on the actual reusable call
369
+ * (`ctx.tools.execute`, `ctx.step`, `ctx.fetch`, or `ctx.runPlay`).
370
+ */
371
+ readonly recompute?: boolean;
372
+ /** Legacy error-recompute flag accepted for older authored plays. */
373
+ readonly recomputeOnError?: boolean;
374
+ /** Legacy cell staleness metadata accepted for older authored plays. */
375
+ readonly staleAfterSeconds?: number;
365
376
  };
366
377
 
367
378
  export type StepProgram<Input, Output, Return = Output> = {
@@ -395,6 +406,9 @@ export type StepProgramResolver<Input, Return> = {
395
406
 
396
407
  export type PlayStepProgramStep = {
397
408
  readonly name: string;
409
+ readonly recompute?: boolean;
410
+ readonly recomputeOnError?: boolean;
411
+ readonly staleAfterSeconds?: number;
398
412
  readonly resolver:
399
413
  | StepResolver<Record<string, unknown>, unknown>
400
414
  | ConditionalStepResolver<Record<string, unknown>, unknown>
@@ -1184,6 +1198,13 @@ class DeeplineStepProgram<Input, Output, ReturnValue> implements StepProgram<
1184
1198
  ...this.steps,
1185
1199
  {
1186
1200
  name,
1201
+ ...(options?.recompute === true ? { recompute: true } : {}),
1202
+ ...(options?.recomputeOnError === true
1203
+ ? { recomputeOnError: true }
1204
+ : {}),
1205
+ ...(typeof options?.staleAfterSeconds === 'number'
1206
+ ? { staleAfterSeconds: options.staleAfterSeconds }
1207
+ : {}),
1187
1208
  resolver: stepResolver as PlayStepProgramStep['resolver'],
1188
1209
  },
1189
1210
  ],
@@ -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.157',
107
+ version: '0.1.159',
108
108
  apiContract: '2026-06-dataset-handle-results-hard-cutover',
109
109
  supportPolicy: {
110
- latest: '0.1.157',
110
+ latest: '0.1.159',
111
111
  minimumSupported: '0.1.53',
112
112
  deprecatedBelow: '0.1.53',
113
113
  commandMinimumSupported: [
@@ -128,6 +128,13 @@ class WorkerStepProgram<Input, Output, ReturnValue> implements StepProgram<
128
128
  ...this.steps,
129
129
  {
130
130
  name,
131
+ ...(options?.recompute === true ? { recompute: true } : {}),
132
+ ...(options?.recomputeOnError === true
133
+ ? { recomputeOnError: true }
134
+ : {}),
135
+ ...(typeof options?.staleAfterSeconds === 'number'
136
+ ? { staleAfterSeconds: options.staleAfterSeconds }
137
+ : {}),
131
138
  resolver: stepResolver as PlayStepProgramStep['resolver'],
132
139
  },
133
140
  ],
@@ -654,6 +654,9 @@ export type RuntimeConditionalStepResolver<
654
654
 
655
655
  export type RuntimeStepProgramStep = {
656
656
  name: string;
657
+ recompute?: boolean;
658
+ recomputeOnError?: boolean;
659
+ staleAfterSeconds?: number;
657
660
  resolver:
658
661
  | RuntimeStepResolver
659
662
  | RuntimeConditionalStepResolver
@@ -1 +1 @@
1
- export const TOOL_CALLING_MAP_CHUNK_SIZE = 25;
1
+ export const TOOL_CALLING_MAP_CHUNK_SIZE = 20;
@@ -612,6 +612,24 @@ function conflictingTerminalSnapshot(
612
612
  );
613
613
  }
614
614
 
615
+ function retryablePlatformDeployFailureSnapshot(
616
+ base: PlayRunLedgerSnapshot,
617
+ eventError?: string | null,
618
+ ): PlayRunLedgerSnapshot | null {
619
+ if (
620
+ isTerminalPlayRunLedgerStatus(base.status) ||
621
+ !eventError ||
622
+ normalizePlayRunFailure(eventError).code !== 'PLATFORM_DEPLOY_INTERRUPTED'
623
+ ) {
624
+ return null;
625
+ }
626
+ return withTiming(
627
+ appendLogLines(base, [
628
+ `[ledger] retryable platform deploy run.failed ignored; status remains ${base.status}`,
629
+ ]),
630
+ );
631
+ }
632
+
615
633
  function settleRunningStepsOnTerminal(
616
634
  snapshot: PlayRunLedgerSnapshot,
617
635
  status: Extract<PlayRunLedgerStepStatus, 'completed' | 'failed'>,
@@ -714,6 +732,7 @@ export function reducePlayRunLedgerEvent(
714
732
  );
715
733
  case 'run.failed':
716
734
  return (
735
+ retryablePlatformDeployFailureSnapshot(base, event.error) ??
717
736
  conflictingTerminalSnapshot(
718
737
  base,
719
738
  event.type,
@@ -610,6 +610,23 @@ async function ensureRuntimeSheetForPreloadedSession(
610
610
  phase: 'ensure_sheet_for_preloaded_session',
611
611
  ms: Date.now() - ensureStartedAt,
612
612
  });
613
+ const recheckStartedAt = Date.now();
614
+ const readyAfterEnsure = await isRuntimeSheetSchemaReady(input.session, {
615
+ sheetContract: input.sheetContract,
616
+ });
617
+ input.timings?.push({
618
+ phase: 'schema_check_after_preloaded_session_ensure',
619
+ ms: Date.now() - recheckStartedAt,
620
+ ready: readyAfterEnsure,
621
+ });
622
+ if (!readyAfterEnsure) {
623
+ if (runtimeSheetEnsureCache.get(cacheKey)?.promise === promise) {
624
+ runtimeSheetEnsureCache.delete(cacheKey);
625
+ }
626
+ throw new Error(
627
+ `Runtime sheet schema for ctx.dataset("${input.tableNamespace}") is still not ready after ensure_sheet.`,
628
+ );
629
+ }
613
630
  } catch (error) {
614
631
  if (runtimeSheetEnsureCache.get(cacheKey)?.promise === promise) {
615
632
  runtimeSheetEnsureCache.delete(cacheKey);
@@ -5,6 +5,9 @@ export type StepProgramDatasetOptions = {
5
5
  row: Record<string, unknown>,
6
6
  index: number,
7
7
  ) => boolean | Promise<boolean>;
8
+ recompute?: boolean;
9
+ recomputeOnError?: boolean;
10
+ staleAfterSeconds?: number;
8
11
  };
9
12
 
10
13
  export type StepProgramDatasetColumnRunInput<Value = unknown> = {
@@ -124,6 +127,13 @@ export class StepProgramDatasetBuilder<
124
127
  ...this.program.steps,
125
128
  {
126
129
  name,
130
+ ...(normalized.options?.recompute === true ? { recompute: true } : {}),
131
+ ...(normalized.options?.recomputeOnError === true
132
+ ? { recomputeOnError: true }
133
+ : {}),
134
+ ...(typeof normalized.options?.staleAfterSeconds === 'number'
135
+ ? { staleAfterSeconds: normalized.options.staleAfterSeconds }
136
+ : {}),
127
137
  resolver: this.applyDerivationOptions(
128
138
  normalized.resolver,
129
139
  normalized.options,
@@ -727,13 +727,15 @@ function staticStringFromExpression(
727
727
  node: AstNode | null | undefined,
728
728
  context: PlayMetadataExtractionContext,
729
729
  seen = new Set<string>(),
730
+ trimResult = true,
730
731
  ): string | null {
731
732
  const expression = unwrapStaticExpression(node);
732
733
  if (!expression) return null;
733
734
 
734
735
  if (expression.type === 'Literal') {
735
736
  const value = expression.value;
736
- return typeof value === 'string' && value.trim() ? value.trim() : null;
737
+ if (typeof value !== 'string' || !value.trim()) return null;
738
+ return trimResult ? value.trim() : value;
737
739
  }
738
740
 
739
741
  if (
@@ -745,9 +747,26 @@ function staticStringFromExpression(
745
747
  firstQuasi && typeof firstQuasi.value === 'object'
746
748
  ? (firstQuasi.value as { cooked?: unknown }).cooked
747
749
  : null;
748
- return typeof cooked === 'string' && cooked.trim()
749
- ? cooked.trim()
750
- : null;
750
+ if (typeof cooked !== 'string' || !cooked.trim()) return null;
751
+ return trimResult ? cooked.trim() : cooked;
752
+ }
753
+
754
+ if (expression.type === 'BinaryExpression' && expression.operator === '+') {
755
+ const left = staticStringFromExpression(
756
+ isAstNode(expression.left) ? expression.left : null,
757
+ context,
758
+ new Set(seen),
759
+ false,
760
+ );
761
+ const right = staticStringFromExpression(
762
+ isAstNode(expression.right) ? expression.right : null,
763
+ context,
764
+ new Set(seen),
765
+ false,
766
+ );
767
+ const value = left !== null && right !== null ? `${left}${right}` : null;
768
+ if (!value?.trim()) return null;
769
+ return trimResult ? value.trim() : value;
751
770
  }
752
771
 
753
772
  const identifier = getIdentifierName(expression);
@@ -757,6 +776,7 @@ function staticStringFromExpression(
757
776
  context.declarations.get(identifier),
758
777
  context,
759
778
  seen,
779
+ trimResult,
760
780
  );
761
781
  }
762
782
 
package/dist/cli/index.js CHANGED
@@ -657,10 +657,10 @@ var SDK_RELEASE = {
657
657
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
658
658
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
659
659
  // fields shipped in 0.1.153.
660
- version: "0.1.157",
660
+ version: "0.1.159",
661
661
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
662
662
  supportPolicy: {
663
- latest: "0.1.157",
663
+ latest: "0.1.159",
664
664
  minimumSupported: "0.1.53",
665
665
  deprecatedBelow: "0.1.53",
666
666
  commandMinimumSupported: [
@@ -642,10 +642,10 @@ var SDK_RELEASE = {
642
642
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
643
643
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
644
644
  // fields shipped in 0.1.153.
645
- version: "0.1.157",
645
+ version: "0.1.159",
646
646
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
647
647
  supportPolicy: {
648
- latest: "0.1.157",
648
+ latest: "0.1.159",
649
649
  minimumSupported: "0.1.53",
650
650
  deprecatedBelow: "0.1.53",
651
651
  commandMinimumSupported: [
package/dist/index.d.mts CHANGED
@@ -2983,6 +2983,17 @@ type ConditionalStepResolver<Row, Value, Else = null> = {
2983
2983
  type StepOptions<Row, Value = unknown> = {
2984
2984
  /** Optional row-level gate. Skipped rows produce `null` for this column. */
2985
2985
  readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
2986
+ /**
2987
+ * Legacy dataset-column recompute flag accepted for older authored plays.
2988
+ *
2989
+ * Prefer putting freshness on the actual reusable call
2990
+ * (`ctx.tools.execute`, `ctx.step`, `ctx.fetch`, or `ctx.runPlay`).
2991
+ */
2992
+ readonly recompute?: boolean;
2993
+ /** Legacy error-recompute flag accepted for older authored plays. */
2994
+ readonly recomputeOnError?: boolean;
2995
+ /** Legacy cell staleness metadata accepted for older authored plays. */
2996
+ readonly staleAfterSeconds?: number;
2986
2997
  };
2987
2998
  type StepProgram<Input, Output, Return = Output> = {
2988
2999
  readonly kind: 'steps';
@@ -3001,6 +3012,9 @@ type StepProgramResolver<Input, Return> = {
3001
3012
  };
3002
3013
  type PlayStepProgramStep = {
3003
3014
  readonly name: string;
3015
+ readonly recompute?: boolean;
3016
+ readonly recomputeOnError?: boolean;
3017
+ readonly staleAfterSeconds?: number;
3004
3018
  readonly resolver: StepResolver<Record<string, unknown>, unknown> | ConditionalStepResolver<Record<string, unknown>, unknown> | StepProgramResolver<Record<string, unknown>, unknown>;
3005
3019
  };
3006
3020
  type ColumnResolver<Row, Value> = StepResolver<Row, Value> | ConditionalStepResolver<Row, Value> | StepProgramResolver<Row, Value>;
package/dist/index.d.ts CHANGED
@@ -2983,6 +2983,17 @@ type ConditionalStepResolver<Row, Value, Else = null> = {
2983
2983
  type StepOptions<Row, Value = unknown> = {
2984
2984
  /** Optional row-level gate. Skipped rows produce `null` for this column. */
2985
2985
  readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean>;
2986
+ /**
2987
+ * Legacy dataset-column recompute flag accepted for older authored plays.
2988
+ *
2989
+ * Prefer putting freshness on the actual reusable call
2990
+ * (`ctx.tools.execute`, `ctx.step`, `ctx.fetch`, or `ctx.runPlay`).
2991
+ */
2992
+ readonly recompute?: boolean;
2993
+ /** Legacy error-recompute flag accepted for older authored plays. */
2994
+ readonly recomputeOnError?: boolean;
2995
+ /** Legacy cell staleness metadata accepted for older authored plays. */
2996
+ readonly staleAfterSeconds?: number;
2986
2997
  };
2987
2998
  type StepProgram<Input, Output, Return = Output> = {
2988
2999
  readonly kind: 'steps';
@@ -3001,6 +3012,9 @@ type StepProgramResolver<Input, Return> = {
3001
3012
  };
3002
3013
  type PlayStepProgramStep = {
3003
3014
  readonly name: string;
3015
+ readonly recompute?: boolean;
3016
+ readonly recomputeOnError?: boolean;
3017
+ readonly staleAfterSeconds?: number;
3004
3018
  readonly resolver: StepResolver<Record<string, unknown>, unknown> | ConditionalStepResolver<Record<string, unknown>, unknown> | StepProgramResolver<Record<string, unknown>, unknown>;
3005
3019
  };
3006
3020
  type ColumnResolver<Row, Value> = StepResolver<Row, Value> | ConditionalStepResolver<Row, Value> | StepProgramResolver<Row, Value>;
package/dist/index.js CHANGED
@@ -421,10 +421,10 @@ var SDK_RELEASE = {
421
421
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
422
422
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
423
423
  // fields shipped in 0.1.153.
424
- version: "0.1.157",
424
+ version: "0.1.159",
425
425
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
426
426
  supportPolicy: {
427
- latest: "0.1.157",
427
+ latest: "0.1.159",
428
428
  minimumSupported: "0.1.53",
429
429
  deprecatedBelow: "0.1.53",
430
430
  commandMinimumSupported: [
@@ -5114,6 +5114,9 @@ var DeeplineStepProgram = class _DeeplineStepProgram {
5114
5114
  ...this.steps,
5115
5115
  {
5116
5116
  name,
5117
+ ...options?.recompute === true ? { recompute: true } : {},
5118
+ ...options?.recomputeOnError === true ? { recomputeOnError: true } : {},
5119
+ ...typeof options?.staleAfterSeconds === "number" ? { staleAfterSeconds: options.staleAfterSeconds } : {},
5117
5120
  resolver: stepResolver
5118
5121
  }
5119
5122
  ],
package/dist/index.mjs CHANGED
@@ -351,10 +351,10 @@ var SDK_RELEASE = {
351
351
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
352
352
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
353
353
  // fields shipped in 0.1.153.
354
- version: "0.1.157",
354
+ version: "0.1.159",
355
355
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
356
356
  supportPolicy: {
357
- latest: "0.1.157",
357
+ latest: "0.1.159",
358
358
  minimumSupported: "0.1.53",
359
359
  deprecatedBelow: "0.1.53",
360
360
  commandMinimumSupported: [
@@ -5044,6 +5044,9 @@ var DeeplineStepProgram = class _DeeplineStepProgram {
5044
5044
  ...this.steps,
5045
5045
  {
5046
5046
  name,
5047
+ ...options?.recompute === true ? { recompute: true } : {},
5048
+ ...options?.recomputeOnError === true ? { recomputeOnError: true } : {},
5049
+ ...typeof options?.staleAfterSeconds === "number" ? { staleAfterSeconds: options.staleAfterSeconds } : {},
5047
5050
  resolver: stepResolver
5048
5051
  }
5049
5052
  ],
@@ -554,17 +554,36 @@ function unwrapStaticExpression(node) {
554
554
  }
555
555
  return current;
556
556
  }
557
- function staticStringFromExpression(node, context, seen = /* @__PURE__ */ new Set()) {
557
+ function staticStringFromExpression(node, context, seen = /* @__PURE__ */ new Set(), trimResult = true) {
558
558
  const expression = unwrapStaticExpression(node);
559
559
  if (!expression) return null;
560
560
  if (expression.type === "Literal") {
561
561
  const value = expression.value;
562
- return typeof value === "string" && value.trim() ? value.trim() : null;
562
+ if (typeof value !== "string" || !value.trim()) return null;
563
+ return trimResult ? value.trim() : value;
563
564
  }
564
565
  if (expression.type === "TemplateLiteral" && astArray(expression.expressions).length === 0) {
565
566
  const firstQuasi = astArray(expression.quasis)[0];
566
567
  const cooked = firstQuasi && typeof firstQuasi.value === "object" ? firstQuasi.value.cooked : null;
567
- return typeof cooked === "string" && cooked.trim() ? cooked.trim() : null;
568
+ if (typeof cooked !== "string" || !cooked.trim()) return null;
569
+ return trimResult ? cooked.trim() : cooked;
570
+ }
571
+ if (expression.type === "BinaryExpression" && expression.operator === "+") {
572
+ const left = staticStringFromExpression(
573
+ isAstNode(expression.left) ? expression.left : null,
574
+ context,
575
+ new Set(seen),
576
+ false
577
+ );
578
+ const right = staticStringFromExpression(
579
+ isAstNode(expression.right) ? expression.right : null,
580
+ context,
581
+ new Set(seen),
582
+ false
583
+ );
584
+ const value = left !== null && right !== null ? `${left}${right}` : null;
585
+ if (!value?.trim()) return null;
586
+ return trimResult ? value.trim() : value;
568
587
  }
569
588
  const identifier = getIdentifierName(expression);
570
589
  if (!identifier || seen.has(identifier)) return null;
@@ -572,7 +591,8 @@ function staticStringFromExpression(node, context, seen = /* @__PURE__ */ new Se
572
591
  return staticStringFromExpression(
573
592
  context.declarations.get(identifier),
574
593
  context,
575
- seen
594
+ seen,
595
+ trimResult
576
596
  );
577
597
  }
578
598
  function propertyNameFromKey(property) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.157",
3
+ "version": "0.1.159",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {