deepline 0.1.253 → 0.1.255

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.
@@ -57,6 +57,12 @@ export type SdkSupportPolicy = {
57
57
  minimumSupported: string;
58
58
  reason: string;
59
59
  }>;
60
+ /**
61
+ * Published package versions that must keep working for direct SDK tool
62
+ * callers. CI installs each package from npm and exercises `tools.get` and
63
+ * `tools.execute` without involving the CLI or Play runtime.
64
+ */
65
+ directToolsCompatibilityVersions?: readonly string[];
60
66
  /**
61
67
  * Diagnostic freshness threshold reported by `/api/v2/sdk/compat`.
62
68
  * Stale-but-supported CLIs warn, but self-update is reserved for unsupported
@@ -116,7 +122,8 @@ export const SDK_RELEASE = {
116
122
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
117
123
  // Deepline-native radars. Older clients must update before discovering,
118
124
  // checking, or deploying an unlaunched monitor integration.
119
- version: '0.1.253',
125
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
126
+ version: '0.1.255',
120
127
  apiContract: '2026-07-native-monitor-launch-hard-cutover',
121
128
  supportPolicy: {
122
129
  minimumSupported: '0.1.53',
@@ -124,9 +131,9 @@ export const SDK_RELEASE = {
124
131
  commandMinimumSupported: [
125
132
  {
126
133
  command: 'enrich',
127
- minimumSupported: '0.1.238',
134
+ minimumSupported: '0.1.253',
128
135
  reason:
129
- 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH.',
136
+ 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH; SDK CLI enrich before 0.1.253 opens the generated play page by default and accepts the removed --no-open flag.',
130
137
  },
131
138
  {
132
139
  command: 'plays',
@@ -136,16 +143,16 @@ export const SDK_RELEASE = {
136
143
  },
137
144
  {
138
145
  command: 'plays run',
139
- minimumSupported: '0.1.241',
146
+ minimumSupported: '0.1.253',
140
147
  reason:
141
- 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
148
+ 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag.',
142
149
  },
143
150
  {
144
151
  command: 'run',
145
152
  displayCommand: 'plays run',
146
- minimumSupported: '0.1.241',
153
+ minimumSupported: '0.1.253',
147
154
  reason:
148
- 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
155
+ 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag.',
149
156
  },
150
157
  {
151
158
  command: 'plays check',
@@ -219,6 +226,7 @@ export const SDK_RELEASE = {
219
226
  'Run result row datasets now use the dataset-handle export contract.',
220
227
  },
221
228
  ],
229
+ directToolsCompatibilityVersions: ['0.1.171'],
222
230
  autoUpdatePatchLag: 2,
223
231
  },
224
232
  } as const satisfies SdkRelease;
@@ -42,7 +42,17 @@ import {
42
42
  mapRowOutcomeRuntimeFields,
43
43
  resolveMapRowOutcomeKey,
44
44
  } from './map-row-outcome';
45
- import { PLAY_RUNTIME_API_COMPAT_PATH } from './runtime-api-paths';
45
+ import {
46
+ PLAY_RUNTIME_API_COMPAT_PATH,
47
+ PLAY_RUNTIME_OPERATION_ATTEMPT_HEADER,
48
+ PLAY_RUNTIME_OPERATION_ID_HEADER,
49
+ } from './runtime-api-paths';
50
+ import {
51
+ isRetryableSecretResolutionStatus,
52
+ secretResolutionRetryDecision,
53
+ SECRET_RESOLUTION_MAX_ATTEMPTS,
54
+ type SecretResolutionRetryDecision,
55
+ } from './secret-resolution-retry-policy';
46
56
  import {
47
57
  createRootRunExecutionScope,
48
58
  deriveChildRunExecutionScope,
@@ -519,6 +529,26 @@ function loadSafeFetch(): Promise<SafeFetchModule> {
519
529
  return safeFetchModule;
520
530
  }
521
531
 
532
+ function waitForSecretResolutionRetry(ms: number): Promise<void> {
533
+ if (ms <= 0) return Promise.resolve();
534
+ return new Promise<void>((resolve) => setTimeout(resolve, ms));
535
+ }
536
+
537
+ function cancelRuntimeResponseBody(response: Response): void {
538
+ try {
539
+ void response.body?.cancel().catch(() => {});
540
+ } catch {
541
+ // Connection cleanup must never replace the resolver failure or retry.
542
+ }
543
+ }
544
+
545
+ const NO_SECRET_RESOLUTION_RETRY: SecretResolutionRetryDecision = {
546
+ retry: false,
547
+ retryDelayMs: 0,
548
+ retryAfterMs: null,
549
+ retryAfterExceedsCap: false,
550
+ };
551
+
522
552
  function isUnsafeOutboundUrlError(error: unknown): boolean {
523
553
  return error instanceof Error && error.name === 'UnsafeOutboundUrlError';
524
554
  }
@@ -1543,106 +1573,160 @@ export class PlayContextImpl {
1543
1573
  this.#options.runId
1544
1574
  ) {
1545
1575
  const url = `${this.#options.baseUrl.replace(/\/$/, '')}${PLAY_RUNTIME_API_COMPAT_PATH}`;
1546
- const requestId = `ctx-secret-${crypto.randomUUID()}`;
1547
- const startedAt = Date.now();
1548
- let response: Response;
1549
- try {
1550
- response = await fetch(url, {
1551
- method: 'POST',
1552
- headers: {
1553
- Authorization: `Bearer ${this.#options.executorToken}`,
1554
- 'Content-Type': 'application/json',
1555
- 'x-deepline-request-id': requestId,
1556
- ...(await this.vercelProtectionHeaders()),
1557
- },
1558
- body: JSON.stringify({
1559
- action: 'resolve_secret',
1560
- name: auth.secret.name,
1561
- playName: this.#options.playName,
1562
- }),
1563
- });
1564
- } catch (error) {
1565
- const diagnostic = describeTransportError(error);
1566
- this.log(
1567
- `[runtime.secret_resolution_failure] ${JSON.stringify({
1568
- stage: 'transport',
1569
- secret_name: auth.secret.name,
1570
- gateway_origin: transportGatewayOriginForDiagnostic(url),
1571
- request_id: requestId,
1572
- elapsed_ms: Date.now() - startedAt,
1573
- error: diagnostic,
1574
- })}`,
1575
- );
1576
- throw new Error(
1577
- `Secret ${auth.secret.name} resolution transport failed (request_id=${requestId}): ${diagnostic.message ?? 'unknown transport error'}`,
1578
- );
1579
- }
1576
+ const operationId = `ctx-secret-operation-${crypto.randomUUID()}`;
1577
+ const operationStartedAt = Date.now();
1578
+ for (
1579
+ let attempt = 1;
1580
+ attempt <= SECRET_RESOLUTION_MAX_ATTEMPTS;
1581
+ attempt += 1
1582
+ ) {
1583
+ const requestId = `ctx-secret-${crypto.randomUUID()}`;
1584
+ const attemptStartedAt = Date.now();
1585
+ let response: Response;
1586
+ try {
1587
+ response = await fetch(url, {
1588
+ method: 'POST',
1589
+ headers: {
1590
+ Authorization: `Bearer ${this.#options.executorToken}`,
1591
+ 'Content-Type': 'application/json',
1592
+ 'x-deepline-request-id': requestId,
1593
+ [PLAY_RUNTIME_OPERATION_ID_HEADER]: operationId,
1594
+ [PLAY_RUNTIME_OPERATION_ATTEMPT_HEADER]: String(attempt),
1595
+ ...(await this.vercelProtectionHeaders()),
1596
+ },
1597
+ body: JSON.stringify({
1598
+ action: 'resolve_secret',
1599
+ name: auth.secret.name,
1600
+ playName: this.#options.playName,
1601
+ }),
1602
+ });
1603
+ } catch (error) {
1604
+ const diagnostic = describeTransportError(error);
1605
+ const retry = secretResolutionRetryDecision({
1606
+ attempt,
1607
+ retryAfter: null,
1608
+ });
1609
+ this.log(
1610
+ `[runtime.secret_resolution_failure] ${JSON.stringify({
1611
+ stage: 'transport',
1612
+ secret_name: auth.secret.name,
1613
+ gateway_origin: transportGatewayOriginForDiagnostic(url),
1614
+ operation_id: operationId,
1615
+ request_id: requestId,
1616
+ attempt,
1617
+ max_attempts: SECRET_RESOLUTION_MAX_ATTEMPTS,
1618
+ retrying: retry.retry,
1619
+ retry_delay_ms: retry.retryDelayMs,
1620
+ elapsed_ms: Date.now() - attemptStartedAt,
1621
+ operation_elapsed_ms: Date.now() - operationStartedAt,
1622
+ error: diagnostic,
1623
+ })}`,
1624
+ );
1625
+ if (!retry.retry) {
1626
+ throw new Error(
1627
+ `Secret ${auth.secret.name} resolution transport failed (request_id=${requestId}): ${diagnostic.message ?? 'unknown transport error'}`,
1628
+ );
1629
+ }
1630
+ await waitForSecretResolutionRetry(retry.retryDelayMs);
1631
+ continue;
1632
+ }
1580
1633
 
1581
- const responseDiagnostic = {
1582
- stage: response.ok ? 'invalid_response' : 'http_response',
1583
- secret_name: auth.secret.name,
1584
- gateway_origin: transportGatewayOriginForDiagnostic(url),
1585
- request_id: requestId,
1586
- elapsed_ms: Date.now() - startedAt,
1587
- http_status: response.status,
1588
- status_text: response.statusText || null,
1589
- content_type: response.headers.get('content-type'),
1590
- server: response.headers.get('server'),
1591
- vercel_request_id:
1592
- response.headers.get('x-vercel-id') ??
1593
- response.headers.get('x-vercel-request-id'),
1594
- response_request_id: response.headers.get('x-deepline-request-id'),
1595
- error_code: response.headers.get('x-deepline-error-code'),
1596
- retry_after: response.headers.get('retry-after'),
1597
- };
1598
- if (!response.ok) {
1599
- this.log(
1600
- `[runtime.secret_resolution_failure] ${JSON.stringify(responseDiagnostic)}`,
1601
- );
1602
- throw new Error(
1603
- `Secret ${auth.secret.name} is not available to this run (resolution status=${response.status}, request_id=${requestId}).`,
1604
- );
1605
- }
1634
+ const retryAfter = response.headers.get('retry-after');
1635
+ const retry = isRetryableSecretResolutionStatus(response.status)
1636
+ ? secretResolutionRetryDecision({ attempt, retryAfter })
1637
+ : NO_SECRET_RESOLUTION_RETRY;
1638
+ const responseDiagnostic = {
1639
+ stage: response.ok ? 'invalid_response' : 'http_response',
1640
+ secret_name: auth.secret.name,
1641
+ gateway_origin: transportGatewayOriginForDiagnostic(url),
1642
+ operation_id: operationId,
1643
+ request_id: requestId,
1644
+ attempt,
1645
+ max_attempts: SECRET_RESOLUTION_MAX_ATTEMPTS,
1646
+ retrying: retry.retry,
1647
+ retry_delay_ms: retry.retryDelayMs,
1648
+ elapsed_ms: Date.now() - attemptStartedAt,
1649
+ operation_elapsed_ms: Date.now() - operationStartedAt,
1650
+ http_status: response.status,
1651
+ status_text: response.statusText || null,
1652
+ content_type: response.headers.get('content-type'),
1653
+ server: response.headers.get('server'),
1654
+ vercel_request_id:
1655
+ response.headers.get('x-vercel-id') ??
1656
+ response.headers.get('x-vercel-request-id'),
1657
+ response_request_id: response.headers.get('x-deepline-request-id'),
1658
+ error_code: response.headers.get('x-deepline-error-code'),
1659
+ retry_after: retryAfter,
1660
+ retry_after_ms: retry.retryAfterMs,
1661
+ retry_after_exceeds_cap: retry.retryAfterExceedsCap,
1662
+ };
1663
+ if (!response.ok) {
1664
+ this.log(
1665
+ `[runtime.secret_resolution_failure] ${JSON.stringify(responseDiagnostic)}`,
1666
+ );
1667
+ cancelRuntimeResponseBody(response);
1668
+ if (retry.retry) {
1669
+ await waitForSecretResolutionRetry(retry.retryDelayMs);
1670
+ continue;
1671
+ }
1672
+ throw new Error(
1673
+ `Secret ${auth.secret.name} is not available to this run (resolution status=${response.status}, request_id=${requestId}).`,
1674
+ );
1675
+ }
1606
1676
 
1607
- let payload: unknown;
1608
- try {
1609
- payload = await response.json();
1610
- } catch (error) {
1611
- this.log(
1612
- `[runtime.secret_resolution_failure] ${JSON.stringify({
1613
- ...responseDiagnostic,
1614
- response_kind: 'invalid_json',
1615
- parse_error_name:
1616
- error instanceof Error ? error.name : typeof error,
1617
- })}`,
1618
- );
1619
- throw new Error(
1620
- `Secret ${auth.secret.name} is not available to this run (invalid resolution response, request_id=${requestId}).`,
1621
- );
1622
- }
1677
+ let payload: unknown;
1678
+ try {
1679
+ payload = await response.json();
1680
+ } catch (error) {
1681
+ this.log(
1682
+ `[runtime.secret_resolution_failure] ${JSON.stringify({
1683
+ ...responseDiagnostic,
1684
+ response_kind: 'invalid_json',
1685
+ parse_error_name:
1686
+ error instanceof Error ? error.name : typeof error,
1687
+ })}`,
1688
+ );
1689
+ throw new Error(
1690
+ `Secret ${auth.secret.name} is not available to this run (invalid resolution response, request_id=${requestId}).`,
1691
+ );
1692
+ }
1623
1693
 
1624
- value =
1625
- payload &&
1626
- typeof payload === 'object' &&
1627
- !Array.isArray(payload) &&
1628
- typeof (payload as { value?: unknown }).value === 'string'
1629
- ? (payload as { value: string }).value
1630
- : null;
1631
- if (!value) {
1632
- this.log(
1633
- `[runtime.secret_resolution_failure] ${JSON.stringify({
1634
- ...responseDiagnostic,
1635
- response_kind:
1636
- payload === null
1637
- ? 'null'
1638
- : Array.isArray(payload)
1639
- ? 'array'
1640
- : typeof payload,
1641
- })}`,
1642
- );
1643
- throw new Error(
1644
- `Secret ${auth.secret.name} is not available to this run (missing resolution value, request_id=${requestId}).`,
1645
- );
1694
+ value =
1695
+ payload &&
1696
+ typeof payload === 'object' &&
1697
+ !Array.isArray(payload) &&
1698
+ typeof (payload as { value?: unknown }).value === 'string'
1699
+ ? (payload as { value: string }).value
1700
+ : null;
1701
+ if (!value) {
1702
+ this.log(
1703
+ `[runtime.secret_resolution_failure] ${JSON.stringify({
1704
+ ...responseDiagnostic,
1705
+ response_kind:
1706
+ payload === null
1707
+ ? 'null'
1708
+ : Array.isArray(payload)
1709
+ ? 'array'
1710
+ : typeof payload,
1711
+ })}`,
1712
+ );
1713
+ throw new Error(
1714
+ `Secret ${auth.secret.name} is not available to this run (missing resolution value, request_id=${requestId}).`,
1715
+ );
1716
+ }
1717
+ if (attempt > 1) {
1718
+ this.log(
1719
+ `[runtime.secret_resolution_recovered] ${JSON.stringify({
1720
+ secret_name: auth.secret.name,
1721
+ gateway_origin: transportGatewayOriginForDiagnostic(url),
1722
+ operation_id: operationId,
1723
+ request_id: requestId,
1724
+ attempts: attempt,
1725
+ operation_elapsed_ms: Date.now() - operationStartedAt,
1726
+ })}`,
1727
+ );
1728
+ }
1729
+ break;
1646
1730
  }
1647
1731
  } else {
1648
1732
  throw new Error(
@@ -1,5 +1,9 @@
1
1
  export const PLAY_RUNTIME_API_COMPAT_PATH = '/api/v2/plays/internal/runtime';
2
2
  export const PLAY_RUNTIME_API_CURRENT_PATH = '/api/v2/internal/play-runtime';
3
+ export const PLAY_RUNTIME_OPERATION_ID_HEADER =
4
+ 'x-deepline-runtime-operation-id';
5
+ export const PLAY_RUNTIME_OPERATION_ATTEMPT_HEADER =
6
+ 'x-deepline-runtime-operation-attempt';
3
7
  export const PLAY_RUNTIME_ATTEMPT_EXECUTOR_TOKEN_PATH =
4
8
  '/api/v2/internal/play-runtime/executor-token';
5
9
  export const PLAY_RUNTIME_TAIL_LOG_COMPAT_PATH =
@@ -0,0 +1,80 @@
1
+ export const SECRET_RESOLUTION_MAX_ATTEMPTS = 3;
2
+ export const SECRET_RESOLUTION_MAX_RETRY_AFTER_MS = 2_000;
3
+
4
+ const SECRET_RESOLUTION_RETRY_JITTER_CAPS_MS = [100, 250] as const;
5
+
6
+ export type SecretResolutionRetryDecision = {
7
+ retry: boolean;
8
+ retryDelayMs: number;
9
+ retryAfterMs: number | null;
10
+ retryAfterExceedsCap: boolean;
11
+ };
12
+
13
+ export function isRetryableSecretResolutionStatus(status: number): boolean {
14
+ return status === 429 || (status >= 500 && status <= 599);
15
+ }
16
+
17
+ function parsedRetryAfterMs(
18
+ value: string | null,
19
+ nowMs: number,
20
+ ): number | null {
21
+ const normalized = value?.trim();
22
+ if (!normalized) return null;
23
+ if (/^\d+$/.test(normalized)) {
24
+ const seconds = Number(normalized);
25
+ const milliseconds = seconds * 1_000;
26
+ return Number.isSafeInteger(milliseconds) ? milliseconds : null;
27
+ }
28
+ const deadlineMs = Date.parse(normalized);
29
+ if (!Number.isFinite(deadlineMs) || deadlineMs <= nowMs) return null;
30
+ return deadlineMs - nowMs;
31
+ }
32
+
33
+ function boundedRandom(value: number): number {
34
+ if (!Number.isFinite(value)) return 0;
35
+ return Math.min(Math.max(value, 0), 1);
36
+ }
37
+
38
+ export function secretResolutionRetryDecision(input: {
39
+ attempt: number;
40
+ retryAfter: string | null;
41
+ nowMs?: number;
42
+ random?: () => number;
43
+ }): SecretResolutionRetryDecision {
44
+ if (input.attempt >= SECRET_RESOLUTION_MAX_ATTEMPTS) {
45
+ return {
46
+ retry: false,
47
+ retryDelayMs: 0,
48
+ retryAfterMs: null,
49
+ retryAfterExceedsCap: false,
50
+ };
51
+ }
52
+
53
+ const retryAfterMs = parsedRetryAfterMs(
54
+ input.retryAfter,
55
+ input.nowMs ?? Date.now(),
56
+ );
57
+ if (retryAfterMs !== null) {
58
+ const retryAfterExceedsCap =
59
+ retryAfterMs > SECRET_RESOLUTION_MAX_RETRY_AFTER_MS;
60
+ return {
61
+ retry: !retryAfterExceedsCap,
62
+ retryDelayMs: retryAfterExceedsCap ? 0 : retryAfterMs,
63
+ retryAfterMs,
64
+ retryAfterExceedsCap,
65
+ };
66
+ }
67
+
68
+ const jitterCapMs =
69
+ SECRET_RESOLUTION_RETRY_JITTER_CAPS_MS[input.attempt - 1] ??
70
+ SECRET_RESOLUTION_RETRY_JITTER_CAPS_MS[1];
71
+ const retryDelayMs = Math.floor(
72
+ boundedRandom((input.random ?? Math.random)()) * (jitterCapMs + 1),
73
+ );
74
+ return {
75
+ retry: true,
76
+ retryDelayMs: Math.min(retryDelayMs, jitterCapMs),
77
+ retryAfterMs: null,
78
+ retryAfterExceedsCap: false,
79
+ };
80
+ }
@@ -1,4 +1,4 @@
1
- import ts from 'typescript';
1
+ import * as ts from 'typescript';
2
2
 
3
3
  type SourceMetadata = {
4
4
  name: string | null;
@@ -37,7 +37,8 @@ function buildContext(sourceFile: ts.SourceFile): SourceContext {
37
37
  for (const statement of sourceFile.statements) {
38
38
  if (ts.isVariableStatement(statement)) {
39
39
  const exported = statement.modifiers?.some(
40
- (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,
40
+ (modifier: ts.ModifierLike) =>
41
+ modifier.kind === ts.SyntaxKind.ExportKeyword,
41
42
  );
42
43
  const immutable = Boolean(
43
44
  statement.declarationList.flags & ts.NodeFlags.Const,
package/dist/cli/index.js CHANGED
@@ -184,7 +184,7 @@ configureProxyFromEnv();
184
184
  var import_promises6 = require("fs/promises");
185
185
  var import_node_path20 = require("path");
186
186
  var import_node_os15 = require("os");
187
- var import_commander3 = require("commander");
187
+ var import_commander4 = require("commander");
188
188
 
189
189
  // src/config.ts
190
190
  var import_node_fs = require("fs");
@@ -635,7 +635,8 @@ var SDK_RELEASE = {
635
635
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
636
636
  // Deepline-native radars. Older clients must update before discovering,
637
637
  // checking, or deploying an unlaunched monitor integration.
638
- version: "0.1.253",
638
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
639
+ version: "0.1.255",
639
640
  apiContract: "2026-07-native-monitor-launch-hard-cutover",
640
641
  supportPolicy: {
641
642
  minimumSupported: "0.1.53",
@@ -643,8 +644,8 @@ var SDK_RELEASE = {
643
644
  commandMinimumSupported: [
644
645
  {
645
646
  command: "enrich",
646
- minimumSupported: "0.1.238",
647
- reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH.'
647
+ minimumSupported: "0.1.253",
648
+ reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH; SDK CLI enrich before 0.1.253 opens the generated play page by default and accepts the removed --no-open flag.'
648
649
  },
649
650
  {
650
651
  command: "plays",
@@ -653,14 +654,14 @@ var SDK_RELEASE = {
653
654
  },
654
655
  {
655
656
  command: "plays run",
656
- minimumSupported: "0.1.241",
657
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
657
+ minimumSupported: "0.1.253",
658
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
658
659
  },
659
660
  {
660
661
  command: "run",
661
662
  displayCommand: "plays run",
662
- minimumSupported: "0.1.241",
663
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
663
+ minimumSupported: "0.1.253",
664
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
664
665
  },
665
666
  {
666
667
  command: "plays check",
@@ -723,6 +724,7 @@ var SDK_RELEASE = {
723
724
  reason: "Run result row datasets now use the dataset-handle export contract."
724
725
  }
725
726
  ],
727
+ directToolsCompatibilityVersions: ["0.1.171"],
726
728
  autoUpdatePatchLag: 2
727
729
  }
728
730
  };
@@ -9017,6 +9019,7 @@ Examples:
9017
9019
  var import_promises3 = require("fs/promises");
9018
9020
  var import_node_os8 = require("os");
9019
9021
  var import_node_path12 = require("path");
9022
+ var import_commander2 = require("commander");
9020
9023
 
9021
9024
  // src/cli/commands/play.ts
9022
9025
  var import_node_crypto4 = require("crypto");
@@ -11270,7 +11273,7 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
11270
11273
  "--logs",
11271
11274
  "--full",
11272
11275
  "--force",
11273
- "--no-open",
11276
+ "--open",
11274
11277
  "--debug-map-latency"
11275
11278
  ]);
11276
11279
  function traceCliSync(phase, fields, run) {
@@ -12557,11 +12560,10 @@ function buildPlayDashboardUrl(baseUrl, playName) {
12557
12560
  const encodedPlayName = encodeURIComponent(playName);
12558
12561
  return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
12559
12562
  }
12560
- function openPlayDashboard(input2) {
12561
- if (input2.noOpen || !input2.dashboardUrl) {
12562
- return;
12563
+ function openPlayDashboard(dashboardUrl, open) {
12564
+ if (open && dashboardUrl) {
12565
+ openInBrowser(dashboardUrl);
12563
12566
  }
12564
- openInBrowser(input2.dashboardUrl);
12565
12567
  }
12566
12568
  function printPlayLogLines(input2) {
12567
12569
  for (const line of input2.lines) {
@@ -12880,10 +12882,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12880
12882
  progress: input2.progress
12881
12883
  });
12882
12884
  }
12883
- openPlayDashboard({
12884
- dashboardUrl,
12885
- noOpen: input2.noOpen
12886
- });
12885
+ openPlayDashboard(dashboardUrl, input2.open ?? false);
12887
12886
  input2.progress.phase("running");
12888
12887
  emittedDashboardUrl = true;
12889
12888
  }
@@ -14156,7 +14155,7 @@ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
14156
14155
  if (options.waitTimeoutMs !== null) {
14157
14156
  parts.push("--tail-timeout-ms", String(options.waitTimeoutMs));
14158
14157
  }
14159
- if (options.noOpen) parts.push("--no-open");
14158
+ if (options.open) parts.push("--open");
14160
14159
  if (options.fullJson) parts.push("--full");
14161
14160
  if (options.jsonOutput && options.emitLogs) parts.push("--logs");
14162
14161
  if (options.jsonOutput) parts.push("--json");
@@ -14993,7 +14992,7 @@ function writeStartedPlayRun(input2) {
14993
14992
  );
14994
14993
  }
14995
14994
  function parsePlayRunOptions(args) {
14996
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
14995
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
14997
14996
  let filePath = null;
14998
14997
  let playName = null;
14999
14998
  let input2 = null;
@@ -15004,7 +15003,7 @@ function parsePlayRunOptions(args) {
15004
15003
  const fullJson = args.includes("--full");
15005
15004
  const emitLogs = !jsonOutput || args.includes("--logs");
15006
15005
  const force = args.includes("--force");
15007
- const noOpen = args.includes("--no-open");
15006
+ const open = args.includes("--open");
15008
15007
  const debugMapLatency = args.includes("--debug-map-latency");
15009
15008
  let waitTimeoutMs = null;
15010
15009
  let profile = null;
@@ -15049,6 +15048,11 @@ function parsePlayRunOptions(args) {
15049
15048
  "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
15050
15049
  );
15051
15050
  }
15051
+ if (arg === "--no-open" || arg.startsWith("--no-open=")) {
15052
+ throw new Error(
15053
+ "--no-open was removed for `plays run`. Play page URLs are printed by default; pass --open to launch a browser."
15054
+ );
15055
+ }
15052
15056
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
15053
15057
  throw new Error(
15054
15058
  `${arg} was removed. --watch uses the canonical run stream directly.`
@@ -15123,7 +15127,7 @@ function parsePlayRunOptions(args) {
15123
15127
  fullJson,
15124
15128
  waitTimeoutMs,
15125
15129
  force,
15126
- noOpen,
15130
+ open,
15127
15131
  profile,
15128
15132
  debugMapLatency
15129
15133
  };
@@ -15705,7 +15709,7 @@ async function handleFileBackedRun(options, hooks) {
15705
15709
  jsonOutput: options.jsonOutput,
15706
15710
  emitLogs: options.emitLogs,
15707
15711
  waitTimeoutMs: options.waitTimeoutMs,
15708
- noOpen: options.noOpen,
15712
+ open: options.open,
15709
15713
  progress,
15710
15714
  onRunStarted: hooks?.onRunStarted
15711
15715
  }).catch(async (error) => {
@@ -15748,10 +15752,7 @@ async function handleFileBackedRun(options, hooks) {
15748
15752
  })
15749
15753
  );
15750
15754
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15751
- openPlayDashboard({
15752
- dashboardUrl: resolvedDashboardUrl,
15753
- noOpen: options.noOpen
15754
- });
15755
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15755
15756
  progress.phase("started run");
15756
15757
  progress.complete();
15757
15758
  writeStartedPlayRun({
@@ -15872,7 +15873,7 @@ async function handleNamedRun(options, hooks) {
15872
15873
  jsonOutput: options.jsonOutput,
15873
15874
  emitLogs: options.emitLogs,
15874
15875
  waitTimeoutMs: options.waitTimeoutMs,
15875
- noOpen: options.noOpen,
15876
+ open: options.open,
15876
15877
  progress,
15877
15878
  onRunStarted: hooks?.onRunStarted
15878
15879
  }).catch(async (error) => {
@@ -15920,10 +15921,7 @@ async function handleNamedRun(options, hooks) {
15920
15921
  })
15921
15922
  );
15922
15923
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15923
- openPlayDashboard({
15924
- dashboardUrl: resolvedDashboardUrl,
15925
- noOpen: options.noOpen
15926
- });
15924
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15927
15925
  progress.phase("started run");
15928
15926
  progress.complete();
15929
15927
  writeStartedPlayRun({
@@ -17221,8 +17219,7 @@ Notes:
17221
17219
  next commands. --watch and --wait are accepted compatibility aliases for the
17222
17220
  default behavior. Use --no-wait only when you intentionally want
17223
17221
  a fire-and-forget run id.
17224
- The play page opens in your browser as soon as the run starts; use --no-open
17225
- to only print the URL.
17222
+ The play page URL is printed when the run starts. Pass --open to open it in a browser.
17226
17223
  Concurrent runs for the same play are allowed.
17227
17224
  --force starts a fresh run graph without refreshing completed provider calls.
17228
17225
  It does not cancel active sibling runs.
@@ -17277,10 +17274,10 @@ Examples:
17277
17274
  ).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(
17278
17275
  "--logs",
17279
17276
  "When output is non-interactive, stream play logs to stderr while waiting"
17280
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
17277
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option("--open", "Open the play page in a browser after the run starts").option(
17281
17278
  "--debug-map-latency",
17282
17279
  "Internal diagnostics: emit one aggregate latency profile per dataset map"
17283
- ).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(
17280
+ ).option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
17284
17281
  "afterAll",
17285
17282
  `
17286
17283
  Pass-through input flags:
@@ -17316,8 +17313,8 @@ Pass-through input flags:
17316
17313
  ...options.logs ? ["--logs"] : [],
17317
17314
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
17318
17315
  ...options.force ? ["--force"] : [],
17316
+ ...options.open ? ["--open"] : [],
17319
17317
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
17320
- ...options.noOpen || options.open === false ? ["--no-open"] : [],
17321
17318
  ...options.json ? ["--json"] : [],
17322
17319
  ...options.full ? ["--full"] : [],
17323
17320
  ...passthroughArgs
@@ -19903,11 +19900,11 @@ async function buildPlanArgs(args) {
19903
19900
  const localBooleanOptions = /* @__PURE__ */ new Set([
19904
19901
  "--dry-run",
19905
19902
  "--json",
19903
+ "--open",
19906
19904
  "--force",
19907
19905
  "--fail-fast",
19908
19906
  "--all",
19909
19907
  "--in-place",
19910
- "--no-open",
19911
19908
  "--debug-map-latency"
19912
19909
  ]);
19913
19910
  const planArgs = [];
@@ -22899,7 +22896,15 @@ function registerEnrichCommand(program) {
22899
22896
  ).option("--all", "Run all rows.").option(
22900
22897
  "--dry-run",
22901
22898
  "Compile and print the generated plan without starting a run."
22902
- ).option("--json", "Emit JSON.").option("--no-open", "Do not open the play page in a browser.").option("--force", "Force rerun for all enrich aliases.").option(
22899
+ ).option("--json", "Emit JSON.").option(
22900
+ "--open",
22901
+ "Open the generated play page in a browser after the run starts."
22902
+ ).addOption(
22903
+ new import_commander2.Option(
22904
+ "--no-open [legacy-value]",
22905
+ "Removed legacy option"
22906
+ ).hideHelp()
22907
+ ).option("--force", "Force rerun for all enrich aliases.").option(
22903
22908
  "--with-force <aliases>",
22904
22909
  "Force rerun for selected aliases.",
22905
22910
  (value, previous = []) => [...previous, value]
@@ -22916,6 +22921,13 @@ function registerEnrichCommand(program) {
22916
22921
  "--fail-fast",
22917
22922
  "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
22918
22923
  ).action(async (options, _command) => {
22924
+ if (currentEnrichArgs().some(
22925
+ (arg) => arg === "--no-open" || arg.startsWith("--no-open=")
22926
+ )) {
22927
+ throw new Error(
22928
+ "--no-open was removed for `enrich`. Play page URLs are printed by default; pass --open to launch a browser."
22929
+ );
22930
+ }
22919
22931
  if (options.inPlace && options.dryRun) {
22920
22932
  throw new Error("--in-place is not supported with --dry-run.");
22921
22933
  }
@@ -23076,8 +23088,8 @@ function registerEnrichCommand(program) {
23076
23088
  if (options.debugMapLatency) {
23077
23089
  runArgs.push("--debug-map-latency");
23078
23090
  }
23079
- if (options.noOpen || input2.suppressOpen) {
23080
- runArgs.push("--no-open");
23091
+ if (options.open) {
23092
+ runArgs.push("--open");
23081
23093
  }
23082
23094
  if (input2.json) {
23083
23095
  runArgs.push("--json");
@@ -26205,7 +26217,7 @@ Examples:
26205
26217
  }
26206
26218
 
26207
26219
  // src/cli/commands/tools.ts
26208
- var import_commander2 = require("commander");
26220
+ var import_commander3 = require("commander");
26209
26221
  var import_node_fs15 = require("fs");
26210
26222
  var import_node_os12 = require("os");
26211
26223
  var import_node_path16 = require("path");
@@ -26930,12 +26942,12 @@ Examples:
26930
26942
  "--examples-only",
26931
26943
  "Only print runnable examples and sample payloads"
26932
26944
  ).option("--getters-only", "Only print extracted list/value getters").addOption(
26933
- new import_commander2.Option(
26945
+ new import_commander3.Option(
26934
26946
  "--compact",
26935
26947
  "Compatibility alias for the default compact view"
26936
26948
  ).hideHelp()
26937
26949
  ).addOption(
26938
- new import_commander2.Option(
26950
+ new import_commander3.Option(
26939
26951
  "--contract-json",
26940
26952
  "Compatibility alias for compact contract JSON"
26941
26953
  ).hideHelp()
@@ -30179,7 +30191,6 @@ async function runPlayRunnerHealthCheck() {
30179
30191
  "--input",
30180
30192
  "{}",
30181
30193
  "--watch",
30182
- "--no-open",
30183
30194
  "--json"
30184
30195
  ]);
30185
30196
  } finally {
@@ -30328,7 +30339,7 @@ async function main() {
30328
30339
  if (printStartupPhase) {
30329
30340
  progress?.phase("loading deepline cli");
30330
30341
  }
30331
- const program = new import_commander3.Command();
30342
+ const program = new import_commander4.Command();
30332
30343
  program.name("deepline").description(
30333
30344
  "Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
30334
30345
  ).version(SDK_VERSION, "-v, --version", "Show version").exitOverride().showHelpAfterError().showSuggestionAfterError(true).addHelpText(
@@ -161,7 +161,7 @@ configureProxyFromEnv();
161
161
  import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile5 } from "fs/promises";
162
162
  import { join as join15 } from "path";
163
163
  import { tmpdir as tmpdir4 } from "os";
164
- import { Command as Command3 } from "commander";
164
+ import { Command as Command4 } from "commander";
165
165
 
166
166
  // src/config.ts
167
167
  import {
@@ -620,7 +620,8 @@ var SDK_RELEASE = {
620
620
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
621
621
  // Deepline-native radars. Older clients must update before discovering,
622
622
  // checking, or deploying an unlaunched monitor integration.
623
- version: "0.1.253",
623
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
624
+ version: "0.1.255",
624
625
  apiContract: "2026-07-native-monitor-launch-hard-cutover",
625
626
  supportPolicy: {
626
627
  minimumSupported: "0.1.53",
@@ -628,8 +629,8 @@ var SDK_RELEASE = {
628
629
  commandMinimumSupported: [
629
630
  {
630
631
  command: "enrich",
631
- minimumSupported: "0.1.238",
632
- reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH.'
632
+ minimumSupported: "0.1.253",
633
+ reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH; SDK CLI enrich before 0.1.253 opens the generated play page by default and accepts the removed --no-open flag.'
633
634
  },
634
635
  {
635
636
  command: "plays",
@@ -638,14 +639,14 @@ var SDK_RELEASE = {
638
639
  },
639
640
  {
640
641
  command: "plays run",
641
- minimumSupported: "0.1.241",
642
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
642
+ minimumSupported: "0.1.253",
643
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
643
644
  },
644
645
  {
645
646
  command: "run",
646
647
  displayCommand: "plays run",
647
- minimumSupported: "0.1.241",
648
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
648
+ minimumSupported: "0.1.253",
649
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
649
650
  },
650
651
  {
651
652
  command: "plays check",
@@ -708,6 +709,7 @@ var SDK_RELEASE = {
708
709
  reason: "Run result row datasets now use the dataset-handle export contract."
709
710
  }
710
711
  ],
712
+ directToolsCompatibilityVersions: ["0.1.171"],
711
713
  autoUpdatePatchLag: 2
712
714
  }
713
715
  };
@@ -9033,6 +9035,7 @@ import {
9033
9035
  } from "fs/promises";
9034
9036
  import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
9035
9037
  import { basename as basename2, dirname as dirname7, extname, join as join7, resolve as resolve9 } from "path";
9038
+ import { Option } from "commander";
9036
9039
 
9037
9040
  // src/cli/commands/play.ts
9038
9041
  import { createHash as createHash2 } from "crypto";
@@ -11299,7 +11302,7 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
11299
11302
  "--logs",
11300
11303
  "--full",
11301
11304
  "--force",
11302
- "--no-open",
11305
+ "--open",
11303
11306
  "--debug-map-latency"
11304
11307
  ]);
11305
11308
  function traceCliSync(phase, fields, run) {
@@ -12586,11 +12589,10 @@ function buildPlayDashboardUrl(baseUrl, playName) {
12586
12589
  const encodedPlayName = encodeURIComponent(playName);
12587
12590
  return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
12588
12591
  }
12589
- function openPlayDashboard(input2) {
12590
- if (input2.noOpen || !input2.dashboardUrl) {
12591
- return;
12592
+ function openPlayDashboard(dashboardUrl, open) {
12593
+ if (open && dashboardUrl) {
12594
+ openInBrowser(dashboardUrl);
12592
12595
  }
12593
- openInBrowser(input2.dashboardUrl);
12594
12596
  }
12595
12597
  function printPlayLogLines(input2) {
12596
12598
  for (const line of input2.lines) {
@@ -12909,10 +12911,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12909
12911
  progress: input2.progress
12910
12912
  });
12911
12913
  }
12912
- openPlayDashboard({
12913
- dashboardUrl,
12914
- noOpen: input2.noOpen
12915
- });
12914
+ openPlayDashboard(dashboardUrl, input2.open ?? false);
12916
12915
  input2.progress.phase("running");
12917
12916
  emittedDashboardUrl = true;
12918
12917
  }
@@ -14185,7 +14184,7 @@ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
14185
14184
  if (options.waitTimeoutMs !== null) {
14186
14185
  parts.push("--tail-timeout-ms", String(options.waitTimeoutMs));
14187
14186
  }
14188
- if (options.noOpen) parts.push("--no-open");
14187
+ if (options.open) parts.push("--open");
14189
14188
  if (options.fullJson) parts.push("--full");
14190
14189
  if (options.jsonOutput && options.emitLogs) parts.push("--logs");
14191
14190
  if (options.jsonOutput) parts.push("--json");
@@ -15022,7 +15021,7 @@ function writeStartedPlayRun(input2) {
15022
15021
  );
15023
15022
  }
15024
15023
  function parsePlayRunOptions(args) {
15025
- const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
15024
+ const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--profile <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--profile <id>] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--open] [--json] [--full] [--<input> value]\n Runs use the Absurd CJS runtime.\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotent call caching and ctx.dataset guidance.";
15026
15025
  let filePath = null;
15027
15026
  let playName = null;
15028
15027
  let input2 = null;
@@ -15033,7 +15032,7 @@ function parsePlayRunOptions(args) {
15033
15032
  const fullJson = args.includes("--full");
15034
15033
  const emitLogs = !jsonOutput || args.includes("--logs");
15035
15034
  const force = args.includes("--force");
15036
- const noOpen = args.includes("--no-open");
15035
+ const open = args.includes("--open");
15037
15036
  const debugMapLatency = args.includes("--debug-map-latency");
15038
15037
  let waitTimeoutMs = null;
15039
15038
  let profile = null;
@@ -15078,6 +15077,11 @@ function parsePlayRunOptions(args) {
15078
15077
  "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
15079
15078
  );
15080
15079
  }
15080
+ if (arg === "--no-open" || arg.startsWith("--no-open=")) {
15081
+ throw new Error(
15082
+ "--no-open was removed for `plays run`. Play page URLs are printed by default; pass --open to launch a browser."
15083
+ );
15084
+ }
15081
15085
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
15082
15086
  throw new Error(
15083
15087
  `${arg} was removed. --watch uses the canonical run stream directly.`
@@ -15152,7 +15156,7 @@ function parsePlayRunOptions(args) {
15152
15156
  fullJson,
15153
15157
  waitTimeoutMs,
15154
15158
  force,
15155
- noOpen,
15159
+ open,
15156
15160
  profile,
15157
15161
  debugMapLatency
15158
15162
  };
@@ -15734,7 +15738,7 @@ async function handleFileBackedRun(options, hooks) {
15734
15738
  jsonOutput: options.jsonOutput,
15735
15739
  emitLogs: options.emitLogs,
15736
15740
  waitTimeoutMs: options.waitTimeoutMs,
15737
- noOpen: options.noOpen,
15741
+ open: options.open,
15738
15742
  progress,
15739
15743
  onRunStarted: hooks?.onRunStarted
15740
15744
  }).catch(async (error) => {
@@ -15777,10 +15781,7 @@ async function handleFileBackedRun(options, hooks) {
15777
15781
  })
15778
15782
  );
15779
15783
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15780
- openPlayDashboard({
15781
- dashboardUrl: resolvedDashboardUrl,
15782
- noOpen: options.noOpen
15783
- });
15784
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15784
15785
  progress.phase("started run");
15785
15786
  progress.complete();
15786
15787
  writeStartedPlayRun({
@@ -15901,7 +15902,7 @@ async function handleNamedRun(options, hooks) {
15901
15902
  jsonOutput: options.jsonOutput,
15902
15903
  emitLogs: options.emitLogs,
15903
15904
  waitTimeoutMs: options.waitTimeoutMs,
15904
- noOpen: options.noOpen,
15905
+ open: options.open,
15905
15906
  progress,
15906
15907
  onRunStarted: hooks?.onRunStarted
15907
15908
  }).catch(async (error) => {
@@ -15949,10 +15950,7 @@ async function handleNamedRun(options, hooks) {
15949
15950
  })
15950
15951
  );
15951
15952
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15952
- openPlayDashboard({
15953
- dashboardUrl: resolvedDashboardUrl,
15954
- noOpen: options.noOpen
15955
- });
15953
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15956
15954
  progress.phase("started run");
15957
15955
  progress.complete();
15958
15956
  writeStartedPlayRun({
@@ -17250,8 +17248,7 @@ Notes:
17250
17248
  next commands. --watch and --wait are accepted compatibility aliases for the
17251
17249
  default behavior. Use --no-wait only when you intentionally want
17252
17250
  a fire-and-forget run id.
17253
- The play page opens in your browser as soon as the run starts; use --no-open
17254
- to only print the URL.
17251
+ The play page URL is printed when the run starts. Pass --open to open it in a browser.
17255
17252
  Concurrent runs for the same play are allowed.
17256
17253
  --force starts a fresh run graph without refreshing completed provider calls.
17257
17254
  It does not cancel active sibling runs.
@@ -17306,10 +17303,10 @@ Examples:
17306
17303
  ).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(
17307
17304
  "--logs",
17308
17305
  "When output is non-interactive, stream play logs to stderr while waiting"
17309
- ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option(
17306
+ ).option("--tail-timeout-ms <ms>", "Timeout while watching the run stream").option("--force", "Start a fresh run graph").option("--open", "Open the play page in a browser after the run starts").option(
17310
17307
  "--debug-map-latency",
17311
17308
  "Internal diagnostics: emit one aggregate latency profile per dataset map"
17312
- ).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(
17309
+ ).option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
17313
17310
  "afterAll",
17314
17311
  `
17315
17312
  Pass-through input flags:
@@ -17345,8 +17342,8 @@ Pass-through input flags:
17345
17342
  ...options.logs ? ["--logs"] : [],
17346
17343
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
17347
17344
  ...options.force ? ["--force"] : [],
17345
+ ...options.open ? ["--open"] : [],
17348
17346
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
17349
- ...options.noOpen || options.open === false ? ["--no-open"] : [],
17350
17347
  ...options.json ? ["--json"] : [],
17351
17348
  ...options.full ? ["--full"] : [],
17352
17349
  ...passthroughArgs
@@ -19932,11 +19929,11 @@ async function buildPlanArgs(args) {
19932
19929
  const localBooleanOptions = /* @__PURE__ */ new Set([
19933
19930
  "--dry-run",
19934
19931
  "--json",
19932
+ "--open",
19935
19933
  "--force",
19936
19934
  "--fail-fast",
19937
19935
  "--all",
19938
19936
  "--in-place",
19939
- "--no-open",
19940
19937
  "--debug-map-latency"
19941
19938
  ]);
19942
19939
  const planArgs = [];
@@ -22928,7 +22925,15 @@ function registerEnrichCommand(program) {
22928
22925
  ).option("--all", "Run all rows.").option(
22929
22926
  "--dry-run",
22930
22927
  "Compile and print the generated plan without starting a run."
22931
- ).option("--json", "Emit JSON.").option("--no-open", "Do not open the play page in a browser.").option("--force", "Force rerun for all enrich aliases.").option(
22928
+ ).option("--json", "Emit JSON.").option(
22929
+ "--open",
22930
+ "Open the generated play page in a browser after the run starts."
22931
+ ).addOption(
22932
+ new Option(
22933
+ "--no-open [legacy-value]",
22934
+ "Removed legacy option"
22935
+ ).hideHelp()
22936
+ ).option("--force", "Force rerun for all enrich aliases.").option(
22932
22937
  "--with-force <aliases>",
22933
22938
  "Force rerun for selected aliases.",
22934
22939
  (value, previous = []) => [...previous, value]
@@ -22945,6 +22950,13 @@ function registerEnrichCommand(program) {
22945
22950
  "--fail-fast",
22946
22951
  "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
22947
22952
  ).action(async (options, _command) => {
22953
+ if (currentEnrichArgs().some(
22954
+ (arg) => arg === "--no-open" || arg.startsWith("--no-open=")
22955
+ )) {
22956
+ throw new Error(
22957
+ "--no-open was removed for `enrich`. Play page URLs are printed by default; pass --open to launch a browser."
22958
+ );
22959
+ }
22948
22960
  if (options.inPlace && options.dryRun) {
22949
22961
  throw new Error("--in-place is not supported with --dry-run.");
22950
22962
  }
@@ -23105,8 +23117,8 @@ function registerEnrichCommand(program) {
23105
23117
  if (options.debugMapLatency) {
23106
23118
  runArgs.push("--debug-map-latency");
23107
23119
  }
23108
- if (options.noOpen || input2.suppressOpen) {
23109
- runArgs.push("--no-open");
23120
+ if (options.open) {
23121
+ runArgs.push("--open");
23110
23122
  }
23111
23123
  if (input2.json) {
23112
23124
  runArgs.push("--json");
@@ -26241,7 +26253,7 @@ Examples:
26241
26253
  }
26242
26254
 
26243
26255
  // src/cli/commands/tools.ts
26244
- import { Option } from "commander";
26256
+ import { Option as Option2 } from "commander";
26245
26257
  import {
26246
26258
  chmodSync,
26247
26259
  existsSync as existsSync10,
@@ -26978,12 +26990,12 @@ Examples:
26978
26990
  "--examples-only",
26979
26991
  "Only print runnable examples and sample payloads"
26980
26992
  ).option("--getters-only", "Only print extracted list/value getters").addOption(
26981
- new Option(
26993
+ new Option2(
26982
26994
  "--compact",
26983
26995
  "Compatibility alias for the default compact view"
26984
26996
  ).hideHelp()
26985
26997
  ).addOption(
26986
- new Option(
26998
+ new Option2(
26987
26999
  "--contract-json",
26988
27000
  "Compatibility alias for compact contract JSON"
26989
27001
  ).hideHelp()
@@ -30242,7 +30254,6 @@ async function runPlayRunnerHealthCheck() {
30242
30254
  "--input",
30243
30255
  "{}",
30244
30256
  "--watch",
30245
- "--no-open",
30246
30257
  "--json"
30247
30258
  ]);
30248
30259
  } finally {
@@ -30391,7 +30402,7 @@ async function main() {
30391
30402
  if (printStartupPhase) {
30392
30403
  progress?.phase("loading deepline cli");
30393
30404
  }
30394
- const program = new Command3();
30405
+ const program = new Command4();
30395
30406
  program.name("deepline").description(
30396
30407
  "Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
30397
30408
  ).version(SDK_VERSION, "-v, --version", "Show version").exitOverride().showHelpAfterError().showSuggestionAfterError(true).addHelpText(
package/dist/index.js CHANGED
@@ -434,7 +434,8 @@ var SDK_RELEASE = {
434
434
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
435
435
  // Deepline-native radars. Older clients must update before discovering,
436
436
  // checking, or deploying an unlaunched monitor integration.
437
- version: "0.1.253",
437
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
438
+ version: "0.1.255",
438
439
  apiContract: "2026-07-native-monitor-launch-hard-cutover",
439
440
  supportPolicy: {
440
441
  minimumSupported: "0.1.53",
@@ -442,8 +443,8 @@ var SDK_RELEASE = {
442
443
  commandMinimumSupported: [
443
444
  {
444
445
  command: "enrich",
445
- minimumSupported: "0.1.238",
446
- reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH.'
446
+ minimumSupported: "0.1.253",
447
+ reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH; SDK CLI enrich before 0.1.253 opens the generated play page by default and accepts the removed --no-open flag.'
447
448
  },
448
449
  {
449
450
  command: "plays",
@@ -452,14 +453,14 @@ var SDK_RELEASE = {
452
453
  },
453
454
  {
454
455
  command: "plays run",
455
- minimumSupported: "0.1.241",
456
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
456
+ minimumSupported: "0.1.253",
457
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
457
458
  },
458
459
  {
459
460
  command: "run",
460
461
  displayCommand: "plays run",
461
- minimumSupported: "0.1.241",
462
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
462
+ minimumSupported: "0.1.253",
463
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
463
464
  },
464
465
  {
465
466
  command: "plays check",
@@ -522,6 +523,7 @@ var SDK_RELEASE = {
522
523
  reason: "Run result row datasets now use the dataset-handle export contract."
523
524
  }
524
525
  ],
526
+ directToolsCompatibilityVersions: ["0.1.171"],
525
527
  autoUpdatePatchLag: 2
526
528
  }
527
529
  };
package/dist/index.mjs CHANGED
@@ -364,7 +364,8 @@ var SDK_RELEASE = {
364
364
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
365
365
  // Deepline-native radars. Older clients must update before discovering,
366
366
  // checking, or deploying an unlaunched monitor integration.
367
- version: "0.1.253",
367
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
+ version: "0.1.255",
368
369
  apiContract: "2026-07-native-monitor-launch-hard-cutover",
369
370
  supportPolicy: {
370
371
  minimumSupported: "0.1.53",
@@ -372,8 +373,8 @@ var SDK_RELEASE = {
372
373
  commandMinimumSupported: [
373
374
  {
374
375
  command: "enrich",
375
- minimumSupported: "0.1.238",
376
- reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH.'
376
+ minimumSupported: "0.1.253",
377
+ reason: 'Older SDK CLI enrich generated stale play source; SDK CLI enrich 0.1.153 generated removed StepOptions fields in play source; SDK CLI enrich before 0.1.175 could silently succeed on the empty-waterfall bug when a requested waterfall returned no values for selected rows; SDK CLI enrich before 0.1.230 could convert extractor failures into successful unmatched results; SDK CLI enrich before 0.1.238 could drop a nested provider email match during generic pick("email") extraction and materialize it as NO_MATCH; SDK CLI enrich before 0.1.253 opens the generated play page by default and accepts the removed --no-open flag.'
377
378
  },
378
379
  {
379
380
  command: "plays",
@@ -382,14 +383,14 @@ var SDK_RELEASE = {
382
383
  },
383
384
  {
384
385
  command: "plays run",
385
- minimumSupported: "0.1.241",
386
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
386
+ minimumSupported: "0.1.253",
387
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
387
388
  },
388
389
  {
389
390
  command: "run",
390
391
  displayCommand: "plays run",
391
- minimumSupported: "0.1.241",
392
- reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract."
392
+ minimumSupported: "0.1.253",
393
+ reason: "Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract; versions before 0.1.253 open the play page by default and accept the removed --no-open flag."
393
394
  },
394
395
  {
395
396
  command: "plays check",
@@ -452,6 +453,7 @@ var SDK_RELEASE = {
452
453
  reason: "Run result row datasets now use the dataset-handle export contract."
453
454
  }
454
455
  ],
456
+ directToolsCompatibilityVersions: ["0.1.171"],
455
457
  autoUpdatePatchLag: 2
456
458
  }
457
459
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.253",
3
+ "version": "0.1.255",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -59,7 +59,7 @@
59
59
  "devDependencies": {
60
60
  "@types/node": "^20.0.0",
61
61
  "tsup": "^8.0.0",
62
- "typescript": "^5.9.3"
62
+ "typescript": "^6.0.2"
63
63
  },
64
64
  "deepline": {
65
65
  "apiContract": "2026-07-native-monitor-launch-hard-cutover"