deepline 0.1.253 → 0.1.254

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.
@@ -116,7 +116,8 @@ export const SDK_RELEASE = {
116
116
  // 0.1.252 hard-cuts the customer Monitor catalog to the two launched
117
117
  // Deepline-native radars. Older clients must update before discovering,
118
118
  // checking, or deploying an unlaunched monitor integration.
119
- version: '0.1.253',
119
+ // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
120
+ version: '0.1.254',
120
121
  apiContract: '2026-07-native-monitor-launch-hard-cutover',
121
122
  supportPolicy: {
122
123
  minimumSupported: '0.1.53',
@@ -124,9 +125,9 @@ export const SDK_RELEASE = {
124
125
  commandMinimumSupported: [
125
126
  {
126
127
  command: 'enrich',
127
- minimumSupported: '0.1.238',
128
+ minimumSupported: '0.1.253',
128
129
  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.',
130
+ '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
131
  },
131
132
  {
132
133
  command: 'plays',
@@ -136,16 +137,16 @@ export const SDK_RELEASE = {
136
137
  },
137
138
  {
138
139
  command: 'plays run',
139
- minimumSupported: '0.1.241',
140
+ minimumSupported: '0.1.253',
140
141
  reason:
141
- 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
142
+ '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
143
  },
143
144
  {
144
145
  command: 'run',
145
146
  displayCommand: 'plays run',
146
- minimumSupported: '0.1.241',
147
+ minimumSupported: '0.1.253',
147
148
  reason:
148
- 'Older SDK CLI versions predate dataset-native Play results and can emit the retired esm_workers artifact contract.',
149
+ '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
150
  },
150
151
  {
151
152
  command: 'plays check',
@@ -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
+ }
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.254",
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",
@@ -9017,6 +9018,7 @@ Examples:
9017
9018
  var import_promises3 = require("fs/promises");
9018
9019
  var import_node_os8 = require("os");
9019
9020
  var import_node_path12 = require("path");
9021
+ var import_commander2 = require("commander");
9020
9022
 
9021
9023
  // src/cli/commands/play.ts
9022
9024
  var import_node_crypto4 = require("crypto");
@@ -11270,7 +11272,7 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
11270
11272
  "--logs",
11271
11273
  "--full",
11272
11274
  "--force",
11273
- "--no-open",
11275
+ "--open",
11274
11276
  "--debug-map-latency"
11275
11277
  ]);
11276
11278
  function traceCliSync(phase, fields, run) {
@@ -12557,11 +12559,10 @@ function buildPlayDashboardUrl(baseUrl, playName) {
12557
12559
  const encodedPlayName = encodeURIComponent(playName);
12558
12560
  return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
12559
12561
  }
12560
- function openPlayDashboard(input2) {
12561
- if (input2.noOpen || !input2.dashboardUrl) {
12562
- return;
12562
+ function openPlayDashboard(dashboardUrl, open) {
12563
+ if (open && dashboardUrl) {
12564
+ openInBrowser(dashboardUrl);
12563
12565
  }
12564
- openInBrowser(input2.dashboardUrl);
12565
12566
  }
12566
12567
  function printPlayLogLines(input2) {
12567
12568
  for (const line of input2.lines) {
@@ -12880,10 +12881,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12880
12881
  progress: input2.progress
12881
12882
  });
12882
12883
  }
12883
- openPlayDashboard({
12884
- dashboardUrl,
12885
- noOpen: input2.noOpen
12886
- });
12884
+ openPlayDashboard(dashboardUrl, input2.open ?? false);
12887
12885
  input2.progress.phase("running");
12888
12886
  emittedDashboardUrl = true;
12889
12887
  }
@@ -14156,7 +14154,7 @@ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
14156
14154
  if (options.waitTimeoutMs !== null) {
14157
14155
  parts.push("--tail-timeout-ms", String(options.waitTimeoutMs));
14158
14156
  }
14159
- if (options.noOpen) parts.push("--no-open");
14157
+ if (options.open) parts.push("--open");
14160
14158
  if (options.fullJson) parts.push("--full");
14161
14159
  if (options.jsonOutput && options.emitLogs) parts.push("--logs");
14162
14160
  if (options.jsonOutput) parts.push("--json");
@@ -14993,7 +14991,7 @@ function writeStartedPlayRun(input2) {
14993
14991
  );
14994
14992
  }
14995
14993
  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.";
14994
+ 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
14995
  let filePath = null;
14998
14996
  let playName = null;
14999
14997
  let input2 = null;
@@ -15004,7 +15002,7 @@ function parsePlayRunOptions(args) {
15004
15002
  const fullJson = args.includes("--full");
15005
15003
  const emitLogs = !jsonOutput || args.includes("--logs");
15006
15004
  const force = args.includes("--force");
15007
- const noOpen = args.includes("--no-open");
15005
+ const open = args.includes("--open");
15008
15006
  const debugMapLatency = args.includes("--debug-map-latency");
15009
15007
  let waitTimeoutMs = null;
15010
15008
  let profile = null;
@@ -15049,6 +15047,11 @@ function parsePlayRunOptions(args) {
15049
15047
  "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
15050
15048
  );
15051
15049
  }
15050
+ if (arg === "--no-open" || arg.startsWith("--no-open=")) {
15051
+ throw new Error(
15052
+ "--no-open was removed for `plays run`. Play page URLs are printed by default; pass --open to launch a browser."
15053
+ );
15054
+ }
15052
15055
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
15053
15056
  throw new Error(
15054
15057
  `${arg} was removed. --watch uses the canonical run stream directly.`
@@ -15123,7 +15126,7 @@ function parsePlayRunOptions(args) {
15123
15126
  fullJson,
15124
15127
  waitTimeoutMs,
15125
15128
  force,
15126
- noOpen,
15129
+ open,
15127
15130
  profile,
15128
15131
  debugMapLatency
15129
15132
  };
@@ -15705,7 +15708,7 @@ async function handleFileBackedRun(options, hooks) {
15705
15708
  jsonOutput: options.jsonOutput,
15706
15709
  emitLogs: options.emitLogs,
15707
15710
  waitTimeoutMs: options.waitTimeoutMs,
15708
- noOpen: options.noOpen,
15711
+ open: options.open,
15709
15712
  progress,
15710
15713
  onRunStarted: hooks?.onRunStarted
15711
15714
  }).catch(async (error) => {
@@ -15748,10 +15751,7 @@ async function handleFileBackedRun(options, hooks) {
15748
15751
  })
15749
15752
  );
15750
15753
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15751
- openPlayDashboard({
15752
- dashboardUrl: resolvedDashboardUrl,
15753
- noOpen: options.noOpen
15754
- });
15754
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15755
15755
  progress.phase("started run");
15756
15756
  progress.complete();
15757
15757
  writeStartedPlayRun({
@@ -15872,7 +15872,7 @@ async function handleNamedRun(options, hooks) {
15872
15872
  jsonOutput: options.jsonOutput,
15873
15873
  emitLogs: options.emitLogs,
15874
15874
  waitTimeoutMs: options.waitTimeoutMs,
15875
- noOpen: options.noOpen,
15875
+ open: options.open,
15876
15876
  progress,
15877
15877
  onRunStarted: hooks?.onRunStarted
15878
15878
  }).catch(async (error) => {
@@ -15920,10 +15920,7 @@ async function handleNamedRun(options, hooks) {
15920
15920
  })
15921
15921
  );
15922
15922
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15923
- openPlayDashboard({
15924
- dashboardUrl: resolvedDashboardUrl,
15925
- noOpen: options.noOpen
15926
- });
15923
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15927
15924
  progress.phase("started run");
15928
15925
  progress.complete();
15929
15926
  writeStartedPlayRun({
@@ -17221,8 +17218,7 @@ Notes:
17221
17218
  next commands. --watch and --wait are accepted compatibility aliases for the
17222
17219
  default behavior. Use --no-wait only when you intentionally want
17223
17220
  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.
17221
+ The play page URL is printed when the run starts. Pass --open to open it in a browser.
17226
17222
  Concurrent runs for the same play are allowed.
17227
17223
  --force starts a fresh run graph without refreshing completed provider calls.
17228
17224
  It does not cancel active sibling runs.
@@ -17277,10 +17273,10 @@ Examples:
17277
17273
  ).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
17274
  "--logs",
17279
17275
  "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(
17276
+ ).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
17277
  "--debug-map-latency",
17282
17278
  "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(
17279
+ ).option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
17284
17280
  "afterAll",
17285
17281
  `
17286
17282
  Pass-through input flags:
@@ -17316,8 +17312,8 @@ Pass-through input flags:
17316
17312
  ...options.logs ? ["--logs"] : [],
17317
17313
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
17318
17314
  ...options.force ? ["--force"] : [],
17315
+ ...options.open ? ["--open"] : [],
17319
17316
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
17320
- ...options.noOpen || options.open === false ? ["--no-open"] : [],
17321
17317
  ...options.json ? ["--json"] : [],
17322
17318
  ...options.full ? ["--full"] : [],
17323
17319
  ...passthroughArgs
@@ -19903,11 +19899,11 @@ async function buildPlanArgs(args) {
19903
19899
  const localBooleanOptions = /* @__PURE__ */ new Set([
19904
19900
  "--dry-run",
19905
19901
  "--json",
19902
+ "--open",
19906
19903
  "--force",
19907
19904
  "--fail-fast",
19908
19905
  "--all",
19909
19906
  "--in-place",
19910
- "--no-open",
19911
19907
  "--debug-map-latency"
19912
19908
  ]);
19913
19909
  const planArgs = [];
@@ -22899,7 +22895,15 @@ function registerEnrichCommand(program) {
22899
22895
  ).option("--all", "Run all rows.").option(
22900
22896
  "--dry-run",
22901
22897
  "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(
22898
+ ).option("--json", "Emit JSON.").option(
22899
+ "--open",
22900
+ "Open the generated play page in a browser after the run starts."
22901
+ ).addOption(
22902
+ new import_commander2.Option(
22903
+ "--no-open [legacy-value]",
22904
+ "Removed legacy option"
22905
+ ).hideHelp()
22906
+ ).option("--force", "Force rerun for all enrich aliases.").option(
22903
22907
  "--with-force <aliases>",
22904
22908
  "Force rerun for selected aliases.",
22905
22909
  (value, previous = []) => [...previous, value]
@@ -22916,6 +22920,13 @@ function registerEnrichCommand(program) {
22916
22920
  "--fail-fast",
22917
22921
  "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
22918
22922
  ).action(async (options, _command) => {
22923
+ if (currentEnrichArgs().some(
22924
+ (arg) => arg === "--no-open" || arg.startsWith("--no-open=")
22925
+ )) {
22926
+ throw new Error(
22927
+ "--no-open was removed for `enrich`. Play page URLs are printed by default; pass --open to launch a browser."
22928
+ );
22929
+ }
22919
22930
  if (options.inPlace && options.dryRun) {
22920
22931
  throw new Error("--in-place is not supported with --dry-run.");
22921
22932
  }
@@ -23076,8 +23087,8 @@ function registerEnrichCommand(program) {
23076
23087
  if (options.debugMapLatency) {
23077
23088
  runArgs.push("--debug-map-latency");
23078
23089
  }
23079
- if (options.noOpen || input2.suppressOpen) {
23080
- runArgs.push("--no-open");
23090
+ if (options.open) {
23091
+ runArgs.push("--open");
23081
23092
  }
23082
23093
  if (input2.json) {
23083
23094
  runArgs.push("--json");
@@ -26205,7 +26216,7 @@ Examples:
26205
26216
  }
26206
26217
 
26207
26218
  // src/cli/commands/tools.ts
26208
- var import_commander2 = require("commander");
26219
+ var import_commander3 = require("commander");
26209
26220
  var import_node_fs15 = require("fs");
26210
26221
  var import_node_os12 = require("os");
26211
26222
  var import_node_path16 = require("path");
@@ -26930,12 +26941,12 @@ Examples:
26930
26941
  "--examples-only",
26931
26942
  "Only print runnable examples and sample payloads"
26932
26943
  ).option("--getters-only", "Only print extracted list/value getters").addOption(
26933
- new import_commander2.Option(
26944
+ new import_commander3.Option(
26934
26945
  "--compact",
26935
26946
  "Compatibility alias for the default compact view"
26936
26947
  ).hideHelp()
26937
26948
  ).addOption(
26938
- new import_commander2.Option(
26949
+ new import_commander3.Option(
26939
26950
  "--contract-json",
26940
26951
  "Compatibility alias for compact contract JSON"
26941
26952
  ).hideHelp()
@@ -30179,7 +30190,6 @@ async function runPlayRunnerHealthCheck() {
30179
30190
  "--input",
30180
30191
  "{}",
30181
30192
  "--watch",
30182
- "--no-open",
30183
30193
  "--json"
30184
30194
  ]);
30185
30195
  } finally {
@@ -30328,7 +30338,7 @@ async function main() {
30328
30338
  if (printStartupPhase) {
30329
30339
  progress?.phase("loading deepline cli");
30330
30340
  }
30331
- const program = new import_commander3.Command();
30341
+ const program = new import_commander4.Command();
30332
30342
  program.name("deepline").description(
30333
30343
  "Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
30334
30344
  ).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.254",
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",
@@ -9033,6 +9034,7 @@ import {
9033
9034
  } from "fs/promises";
9034
9035
  import { homedir as homedir7, tmpdir as tmpdir2 } from "os";
9035
9036
  import { basename as basename2, dirname as dirname7, extname, join as join7, resolve as resolve9 } from "path";
9037
+ import { Option } from "commander";
9036
9038
 
9037
9039
  // src/cli/commands/play.ts
9038
9040
  import { createHash as createHash2 } from "crypto";
@@ -11299,7 +11301,7 @@ var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
11299
11301
  "--logs",
11300
11302
  "--full",
11301
11303
  "--force",
11302
- "--no-open",
11304
+ "--open",
11303
11305
  "--debug-map-latency"
11304
11306
  ]);
11305
11307
  function traceCliSync(phase, fields, run) {
@@ -12586,11 +12588,10 @@ function buildPlayDashboardUrl(baseUrl, playName) {
12586
12588
  const encodedPlayName = encodeURIComponent(playName);
12587
12589
  return `${trimmedBase}/dashboard/plays/${encodedPlayName}`;
12588
12590
  }
12589
- function openPlayDashboard(input2) {
12590
- if (input2.noOpen || !input2.dashboardUrl) {
12591
- return;
12591
+ function openPlayDashboard(dashboardUrl, open) {
12592
+ if (open && dashboardUrl) {
12593
+ openInBrowser(dashboardUrl);
12592
12594
  }
12593
- openInBrowser(input2.dashboardUrl);
12594
12595
  }
12595
12596
  function printPlayLogLines(input2) {
12596
12597
  for (const line of input2.lines) {
@@ -12909,10 +12910,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
12909
12910
  progress: input2.progress
12910
12911
  });
12911
12912
  }
12912
- openPlayDashboard({
12913
- dashboardUrl,
12914
- noOpen: input2.noOpen
12915
- });
12913
+ openPlayDashboard(dashboardUrl, input2.open ?? false);
12916
12914
  input2.progress.phase("running");
12917
12915
  emittedDashboardUrl = true;
12918
12916
  }
@@ -14185,7 +14183,7 @@ function buildOrdinaryPlayRunCommand(options, resolvedRevisionId) {
14185
14183
  if (options.waitTimeoutMs !== null) {
14186
14184
  parts.push("--tail-timeout-ms", String(options.waitTimeoutMs));
14187
14185
  }
14188
- if (options.noOpen) parts.push("--no-open");
14186
+ if (options.open) parts.push("--open");
14189
14187
  if (options.fullJson) parts.push("--full");
14190
14188
  if (options.jsonOutput && options.emitLogs) parts.push("--logs");
14191
14189
  if (options.jsonOutput) parts.push("--json");
@@ -15022,7 +15020,7 @@ function writeStartedPlayRun(input2) {
15022
15020
  );
15023
15021
  }
15024
15022
  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.";
15023
+ 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
15024
  let filePath = null;
15027
15025
  let playName = null;
15028
15026
  let input2 = null;
@@ -15033,7 +15031,7 @@ function parsePlayRunOptions(args) {
15033
15031
  const fullJson = args.includes("--full");
15034
15032
  const emitLogs = !jsonOutput || args.includes("--logs");
15035
15033
  const force = args.includes("--force");
15036
- const noOpen = args.includes("--no-open");
15034
+ const open = args.includes("--open");
15037
15035
  const debugMapLatency = args.includes("--debug-map-latency");
15038
15036
  let waitTimeoutMs = null;
15039
15037
  let profile = null;
@@ -15078,6 +15076,11 @@ function parsePlayRunOptions(args) {
15078
15076
  "--out is not a plays run flag. Run the play first, then export rows with: deepline runs export <run-id> --out output.csv"
15079
15077
  );
15080
15078
  }
15079
+ if (arg === "--no-open" || arg.startsWith("--no-open=")) {
15080
+ throw new Error(
15081
+ "--no-open was removed for `plays run`. Play page URLs are printed by default; pass --open to launch a browser."
15082
+ );
15083
+ }
15081
15084
  if (arg === "--poll-interval-ms" || arg === "--interval-ms") {
15082
15085
  throw new Error(
15083
15086
  `${arg} was removed. --watch uses the canonical run stream directly.`
@@ -15152,7 +15155,7 @@ function parsePlayRunOptions(args) {
15152
15155
  fullJson,
15153
15156
  waitTimeoutMs,
15154
15157
  force,
15155
- noOpen,
15158
+ open,
15156
15159
  profile,
15157
15160
  debugMapLatency
15158
15161
  };
@@ -15734,7 +15737,7 @@ async function handleFileBackedRun(options, hooks) {
15734
15737
  jsonOutput: options.jsonOutput,
15735
15738
  emitLogs: options.emitLogs,
15736
15739
  waitTimeoutMs: options.waitTimeoutMs,
15737
- noOpen: options.noOpen,
15740
+ open: options.open,
15738
15741
  progress,
15739
15742
  onRunStarted: hooks?.onRunStarted
15740
15743
  }).catch(async (error) => {
@@ -15777,10 +15780,7 @@ async function handleFileBackedRun(options, hooks) {
15777
15780
  })
15778
15781
  );
15779
15782
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15780
- openPlayDashboard({
15781
- dashboardUrl: resolvedDashboardUrl,
15782
- noOpen: options.noOpen
15783
- });
15783
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15784
15784
  progress.phase("started run");
15785
15785
  progress.complete();
15786
15786
  writeStartedPlayRun({
@@ -15901,7 +15901,7 @@ async function handleNamedRun(options, hooks) {
15901
15901
  jsonOutput: options.jsonOutput,
15902
15902
  emitLogs: options.emitLogs,
15903
15903
  waitTimeoutMs: options.waitTimeoutMs,
15904
- noOpen: options.noOpen,
15904
+ open: options.open,
15905
15905
  progress,
15906
15906
  onRunStarted: hooks?.onRunStarted
15907
15907
  }).catch(async (error) => {
@@ -15949,10 +15949,7 @@ async function handleNamedRun(options, hooks) {
15949
15949
  })
15950
15950
  );
15951
15951
  const resolvedDashboardUrl = buildPlayDashboardUrl(client2.baseUrl, playName);
15952
- openPlayDashboard({
15953
- dashboardUrl: resolvedDashboardUrl,
15954
- noOpen: options.noOpen
15955
- });
15952
+ openPlayDashboard(resolvedDashboardUrl, options.open);
15956
15953
  progress.phase("started run");
15957
15954
  progress.complete();
15958
15955
  writeStartedPlayRun({
@@ -17250,8 +17247,7 @@ Notes:
17250
17247
  next commands. --watch and --wait are accepted compatibility aliases for the
17251
17248
  default behavior. Use --no-wait only when you intentionally want
17252
17249
  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.
17250
+ The play page URL is printed when the run starts. Pass --open to open it in a browser.
17255
17251
  Concurrent runs for the same play are allowed.
17256
17252
  --force starts a fresh run graph without refreshing completed provider calls.
17257
17253
  It does not cancel active sibling runs.
@@ -17306,10 +17302,10 @@ Examples:
17306
17302
  ).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
17303
  "--logs",
17308
17304
  "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(
17305
+ ).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
17306
  "--debug-map-latency",
17311
17307
  "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(
17308
+ ).option("--json", "Emit JSON output").option("--full", "Debug only: with --json, emit the raw status payload").addHelpText(
17313
17309
  "afterAll",
17314
17310
  `
17315
17311
  Pass-through input flags:
@@ -17345,8 +17341,8 @@ Pass-through input flags:
17345
17341
  ...options.logs ? ["--logs"] : [],
17346
17342
  ...options.tailTimeoutMs ? ["--tail-timeout-ms", options.tailTimeoutMs] : [],
17347
17343
  ...options.force ? ["--force"] : [],
17344
+ ...options.open ? ["--open"] : [],
17348
17345
  ...options.debugMapLatency ? ["--debug-map-latency"] : [],
17349
- ...options.noOpen || options.open === false ? ["--no-open"] : [],
17350
17346
  ...options.json ? ["--json"] : [],
17351
17347
  ...options.full ? ["--full"] : [],
17352
17348
  ...passthroughArgs
@@ -19932,11 +19928,11 @@ async function buildPlanArgs(args) {
19932
19928
  const localBooleanOptions = /* @__PURE__ */ new Set([
19933
19929
  "--dry-run",
19934
19930
  "--json",
19931
+ "--open",
19935
19932
  "--force",
19936
19933
  "--fail-fast",
19937
19934
  "--all",
19938
19935
  "--in-place",
19939
- "--no-open",
19940
19936
  "--debug-map-latency"
19941
19937
  ]);
19942
19938
  const planArgs = [];
@@ -22928,7 +22924,15 @@ function registerEnrichCommand(program) {
22928
22924
  ).option("--all", "Run all rows.").option(
22929
22925
  "--dry-run",
22930
22926
  "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(
22927
+ ).option("--json", "Emit JSON.").option(
22928
+ "--open",
22929
+ "Open the generated play page in a browser after the run starts."
22930
+ ).addOption(
22931
+ new Option(
22932
+ "--no-open [legacy-value]",
22933
+ "Removed legacy option"
22934
+ ).hideHelp()
22935
+ ).option("--force", "Force rerun for all enrich aliases.").option(
22932
22936
  "--with-force <aliases>",
22933
22937
  "Force rerun for selected aliases.",
22934
22938
  (value, previous = []) => [...previous, value]
@@ -22945,6 +22949,13 @@ function registerEnrichCommand(program) {
22945
22949
  "--fail-fast",
22946
22950
  "Fail the generated play when any selected row errors, while preserving recovered runtime-sheet rows for export."
22947
22951
  ).action(async (options, _command) => {
22952
+ if (currentEnrichArgs().some(
22953
+ (arg) => arg === "--no-open" || arg.startsWith("--no-open=")
22954
+ )) {
22955
+ throw new Error(
22956
+ "--no-open was removed for `enrich`. Play page URLs are printed by default; pass --open to launch a browser."
22957
+ );
22958
+ }
22948
22959
  if (options.inPlace && options.dryRun) {
22949
22960
  throw new Error("--in-place is not supported with --dry-run.");
22950
22961
  }
@@ -23105,8 +23116,8 @@ function registerEnrichCommand(program) {
23105
23116
  if (options.debugMapLatency) {
23106
23117
  runArgs.push("--debug-map-latency");
23107
23118
  }
23108
- if (options.noOpen || input2.suppressOpen) {
23109
- runArgs.push("--no-open");
23119
+ if (options.open) {
23120
+ runArgs.push("--open");
23110
23121
  }
23111
23122
  if (input2.json) {
23112
23123
  runArgs.push("--json");
@@ -26241,7 +26252,7 @@ Examples:
26241
26252
  }
26242
26253
 
26243
26254
  // src/cli/commands/tools.ts
26244
- import { Option } from "commander";
26255
+ import { Option as Option2 } from "commander";
26245
26256
  import {
26246
26257
  chmodSync,
26247
26258
  existsSync as existsSync10,
@@ -26978,12 +26989,12 @@ Examples:
26978
26989
  "--examples-only",
26979
26990
  "Only print runnable examples and sample payloads"
26980
26991
  ).option("--getters-only", "Only print extracted list/value getters").addOption(
26981
- new Option(
26992
+ new Option2(
26982
26993
  "--compact",
26983
26994
  "Compatibility alias for the default compact view"
26984
26995
  ).hideHelp()
26985
26996
  ).addOption(
26986
- new Option(
26997
+ new Option2(
26987
26998
  "--contract-json",
26988
26999
  "Compatibility alias for compact contract JSON"
26989
27000
  ).hideHelp()
@@ -30242,7 +30253,6 @@ async function runPlayRunnerHealthCheck() {
30242
30253
  "--input",
30243
30254
  "{}",
30244
30255
  "--watch",
30245
- "--no-open",
30246
30256
  "--json"
30247
30257
  ]);
30248
30258
  } finally {
@@ -30391,7 +30401,7 @@ async function main() {
30391
30401
  if (printStartupPhase) {
30392
30402
  progress?.phase("loading deepline cli");
30393
30403
  }
30394
- const program = new Command3();
30404
+ const program = new Command4();
30395
30405
  program.name("deepline").description(
30396
30406
  "Deepline CLI \u2014 GTM enrichment tools, plays, and runs from your terminal."
30397
30407
  ).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.254",
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",
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.254",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.253",
3
+ "version": "0.1.254",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {