deepline 0.1.174 → 0.1.175

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.
@@ -103,6 +103,7 @@ export type PlayWorkflowParams = {
103
103
  executionPlan?: ExecutionPlan | null;
104
104
  childPlayManifests?: PlayRuntimeManifestMap | null;
105
105
  playCallGovernance?: PlayCallGovernanceSnapshot | null;
106
+ forceToolRefresh?: boolean | null;
106
107
  preloadedDbSessions?: PreloadedRuntimeDbSession[] | null;
107
108
  preloadedDbSessionRef?: {
108
109
  runId: string;
@@ -2214,6 +2215,7 @@ function buildChildWorkflowParams(input: {
2214
2215
  executorToken: childToken,
2215
2216
  baseUrl,
2216
2217
  integrationMode: normalizeIntegrationMode(body.integrationMode),
2218
+ forceToolRefresh: body.forceToolRefresh === true,
2217
2219
  orgId,
2218
2220
  userEmail: typeof body.userEmail === 'string' ? body.userEmail : '',
2219
2221
  userId: typeof body.userId === 'string' ? body.userId : null,
@@ -2274,6 +2276,7 @@ function runRequestFromPlayWorkflowParams(
2274
2276
  executionPlan: params.executionPlan ?? null,
2275
2277
  childPlayManifests: params.childPlayManifests ?? null,
2276
2278
  playCallGovernance: params.playCallGovernance ?? null,
2279
+ force: params.forceToolRefresh === true,
2277
2280
  preloadedDbSessions: params.preloadedDbSessions ?? null,
2278
2281
  inlineChildRunRegistered:
2279
2282
  params.runtimeBackend === 'cf_workflows_dynamic_worker_inline_child',
@@ -270,6 +270,7 @@ type RunRequest = {
270
270
  playName: string;
271
271
  graphHash?: string | null;
272
272
  userEmail: string | null;
273
+ force?: boolean | null;
273
274
  runtimeInput: Record<string, unknown>;
274
275
  /** Optional inline CSV rows (for plays where ctx.csv was passed inline data). */
275
276
  inlineCsv?: { name: string; rows: Record<string, unknown>[] } | null;
@@ -1857,7 +1858,9 @@ class WorkerToolBatchScheduler {
1857
1858
  id,
1858
1859
  cacheKey: receiptKey,
1859
1860
  receiptKey,
1860
- force: options?.force === true,
1861
+ force:
1862
+ options?.force === true ||
1863
+ !!this.req.force,
1861
1864
  receiptWaitMaxAttempts: resolveRuntimeToolReceiptWaitMaxAttempts(
1862
1865
  typeof runtimeOptions?.receiptWaitMs === 'number'
1863
1866
  ? { max_wait_ms: runtimeOptions.receiptWaitMs }
@@ -4088,6 +4091,7 @@ async function prepareMapRows(input: {
4088
4091
  rows: Record<string, unknown>[];
4089
4092
  inputOffset: number;
4090
4093
  outputFields: string[];
4094
+ force?: boolean;
4091
4095
  }): Promise<{
4092
4096
  inserted: number;
4093
4097
  skipped: number;
@@ -4109,6 +4113,7 @@ async function prepareMapRows(input: {
4109
4113
  }),
4110
4114
  rows,
4111
4115
  inputOffset: input.inputOffset,
4116
+ ...(input.force ? { force: true } : {}),
4112
4117
  });
4113
4118
  for (const timing of result.timings ?? []) {
4114
4119
  const phase =
@@ -4682,9 +4687,7 @@ function createMinimalWorkerCtx(
4682
4687
  return formatMapProgressMessage(completed, input.total);
4683
4688
  };
4684
4689
  const formatMapProcessingMessage = (rowsToExecute: number) =>
4685
- rowsToExecute > 0
4686
- ? `Processing ${rowsToExecute.toLocaleString()} rows`
4687
- : null;
4690
+ rowsToExecute > 0 ? `${rowsToExecute.toLocaleString()} rows` : null;
4688
4691
  const formatMapExecutionHeartbeatMessage = (input: {
4689
4692
  rowsToExecute: number;
4690
4693
  startedRows: number;
@@ -4698,7 +4701,7 @@ function createMinimalWorkerCtx(
4698
4701
  const waitingRows = Math.max(0, rowsToExecute - startedRows);
4699
4702
  const parts = [
4700
4703
  activeRows > 0 ? `${activeRows.toLocaleString()} active` : null,
4701
- waitingRows > 0 ? `${waitingRows.toLocaleString()} waiting` : null,
4704
+ waitingRows > 0 ? `${waitingRows.toLocaleString()} queued` : null,
4702
4705
  completedRows > 0 ? `${completedRows.toLocaleString()} done` : null,
4703
4706
  ].filter((part): part is string => Boolean(part));
4704
4707
  const base =
@@ -4889,6 +4892,7 @@ function createMinimalWorkerCtx(
4889
4892
  ...mapRowOutcomeRuntimeFields({ key: rowKey }),
4890
4893
  })),
4891
4894
  inputOffset: baseOffset + chunkStart,
4895
+ force: !!req.force,
4892
4896
  });
4893
4897
  recordRunnerPerfTrace({
4894
4898
  req,
@@ -5366,7 +5370,9 @@ function createMinimalWorkerCtx(
5366
5370
  request.input,
5367
5371
  workflowStep,
5368
5372
  {
5369
- force: request.force === true,
5373
+ force:
5374
+ request.force === true ||
5375
+ !!req.force,
5370
5376
  staleAfterSeconds: request.staleAfterSeconds,
5371
5377
  },
5372
5378
  );
@@ -6354,7 +6360,9 @@ function createMinimalWorkerCtx(
6354
6360
  request.input,
6355
6361
  workflowStep,
6356
6362
  {
6357
- force: request.force === true,
6363
+ force:
6364
+ request.force === true ||
6365
+ !!req.force,
6358
6366
  staleAfterSeconds: request.staleAfterSeconds,
6359
6367
  },
6360
6368
  {
@@ -6500,6 +6508,7 @@ function createMinimalWorkerCtx(
6500
6508
  callbackBaseUrl: req.callbackUrl,
6501
6509
  baseUrl: req.baseUrl,
6502
6510
  integrationMode: req.integrationMode ?? null,
6511
+ forceToolRefresh: req.force === true,
6503
6512
  parentExecutorToken: req.executorToken,
6504
6513
  userEmail: req.userEmail ?? '',
6505
6514
  profile: 'workers_edge',
@@ -7956,6 +7965,7 @@ function runRequestFromWorkflowParams(
7956
7965
  runtimeInput: isRecord(params.input)
7957
7966
  ? (params.input as Record<string, unknown>)
7958
7967
  : {},
7968
+ force: params.forceToolRefresh === true,
7959
7969
  inlineCsv: isInlineCsv(params.inlineCsv) ? params.inlineCsv : null,
7960
7970
  inputFiles:
7961
7971
  inputFile && inputStorageKey
@@ -1285,6 +1285,7 @@ export class DeeplineClient {
1285
1285
  */
1286
1286
  async startPlayRun(request: StartPlayRunRequest): Promise<PlayRunStart> {
1287
1287
  const integrationMode = resolvePlayRunIntegrationMode(request);
1288
+ const forceToolRefresh = request.forceToolRefresh === true;
1288
1289
  const response = await this.http.post<Record<string, unknown>>(
1289
1290
  '/api/v2/plays/run',
1290
1291
  {
@@ -1319,6 +1320,7 @@ export class DeeplineClient {
1319
1320
  ? { packagedFiles: request.packagedFiles }
1320
1321
  : {}),
1321
1322
  ...(request.force ? { force: true } : {}),
1323
+ ...(forceToolRefresh ? { forceToolRefresh: true } : {}),
1322
1324
  ...(typeof request.waitForCompletionMs === 'number'
1323
1325
  ? { waitForCompletionMs: request.waitForCompletionMs }
1324
1326
  : {}),
@@ -1348,6 +1350,7 @@ export class DeeplineClient {
1348
1350
  options?: { signal?: AbortSignal },
1349
1351
  ): AsyncGenerator<PlayLiveEvent> {
1350
1352
  const integrationMode = resolvePlayRunIntegrationMode(request);
1353
+ const forceToolRefresh = request.forceToolRefresh === true;
1351
1354
  const body = {
1352
1355
  ...(request.name ? { name: request.name } : {}),
1353
1356
  ...(request.revisionId ? { revisionId: request.revisionId } : {}),
@@ -1380,6 +1383,7 @@ export class DeeplineClient {
1380
1383
  ? { packagedFiles: request.packagedFiles }
1381
1384
  : {}),
1382
1385
  ...(request.force ? { force: true } : {}),
1386
+ ...(forceToolRefresh ? { forceToolRefresh: true } : {}),
1383
1387
  ...(typeof request.waitForCompletionMs === 'number'
1384
1388
  ? { waitForCompletionMs: request.waitForCompletionMs }
1385
1389
  : {}),
@@ -1630,6 +1634,7 @@ export class DeeplineClient {
1630
1634
  inputFile?: PlayStagedFileRef | null;
1631
1635
  packagedFiles?: PlayStagedFileRef[];
1632
1636
  force?: boolean;
1637
+ forceToolRefresh?: boolean;
1633
1638
  }): Promise<PlayRunStart> {
1634
1639
  const compilerManifest =
1635
1640
  input.compilerManifest ??
@@ -1665,6 +1670,7 @@ export class DeeplineClient {
1665
1670
  ? { packagedFiles: input.packagedFiles }
1666
1671
  : {}),
1667
1672
  ...(input.force ? { force: true } : {}),
1673
+ ...(input.forceToolRefresh ? { forceToolRefresh: true } : {}),
1668
1674
  });
1669
1675
  }
1670
1676
 
@@ -1706,6 +1712,7 @@ export class DeeplineClient {
1706
1712
  inputFile?: PlayStagedFileRef | null;
1707
1713
  packagedFiles?: PlayStagedFileRef[];
1708
1714
  force?: boolean;
1715
+ forceToolRefresh?: boolean;
1709
1716
  },
1710
1717
  ): Promise<PlayRunStart> {
1711
1718
  const runtimeInput = options?.input ? { ...options.input } : {};
@@ -1766,6 +1773,7 @@ export class DeeplineClient {
1766
1773
  ? { packagedFiles: options.packagedFiles }
1767
1774
  : {}),
1768
1775
  ...(options?.force ? { force: true } : {}),
1776
+ ...(options?.forceToolRefresh ? { forceToolRefresh: true } : {}),
1769
1777
  });
1770
1778
  }
1771
1779
 
@@ -2858,6 +2866,8 @@ export class DeeplineClient {
2858
2866
  packagedFiles?: PlayStagedFileRef[];
2859
2867
  /** Compatibility flag; active sibling runs are allowed. */
2860
2868
  force?: boolean;
2869
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
2870
+ forceToolRefresh?: boolean;
2861
2871
  },
2862
2872
  ): Promise<PlayRunResult> {
2863
2873
  const { workflowId } = await this.submitPlay(code, csvPath, name, {
@@ -2868,6 +2878,7 @@ export class DeeplineClient {
2868
2878
  inputFile: options?.inputFile,
2869
2879
  packagedFiles: options?.packagedFiles,
2870
2880
  force: options?.force,
2881
+ forceToolRefresh: options?.forceToolRefresh,
2871
2882
  });
2872
2883
  const start = Date.now();
2873
2884
  const state: PlayLiveStatusState = {
@@ -225,6 +225,7 @@ export async function harnessStartSheetDataset(input: {
225
225
  rows: Array<Record<string, unknown>>;
226
226
  runId: string;
227
227
  inputOffset?: number;
228
+ force?: boolean;
228
229
  userEmail?: string | null;
229
230
  }): Promise<{
230
231
  inserted: number;
@@ -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.174',
107
+ version: '0.1.175',
108
108
  apiContract: '2026-06-dataset-handle-results-hard-cutover',
109
109
  supportPolicy: {
110
- latest: '0.1.174',
110
+ latest: '0.1.175',
111
111
  minimumSupported: '0.1.53',
112
112
  deprecatedBelow: '0.1.53',
113
113
  commandMinimumSupported: [
@@ -998,6 +998,8 @@ export interface StartPlayRunRequest {
998
998
  packagedFiles?: unknown[];
999
999
  /** Compatibility flag; active sibling runs are allowed. */
1000
1000
  force?: boolean;
1001
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
1002
+ forceToolRefresh?: boolean;
1001
1003
  /** Optionally let the start request wait briefly and return a terminal result. */
1002
1004
  waitForCompletionMs?: number;
1003
1005
  /**
@@ -1579,7 +1579,9 @@ export class PlayContextImpl {
1579
1579
  staleAfterSeconds?: number | null;
1580
1580
  } {
1581
1581
  return {
1582
- force: options?.force === true,
1582
+ force:
1583
+ options?.force === true ||
1584
+ this.#options.cachePolicy?.forceToolRefresh === true,
1583
1585
  staleAfterSeconds: options?.staleAfterSeconds ?? null,
1584
1586
  };
1585
1587
  }
@@ -2152,6 +2154,8 @@ export class PlayContextImpl {
2152
2154
  playId: this.#options.playId,
2153
2155
  runId: this.#options.runId,
2154
2156
  staticPipeline: this.#options.staticPipeline,
2157
+ forceRefresh:
2158
+ this.#options.cachePolicy?.forceToolRefresh === true,
2155
2159
  },
2156
2160
  );
2157
2161
  resolvedTableNamespace = normalizeTableNamespace(
@@ -3454,7 +3458,7 @@ export class PlayContextImpl {
3454
3458
  ? null
3455
3459
  : this.getCachedToolResult(toolId, directCacheKey);
3456
3460
  if (cached?.done) {
3457
- this.log(`Calling tool: ${toolId} recovered from checkpoint`);
3461
+ this.log(`Tool cache hit: ${toolId} exact payload`);
3458
3462
  return await this.wrapToolExecutionResult({
3459
3463
  toolId,
3460
3464
  status: cached.result == null ? 'no_result' : 'completed',
@@ -3465,7 +3469,11 @@ export class PlayContextImpl {
3465
3469
  }),
3466
3470
  });
3467
3471
  }
3468
- this.log(`Calling tool: ${toolId}`);
3472
+ this.log(
3473
+ toolCachePolicy.force
3474
+ ? `Calling tool: ${toolId} (force)`
3475
+ : `Calling tool: ${toolId}`,
3476
+ );
3469
3477
  const execution = await this.callToolExecutionAPI(toolId, input, {
3470
3478
  timeoutMs: options?.timeoutMs,
3471
3479
  });
@@ -3513,7 +3521,7 @@ export class PlayContextImpl {
3513
3521
  ? null
3514
3522
  : this.getCachedToolResult(toolId, toolResultCacheKey);
3515
3523
  if (cached?.done) {
3516
- this.log(` Row ${rowId} ${toolId}: recovered from checkpoint`);
3524
+ this.log(` Row ${rowId} ${toolId}: cache hit exact payload`);
3517
3525
  return await this.wrapToolExecutionResult({
3518
3526
  toolId,
3519
3527
  status: cached.result == null ? 'no_result' : 'completed',
@@ -3582,7 +3590,7 @@ export class PlayContextImpl {
3582
3590
  staleAfterSeconds: toolCachePolicy.staleAfterSeconds,
3583
3591
  markSkipped: () => {
3584
3592
  this.log(
3585
- `ctx.tools.execute(${toolId}): no-op due completed receipt ${toolRequestIdentity} (label: ${normalizedKey})`,
3593
+ `Tool cache hit: ${toolId} exact payload (${normalizedKey}:${toolRequestIdentity})`,
3586
3594
  );
3587
3595
  },
3588
3596
  onClaimedResult: (output, receiptKey) =>
@@ -4303,7 +4311,9 @@ export class PlayContextImpl {
4303
4311
  const pendingRequests: ToolCallRequest[] = [];
4304
4312
  const recoveredRequests: ToolCallRequest[] = [];
4305
4313
  for (const req of requests) {
4306
- const cached = this.getCachedToolResult(toolId, req.cacheKey);
4314
+ const cached = req.force
4315
+ ? undefined
4316
+ : this.getCachedToolResult(toolId, req.cacheKey);
4307
4317
  if (cached?.done) {
4308
4318
  this.log(` Row ${req.rowId} ${toolId}: recovered from checkpoint`);
4309
4319
  const resolver = this.toolCallResolvers.get(req.callId);
@@ -410,6 +410,10 @@ export interface ContextOptions {
410
410
  checkpoint?: PlayCheckpoint;
411
411
  /** Enables durable boundary replay such as ctx.sleep() resumptions. */
412
412
  durableBoundaries?: boolean;
413
+ /** Run-level cache policy. forceToolRefresh bypasses ctx.tools.execute receipts. */
414
+ cachePolicy?: {
415
+ forceToolRefresh?: boolean;
416
+ };
413
417
  /** Called after each durable batch completes — for Temporal heartbeating. */
414
418
  onBatchComplete?: (checkpoint: PlayCheckpoint) => void;
415
419
  /** Called when the runtime emits a new execution log line. */
@@ -435,6 +439,7 @@ export interface ContextOptions {
435
439
  playId?: string;
436
440
  runId?: string;
437
441
  staticPipeline?: PlayStaticPipeline | null;
442
+ forceRefresh?: boolean;
438
443
  },
439
444
  ) => Promise<MapStartResult>;
440
445
  /**
@@ -58,21 +58,15 @@ export function buildDurableToolCallCacheKey(input: {
58
58
  const orgId = input.orgId?.trim() || 'org';
59
59
  const playId = input.playId.trim();
60
60
  if (!playId) {
61
- throw new Error(
62
- 'Durable tool call cache key requires a non-empty play id.',
63
- );
61
+ throw new Error('Missing durable tool play id.');
64
62
  }
65
63
  const toolId = input.toolId.trim();
66
64
  if (!toolId) {
67
- throw new Error(
68
- 'Durable tool call cache key requires a non-empty tool id.',
69
- );
65
+ throw new Error('Missing durable tool id.');
70
66
  }
71
- const providerActionVersion = input.providerActionVersion?.trim();
72
- if (!providerActionVersion) {
73
- throw new Error(
74
- 'Durable tool call cache key requires a provider action version.',
75
- );
67
+ const p = input.providerActionVersion?.trim();
68
+ if (!p) {
69
+ throw new Error('Missing durable tool action version.');
76
70
  }
77
71
  const digest = sha256Hex(
78
72
  stableStringify({
@@ -83,7 +77,7 @@ export function buildDurableToolCallCacheKey(input: {
83
77
  normalizedToolId: normalizeTableNamespace(toolId),
84
78
  requestInput: input.requestInput,
85
79
  authScopeDigest: input.authScopeDigest ?? null,
86
- providerActionVersion,
80
+ providerActionVersion: p,
87
81
  cachePolicyVersion:
88
82
  input.cachePolicyVersion ?? DURABLE_CALL_CACHE_POLICY_VERSION,
89
83
  staleBucket: durableCacheStaleBucket({
@@ -23,6 +23,7 @@ export interface PlayRunnerContextConfig {
23
23
  userEmail?: string;
24
24
  convexUrl?: string;
25
25
  staticPipeline?: PlayStaticPipeline | null;
26
+ forceToolRefresh?: boolean | null;
26
27
  /**
27
28
  * Controls how scoped Postgres sessions enter the runner. `preloaded` means
28
29
  * the launch config carries short-lived encrypted sessions minted before
@@ -2224,7 +2224,10 @@ async function prepareRuntimeSheetDatasetRows(
2224
2224
  normalizedTableNamespace: string;
2225
2225
  physicalInsertColumnsSql: string;
2226
2226
  physicalInsertValuesSql: string;
2227
+ physicalRefreshSetSql: string;
2228
+ physicalUpsertSetSql: string;
2227
2229
  outputPhysicalColumns: PhysicalSheetColumnProjection[];
2230
+ force?: boolean;
2228
2231
  },
2229
2232
  ): Promise<{ inserted: number; pendingKeys: string[] }> {
2230
2233
  let inserted = 0;
@@ -2259,10 +2262,14 @@ async function prepareRuntimeSheetDatasetRows(
2259
2262
  UPDATE ${sheetTable(session)} AS target
2260
2263
  SET _input_index = input_rows._input_index,
2261
2264
  _updated_at = now(),
2262
- _version = ${nextRuntimeSheetVersionExpression(session)}
2265
+ _version = ${nextRuntimeSheetVersionExpression(session)}${input.physicalRefreshSetSql}
2263
2266
  FROM input_rows
2264
2267
  WHERE target._key = input_rows._key
2265
- AND target._input_index IS DISTINCT FROM input_rows._input_index
2268
+ AND target._status <> 'stale'
2269
+ AND (
2270
+ $7::boolean
2271
+ OR target._input_index IS DISTINCT FROM input_rows._input_index
2272
+ )
2266
2273
  RETURNING target._key
2267
2274
  ),
2268
2275
  inserted_rows AS (
@@ -2274,7 +2281,7 @@ async function prepareRuntimeSheetDatasetRows(
2274
2281
  _run_id = EXCLUDED._run_id,
2275
2282
  _input_index = EXCLUDED._input_index,
2276
2283
  _updated_at = now(),
2277
- _version = ${nextRuntimeSheetVersionExpression(session)}
2284
+ _version = ${nextRuntimeSheetVersionExpression(session)}${input.physicalUpsertSetSql}
2278
2285
  WHERE ${sheetTable(session)}._status = 'stale'
2279
2286
  RETURNING _key
2280
2287
  ),
@@ -2375,6 +2382,7 @@ async function prepareRuntimeSheetDatasetRows(
2375
2382
  input.runId,
2376
2383
  input.normalizedPlayName,
2377
2384
  input.normalizedTableNamespace,
2385
+ input.force === true,
2378
2386
  ],
2379
2387
  );
2380
2388
  inserted += Number(rows[0]?.inserted_count ?? 0);
@@ -2398,30 +2406,35 @@ async function buildRuntimeSheetDatasetStartResult(
2398
2406
  runId: string;
2399
2407
  inserted: number;
2400
2408
  pendingKeys: string[];
2409
+ force?: boolean;
2401
2410
  timings?: RuntimeSheetTiming[];
2402
2411
  },
2403
2412
  ): Promise<PrepareRuntimeSheetResult> {
2413
+ const datasetFields = input.sheetContract.columns.flatMap((column) =>
2414
+ column.source === 'datasetColumn' && typeof column.field === 'string'
2415
+ ? [column.field]
2416
+ : [],
2417
+ );
2418
+ const buildFreshPendingRows = () => {
2419
+ return input.rowEntries.map((entry) => {
2420
+ const row: Record<string, unknown> = {
2421
+ ...sanitizePostgresJsonValue(entry.row),
2422
+ __deeplineRowKey: entry.key,
2423
+ };
2424
+ for (const field of datasetFields) {
2425
+ if (!Object.prototype.hasOwnProperty.call(row, field)) {
2426
+ row[field] = null;
2427
+ }
2428
+ }
2429
+ return row;
2430
+ });
2431
+ };
2432
+
2404
2433
  if (input.inserted === input.rowEntries.length) {
2405
- const datasetFields = input.sheetContract.columns.flatMap((column) =>
2406
- column.source === 'datasetColumn' && typeof column.field === 'string'
2407
- ? [column.field]
2408
- : [],
2409
- );
2410
2434
  return {
2411
2435
  inserted: input.inserted,
2412
2436
  skipped: input.sourceRowsLength - input.rowEntries.length,
2413
- pendingRows: input.rowEntries.map((entry) => {
2414
- const row: Record<string, unknown> = {
2415
- ...sanitizePostgresJsonValue(entry.row),
2416
- __deeplineRowKey: entry.key,
2417
- };
2418
- for (const field of datasetFields) {
2419
- if (!Object.prototype.hasOwnProperty.call(row, field)) {
2420
- row[field] = null;
2421
- }
2422
- }
2423
- return row;
2424
- }),
2437
+ pendingRows: buildFreshPendingRows(),
2425
2438
  completedRows: [],
2426
2439
  tableNamespace: input.tableNamespace,
2427
2440
  };
@@ -2434,7 +2447,24 @@ async function buildRuntimeSheetDatasetStartResult(
2434
2447
  runId: input.runId,
2435
2448
  normalizedPlayName: input.normalizedPlayName,
2436
2449
  normalizedTableNamespace: input.normalizedTableNamespace,
2450
+ outputFields: input.force === true ? datasetFields : [],
2437
2451
  });
2452
+ if (pendingKeys.size > 0) {
2453
+ input.timings?.push({
2454
+ phase: 'mark_rows_pending_for_recompute',
2455
+ ms: Date.now() - startedAt,
2456
+ rows: pendingKeys.size,
2457
+ });
2458
+ }
2459
+ if (input.force === true) {
2460
+ return {
2461
+ inserted: input.inserted,
2462
+ skipped: input.sourceRowsLength - input.rowEntries.length,
2463
+ pendingRows: buildFreshPendingRows(),
2464
+ completedRows: [],
2465
+ tableNamespace: input.tableNamespace,
2466
+ };
2467
+ }
2438
2468
  const persistedRows = await readRuntimeRowsByKey(
2439
2469
  client,
2440
2470
  session,
@@ -2444,13 +2474,6 @@ async function buildRuntimeSheetDatasetStartResult(
2444
2474
  const persistedRowsByKey = new Map(
2445
2475
  persistedRows.map((row) => [row.key, row.data]),
2446
2476
  );
2447
- if (pendingKeys.size > 0) {
2448
- input.timings?.push({
2449
- phase: 'mark_rows_pending_for_recompute',
2450
- ms: Date.now() - startedAt,
2451
- rows: pendingKeys.size,
2452
- });
2453
- }
2454
2477
  const buildMergedRow = (entry: RuntimeDatasetRowEntry) => {
2455
2478
  const merged = { ...entry.row };
2456
2479
  for (const [field, value] of Object.entries(
@@ -2489,12 +2512,14 @@ async function markRuntimeRowsPendingForRecompute(
2489
2512
  runId: string;
2490
2513
  normalizedPlayName: string;
2491
2514
  normalizedTableNamespace: string;
2515
+ outputFields?: string[];
2492
2516
  },
2493
2517
  ): Promise<void> {
2494
2518
  if (input.keys.length === 0) return;
2519
+ const outputFields = [...new Set(input.outputFields ?? [])];
2495
2520
  await client.query(
2496
2521
  `WITH target_rows AS (
2497
- SELECT _key, _status
2522
+ SELECT _key, _status, _cell_meta
2498
2523
  FROM ${sheetTable(session)}
2499
2524
  WHERE _key = ANY($1::text[])
2500
2525
  FOR UPDATE
@@ -2511,7 +2536,8 @@ async function markRuntimeRowsPendingForRecompute(
2511
2536
  target._status <> 'pending'
2512
2537
  OR target._run_id IS DISTINCT FROM $2::text
2513
2538
  )
2514
- RETURNING target_rows._status AS previous_status
2539
+ RETURNING target_rows._status AS previous_status,
2540
+ target_rows._cell_meta AS previous_cell_meta
2515
2541
  ),
2516
2542
  summary_counts AS (
2517
2543
  SELECT
@@ -2520,6 +2546,18 @@ async function markRuntimeRowsPendingForRecompute(
2520
2546
  count(*) FILTER (WHERE previous_status = 'running')::int AS running_to_pending
2521
2547
  FROM updated
2522
2548
  ),
2549
+ column_delta_counts AS (
2550
+ SELECT field_values.field,
2551
+ count(*) FILTER (
2552
+ WHERE previous_cell_meta -> field_values.field ->> 'status' = 'completed'
2553
+ )::int AS completed_to_pending,
2554
+ count(*) FILTER (
2555
+ WHERE previous_cell_meta -> field_values.field ->> 'status' = 'failed'
2556
+ )::int AS failed_to_pending
2557
+ FROM updated
2558
+ JOIN unnest($5::text[]) AS field_values(field) ON true
2559
+ GROUP BY field_values.field
2560
+ ),
2523
2561
  summary_delta AS (
2524
2562
  INSERT INTO ${summaryTable(session)} AS target (play_name, table_namespace, total, queued, running, completed, failed)
2525
2563
  SELECT
@@ -2547,6 +2585,27 @@ async function markRuntimeRowsPendingForRecompute(
2547
2585
  })},
2548
2586
  _updated_at = now()
2549
2587
  RETURNING 1
2588
+ ),
2589
+ column_summary_delta AS (
2590
+ INSERT INTO ${columnSummaryTable(session)} AS target (
2591
+ play_name,
2592
+ table_namespace,
2593
+ field,
2594
+ completed,
2595
+ failed
2596
+ )
2597
+ SELECT $3::text,
2598
+ $4::text,
2599
+ field,
2600
+ -completed_to_pending,
2601
+ -failed_to_pending
2602
+ FROM column_delta_counts
2603
+ WHERE completed_to_pending > 0 OR failed_to_pending > 0
2604
+ ON CONFLICT (play_name, table_namespace, field) DO UPDATE SET
2605
+ completed = GREATEST(target.completed + EXCLUDED.completed, 0),
2606
+ failed = GREATEST(target.failed + EXCLUDED.failed, 0),
2607
+ _updated_at = now()
2608
+ RETURNING 1
2550
2609
  )
2551
2610
  SELECT 1`,
2552
2611
  [
@@ -2554,6 +2613,7 @@ async function markRuntimeRowsPendingForRecompute(
2554
2613
  input.runId,
2555
2614
  input.normalizedPlayName,
2556
2615
  input.normalizedTableNamespace,
2616
+ outputFields,
2557
2617
  ],
2558
2618
  );
2559
2619
  }
@@ -3237,6 +3297,7 @@ export async function startRuntimeSheetDataset(
3237
3297
  rows: Record<string, unknown>[];
3238
3298
  runId: string;
3239
3299
  inputOffset?: number;
3300
+ force?: boolean;
3240
3301
  },
3241
3302
  ): Promise<PrepareRuntimeSheetResult> {
3242
3303
  const totalStartedAt = Date.now();
@@ -3334,6 +3395,24 @@ export async function startRuntimeSheetDataset(
3334
3395
  .map((column) => `payload -> ${quoteLiteral(column)}`)
3335
3396
  .join(', ')}`
3336
3397
  : '';
3398
+ const physicalRefreshSetSql =
3399
+ physicalColumns.length > 0
3400
+ ? `, ${physicalColumns
3401
+ .map(
3402
+ (column) =>
3403
+ `${quoteIdentifier(column)} = input_rows.payload -> ${quoteLiteral(column)}`,
3404
+ )
3405
+ .join(', ')}`
3406
+ : '';
3407
+ const physicalUpsertSetSql =
3408
+ physicalColumns.length > 0
3409
+ ? `, ${physicalColumns
3410
+ .map(
3411
+ (column) =>
3412
+ `${quoteIdentifier(column)} = EXCLUDED.${quoteIdentifier(column)}`,
3413
+ )
3414
+ .join(', ')}`
3415
+ : '';
3337
3416
  const outputPhysicalColumns = outputPhysicalSheetColumnProjections(
3338
3417
  input.sheetContract,
3339
3418
  );
@@ -3364,15 +3443,26 @@ export async function startRuntimeSheetDataset(
3364
3443
  normalizedTableNamespace,
3365
3444
  physicalInsertColumnsSql,
3366
3445
  physicalInsertValuesSql,
3446
+ physicalRefreshSetSql:
3447
+ input.force === true ? physicalRefreshSetSql : '',
3448
+ physicalUpsertSetSql,
3367
3449
  outputPhysicalColumns,
3450
+ force: input.force === true,
3368
3451
  });
3452
+ const effectivePrepared = input.force
3453
+ ? {
3454
+ inserted: prepared.inserted,
3455
+ pendingKeys: rowEntries.map((entry) => entry.key),
3456
+ }
3457
+ : prepared;
3369
3458
  timings.push({
3370
3459
  phase: 'prepare_rows_sql',
3371
3460
  ms: Date.now() - prepareStartedAt,
3372
3461
  rows: rowEntries.length,
3373
3462
  chunks: chunks.length,
3374
- inserted: prepared.inserted,
3375
- pending: prepared.pendingKeys.length,
3463
+ inserted: effectivePrepared.inserted,
3464
+ pending: effectivePrepared.pendingKeys.length,
3465
+ ...(input.force ? { force: true } : {}),
3376
3466
  });
3377
3467
  const buildStartedAt = Date.now();
3378
3468
  const built = await buildRuntimeSheetDatasetStartResult(client, session, {
@@ -3384,7 +3474,8 @@ export async function startRuntimeSheetDataset(
3384
3474
  normalizedTableNamespace,
3385
3475
  runId: input.runId,
3386
3476
  timings,
3387
- ...prepared,
3477
+ force: input.force === true,
3478
+ ...effectivePrepared,
3388
3479
  });
3389
3480
  timings.push({
3390
3481
  phase: 'build_result',
@@ -83,6 +83,8 @@ export type PlaySchedulerSubmitInput = {
83
83
  artifactHash: string;
84
84
  graphHash: string;
85
85
  input: Record<string, unknown>;
86
+ /** Run-level --force cache bypass for dataset rows and ctx.tools.execute receipts. */
87
+ forceToolRefresh?: boolean | null;
86
88
  inputFile?: {
87
89
  name?: string;
88
90
  path?: string;
package/dist/cli/index.js CHANGED
@@ -622,10 +622,10 @@ var SDK_RELEASE = {
622
622
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
623
623
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
624
624
  // fields shipped in 0.1.153.
625
- version: "0.1.174",
625
+ version: "0.1.175",
626
626
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
627
627
  supportPolicy: {
628
- latest: "0.1.174",
628
+ latest: "0.1.175",
629
629
  minimumSupported: "0.1.53",
630
630
  deprecatedBelow: "0.1.53",
631
631
  commandMinimumSupported: [
@@ -2686,6 +2686,7 @@ var DeeplineClient = class {
2686
2686
  */
2687
2687
  async startPlayRun(request) {
2688
2688
  const integrationMode = resolvePlayRunIntegrationMode(request);
2689
+ const forceToolRefresh = request.forceToolRefresh === true;
2689
2690
  const response = await this.http.post(
2690
2691
  "/api/v2/plays/run",
2691
2692
  {
@@ -2706,6 +2707,7 @@ var DeeplineClient = class {
2706
2707
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2707
2708
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2708
2709
  ...request.force ? { force: true } : {},
2710
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2709
2711
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2710
2712
  // Profile selection is the API's job, not the CLI's. The server
2711
2713
  // defaults to workers_edge; tests and runtime probes that want a
@@ -2729,6 +2731,7 @@ var DeeplineClient = class {
2729
2731
  */
2730
2732
  async *startPlayRunStream(request, options) {
2731
2733
  const integrationMode = resolvePlayRunIntegrationMode(request);
2734
+ const forceToolRefresh = request.forceToolRefresh === true;
2732
2735
  const body = {
2733
2736
  ...request.name ? { name: request.name } : {},
2734
2737
  ...request.revisionId ? { revisionId: request.revisionId } : {},
@@ -2747,6 +2750,7 @@ var DeeplineClient = class {
2747
2750
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2748
2751
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2749
2752
  ...request.force ? { force: true } : {},
2753
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2750
2754
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2751
2755
  ...request.profile ? { profile: request.profile } : {},
2752
2756
  ...integrationMode ? { integrationMode } : {}
@@ -2918,7 +2922,8 @@ var DeeplineClient = class {
2918
2922
  ...input2.input ? { input: input2.input } : {},
2919
2923
  ...input2.inputFile ? { inputFile: input2.inputFile } : {},
2920
2924
  ...input2.packagedFiles?.length ? { packagedFiles: input2.packagedFiles } : {},
2921
- ...input2.force ? { force: true } : {}
2925
+ ...input2.force ? { force: true } : {},
2926
+ ...input2.forceToolRefresh ? { forceToolRefresh: true } : {}
2922
2927
  });
2923
2928
  }
2924
2929
  /**
@@ -2991,7 +2996,8 @@ var DeeplineClient = class {
2991
2996
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
2992
2997
  ...options?.inputFile ? { inputFile: options.inputFile } : {},
2993
2998
  ...options?.packagedFiles?.length ? { packagedFiles: options.packagedFiles } : {},
2994
- ...options?.force ? { force: true } : {}
2999
+ ...options?.force ? { force: true } : {},
3000
+ ...options?.forceToolRefresh ? { forceToolRefresh: true } : {}
2995
3001
  });
2996
3002
  }
2997
3003
  /**
@@ -3873,7 +3879,8 @@ var DeeplineClient = class {
3873
3879
  compilerManifest: options?.compilerManifest,
3874
3880
  inputFile: options?.inputFile,
3875
3881
  packagedFiles: options?.packagedFiles,
3876
- force: options?.force
3882
+ force: options?.force,
3883
+ forceToolRefresh: options?.forceToolRefresh
3877
3884
  });
3878
3885
  const start = Date.now();
3879
3886
  const state = {
@@ -13357,7 +13364,7 @@ async function handleFileBackedRun(options) {
13357
13364
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
13358
13365
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
13359
13366
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
13360
- ...options.force ? { force: true } : {},
13367
+ ...options.force ? { force: true, forceToolRefresh: true } : {},
13361
13368
  ...options.profile ? { profile: options.profile } : {},
13362
13369
  ...integrationMode ? { integrationMode } : {}
13363
13370
  };
@@ -13516,7 +13523,7 @@ async function handleNamedRun(options) {
13516
13523
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
13517
13524
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
13518
13525
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
13519
- ...options.force ? { force: true } : {},
13526
+ ...options.force ? { force: true, forceToolRefresh: true } : {},
13520
13527
  ...options.profile ? { profile: options.profile } : {},
13521
13528
  ...integrationMode ? { integrationMode } : {}
13522
13529
  };
@@ -14702,9 +14709,9 @@ Notes:
14702
14709
  a fire-and-forget run id.
14703
14710
  The play page opens in your browser as soon as the run starts; use --no-open
14704
14711
  to only print the URL.
14705
- Concurrent runs for the same play are allowed. --force is accepted for
14706
- compatibility, but it does not cancel active sibling runs or bypass completed
14707
- reuse.
14712
+ Concurrent runs for the same play are allowed.
14713
+ --force bypasses durable dataset/tool cache reuse for this run.
14714
+ It does not cancel active sibling runs.
14708
14715
  This command starts cloud work and may spend Deepline credits through tool calls.
14709
14716
 
14710
14717
  Idempotent execution:
@@ -14755,7 +14762,7 @@ Examples:
14755
14762
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
14756
14763
  "--logs",
14757
14764
  "When output is non-interactive, stream play logs to stderr while waiting"
14758
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Compatibility flag; active sibling runs are allowed").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
14765
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Bypass durable dataset/tool cache reuse").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
14759
14766
  "afterAll",
14760
14767
  `
14761
14768
  Pass-through input flags:
@@ -607,10 +607,10 @@ var SDK_RELEASE = {
607
607
  // 0.1.111 ships dataset-native tool list getters and result row datasets.
608
608
  // 0.1.154 removes the short-lived generated enrich StepOptions recompute
609
609
  // fields shipped in 0.1.153.
610
- version: "0.1.174",
610
+ version: "0.1.175",
611
611
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
612
612
  supportPolicy: {
613
- latest: "0.1.174",
613
+ latest: "0.1.175",
614
614
  minimumSupported: "0.1.53",
615
615
  deprecatedBelow: "0.1.53",
616
616
  commandMinimumSupported: [
@@ -2671,6 +2671,7 @@ var DeeplineClient = class {
2671
2671
  */
2672
2672
  async startPlayRun(request) {
2673
2673
  const integrationMode = resolvePlayRunIntegrationMode(request);
2674
+ const forceToolRefresh = request.forceToolRefresh === true;
2674
2675
  const response = await this.http.post(
2675
2676
  "/api/v2/plays/run",
2676
2677
  {
@@ -2691,6 +2692,7 @@ var DeeplineClient = class {
2691
2692
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2692
2693
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2693
2694
  ...request.force ? { force: true } : {},
2695
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2694
2696
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2695
2697
  // Profile selection is the API's job, not the CLI's. The server
2696
2698
  // defaults to workers_edge; tests and runtime probes that want a
@@ -2714,6 +2716,7 @@ var DeeplineClient = class {
2714
2716
  */
2715
2717
  async *startPlayRunStream(request, options) {
2716
2718
  const integrationMode = resolvePlayRunIntegrationMode(request);
2719
+ const forceToolRefresh = request.forceToolRefresh === true;
2717
2720
  const body = {
2718
2721
  ...request.name ? { name: request.name } : {},
2719
2722
  ...request.revisionId ? { revisionId: request.revisionId } : {},
@@ -2732,6 +2735,7 @@ var DeeplineClient = class {
2732
2735
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2733
2736
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2734
2737
  ...request.force ? { force: true } : {},
2738
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2735
2739
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2736
2740
  ...request.profile ? { profile: request.profile } : {},
2737
2741
  ...integrationMode ? { integrationMode } : {}
@@ -2903,7 +2907,8 @@ var DeeplineClient = class {
2903
2907
  ...input2.input ? { input: input2.input } : {},
2904
2908
  ...input2.inputFile ? { inputFile: input2.inputFile } : {},
2905
2909
  ...input2.packagedFiles?.length ? { packagedFiles: input2.packagedFiles } : {},
2906
- ...input2.force ? { force: true } : {}
2910
+ ...input2.force ? { force: true } : {},
2911
+ ...input2.forceToolRefresh ? { forceToolRefresh: true } : {}
2907
2912
  });
2908
2913
  }
2909
2914
  /**
@@ -2976,7 +2981,8 @@ var DeeplineClient = class {
2976
2981
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
2977
2982
  ...options?.inputFile ? { inputFile: options.inputFile } : {},
2978
2983
  ...options?.packagedFiles?.length ? { packagedFiles: options.packagedFiles } : {},
2979
- ...options?.force ? { force: true } : {}
2984
+ ...options?.force ? { force: true } : {},
2985
+ ...options?.forceToolRefresh ? { forceToolRefresh: true } : {}
2980
2986
  });
2981
2987
  }
2982
2988
  /**
@@ -3858,7 +3864,8 @@ var DeeplineClient = class {
3858
3864
  compilerManifest: options?.compilerManifest,
3859
3865
  inputFile: options?.inputFile,
3860
3866
  packagedFiles: options?.packagedFiles,
3861
- force: options?.force
3867
+ force: options?.force,
3868
+ forceToolRefresh: options?.forceToolRefresh
3862
3869
  });
3863
3870
  const start = Date.now();
3864
3871
  const state = {
@@ -13384,7 +13391,7 @@ async function handleFileBackedRun(options) {
13384
13391
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
13385
13392
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
13386
13393
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
13387
- ...options.force ? { force: true } : {},
13394
+ ...options.force ? { force: true, forceToolRefresh: true } : {},
13388
13395
  ...options.profile ? { profile: options.profile } : {},
13389
13396
  ...integrationMode ? { integrationMode } : {}
13390
13397
  };
@@ -13543,7 +13550,7 @@ async function handleNamedRun(options) {
13543
13550
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
13544
13551
  ...stagedFileInputs.inputFile ? { inputFile: stagedFileInputs.inputFile } : {},
13545
13552
  ...stagedFileInputs.packagedFiles.length ? { packagedFiles: stagedFileInputs.packagedFiles } : {},
13546
- ...options.force ? { force: true } : {},
13553
+ ...options.force ? { force: true, forceToolRefresh: true } : {},
13547
13554
  ...options.profile ? { profile: options.profile } : {},
13548
13555
  ...integrationMode ? { integrationMode } : {}
13549
13556
  };
@@ -14729,9 +14736,9 @@ Notes:
14729
14736
  a fire-and-forget run id.
14730
14737
  The play page opens in your browser as soon as the run starts; use --no-open
14731
14738
  to only print the URL.
14732
- Concurrent runs for the same play are allowed. --force is accepted for
14733
- compatibility, but it does not cancel active sibling runs or bypass completed
14734
- reuse.
14739
+ Concurrent runs for the same play are allowed.
14740
+ --force bypasses durable dataset/tool cache reuse for this run.
14741
+ It does not cancel active sibling runs.
14735
14742
  This command starts cloud work and may spend Deepline credits through tool calls.
14736
14743
 
14737
14744
  Idempotent execution:
@@ -14782,7 +14789,7 @@ Examples:
14782
14789
  ).option("--watch", "Compatibility alias; run waits by default").option("--wait", "Compatibility alias; run waits by default").option("--no-wait", "Start the run and return immediately").option(
14783
14790
  "--logs",
14784
14791
  "When output is non-interactive, stream play logs to stderr while waiting"
14785
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Compatibility flag; active sibling runs are allowed").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
14792
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Bypass durable dataset/tool cache reuse").option("--no-open", "Print the play page URL without opening a browser").option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
14786
14793
  "afterAll",
14787
14794
  `
14788
14795
  Pass-through input flags:
package/dist/index.d.mts CHANGED
@@ -940,6 +940,8 @@ interface StartPlayRunRequest {
940
940
  packagedFiles?: unknown[];
941
941
  /** Compatibility flag; active sibling runs are allowed. */
942
942
  force?: boolean;
943
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
944
+ forceToolRefresh?: boolean;
943
945
  /** Optionally let the start request wait briefly and return a terminal result. */
944
946
  waitForCompletionMs?: number;
945
947
  /**
@@ -1690,6 +1692,7 @@ declare class DeeplineClient {
1690
1692
  inputFile?: PlayStagedFileRef | null;
1691
1693
  packagedFiles?: PlayStagedFileRef[];
1692
1694
  force?: boolean;
1695
+ forceToolRefresh?: boolean;
1693
1696
  }): Promise<PlayRunStart>;
1694
1697
  /**
1695
1698
  * Register a bundled play artifact and start a run from the live revision.
@@ -1725,6 +1728,7 @@ declare class DeeplineClient {
1725
1728
  inputFile?: PlayStagedFileRef | null;
1726
1729
  packagedFiles?: PlayStagedFileRef[];
1727
1730
  force?: boolean;
1731
+ forceToolRefresh?: boolean;
1728
1732
  }): Promise<PlayRunStart>;
1729
1733
  /**
1730
1734
  * Upload files to the staging area for use in play runs.
@@ -2176,6 +2180,8 @@ declare class DeeplineClient {
2176
2180
  packagedFiles?: PlayStagedFileRef[];
2177
2181
  /** Compatibility flag; active sibling runs are allowed. */
2178
2182
  force?: boolean;
2183
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
2184
+ forceToolRefresh?: boolean;
2179
2185
  }): Promise<PlayRunResult>;
2180
2186
  /**
2181
2187
  * Published plans plus the caller's active plan: prices, monthly grant
package/dist/index.d.ts CHANGED
@@ -940,6 +940,8 @@ interface StartPlayRunRequest {
940
940
  packagedFiles?: unknown[];
941
941
  /** Compatibility flag; active sibling runs are allowed. */
942
942
  force?: boolean;
943
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
944
+ forceToolRefresh?: boolean;
943
945
  /** Optionally let the start request wait briefly and return a terminal result. */
944
946
  waitForCompletionMs?: number;
945
947
  /**
@@ -1690,6 +1692,7 @@ declare class DeeplineClient {
1690
1692
  inputFile?: PlayStagedFileRef | null;
1691
1693
  packagedFiles?: PlayStagedFileRef[];
1692
1694
  force?: boolean;
1695
+ forceToolRefresh?: boolean;
1693
1696
  }): Promise<PlayRunStart>;
1694
1697
  /**
1695
1698
  * Register a bundled play artifact and start a run from the live revision.
@@ -1725,6 +1728,7 @@ declare class DeeplineClient {
1725
1728
  inputFile?: PlayStagedFileRef | null;
1726
1729
  packagedFiles?: PlayStagedFileRef[];
1727
1730
  force?: boolean;
1731
+ forceToolRefresh?: boolean;
1728
1732
  }): Promise<PlayRunStart>;
1729
1733
  /**
1730
1734
  * Upload files to the staging area for use in play runs.
@@ -2176,6 +2180,8 @@ declare class DeeplineClient {
2176
2180
  packagedFiles?: PlayStagedFileRef[];
2177
2181
  /** Compatibility flag; active sibling runs are allowed. */
2178
2182
  force?: boolean;
2183
+ /** Explicit cache-bypass flag for durable dataset and tool-call reuse. */
2184
+ forceToolRefresh?: boolean;
2179
2185
  }): Promise<PlayRunResult>;
2180
2186
  /**
2181
2187
  * Published plans plus the caller's active plan: prices, monthly grant
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.174",
424
+ version: "0.1.175",
425
425
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
426
426
  supportPolicy: {
427
- latest: "0.1.174",
427
+ latest: "0.1.175",
428
428
  minimumSupported: "0.1.53",
429
429
  deprecatedBelow: "0.1.53",
430
430
  commandMinimumSupported: [
@@ -2485,6 +2485,7 @@ var DeeplineClient = class {
2485
2485
  */
2486
2486
  async startPlayRun(request) {
2487
2487
  const integrationMode = resolvePlayRunIntegrationMode(request);
2488
+ const forceToolRefresh = request.forceToolRefresh === true;
2488
2489
  const response = await this.http.post(
2489
2490
  "/api/v2/plays/run",
2490
2491
  {
@@ -2505,6 +2506,7 @@ var DeeplineClient = class {
2505
2506
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2506
2507
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2507
2508
  ...request.force ? { force: true } : {},
2509
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2508
2510
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2509
2511
  // Profile selection is the API's job, not the CLI's. The server
2510
2512
  // defaults to workers_edge; tests and runtime probes that want a
@@ -2528,6 +2530,7 @@ var DeeplineClient = class {
2528
2530
  */
2529
2531
  async *startPlayRunStream(request, options) {
2530
2532
  const integrationMode = resolvePlayRunIntegrationMode(request);
2533
+ const forceToolRefresh = request.forceToolRefresh === true;
2531
2534
  const body = {
2532
2535
  ...request.name ? { name: request.name } : {},
2533
2536
  ...request.revisionId ? { revisionId: request.revisionId } : {},
@@ -2546,6 +2549,7 @@ var DeeplineClient = class {
2546
2549
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2547
2550
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2548
2551
  ...request.force ? { force: true } : {},
2552
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2549
2553
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2550
2554
  ...request.profile ? { profile: request.profile } : {},
2551
2555
  ...integrationMode ? { integrationMode } : {}
@@ -2717,7 +2721,8 @@ var DeeplineClient = class {
2717
2721
  ...input.input ? { input: input.input } : {},
2718
2722
  ...input.inputFile ? { inputFile: input.inputFile } : {},
2719
2723
  ...input.packagedFiles?.length ? { packagedFiles: input.packagedFiles } : {},
2720
- ...input.force ? { force: true } : {}
2724
+ ...input.force ? { force: true } : {},
2725
+ ...input.forceToolRefresh ? { forceToolRefresh: true } : {}
2721
2726
  });
2722
2727
  }
2723
2728
  /**
@@ -2790,7 +2795,8 @@ var DeeplineClient = class {
2790
2795
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
2791
2796
  ...options?.inputFile ? { inputFile: options.inputFile } : {},
2792
2797
  ...options?.packagedFiles?.length ? { packagedFiles: options.packagedFiles } : {},
2793
- ...options?.force ? { force: true } : {}
2798
+ ...options?.force ? { force: true } : {},
2799
+ ...options?.forceToolRefresh ? { forceToolRefresh: true } : {}
2794
2800
  });
2795
2801
  }
2796
2802
  /**
@@ -3672,7 +3678,8 @@ var DeeplineClient = class {
3672
3678
  compilerManifest: options?.compilerManifest,
3673
3679
  inputFile: options?.inputFile,
3674
3680
  packagedFiles: options?.packagedFiles,
3675
- force: options?.force
3681
+ force: options?.force,
3682
+ forceToolRefresh: options?.forceToolRefresh
3676
3683
  });
3677
3684
  const start = Date.now();
3678
3685
  const state = {
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.174",
354
+ version: "0.1.175",
355
355
  apiContract: "2026-06-dataset-handle-results-hard-cutover",
356
356
  supportPolicy: {
357
- latest: "0.1.174",
357
+ latest: "0.1.175",
358
358
  minimumSupported: "0.1.53",
359
359
  deprecatedBelow: "0.1.53",
360
360
  commandMinimumSupported: [
@@ -2415,6 +2415,7 @@ var DeeplineClient = class {
2415
2415
  */
2416
2416
  async startPlayRun(request) {
2417
2417
  const integrationMode = resolvePlayRunIntegrationMode(request);
2418
+ const forceToolRefresh = request.forceToolRefresh === true;
2418
2419
  const response = await this.http.post(
2419
2420
  "/api/v2/plays/run",
2420
2421
  {
@@ -2435,6 +2436,7 @@ var DeeplineClient = class {
2435
2436
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2436
2437
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2437
2438
  ...request.force ? { force: true } : {},
2439
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2438
2440
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2439
2441
  // Profile selection is the API's job, not the CLI's. The server
2440
2442
  // defaults to workers_edge; tests and runtime probes that want a
@@ -2458,6 +2460,7 @@ var DeeplineClient = class {
2458
2460
  */
2459
2461
  async *startPlayRunStream(request, options) {
2460
2462
  const integrationMode = resolvePlayRunIntegrationMode(request);
2463
+ const forceToolRefresh = request.forceToolRefresh === true;
2461
2464
  const body = {
2462
2465
  ...request.name ? { name: request.name } : {},
2463
2466
  ...request.revisionId ? { revisionId: request.revisionId } : {},
@@ -2476,6 +2479,7 @@ var DeeplineClient = class {
2476
2479
  ...request.inputFile ? { inputFile: request.inputFile } : {},
2477
2480
  ...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
2478
2481
  ...request.force ? { force: true } : {},
2482
+ ...forceToolRefresh ? { forceToolRefresh: true } : {},
2479
2483
  ...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
2480
2484
  ...request.profile ? { profile: request.profile } : {},
2481
2485
  ...integrationMode ? { integrationMode } : {}
@@ -2647,7 +2651,8 @@ var DeeplineClient = class {
2647
2651
  ...input.input ? { input: input.input } : {},
2648
2652
  ...input.inputFile ? { inputFile: input.inputFile } : {},
2649
2653
  ...input.packagedFiles?.length ? { packagedFiles: input.packagedFiles } : {},
2650
- ...input.force ? { force: true } : {}
2654
+ ...input.force ? { force: true } : {},
2655
+ ...input.forceToolRefresh ? { forceToolRefresh: true } : {}
2651
2656
  });
2652
2657
  }
2653
2658
  /**
@@ -2720,7 +2725,8 @@ var DeeplineClient = class {
2720
2725
  ...Object.keys(runtimeInput).length > 0 ? { input: runtimeInput } : {},
2721
2726
  ...options?.inputFile ? { inputFile: options.inputFile } : {},
2722
2727
  ...options?.packagedFiles?.length ? { packagedFiles: options.packagedFiles } : {},
2723
- ...options?.force ? { force: true } : {}
2728
+ ...options?.force ? { force: true } : {},
2729
+ ...options?.forceToolRefresh ? { forceToolRefresh: true } : {}
2724
2730
  });
2725
2731
  }
2726
2732
  /**
@@ -3602,7 +3608,8 @@ var DeeplineClient = class {
3602
3608
  compilerManifest: options?.compilerManifest,
3603
3609
  inputFile: options?.inputFile,
3604
3610
  packagedFiles: options?.packagedFiles,
3605
- force: options?.force
3611
+ force: options?.force,
3612
+ forceToolRefresh: options?.forceToolRefresh
3606
3613
  });
3607
3614
  const start = Date.now();
3608
3615
  const state = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.174",
3
+ "version": "0.1.175",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {