deepline 0.1.265 → 0.1.266

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.
@@ -125,7 +125,7 @@ export const SDK_RELEASE = {
125
125
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
126
126
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
127
127
  // Operators use the checkout-local deepline-admin binary instead.
128
- version: '0.1.265',
128
+ version: '0.1.266',
129
129
  apiContract: '2026-07-admin-cli-local-cutover',
130
130
  supportPolicy: {
131
131
  minimumSupported: '0.1.53',
@@ -677,6 +677,64 @@ export interface PlayStatus {
677
677
  };
678
678
  /** Exact ordinary `plays run` command that can rerun a failed execution. */
679
679
  rerunCommand?: string;
680
+ /**
681
+ * Projected settled-charge billing for the run. Returned by `runs.get`.
682
+ * `totalCredits`/`providerEvents` describe THIS run only; `rollup` (present
683
+ * with `--full`) carries the true subtree cost including ctx.runPlay children.
684
+ * Deepline credits only — provider spend is never exposed.
685
+ */
686
+ billing?: RunBillingSummary;
687
+ /**
688
+ * True subtree cost in Deepline credits (this run + every descendant run),
689
+ * mirrored to the top level for convenience. Present only with `--full`.
690
+ */
691
+ billingTotalCreditsRollup?: number;
692
+ /** Deepline credits attributable to descendant runs only. Present with `--full`. */
693
+ billingChildCredits?: number;
694
+ /** True when the child-run billing rollup could not be fully resolved. */
695
+ billingRollupIncomplete?: boolean;
696
+ /** Durable summaries of ctx.runPlay children, returned by `runs.get --full`. */
697
+ childRuns?: ChildRunSummary[];
698
+ }
699
+
700
+ /** One ctx.runPlay child run exposed on the parent's `--full` payload. */
701
+ export interface ChildRunSummary {
702
+ runId: string;
703
+ playName?: string | null;
704
+ status: string;
705
+ parentRunId?: string | null;
706
+ rootRunId?: string | null;
707
+ createdAt?: number | null;
708
+ startedAt?: number | null;
709
+ finishedAt?: number | null;
710
+ }
711
+
712
+ /**
713
+ * Rolled-up billing for a run subtree, projected from settled Charge Lifecycle
714
+ * facts. Deepline credits only — never provider spend.
715
+ */
716
+ export interface RunBillingSummary {
717
+ runId: string;
718
+ /** THIS run's own charges (parent-only; excludes descendant runs). */
719
+ totalCalls: number;
720
+ totalCredits: number;
721
+ providerEvents: number;
722
+ computeEvents: number;
723
+ /** Subtree rollup including descendant ctx.runPlay runs. Present with `--full`. */
724
+ rollup?: {
725
+ totalCreditsRollup: number;
726
+ childCredits: number;
727
+ ownCredits: number;
728
+ totalCallsRollup: number;
729
+ providerEventsRollup: number;
730
+ computeEventsRollup: number;
731
+ childProviderEvents: number;
732
+ childComputeEvents: number;
733
+ descendantRunCount: number;
734
+ rollupComplete: boolean;
735
+ rollupError?: string;
736
+ };
737
+ [key: string]: unknown;
680
738
  }
681
739
 
682
740
  export type LiveEventScope = 'play' | 'agent';
@@ -51,6 +51,7 @@ import {
51
51
  isRetryableSecretResolutionStatus,
52
52
  secretResolutionRetryDecision,
53
53
  SECRET_RESOLUTION_MAX_ATTEMPTS,
54
+ SECRET_RESOLUTION_ATTEMPT_TIMEOUT_MS,
54
55
  type SecretResolutionRetryDecision,
55
56
  } from './secret-resolution-retry-policy';
56
57
  import {
@@ -307,6 +308,16 @@ const TOOL_BATCH_COALESCE_WINDOW_MS = 5;
307
308
  const TOOL_RETRY_AFTER_FALLBACK_MS = 1_000;
308
309
  const TOOL_RETRY_HEARTBEAT_INTERVAL_MS = 30_000;
309
310
  const DEEPLINEAGENT_TOOL_RUNTIME_TIMEOUT_MS = 15 * 60 * 1000;
311
+ // Every runtime-API tool fetch needs a client-side deadline. Without one, a
312
+ // stalled execute request (e.g. a credential-less call whose gateway connection
313
+ // hangs before the fast 403 can return) leaves the row "1 in flight" for minutes
314
+ // until the outer run deadline, violating loud-failure. The integrations execute
315
+ // route caps server work at maxDuration=900s, so this ceiling sits just above it:
316
+ // a healthy server (including the fast INTEGRATION_CREDENTIALS_MISSING 403) always
317
+ // responds first, and only a genuinely stuck socket trips the abort — surfacing as
318
+ // a bounded, repairable transport failure that row-isolation settles per row
319
+ // instead of hanging the whole run.
320
+ const DEFAULT_TOOL_RUNTIME_TIMEOUT_MS = 15 * 60 * 1000 + 30_000;
310
321
  const FETCH_TRANSPORT_MAX_ATTEMPTS = 3;
311
322
  const FETCH_TRANSPORT_RETRY_DELAY_MS = 100;
312
323
  // cloudflared returns this branded HTML when its connection to the local app
@@ -493,13 +504,17 @@ export function resolveToolRuntimeTimeoutMs(
493
504
  return Math.max(1, Math.ceil(requestedTimeoutMs));
494
505
  }
495
506
  const normalized = toolId.trim().toLowerCase();
507
+ // Long-inference tools keep their explicit 15-minute budget. Every other tool
508
+ // gets the default ceiling so no runtime-API fetch is ever unbounded — a
509
+ // missing-credential or otherwise stuck request fails loudly and fast within
510
+ // the deadline instead of hanging "1 in flight".
496
511
  return normalized === 'deeplineagent' ||
497
512
  normalized === 'deeplineagent_deeplineagent' ||
498
513
  normalized === 'ai_inference' ||
499
514
  normalized === 'deeplineagent_ai_inference' ||
500
515
  normalized === 'aiinference'
501
516
  ? DEEPLINEAGENT_TOOL_RUNTIME_TIMEOUT_MS
502
- : undefined;
517
+ : DEFAULT_TOOL_RUNTIME_TIMEOUT_MS;
503
518
  }
504
519
 
505
520
  function isDeeplineDeveloperTunnelOrigin502(input: {
@@ -1586,6 +1601,10 @@ export class PlayContextImpl {
1586
1601
  try {
1587
1602
  response = await fetch(url, {
1588
1603
  method: 'POST',
1604
+ // Bound the control-plane call so a stalled connection aborts and is
1605
+ // caught below as a transport failure instead of hanging the tool
1606
+ // call "1 in flight" forever.
1607
+ signal: AbortSignal.timeout(SECRET_RESOLUTION_ATTEMPT_TIMEOUT_MS),
1589
1608
  headers: {
1590
1609
  Authorization: `Bearer ${this.#options.executorToken}`,
1591
1610
  'Content-Type': 'application/json',
@@ -44,6 +44,29 @@ function sourceAliases(target: string, aliases: string | readonly string[]) {
44
44
  return [target, ...(Array.isArray(aliases) ? aliases : [aliases])];
45
45
  }
46
46
 
47
+ /**
48
+ * `required` is a HEADER-presence guarantee, not a per-row non-null check.
49
+ *
50
+ * A required target is satisfied when at least one of its source aliases exists
51
+ * as a column in the CSV row (present in the header), regardless of whether this
52
+ * particular row's cell is blank. Blank cells in a present column are DATA, not a
53
+ * schema violation: they must flow through to the dataset so `onRowError` (or the
54
+ * play's own branching) governs them per row, never guillotine the whole run.
55
+ * Only a column that is entirely absent from the CSV is a `required` violation.
56
+ */
57
+ function hasAliasColumnPresent(
58
+ lookup: Map<string, unknown>,
59
+ target: string,
60
+ sourceNames: string | readonly string[],
61
+ ): boolean {
62
+ for (const alias of sourceAliases(target, sourceNames)) {
63
+ if (lookup.has(alias) || lookup.has(normalizeCsvHeader(alias))) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+
47
70
  export function applyCsvRenameProjection<T extends Record<string, unknown>>(
48
71
  rows: readonly T[],
49
72
  options?: CsvRenameOptions,
@@ -52,11 +75,26 @@ export function applyCsvRenameProjection<T extends Record<string, unknown>>(
52
75
  ...(options?.rename ?? {}),
53
76
  ...(options?.columns ?? {}),
54
77
  };
78
+ const required = new Set(options?.required ?? []);
79
+
55
80
  if (Object.keys(aliases).length === 0) {
81
+ // No rename/alias projection requested. `required` is still a
82
+ // header-presence guarantee: assert each required column exists in the CSV
83
+ // (checked against the first row's shape), then pass rows through untouched.
84
+ // A present-but-blank cell is data, never a `required` violation.
85
+ if (required.size > 0 && rows.length > 0) {
86
+ const lookup = buildRowLookup(rows[0]!);
87
+ for (const target of required) {
88
+ if (!hasAliasColumnPresent(lookup, target, target)) {
89
+ throw new Error(
90
+ `ctx.csv(..., { required }) is missing required column "${target}". ` +
91
+ `Add a "${target}" column to the CSV header.`,
92
+ );
93
+ }
94
+ }
95
+ }
56
96
  return [...rows];
57
97
  }
58
-
59
- const required = new Set(options?.required ?? []);
60
98
  return rows.map((row, index) => {
61
99
  const lookup = buildRowLookup(row);
62
100
  const projectedFields = new Set<string>();
@@ -88,9 +126,17 @@ export function applyCsvRenameProjection<T extends Record<string, unknown>>(
88
126
  } else {
89
127
  projected[target] = selected;
90
128
  }
91
- } else if (required.has(target)) {
129
+ } else if (
130
+ required.has(target) &&
131
+ !hasAliasColumnPresent(lookup, target, sourceNames)
132
+ ) {
133
+ // The column is entirely absent from the CSV header — a schema/config
134
+ // error that is identical for every row. A present-but-blank cell is
135
+ // data and must NOT trip this: it flows through so onRowError can
136
+ // isolate that row instead of failing the whole run.
92
137
  throw new Error(
93
- `ctx.csv(..., { rename }) row ${index + 1} is missing required column "${target}".`,
138
+ `ctx.csv(..., { required }) is missing required column "${target}". ` +
139
+ `Add a "${target}" column (or one of its aliases) to the CSV header.`,
94
140
  );
95
141
  }
96
142
  }
@@ -1,5 +1,11 @@
1
1
  export const SECRET_RESOLUTION_MAX_ATTEMPTS = 3;
2
2
  export const SECRET_RESOLUTION_MAX_RETRY_AFTER_MS = 2_000;
3
+ // Per-attempt client deadline for the secret-resolution gateway call. This is an
4
+ // internal control-plane fetch (resolve a named secret), not provider work, so it
5
+ // must return quickly. Without a bound, a stalled connection hangs the tool call
6
+ // "1 in flight" indefinitely; an abort here is caught as a transport failure and
7
+ // retried/failed loudly via secretResolutionRetryDecision.
8
+ export const SECRET_RESOLUTION_ATTEMPT_TIMEOUT_MS = 30_000;
3
9
 
4
10
  const SECRET_RESOLUTION_RETRY_JITTER_CAPS_MS = [100, 250] as const;
5
11
 
package/dist/cli/index.js CHANGED
@@ -718,7 +718,7 @@ var SDK_RELEASE = {
718
718
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
719
719
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
720
720
  // Operators use the checkout-local deepline-admin binary instead.
721
- version: "0.1.265",
721
+ version: "0.1.266",
722
722
  apiContract: "2026-07-admin-cli-local-cutover",
723
723
  supportPolicy: {
724
724
  minimumSupported: "0.1.53",
@@ -14256,6 +14256,26 @@ function withOrdinaryRunAgainCommand(status, options, resolvedRevisionId) {
14256
14256
  rerunCommand: buildOrdinaryPlayRunCommand(options, resolvedRevisionId)
14257
14257
  } : status;
14258
14258
  }
14259
+ function buildBillingRollupTextLines(status) {
14260
+ const billing = status.billing;
14261
+ const rollup = billing?.rollup;
14262
+ if (!rollup) return [];
14263
+ const total = formatCreditAmount(rollup.totalCreditsRollup);
14264
+ if (rollup.childCredits > 0 && rollup.descendantRunCount > 0) {
14265
+ const own = formatCreditAmount(rollup.ownCredits);
14266
+ const child = formatCreditAmount(rollup.childCredits);
14267
+ const suffix = rollup.rollupComplete ? "" : " (incomplete: child billing could not be fully resolved)";
14268
+ return [
14269
+ ` cost: ${total} credits total \u2014 ${own} this run + ${child} across ${rollup.descendantRunCount} child run${rollup.descendantRunCount === 1 ? "" : "s"}${suffix}`
14270
+ ];
14271
+ }
14272
+ if (!rollup.rollupComplete) {
14273
+ return [
14274
+ ` cost: ${total} credits (incomplete: child billing could not be fully resolved${rollup.rollupError ? ` \u2014 ${rollup.rollupError}` : ""})`
14275
+ ];
14276
+ }
14277
+ return [` cost: ${total} credits`];
14278
+ }
14259
14279
  function writePlayResult(status, jsonOutput, options) {
14260
14280
  const packaged = getPlayRunPackage(status);
14261
14281
  if (jsonOutput) {
@@ -14318,6 +14338,7 @@ function writePlayResult(status, jsonOutput, options) {
14318
14338
  lines.push(...renderedServerView.lines);
14319
14339
  }
14320
14340
  lines.push(...renderedServerView.actions);
14341
+ lines.push(...buildBillingRollupTextLines(status));
14321
14342
  const compact = compactPlayStatus(status);
14322
14343
  const payload = options?.fullJson ? status : compact;
14323
14344
  printCommandEnvelope(
@@ -703,7 +703,7 @@ var SDK_RELEASE = {
703
703
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
704
704
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
705
705
  // Operators use the checkout-local deepline-admin binary instead.
706
- version: "0.1.265",
706
+ version: "0.1.266",
707
707
  apiContract: "2026-07-admin-cli-local-cutover",
708
708
  supportPolicy: {
709
709
  minimumSupported: "0.1.53",
@@ -14285,6 +14285,26 @@ function withOrdinaryRunAgainCommand(status, options, resolvedRevisionId) {
14285
14285
  rerunCommand: buildOrdinaryPlayRunCommand(options, resolvedRevisionId)
14286
14286
  } : status;
14287
14287
  }
14288
+ function buildBillingRollupTextLines(status) {
14289
+ const billing = status.billing;
14290
+ const rollup = billing?.rollup;
14291
+ if (!rollup) return [];
14292
+ const total = formatCreditAmount(rollup.totalCreditsRollup);
14293
+ if (rollup.childCredits > 0 && rollup.descendantRunCount > 0) {
14294
+ const own = formatCreditAmount(rollup.ownCredits);
14295
+ const child = formatCreditAmount(rollup.childCredits);
14296
+ const suffix = rollup.rollupComplete ? "" : " (incomplete: child billing could not be fully resolved)";
14297
+ return [
14298
+ ` cost: ${total} credits total \u2014 ${own} this run + ${child} across ${rollup.descendantRunCount} child run${rollup.descendantRunCount === 1 ? "" : "s"}${suffix}`
14299
+ ];
14300
+ }
14301
+ if (!rollup.rollupComplete) {
14302
+ return [
14303
+ ` cost: ${total} credits (incomplete: child billing could not be fully resolved${rollup.rollupError ? ` \u2014 ${rollup.rollupError}` : ""})`
14304
+ ];
14305
+ }
14306
+ return [` cost: ${total} credits`];
14307
+ }
14288
14308
  function writePlayResult(status, jsonOutput, options) {
14289
14309
  const packaged = getPlayRunPackage(status);
14290
14310
  if (jsonOutput) {
@@ -14347,6 +14367,7 @@ function writePlayResult(status, jsonOutput, options) {
14347
14367
  lines.push(...renderedServerView.lines);
14348
14368
  }
14349
14369
  lines.push(...renderedServerView.actions);
14370
+ lines.push(...buildBillingRollupTextLines(status));
14350
14371
  const compact = compactPlayStatus(status);
14351
14372
  const payload = options?.fullJson ? status : compact;
14352
14373
  printCommandEnvelope(
package/dist/index.d.mts CHANGED
@@ -667,6 +667,62 @@ interface PlayStatus {
667
667
  };
668
668
  /** Exact ordinary `plays run` command that can rerun a failed execution. */
669
669
  rerunCommand?: string;
670
+ /**
671
+ * Projected settled-charge billing for the run. Returned by `runs.get`.
672
+ * `totalCredits`/`providerEvents` describe THIS run only; `rollup` (present
673
+ * with `--full`) carries the true subtree cost including ctx.runPlay children.
674
+ * Deepline credits only — provider spend is never exposed.
675
+ */
676
+ billing?: RunBillingSummary;
677
+ /**
678
+ * True subtree cost in Deepline credits (this run + every descendant run),
679
+ * mirrored to the top level for convenience. Present only with `--full`.
680
+ */
681
+ billingTotalCreditsRollup?: number;
682
+ /** Deepline credits attributable to descendant runs only. Present with `--full`. */
683
+ billingChildCredits?: number;
684
+ /** True when the child-run billing rollup could not be fully resolved. */
685
+ billingRollupIncomplete?: boolean;
686
+ /** Durable summaries of ctx.runPlay children, returned by `runs.get --full`. */
687
+ childRuns?: ChildRunSummary[];
688
+ }
689
+ /** One ctx.runPlay child run exposed on the parent's `--full` payload. */
690
+ interface ChildRunSummary {
691
+ runId: string;
692
+ playName?: string | null;
693
+ status: string;
694
+ parentRunId?: string | null;
695
+ rootRunId?: string | null;
696
+ createdAt?: number | null;
697
+ startedAt?: number | null;
698
+ finishedAt?: number | null;
699
+ }
700
+ /**
701
+ * Rolled-up billing for a run subtree, projected from settled Charge Lifecycle
702
+ * facts. Deepline credits only — never provider spend.
703
+ */
704
+ interface RunBillingSummary {
705
+ runId: string;
706
+ /** THIS run's own charges (parent-only; excludes descendant runs). */
707
+ totalCalls: number;
708
+ totalCredits: number;
709
+ providerEvents: number;
710
+ computeEvents: number;
711
+ /** Subtree rollup including descendant ctx.runPlay runs. Present with `--full`. */
712
+ rollup?: {
713
+ totalCreditsRollup: number;
714
+ childCredits: number;
715
+ ownCredits: number;
716
+ totalCallsRollup: number;
717
+ providerEventsRollup: number;
718
+ computeEventsRollup: number;
719
+ childProviderEvents: number;
720
+ childComputeEvents: number;
721
+ descendantRunCount: number;
722
+ rollupComplete: boolean;
723
+ rollupError?: string;
724
+ };
725
+ [key: string]: unknown;
670
726
  }
671
727
  type LiveEventScope = 'play' | 'agent';
672
728
  interface LiveEventEnvelope<TPayload = unknown> {
package/dist/index.d.ts CHANGED
@@ -667,6 +667,62 @@ interface PlayStatus {
667
667
  };
668
668
  /** Exact ordinary `plays run` command that can rerun a failed execution. */
669
669
  rerunCommand?: string;
670
+ /**
671
+ * Projected settled-charge billing for the run. Returned by `runs.get`.
672
+ * `totalCredits`/`providerEvents` describe THIS run only; `rollup` (present
673
+ * with `--full`) carries the true subtree cost including ctx.runPlay children.
674
+ * Deepline credits only — provider spend is never exposed.
675
+ */
676
+ billing?: RunBillingSummary;
677
+ /**
678
+ * True subtree cost in Deepline credits (this run + every descendant run),
679
+ * mirrored to the top level for convenience. Present only with `--full`.
680
+ */
681
+ billingTotalCreditsRollup?: number;
682
+ /** Deepline credits attributable to descendant runs only. Present with `--full`. */
683
+ billingChildCredits?: number;
684
+ /** True when the child-run billing rollup could not be fully resolved. */
685
+ billingRollupIncomplete?: boolean;
686
+ /** Durable summaries of ctx.runPlay children, returned by `runs.get --full`. */
687
+ childRuns?: ChildRunSummary[];
688
+ }
689
+ /** One ctx.runPlay child run exposed on the parent's `--full` payload. */
690
+ interface ChildRunSummary {
691
+ runId: string;
692
+ playName?: string | null;
693
+ status: string;
694
+ parentRunId?: string | null;
695
+ rootRunId?: string | null;
696
+ createdAt?: number | null;
697
+ startedAt?: number | null;
698
+ finishedAt?: number | null;
699
+ }
700
+ /**
701
+ * Rolled-up billing for a run subtree, projected from settled Charge Lifecycle
702
+ * facts. Deepline credits only — never provider spend.
703
+ */
704
+ interface RunBillingSummary {
705
+ runId: string;
706
+ /** THIS run's own charges (parent-only; excludes descendant runs). */
707
+ totalCalls: number;
708
+ totalCredits: number;
709
+ providerEvents: number;
710
+ computeEvents: number;
711
+ /** Subtree rollup including descendant ctx.runPlay runs. Present with `--full`. */
712
+ rollup?: {
713
+ totalCreditsRollup: number;
714
+ childCredits: number;
715
+ ownCredits: number;
716
+ totalCallsRollup: number;
717
+ providerEventsRollup: number;
718
+ computeEventsRollup: number;
719
+ childProviderEvents: number;
720
+ childComputeEvents: number;
721
+ descendantRunCount: number;
722
+ rollupComplete: boolean;
723
+ rollupError?: string;
724
+ };
725
+ [key: string]: unknown;
670
726
  }
671
727
  type LiveEventScope = 'play' | 'agent';
672
728
  interface LiveEventEnvelope<TPayload = unknown> {
package/dist/index.js CHANGED
@@ -437,7 +437,7 @@ var SDK_RELEASE = {
437
437
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
438
438
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
439
439
  // Operators use the checkout-local deepline-admin binary instead.
440
- version: "0.1.265",
440
+ version: "0.1.266",
441
441
  apiContract: "2026-07-admin-cli-local-cutover",
442
442
  supportPolicy: {
443
443
  minimumSupported: "0.1.53",
package/dist/index.mjs CHANGED
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.265",
370
+ version: "0.1.266",
371
371
  apiContract: "2026-07-admin-cli-local-cutover",
372
372
  supportPolicy: {
373
373
  minimumSupported: "0.1.53",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.265",
3
+ "version": "0.1.266",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {