deepline 0.3.279 → 0.3.281

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.
Files changed (35) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +7 -2
  2. package/dist/bundling-sources/sdk/src/csv-header-matching.ts +7 -0
  3. package/dist/bundling-sources/sdk/src/http.ts +16 -8
  4. package/dist/bundling-sources/sdk/src/index.ts +1 -1
  5. package/dist/bundling-sources/sdk/src/play.ts +1 -1
  6. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  7. package/dist/bundling-sources/sdk/src/tool-calls.ts +2 -1
  8. package/dist/bundling-sources/sdk/src/types.ts +2 -0
  9. package/dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-storage-contract.ts +27 -0
  10. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +24 -5
  11. package/dist/bundling-sources/shared_libs/play-runtime/cell-provenance.ts +3 -1
  12. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +14 -1
  13. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +32 -9
  14. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +1 -0
  15. package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +6 -5
  16. package/dist/cli/index.js +426 -53
  17. package/dist/cli/index.mjs +426 -53
  18. package/dist/{client-C0EhEIQO.d.mts → client-B0AjIkgb.d.mts} +6 -3
  19. package/dist/{client-HxPrGPbv.d.ts → client-BCXQ_Ftc.d.ts} +6 -3
  20. package/dist/{compiler-manifest-C1bKB9bY.d.mts → compiler-manifest-B1zo3igW.d.mts} +6 -5
  21. package/dist/{compiler-manifest-C1bKB9bY.d.ts → compiler-manifest-B1zo3igW.d.ts} +6 -5
  22. package/dist/index.d.mts +5 -5
  23. package/dist/index.d.ts +5 -5
  24. package/dist/index.js +198 -12
  25. package/dist/index.mjs +198 -12
  26. package/dist/install-integrity.json +5 -4
  27. package/dist/plays/bundle-play-file.d.mts +2 -2
  28. package/dist/plays/bundle-play-file.d.ts +2 -2
  29. package/dist/plays/run-request.d.mts +2 -2
  30. package/dist/plays/run-request.d.ts +2 -2
  31. package/dist/release.d.mts +1 -1
  32. package/dist/release.d.ts +1 -1
  33. package/dist/release.js +1 -1
  34. package/dist/release.mjs +1 -1
  35. package/package.json +1 -1
@@ -11,6 +11,7 @@ import type {
11
11
  // Value import from the dependency-free module: the client is bundled into
12
12
  // authored Plays, where `zod` (the contract's schemas) cannot resolve.
13
13
  import { playTriggerConfigPath } from '../../shared_libs/plays/trigger-config-route';
14
+ import { CSV_HEADER_MATCHING_NOTE } from './csv-header-matching.js';
14
15
  import { iterateCursorPages } from './pagination.js';
15
16
  import { playInputExampleArgs } from './plays/input-example.js';
16
17
  /**
@@ -3033,7 +3034,11 @@ export class DeeplineClient {
3033
3034
  : isRecord(play.liveRevision?.staticPipeline)
3034
3035
  ? play.liveRevision.staticPipeline
3035
3036
  : null,
3036
- ...(csvInput ? { csvInput } : {}),
3037
+ ...(csvInput
3038
+ ? {
3039
+ csvInput: { ...csvInput, headerMatching: CSV_HEADER_MATCHING_NOTE },
3040
+ }
3041
+ : {}),
3037
3042
  ...(rowOutputSchema ? { rowOutputSchema } : {}),
3038
3043
  runCommand,
3039
3044
  examples: [runCommand],
@@ -3292,7 +3297,7 @@ export class DeeplineClient {
3292
3297
  /**
3293
3298
  * Execute a tool and return the standard execution envelope.
3294
3299
  *
3295
- * The `toolResponse.raw` field contains the raw tool response.
3300
+ * The `toolResponse.rawV2` field contains the complete parsed and scrubbed tool response.
3296
3301
  * `toolResponse.meta` contains tool/provider metadata.
3297
3302
  * Top-level fields such as `status`, `job_id`, and `billing` describe the
3298
3303
  * Deepline execution envelope.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * How a CSV header is matched to a play column (`normalizeCsvHeader` in the
3
+ * runtime). Returned with every play description that takes a CSV, because
4
+ * agents otherwise read the SDK source to find out whether LINKEDIN_URL matches.
5
+ */
6
+ export const CSV_HEADER_MATCHING_NOTE =
7
+ 'A header matches a column when it equals the column name or its default header, ignoring case, spaces and punctuation: LINKEDIN_URL, linkedin-url and "Linkedin Url" all match linkedin_url. A capital inside a word starts a new word, so "LinkedIn URL" reads as linked_in_url and does not match. Map any other header in the input: {"csv":"<path>","columns":{"<column>":"<your header>"}}.';
@@ -123,7 +123,7 @@ function normalizeRequestAbortError(
123
123
  * from the environment, so an explicitly passed header always wins.
124
124
  *
125
125
  * HTTP header names are case-insensitive, so an existing header is removed by
126
- * case-insensitive match before the normalized lowercase name is set. Without
126
+ * case-insensitive match before the incoming name is set. Without
127
127
  * that, `Authorization` and `authorization` would both survive into the record
128
128
  * and `new Headers(record)` would concatenate the two values.
129
129
  */
@@ -138,7 +138,7 @@ function applyExplicitHeaders(
138
138
  for (const existing of Object.keys(headers)) {
139
139
  if (existing.toLowerCase() === name) delete headers[existing];
140
140
  }
141
- headers[name] = value;
141
+ headers[rawName.trim()] = value;
142
142
  }
143
143
  return headers;
144
144
  }
@@ -270,7 +270,7 @@ export class HttpClient {
270
270
  }
271
271
 
272
272
  private authHeaders(extra?: Record<string, string>): Record<string, string> {
273
- const headers: Record<string, string> = {
273
+ const transportHeaders: Record<string, string> = {
274
274
  Authorization: `Bearer ${this.config.apiKey}`,
275
275
  'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,
276
276
  'X-Deepline-Client-Family': 'sdk',
@@ -280,9 +280,8 @@ export class HttpClient {
280
280
  'X-Deepline-SDK-Version': SDK_VERSION,
281
281
  'X-Deepline-API-Contract': SDK_API_CONTRACT,
282
282
  'X-Deepline-Run-Result-Shape': 'canonical',
283
- ...extra,
284
- ...deploymentProtectionHeaders(),
285
283
  };
284
+ const headers = deploymentProtectionHeaders();
286
285
  const skillsVersion = this.readSkillsVersionHeader();
287
286
  if (skillsVersion) {
288
287
  headers['X-Deepline-Skills-Version'] = skillsVersion;
@@ -381,7 +380,16 @@ export class HttpClient {
381
380
  // applied last so an operator can override an env-derived header without
382
381
  // rewriting the environment. Authorization of these headers stays
383
382
  // server-side.
384
- return applyExplicitHeaders(headers, this.config.headers);
383
+ // Preserve layer precedence without leaving differently-cased duplicates
384
+ // for Fetch to concatenate. Environment-derived headers still supersede
385
+ // per-request headers, and explicit client-option headers remain last.
386
+ return applyExplicitHeaders(
387
+ applyExplicitHeaders(
388
+ applyExplicitHeaders(transportHeaders, extra),
389
+ headers,
390
+ ),
391
+ this.config.headers,
392
+ );
385
393
  }
386
394
 
387
395
  /**
@@ -415,7 +423,7 @@ export class HttpClient {
415
423
  const headers = this.authHeaders(options?.headers);
416
424
 
417
425
  if (options?.body !== undefined) {
418
- headers['Content-Type'] = 'application/json';
426
+ applyExplicitHeaders(headers, { 'Content-Type': 'application/json' });
419
427
  }
420
428
 
421
429
  let lastError: Error | null = null;
@@ -779,7 +787,7 @@ export class HttpClient {
779
787
  ...options?.headers,
780
788
  });
781
789
  if (options?.body !== undefined) {
782
- headers['Content-Type'] = 'application/json';
790
+ applyExplicitHeaders(headers, { 'Content-Type': 'application/json' });
783
791
  }
784
792
  let lastError: Error | null = null;
785
793
 
@@ -26,7 +26,7 @@ export type {
26
26
  *
27
27
  * // Execute a tool
28
28
  * const result = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
29
- * const company = result.toolResponse.raw;
29
+ * const providerResponse = result.toolResponse.rawV2;
30
30
  *
31
31
  * // Run a named play
32
32
  * const job = await deepline.play('email-waterfall').run({ domain: 'stripe.com' });
@@ -1096,7 +1096,7 @@ export class DeeplineContext {
1096
1096
  * const tools = await deepline.tools.list();
1097
1097
  * const meta = await deepline.tools.get('dropleads_search_people');
1098
1098
  * const companyLookup = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
1099
- * const company = companyLookup.toolResponse.raw;
1099
+ * const providerResponse = companyLookup.toolResponse.rawV2;
1100
1100
  * ```
1101
1101
  */
1102
1102
  get tools(): DeeplineToolsNamespace {
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
202
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
203
- version: '0.3.279',
203
+ version: '0.3.281',
204
204
  updateSummary:
205
205
  'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
206
206
  packageCapabilities: {
@@ -227,7 +227,7 @@ function resolveToolExecuteTimeoutMs(
227
227
  * Standard provider/tool execution envelope returned by low-level SDK calls.
228
228
  *
229
229
  * `toolResponse.rawV2` contains the complete scrubbed provider response;
230
- * `toolResponse.raw` is derived locally as the legacy provider-result projection. `extractedValues` and
230
+ * `extractedValues` and
231
231
  * `extractedLists` contain Deepline-normalized getters when the tool exposes
232
232
  * them. Billing fields are Deepline-facing and must not expose provider spend.
233
233
  */
@@ -236,6 +236,7 @@ export type ToolExecution<TData = unknown, TMeta = Record<string, unknown>> = {
236
236
  job_id?: string;
237
237
  meta?: Record<string, unknown>;
238
238
  toolResponse: {
239
+ /** @deprecated Use declared getters or toolResponse.rawV2. */
239
240
  raw: TData;
240
241
  rawV2?: unknown;
241
242
  view?: 'data' | 'rawV2';
@@ -243,6 +243,7 @@ export interface ToolDefinition extends ToolExecutionMetadataFields {
243
243
  expression?: string;
244
244
  meaning?: string;
245
245
  };
246
+ /** @deprecated Use canonicalToolResponse. */
246
247
  rawToolResponse?: {
247
248
  expression?: string;
248
249
  meaning?: string;
@@ -256,6 +257,7 @@ export interface ToolDefinition extends ToolExecutionMetadataFields {
256
257
  toolExecutionResult?: {
257
258
  type?: 'ToolExecutionResult';
258
259
  toolResponse?: {
260
+ /** @deprecated Use rawV2. */
259
261
  raw?: string;
260
262
  rawV2?: string;
261
263
  view?: string;
@@ -3,6 +3,33 @@ import { RUNTIME_SHEET_CELL_META_COLUMN } from './runtime-sheet-orm';
3
3
 
4
4
  export { RUNTIME_SHEET_CELL_META_COLUMN } from './runtime-sheet-orm';
5
5
 
6
+ /** Reserved metadata shared by row provenance and result ownership. */
7
+ export const ROW_META_CELL_KEY = '_row';
8
+
9
+ /**
10
+ * A witnessed rerun admission preserves cached cells but changes the row to
11
+ * pending. Only a terminal row write accepts those values for this admission.
12
+ * Older admissions leave the witness untouched and retain legacy read behavior.
13
+ */
14
+ export function runtimeSheetResultFreshnessSql(
15
+ cellMetaExpression: string,
16
+ runIdExpression: string,
17
+ statusExpression = '_status',
18
+ ): string {
19
+ const admission = `(${cellMetaExpression}) -> '${ROW_META_CELL_KEY}' ->> 'resultAdmissionRunId'`;
20
+ return `(${admission} IS DISTINCT FROM ${runIdExpression} OR ${statusExpression} IN ('enriched', 'failed'))`;
21
+ }
22
+
23
+ /** Preserve all row/cell facts while witnessing the pending admission. */
24
+ export function runtimeSheetResultAdmissionSql(
25
+ cellMetaExpression: string,
26
+ runIdExpression: string,
27
+ ): string {
28
+ return `coalesce(${cellMetaExpression}, '{}'::jsonb) || jsonb_build_object(
29
+ '${ROW_META_CELL_KEY}', coalesce((${cellMetaExpression}) -> '${ROW_META_CELL_KEY}', '{}'::jsonb)
30
+ || jsonb_build_object('resultAdmissionRunId', ${runIdExpression}))`;
31
+ }
32
+
6
33
  export type RuntimeSheetCellMetaColumnState = {
7
34
  data_type: string;
8
35
  is_nullable: string;
@@ -411,22 +411,38 @@ function positiveStartInputNumber(
411
411
  export function resolveAsyncOperationPolling(input: {
412
412
  contract: AsyncOperationContract;
413
413
  startInput: Readonly<Record<string, unknown>>;
414
+ /**
415
+ * Set only by Play row execution. Direct and keyed API calls leave it unset
416
+ * so a caller's `max_wait_ms` keeps bounding their request.
417
+ */
418
+ playRuntimeWait?: boolean;
414
419
  }): { intervalMs: number; timeoutMs: number; maxAttempts?: number } {
415
420
  const maxAttempts = positiveStartInputNumber(
416
421
  input.startInput,
417
422
  input.contract.polling.maxAttemptsInputField,
418
423
  );
424
+ const requestedTimeoutMs = positiveStartInputNumber(
425
+ input.startInput,
426
+ input.contract.polling.timeoutInputField,
427
+ );
428
+ // The public timeout field (`max_wait_ms`) is a direct caller's sync-wait
429
+ // control: the provider clamps it to the ~30s ceiling and hands back a
430
+ // pollable `running` envelope when it expires, so direct and keyed API calls
431
+ // honor it. A runtime-managed Play wait has no such envelope; expiry fails
432
+ // the run and abandons an accepted, already-billed provider job. So in a Play
433
+ // the per-call value may only lengthen the lifecycle bound, never shorten it
434
+ // below the contract's own timeout.
435
+ const timeoutMs =
436
+ input.playRuntimeWait === true && input.contract.runtimeManagedWait === true
437
+ ? Math.max(requestedTimeoutMs ?? 0, input.contract.polling.timeoutMs)
438
+ : (requestedTimeoutMs ?? input.contract.polling.timeoutMs);
419
439
  return {
420
440
  intervalMs:
421
441
  positiveStartInputNumber(
422
442
  input.startInput,
423
443
  input.contract.polling.intervalInputField,
424
444
  ) ?? input.contract.polling.intervalMs,
425
- timeoutMs:
426
- positiveStartInputNumber(
427
- input.startInput,
428
- input.contract.polling.timeoutInputField,
429
- ) ?? input.contract.polling.timeoutMs,
445
+ timeoutMs,
430
446
  ...(maxAttempts ? { maxAttempts: Math.floor(maxAttempts) } : {}),
431
447
  };
432
448
  }
@@ -977,6 +993,8 @@ export async function executeAsyncOperationLifecycle<Response>(input: {
977
993
  }) => void;
978
994
  /** Legacy direct callers historically poll once immediately after launch. */
979
995
  pollImmediately?: boolean;
996
+ /** Play row execution only; see `resolveAsyncOperationPolling`. */
997
+ playRuntimeWait?: boolean;
980
998
  }): Promise<
981
999
  | {
982
1000
  kind: 'terminal';
@@ -1017,6 +1035,7 @@ export async function executeAsyncOperationLifecycle<Response>(input: {
1017
1035
  const polling = resolveAsyncOperationPolling({
1018
1036
  contract: input.contract,
1019
1037
  startInput: input.startInput,
1038
+ playRuntimeWait: input.playRuntimeWait,
1020
1039
  });
1021
1040
  const effectiveContract: AsyncOperationContractWire = {
1022
1041
  ...input.contract,
@@ -80,7 +80,7 @@ export const MAX_CELL_READ_REFS = 12;
80
80
  export const MAX_ROW_READ_CELLS = 24;
81
81
 
82
82
  /** Reserved `_cell_meta` key holding row-grain facts rather than a cell. */
83
- export const ROW_META_CELL_KEY = '_row';
83
+ export { ROW_META_CELL_KEY } from '../play-data-plane/runtime-sheet-storage-contract';
84
84
 
85
85
  /**
86
86
  * Row-grain read order (ADR 0019).
@@ -126,6 +126,8 @@ export function cellReadCut(
126
126
  export interface PlayRowMeta {
127
127
  reads?: PlayRowReadOrder;
128
128
  bornFrom?: PlayRowBornFromRow;
129
+ /** Rerun admission whose cached cells await a terminal row write. */
130
+ resultAdmissionRunId?: string;
129
131
  }
130
132
 
131
133
  /**
@@ -3129,7 +3129,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
3129
3129
  ...(options?.timeoutMs !== undefined
3130
3130
  ? { timeoutMs: options.timeoutMs }
3131
3131
  : {}),
3132
- })) as { toolOutput?: { raw?: unknown } };
3132
+ })) as ToolExecuteResult;
3133
3133
  const raw = result.toolOutput?.raw;
3134
3134
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
3135
3135
  throw new Error(
@@ -3143,6 +3143,18 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
3143
3143
  'query_customer_db returned an invalid Customer DB rows result.',
3144
3144
  );
3145
3145
  }
3146
+ const dataset = result.extractedLists.rows?.get();
3147
+ if (isPlayDataset(dataset)) {
3148
+ const count = await dataset.count();
3149
+ const materialized = await dataset.materialize(options?.maxRows);
3150
+ const expectedCount = Math.min(count, options?.maxRows ?? count);
3151
+ if (materialized.length !== expectedCount) {
3152
+ throw new Error(
3153
+ `query_customer_db returned ${materialized.length} of ${expectedCount} requested rows. The result changed while paging; retry the query.`,
3154
+ );
3155
+ }
3156
+ return materialized as TRow[];
3157
+ }
3146
3158
  return [...rows] as TRow[];
3147
3159
  },
3148
3160
  };
@@ -18599,6 +18611,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
18599
18611
  startInput: input.startInput,
18600
18612
  startResult,
18601
18613
  jobId,
18614
+ playRuntimeWait: true,
18602
18615
  executeAction: ({ action, input: actionInput, timeoutMs, abortSignal }) =>
18603
18616
  this.callToolExecutionAPI(action, actionInput, {
18604
18617
  timeoutMs,
@@ -32,7 +32,11 @@ import {
32
32
  RuntimeSheetColumns,
33
33
  type RuntimeSheetColumnTypes,
34
34
  } from '../play-data-plane/sheet-column-storage';
35
- import { RUNTIME_SHEET_CELL_META_COLUMN } from '../play-data-plane/runtime-sheet-storage-contract';
35
+ import {
36
+ RUNTIME_SHEET_CELL_META_COLUMN,
37
+ runtimeSheetResultFreshnessSql,
38
+ runtimeSheetResultAdmissionSql,
39
+ } from '../play-data-plane/runtime-sheet-storage-contract';
36
40
  import {
37
41
  createRuntimeSheetOrm,
38
42
  isRuntimeSheetOwnerMetadataConstraintError,
@@ -3237,6 +3241,7 @@ async function readRuntimeRows(
3237
3241
  bool_or(_status = 'failed') OVER () AS __has_failed
3238
3242
  FROM ${sheetTable(session)}
3239
3243
  WHERE _run_id = $1::text
3244
+ AND ${runtimeSheetResultFreshnessSql('_cell_meta', '$1::text')}
3240
3245
  )
3241
3246
  SELECT *
3242
3247
  FROM scoped
@@ -3637,6 +3642,7 @@ async function prepareRuntimeSheetDatasetRows(
3637
3642
  physicalRefreshSetSql: string;
3638
3643
  physicalUpsertSetSql: string;
3639
3644
  outputPhysicalColumns: PhysicalSheetColumnProjection[];
3645
+ pendingRerunAdmission?: boolean;
3640
3646
  force?: boolean;
3641
3647
  mode?: RuntimeSheetDatasetMode;
3642
3648
  },
@@ -3721,8 +3727,13 @@ async function prepareRuntimeSheetDatasetRows(
3721
3727
  versioned_completed_rows AS (
3722
3728
  UPDATE ${sheetTable(session)} AS target
3723
3729
  SET _run_id = $4::text,
3730
+ _status = ${input.pendingRerunAdmission === true ? "'pending'" : 'target._status'},
3731
+ ${input.pendingRerunAdmission === true ? '_attempt_id = $7::text, _attempt_owner_run_id = $8::text, _attempt_expires_at = $9::timestamptz, _attempt_seq = $10::integer,' : ''}
3724
3732
  _writer_run_id = $4::text,
3725
3733
  _write_version = $12::bigint,
3734
+ -- Retain cached cells for resolver hydration while the new
3735
+ -- admission waits for its own terminal row write.
3736
+ _cell_meta = ${input.pendingRerunAdmission === true ? runtimeSheetResultAdmissionSql('target._cell_meta', '$4::text') : 'target._cell_meta'},
3726
3737
  _input_index = input_rows._input_index,
3727
3738
  _updated_at = now(),
3728
3739
  _version = ${nextRuntimeSheetVersionExpression(session)}${input.physicalRefreshSetSql}
@@ -3736,12 +3747,14 @@ async function prepareRuntimeSheetDatasetRows(
3736
3747
  versioned_failed_rows AS (
3737
3748
  UPDATE ${sheetTable(session)} AS target
3738
3749
  SET _run_id = $4::text,
3750
+ _status = ${input.pendingRerunAdmission === true ? "'pending'" : 'target._status'},
3739
3751
  _writer_run_id = $4::text,
3740
3752
  _write_version = $12::bigint,
3753
+ _cell_meta = ${input.pendingRerunAdmission === true ? runtimeSheetResultAdmissionSql('target._cell_meta', '$4::text') : 'target._cell_meta'},
3741
3754
  _input_index = input_rows._input_index,
3742
3755
  _attempt_id = $7::text,
3743
3756
  _attempt_owner_run_id = $8::text,
3744
- _attempt_expires_at = NULL,
3757
+ _attempt_expires_at = ${input.pendingRerunAdmission === true ? '$9::timestamptz' : 'NULL'},
3745
3758
  _attempt_seq = $10::integer,
3746
3759
  _updated_at = now(),
3747
3760
  _version = ${nextRuntimeSheetVersionExpression(session)}${input.physicalRefreshSetSql}
@@ -3830,6 +3843,7 @@ async function prepareRuntimeSheetDatasetRows(
3830
3843
  superseded_rows AS (
3831
3844
  UPDATE ${sheetTable(session)} AS target
3832
3845
  SET _run_id = $4::text,
3846
+ _cell_meta = ${input.pendingRerunAdmission === true ? runtimeSheetResultAdmissionSql('target._cell_meta', '$4::text') : 'target._cell_meta'},
3833
3847
  _input_index = input_rows._input_index,
3834
3848
  _attempt_id = $7::text,
3835
3849
  _attempt_owner_run_id = $8::text,
@@ -3993,7 +4007,9 @@ async function prepareRuntimeSheetDatasetRows(
3993
4007
  summary_counts AS (
3994
4008
  SELECT
3995
4009
  (SELECT c FROM inserted_count_cte) AS inserted_count,
3996
- (SELECT c FROM missing_output_count_cte) AS missing_output_count
4010
+ (SELECT c FROM missing_output_count_cte) AS missing_output_count,
4011
+ ${input.pendingRerunAdmission === true ? '(SELECT count(*) FROM versioned_completed_rows)' : '0'}::int AS completed_reopened_count,
4012
+ ${input.pendingRerunAdmission === true ? '(SELECT count(*) FROM versioned_failed_rows)' : '0'}::int AS failed_reopened_count
3997
4013
  ),
3998
4014
  summary_delta AS (
3999
4015
  INSERT INTO ${summaryTable(session)} AS target (play_name, table_namespace, total, queued, running, completed, failed)
@@ -4001,22 +4017,26 @@ async function prepareRuntimeSheetDatasetRows(
4001
4017
  $5::text,
4002
4018
  $6::text,
4003
4019
  inserted_count::int,
4004
- (inserted_count + missing_output_count)::int,
4020
+ (inserted_count + missing_output_count + completed_reopened_count + failed_reopened_count)::int,
4005
4021
  0,
4006
- (-missing_output_count)::int,
4007
- 0
4022
+ (-missing_output_count - completed_reopened_count)::int,
4023
+ -failed_reopened_count
4008
4024
  FROM summary_counts
4009
- WHERE inserted_count > 0 OR missing_output_count > 0
4025
+ WHERE inserted_count > 0 OR missing_output_count > 0 OR completed_reopened_count > 0 OR failed_reopened_count > 0
4010
4026
  ON CONFLICT (play_name, table_namespace) DO UPDATE SET
4011
4027
  queued = GREATEST(target.queued + EXCLUDED.queued, 0),
4012
4028
  completed = GREATEST(target.completed + EXCLUDED.completed, 0),
4029
+ ${input.pendingRerunAdmission === true ? 'failed = GREATEST(target.failed + EXCLUDED.failed, 0),' : ''}
4013
4030
  total = ${runtimeSummaryTotalSql({
4014
4031
  currentTotal: 'target.total',
4015
4032
  totalDelta: 'EXCLUDED.total',
4016
4033
  queued: 'GREATEST(target.queued + EXCLUDED.queued, 0)',
4017
4034
  running: 'target.running',
4018
4035
  completed: 'GREATEST(target.completed + EXCLUDED.completed, 0)',
4019
- failed: 'target.failed',
4036
+ failed:
4037
+ input.pendingRerunAdmission === true
4038
+ ? 'GREATEST(target.failed + EXCLUDED.failed, 0)'
4039
+ : 'target.failed',
4020
4040
  })},
4021
4041
  _updated_at = now()
4022
4042
  RETURNING 1
@@ -6555,12 +6575,14 @@ export async function startRuntimeSheetDataset(
6555
6575
  inputOffset?: number;
6556
6576
  force?: boolean;
6557
6577
  mode?: RuntimeSheetDatasetMode;
6578
+ /** Preserve cached cells while making a rerun await its own terminal write. */
6579
+ pendingRerunAdmission?: boolean;
6558
6580
  },
6559
6581
  ): Promise<PrepareRuntimeSheetResult> {
6560
6582
  if (context.dbSessionStrategy === 'gateway_only') {
6561
6583
  return await postRuntimeApi<PrepareRuntimeSheetResult>(context, {
6562
6584
  action: 'runtime_sheet_start',
6563
- input,
6585
+ input: { ...input, pendingRerunAdmission: true },
6564
6586
  });
6565
6587
  }
6566
6588
  const totalStartedAt = Date.now();
@@ -6835,6 +6857,7 @@ export async function startRuntimeSheetDataset(
6835
6857
  input.force === true ? physicalRefreshSetSql : '',
6836
6858
  physicalUpsertSetSql,
6837
6859
  outputPhysicalColumns,
6860
+ pendingRerunAdmission: input.pendingRerunAdmission,
6838
6861
  force: input.force === true,
6839
6862
  });
6840
6863
  timings.push({
@@ -149,6 +149,7 @@ export const PLAY_AUTHORING_CONTRACT_ISSUE_CODES = [
149
149
  'play_authoring_slack_action_wait_result_ignored',
150
150
  'play_authoring_slack_action_wait_unbounded_loop',
151
151
  'play_authoring_tool_deprecated',
152
+ 'play_authoring_tool_response_raw_deprecated',
152
153
  'play_authoring_replay_unsafe_nondeterminism',
153
154
  'play_authoring_row_sleep_unsupported',
154
155
  'play_authoring_hitl_retry_loop_unsafe',
@@ -159,6 +159,7 @@ export type ToolResponseEnvelope<
159
159
  TData = unknown,
160
160
  TMeta = Record<string, unknown>,
161
161
  > = {
162
+ /** @deprecated Use declared getters or toolResponse.rawV2. */
162
163
  raw: TData;
163
164
  /** Complete parsed and scrubbed provider response, materialized from raw-v2. */
164
165
  rawV2?: unknown;
@@ -219,15 +220,15 @@ export type ToolExecuteResultAccessors<
219
220
  *
220
221
  * The top-level object is Deepline-owned execution metadata and semantic
221
222
  * extraction state. The canonical provider response lives under
222
- * `toolResponse.rawV2`; `toolResponse.raw` remains the legacy compatibility
223
- * projection. Response metadata lives under `toolResponse.meta`. Semantic single-value
223
+ * `toolResponse.rawV2`. Response metadata lives under `toolResponse.meta`. Semantic single-value
224
224
  * getters live under `extractedValues.<name>.get()`, and list getters live
225
225
  * under `extractedLists.<name>.get()`.
226
226
  *
227
227
  * Use extractors first when a tool contract exposes them. Use list getters for
228
- * row-shaped data. Drop to `toolResponse.raw` only for provider-specific scalar
229
- * fields or bounded debugging context; persisted rows may clip declared lists to
230
- * previews.
228
+ * row-shaped data. Use `toolResponse.rawV2` for provider-specific fields or
229
+ * debugging. Inspect the observed response before selecting a nested field;
230
+ * provider envelopes are preserved, including pagination and sibling resources.
231
+ * This is parsed, scrubbed data, not the original HTTP bytes or headers.
231
232
  *
232
233
  * @sdkReference runtime 200
233
234
  */