deepline 0.1.266 → 0.1.268

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.
@@ -1,4 +1,4 @@
1
- import { SDK_API_CONTRACT, SDK_VERSION } from './version.js';
1
+ import { SDK_API_CONTRACT, SDK_API_MAJOR, SDK_VERSION } from './version.js';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
@@ -87,6 +87,7 @@ function compatibilityCacheKey(
87
87
  baseUrl: baseUrl.replace(/\/$/, ''),
88
88
  version: SDK_VERSION,
89
89
  apiContract: SDK_API_CONTRACT,
90
+ apiMajor: SDK_API_MAJOR,
90
91
  command: command?.trim() || null,
91
92
  skillsVersion: skillsVersion ?? null,
92
93
  });
@@ -186,6 +187,7 @@ export async function checkSdkCompatibility(
186
187
  headers: {
187
188
  'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,
188
189
  'X-Deepline-SDK-Version': SDK_VERSION,
190
+ 'X-Deepline-API-Major': String(SDK_API_MAJOR),
189
191
  'X-Deepline-API-Contract': SDK_API_CONTRACT,
190
192
  },
191
193
  signal: controller.signal,
@@ -12,9 +12,10 @@
12
12
  *
13
13
  * Edit THIS file by hand only for deliberate release decisions:
14
14
  * - minor/major version bumps (set `version`),
15
- * - `apiContract` cutovers (see `docs/sdk-runtime-compatibility.md`),
15
+ * - API-major cutovers (set `contracts.api.currentMajor`; leave `version` to the
16
+ * publish-time patch selector),
16
17
  * - support-window moves (`minimumSupported` / `deprecatedBelow`).
17
- * The automation never touches `apiContract`, `minimumSupported`, or
18
+ * The automation never touches API compatibility policy, `minimumSupported`, or
18
19
  * `deprecatedBelow`.
19
20
  *
20
21
  * Everything else derives from these values:
@@ -35,6 +36,37 @@
35
36
 
36
37
  export type SdkReleaseChannel = 'latest' | 'next' | 'beta';
37
38
 
39
+ /**
40
+ * The named public protocols. These are intentionally independent:
41
+ *
42
+ * - `api` is the HTTP SDK/CLI protocol. It is additive within a major.
43
+ * - `playArtifact` is the immutable client-bundled Play payload ABI.
44
+ * - `release` controls promotion/publishing; it is not a client protocol.
45
+ *
46
+ * Do not use an SDK package version or a date string as an artifact ABI.
47
+ */
48
+ export type DeeplineContractPolicy = {
49
+ api: {
50
+ name: 'sdk-http-api';
51
+ currentMajor: number;
52
+ supportedMajors: readonly number[];
53
+ /** Transitional value for installed SDKs that only send the old header. */
54
+ legacyWireIds: readonly string[];
55
+ };
56
+ playArtifact: {
57
+ name: 'play-artifact-runtime';
58
+ currentVersion: number;
59
+ supportedVersions: readonly number[];
60
+ };
61
+ release: {
62
+ name: 'production-sdk-release';
63
+ /** npm may publish only from the active, healthy Production SHA. */
64
+ publishFrom: 'latest-successful-production-deployment';
65
+ /** A newer merge cancels an in-flight decision; reconciliation picks the last healthy SHA. */
66
+ coalesce: 'latest-healthy';
67
+ };
68
+ };
69
+
38
70
  export type SdkSupportPolicy = {
39
71
  /**
40
72
  * Anything strictly below this returns `status: "unsupported"` from
@@ -57,6 +89,8 @@ export type SdkSupportPolicy = {
57
89
  minimumSupported: string;
58
90
  reason: string;
59
91
  }>;
92
+ /** Previously published wire contracts that remain supported. */
93
+ compatibleApiContracts?: readonly string[];
60
94
  /**
61
95
  * Published package versions that must keep working for direct SDK tool
62
96
  * callers. CI installs each package from npm and exercises `tools.get` and
@@ -77,12 +111,8 @@ export type SdkRelease = {
77
111
  * publish time (auto-bump); edit by hand only for minor/major releases.
78
112
  */
79
113
  version: string;
80
- /**
81
- * SDK/API contract identifier. Bump on incompatible protocol or schema
82
- * changes between the installed SDK/CLI and the Deepline backend.
83
- * See `docs/sdk-runtime-compatibility.md`.
84
- */
85
- apiContract: string;
114
+ /** Named compatibility policies. This is the only authored contract policy. */
115
+ contracts: DeeplineContractPolicy;
86
116
  /** Public support policy reported by `/api/v2/sdk/compat`. */
87
117
  supportPolicy: SdkSupportPolicy;
88
118
  };
@@ -125,8 +155,31 @@ export const SDK_RELEASE = {
125
155
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
126
156
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
127
157
  // Operators use the checkout-local deepline-admin binary instead.
128
- version: '0.1.266',
129
- apiContract: '2026-07-admin-cli-local-cutover',
158
+ version: '0.1.268',
159
+ contracts: {
160
+ api: {
161
+ name: 'sdk-http-api',
162
+ // API v2 is append-only. A breaking public request/response change needs
163
+ // v3 and an explicit v2 support-window decision, never a patch release.
164
+ currentMajor: 2,
165
+ supportedMajors: [2],
166
+ // Accepted only to bridge SDKs released before X-Deepline-API-Major.
167
+ legacyWireIds: [
168
+ '2026-07-admin-cli-local-cutover',
169
+ '2026-07-native-monitor-launch-hard-cutover',
170
+ ],
171
+ },
172
+ playArtifact: {
173
+ name: 'play-artifact-runtime',
174
+ currentVersion: 2,
175
+ supportedVersions: [1, 2],
176
+ },
177
+ release: {
178
+ name: 'production-sdk-release',
179
+ publishFrom: 'latest-successful-production-deployment',
180
+ coalesce: 'latest-healthy',
181
+ },
182
+ },
130
183
  supportPolicy: {
131
184
  minimumSupported: '0.1.53',
132
185
  deprecatedBelow: '0.1.219',
@@ -3,4 +3,8 @@
3
3
  import { SDK_RELEASE } from './release.js';
4
4
 
5
5
  export const SDK_VERSION: string = SDK_RELEASE.version;
6
- export const SDK_API_CONTRACT: string = SDK_RELEASE.apiContract;
6
+ /** Numbered SDK HTTP API major sent by current SDK/CLI clients. */
7
+ export const SDK_API_MAJOR: number = SDK_RELEASE.contracts.api.currentMajor;
8
+ /** @deprecated Transitional wire id for pre-major-header SDKs only. */
9
+ export const SDK_API_CONTRACT: string =
10
+ SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
@@ -5432,13 +5432,13 @@ export class PlayContextImpl {
5432
5432
  this.rowStates.get(idx)?.results.set(fieldName, cellValue);
5433
5433
  const currentCellMeta =
5434
5434
  this.activeMapCellMeta?.get(rowKey)?.[fieldName];
5435
- const currentCellStatus =
5435
+ const currentCellRecord =
5436
5436
  currentCellMeta &&
5437
5437
  typeof currentCellMeta === 'object' &&
5438
- !Array.isArray(currentCellMeta) &&
5439
- 'status' in currentCellMeta
5440
- ? (currentCellMeta as { status?: unknown }).status
5438
+ !Array.isArray(currentCellMeta)
5439
+ ? (currentCellMeta as { status?: unknown; reused?: unknown })
5441
5440
  : null;
5441
+ const currentCellStatus = currentCellRecord?.status ?? null;
5442
5442
  if (currentCellStatus === 'skipped') {
5443
5443
  if (
5444
5444
  shouldPersistMapCellField(fieldName) &&
@@ -5455,13 +5455,25 @@ export class PlayContextImpl {
5455
5455
  }
5456
5456
  continue;
5457
5457
  }
5458
+ // A cell whose underlying durable work was fully satisfied from
5459
+ // content-addressed receipts recorded a `cached`/`reused` cell-meta
5460
+ // marker while the body ran (see resolveRequestsFromReceipt). Emitting
5461
+ // an unconditional `completed` here would clobber that marker to a
5462
+ // non-reused `completed`, so the run's per-column `cached` counter
5463
+ // reads 0 on a full-reuse rerun even though provider spend was 0.
5464
+ // Preserve the reuse signal so `columnStats.cached` reflects real
5465
+ // receipt reuse consistent with the near-zero provider spend.
5466
+ const cellWasReused =
5467
+ currentCellStatus === 'cached' &&
5468
+ currentCellRecord?.reused === true;
5458
5469
  this.emitScopedFieldMetaUpdate({
5459
5470
  rowId: idx,
5460
5471
  key: rowKey,
5461
5472
  tableNamespace: normalizedTableNamespace,
5462
5473
  fieldName,
5463
- status: 'completed',
5464
- stage: 'completed',
5474
+ status: cellWasReused ? 'cached' : 'completed',
5475
+ stage: cellWasReused ? 'cached' : 'completed',
5476
+ ...(cellWasReused ? { reused: true } : {}),
5465
5477
  completedAt: Date.now(),
5466
5478
  dataPatch: shouldPersistMapCellField(fieldName)
5467
5479
  ? { [fieldName]: cellValue }
@@ -0,0 +1,30 @@
1
+ type DatasetLogIdentity = {
2
+ path: string;
3
+ tableNamespace: string;
4
+ };
5
+
6
+ /**
7
+ * Dataset paths identify runtime state. They are not CLI export selectors: a
8
+ * returned result field (for example `result.rows`) is the supported export
9
+ * handle. Keep this distinction explicit in operator logs.
10
+ */
11
+ export function formatDatasetRegistrationLog(input: {
12
+ dataset: DatasetLogIdentity;
13
+ rows: number;
14
+ }): string {
15
+ if (input.rows === 0) {
16
+ return `Dataset ${input.dataset.path} registered (0 rows); export unavailable: empty dataset`;
17
+ }
18
+ return `Dataset ${input.dataset.path} registered (${input.rows} rows); awaiting terminal persistence`;
19
+ }
20
+
21
+ export function formatDatasetAvailabilityLog(input: {
22
+ runId: string;
23
+ dataset: DatasetLogIdentity;
24
+ persistedRows: number;
25
+ }): string {
26
+ if (input.persistedRows === 0) {
27
+ return `Dataset ${input.dataset.path} available: 0 persisted rows; export unavailable: empty dataset`;
28
+ }
29
+ return `Dataset ${input.dataset.path} available: ${input.persistedRows} persisted rows; inspect deepline runs get ${input.runId} --full --json for the verified export action`;
30
+ }
package/dist/cli/index.js CHANGED
@@ -718,8 +718,31 @@ var SDK_RELEASE = {
718
718
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
719
719
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
720
720
  // Operators use the checkout-local deepline-admin binary instead.
721
- version: "0.1.266",
722
- apiContract: "2026-07-admin-cli-local-cutover",
721
+ version: "0.1.268",
722
+ contracts: {
723
+ api: {
724
+ name: "sdk-http-api",
725
+ // API v2 is append-only. A breaking public request/response change needs
726
+ // v3 and an explicit v2 support-window decision, never a patch release.
727
+ currentMajor: 2,
728
+ supportedMajors: [2],
729
+ // Accepted only to bridge SDKs released before X-Deepline-API-Major.
730
+ legacyWireIds: [
731
+ "2026-07-admin-cli-local-cutover",
732
+ "2026-07-native-monitor-launch-hard-cutover"
733
+ ]
734
+ },
735
+ playArtifact: {
736
+ name: "play-artifact-runtime",
737
+ currentVersion: 2,
738
+ supportedVersions: [1, 2]
739
+ },
740
+ release: {
741
+ name: "production-sdk-release",
742
+ publishFrom: "latest-successful-production-deployment",
743
+ coalesce: "latest-healthy"
744
+ }
745
+ },
723
746
  supportPolicy: {
724
747
  minimumSupported: "0.1.53",
725
748
  deprecatedBelow: "0.1.219",
@@ -816,7 +839,8 @@ var SDK_RELEASE = {
816
839
 
817
840
  // src/version.ts
818
841
  var SDK_VERSION = SDK_RELEASE.version;
819
- var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
842
+ var SDK_API_MAJOR = SDK_RELEASE.contracts.api.currentMajor;
843
+ var SDK_API_CONTRACT = SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
820
844
 
821
845
  // src/agent-runtime.ts
822
846
  var import_node_os2 = require("os");
@@ -4838,6 +4862,7 @@ function compatibilityCacheKey(baseUrl, command, skillsVersion) {
4838
4862
  baseUrl: baseUrl.replace(/\/$/, ""),
4839
4863
  version: SDK_VERSION,
4840
4864
  apiContract: SDK_API_CONTRACT,
4865
+ apiMajor: SDK_API_MAJOR,
4841
4866
  command: command?.trim() || null,
4842
4867
  skillsVersion: skillsVersion ?? null
4843
4868
  });
@@ -4906,6 +4931,7 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
4906
4931
  headers: {
4907
4932
  "User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
4908
4933
  "X-Deepline-SDK-Version": SDK_VERSION,
4934
+ "X-Deepline-API-Major": String(SDK_API_MAJOR),
4909
4935
  "X-Deepline-API-Contract": SDK_API_CONTRACT
4910
4936
  },
4911
4937
  signal: controller.signal
@@ -5284,26 +5310,29 @@ function browserOpeningDisabled() {
5284
5310
  ).trim().toLowerCase();
5285
5311
  return value === "1" || value === "true" || value === "yes" || value === "on";
5286
5312
  }
5287
- function openInBrowser(url) {
5313
+ function openInBrowser(url, options = {}) {
5288
5314
  try {
5289
- if (browserOpeningDisabled()) return;
5315
+ if (browserOpeningDisabled()) return "failed";
5290
5316
  const targetUrl = String(url || "").trim();
5291
- if (!targetUrl) return;
5292
- if (!claimBrowserOpen(Date.now(), void 0, targetUrl)) return;
5317
+ if (!targetUrl) return "failed";
5318
+ if (options.deduplicate !== false && !claimBrowserOpen(Date.now(), void 0, targetUrl)) {
5319
+ return "suppressed";
5320
+ }
5293
5321
  const allowFocus = true;
5294
5322
  if (process.platform === "darwin") {
5295
- openUrlMacos(targetUrl, allowFocus);
5296
- return;
5323
+ return openUrlMacos(targetUrl, allowFocus) ? "opened" : "failed";
5297
5324
  }
5298
- if (!allowFocus) return;
5325
+ if (!allowFocus) return "failed";
5299
5326
  if (process.platform === "win32") {
5300
5327
  childProcess.execFileSync("cmd.exe", ["/c", "start", "", targetUrl], {
5301
5328
  stdio: "ignore"
5302
5329
  });
5303
- return;
5330
+ return "opened";
5304
5331
  }
5305
5332
  childProcess.execFileSync("xdg-open", [targetUrl], { stdio: "ignore" });
5333
+ return "opened";
5306
5334
  } catch {
5335
+ return "failed";
5307
5336
  }
5308
5337
  }
5309
5338
  function sleep3(ms) {
@@ -29514,6 +29543,18 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
29514
29543
  const prefix = normalized.startsWith("/") && prefixParts[0] !== "" ? `/${prefixParts.join("/")}` : prefixParts.join("/");
29515
29544
  return prefix || null;
29516
29545
  }
29546
+ function isHomebrewFormulaEntrypoint(entrypoint) {
29547
+ const normalized = (() => {
29548
+ try {
29549
+ return (0, import_node_fs17.realpathSync)(entrypoint);
29550
+ } catch {
29551
+ return (0, import_node_path19.resolve)(entrypoint);
29552
+ }
29553
+ })();
29554
+ const parts = normalized.split(/[\\/]+/);
29555
+ const cellarIndex = parts.lastIndexOf("Cellar");
29556
+ return cellarIndex >= 0 && parts[cellarIndex + 1] === "deepline" && parts.slice(cellarIndex + 3).includes("libexec");
29557
+ }
29517
29558
  function resolveUpdatePlan(options = {}) {
29518
29559
  const env = options.env ?? process.env;
29519
29560
  const homeDir2 = options.homeDir ?? (0, import_node_os14.homedir)();
@@ -29526,6 +29567,12 @@ function resolveUpdatePlan(options = {}) {
29526
29567
  manualCommand: buildSourceUpdateCommand(sourceRoot)
29527
29568
  };
29528
29569
  }
29570
+ if (entrypoint && isHomebrewFormulaEntrypoint(entrypoint)) {
29571
+ return {
29572
+ kind: "homebrew",
29573
+ manualCommand: "brew upgrade deepline"
29574
+ };
29575
+ }
29529
29576
  const sidecarPlan = resolvePythonSidecarUpdatePlan({
29530
29577
  entrypoint,
29531
29578
  env,
@@ -29557,7 +29604,7 @@ function resolveUpdatePlan(options = {}) {
29557
29604
  }
29558
29605
  var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
29559
29606
  function autoUpdateFailurePath(plan) {
29560
- if (plan.kind === "source") return null;
29607
+ if (plan.kind === "source" || plan.kind === "homebrew") return null;
29561
29608
  if (plan.kind === "python-sidecar") {
29562
29609
  return (0, import_node_path19.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
29563
29610
  }
@@ -29570,7 +29617,7 @@ function autoUpdateFailurePath(plan) {
29570
29617
  );
29571
29618
  }
29572
29619
  function autoUpdatePackageSpec(plan) {
29573
- if (plan.kind === "source") return "";
29620
+ if (plan.kind === "source" || plan.kind === "homebrew") return "";
29574
29621
  if (plan.kind === "python-sidecar") return plan.packageSpec;
29575
29622
  return plan.args[plan.args.length - 1] ?? plan.manualCommand;
29576
29623
  }
@@ -29591,7 +29638,7 @@ function readAutoUpdateFailure(plan) {
29591
29638
  }
29592
29639
  function writeAutoUpdateFailure(plan, exitCode) {
29593
29640
  const path = autoUpdateFailurePath(plan);
29594
- if (!path || plan.kind === "source") return;
29641
+ if (!path || plan.kind === "source" || plan.kind === "homebrew") return;
29595
29642
  const marker = {
29596
29643
  kind: plan.kind,
29597
29644
  packageSpec: autoUpdatePackageSpec(plan),
@@ -29616,7 +29663,9 @@ function clearAutoUpdateFailure(plan) {
29616
29663
  }
29617
29664
  function matchingAutoUpdateFailure(plan) {
29618
29665
  const marker = readAutoUpdateFailure(plan);
29619
- if (!marker || plan.kind === "source") return null;
29666
+ if (!marker || plan.kind === "source" || plan.kind === "homebrew") {
29667
+ return null;
29668
+ }
29620
29669
  if (marker.kind !== plan.kind) return null;
29621
29670
  if (marker.packageSpec !== autoUpdatePackageSpec(plan)) return null;
29622
29671
  return marker;
@@ -29874,6 +29923,8 @@ async function runUpdatePlan(plan) {
29874
29923
  });
29875
29924
  } else if (plan.kind === "python-sidecar") {
29876
29925
  exitCode = await runPythonSidecarUpdatePlan(plan);
29926
+ } else if (plan.kind === "homebrew") {
29927
+ exitCode = 0;
29877
29928
  }
29878
29929
  if (exitCode === 0) {
29879
29930
  clearAutoUpdateFailure(plan);
@@ -29912,6 +29963,9 @@ async function runUpdateCommand(options, dependencies = {}) {
29912
29963
  lines: plan.kind === "source" ? [
29913
29964
  "This Deepline CLI is running from SDK source, so it cannot safely update itself like an npm global.",
29914
29965
  `Update the backing checkout with: ${plan.manualCommand}`
29966
+ ] : plan.kind === "homebrew" ? [
29967
+ "This Deepline CLI was installed by Homebrew, which owns its upgrades.",
29968
+ `Update it with: ${plan.manualCommand}`
29915
29969
  ] : plan.kind === "python-sidecar" ? [
29916
29970
  "This Deepline CLI is running from the Python-managed SDK sidecar.",
29917
29971
  "Updating will refresh that sidecar, not a global npm binary."
@@ -29936,7 +29990,7 @@ async function runUpdateCommand(options, dependencies = {}) {
29936
29990
  );
29937
29991
  return 0;
29938
29992
  }
29939
- if (plan.kind === "source") {
29993
+ if (plan.kind === "source" || plan.kind === "homebrew") {
29940
29994
  printCommandEnvelope({ ...plan, render }, { json: false });
29941
29995
  return 0;
29942
29996
  }
@@ -29955,6 +30009,8 @@ function registerUpdateCommand(program) {
29955
30009
  `
29956
30010
  Notes:
29957
30011
  For the published npm CLI, this runs npm install -g deepline@latest.
30012
+ For a Homebrew installation, this prints brew upgrade deepline; Homebrew
30013
+ owns formula upgrades and Deepline never runs npm inside its Cellar.
29958
30014
  For Python-managed SDK sidecars, this refreshes the sidecar that launched
29959
30015
  the current SDK CLI instead of changing a global npm binary.
29960
30016
  For repo-backed SDK wrappers such as cli-env sdk-prod or sdk-worktree, this
@@ -30074,14 +30130,37 @@ function resolveScopeRoot(scope) {
30074
30130
  function authScopeForSetup(scope) {
30075
30131
  return scope === "local" ? "folder" : "global";
30076
30132
  }
30077
- function shouldOpenSetupAuthorization(runtime = detectAgentRuntime()) {
30078
- return runtime !== "claude_cowork";
30079
- }
30080
30133
  function openSetupAuthorization(authorizationUrl, options = {}) {
30081
30134
  const url = authorizationUrl.trim();
30082
- if (!url || !shouldOpenSetupAuthorization(options.runtime)) return false;
30083
- (options.open ?? openInBrowser)(url);
30084
- return true;
30135
+ if (!url) return "failed";
30136
+ if (options.open) return options.open(url);
30137
+ const result = openInBrowser(url, { deduplicate: false });
30138
+ return result === "opened" ? "opened" : "failed";
30139
+ }
30140
+ function buildPendingAuthorizationOutput(input2) {
30141
+ const authorizationUrl = input2.authorizationUrl.trim();
30142
+ if (input2.browserOpenStatus === "opened") {
30143
+ return {
30144
+ authorizationUrl: null,
30145
+ next: `Complete browser approval, then run: ${input2.resumeCommand}`,
30146
+ lines: ["Complete authorization in the browser window Deepline opened."]
30147
+ };
30148
+ }
30149
+ if (authorizationUrl) {
30150
+ return {
30151
+ authorizationUrl,
30152
+ next: `Open the authorization URL, approve it, then run: ${input2.resumeCommand}`,
30153
+ lines: [
30154
+ "Browser launch failed. Open the authorization URL to continue.",
30155
+ authorizationUrl
30156
+ ]
30157
+ };
30158
+ }
30159
+ return {
30160
+ authorizationUrl: null,
30161
+ next: `Authorization is pending without a browser URL. Retry: ${input2.resumeCommand}`,
30162
+ lines: ["Authorization is pending, but no browser URL was returned."]
30163
+ };
30085
30164
  }
30086
30165
  function setupStatePath(baseUrl, scope, root) {
30087
30166
  return scope === "local" && root ? (0, import_node_path20.join)(root, ".deepline", "setup", "state.json") : (0, import_node_path20.join)(sdkCliStateDirPath(baseUrl), "setup.json");
@@ -30111,15 +30190,6 @@ function parseCapturedJson(stdout) {
30111
30190
  function asRecord2(value) {
30112
30191
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
30113
30192
  }
30114
- function printCapturedAuthorizationUrl(stdout) {
30115
- const urls = stdout.match(/https:\/\/[^\s]+/g) ?? [];
30116
- for (const url of new Set(
30117
- urls.map((value) => value.replace(/[).,]+$/, ""))
30118
- )) {
30119
- process.stderr.write(`Authorize Deepline: ${url}
30120
- `);
30121
- }
30122
- }
30123
30193
  function safeRead(path) {
30124
30194
  try {
30125
30195
  return (0, import_node_fs18.readFileSync)(path, "utf8");
@@ -30134,13 +30204,19 @@ function isNpmManagedDeeplinePath(path) {
30134
30204
  return false;
30135
30205
  }
30136
30206
  }
30207
+ function isInstallerManagedLegacyLauncher(path) {
30208
+ const content = safeRead(path);
30209
+ return content.includes("DEEPLINE_REAL_BINARY") && content.includes("DEEPLINE_ACTIVE_FILE");
30210
+ }
30137
30211
  function removeKnownLegacyPaths(baseUrl) {
30138
30212
  const home = (0, import_node_os15.homedir)();
30139
30213
  const hostDir = (0, import_node_path20.join)(home, ".local", "deepline", baseUrlSlug(baseUrl));
30214
+ const legacyLauncherPath = (0, import_node_path20.join)(home, ".local", "bin", "deepline");
30140
30215
  const installerCommandPath = safeRead(
30141
30216
  (0, import_node_path20.join)(hostDir, "sdk", ".command-path")
30142
30217
  ).trim();
30143
30218
  const candidates = [
30219
+ ...isInstallerManagedLegacyLauncher(legacyLauncherPath) ? [legacyLauncherPath] : [],
30144
30220
  (0, import_node_path20.join)(home, ".local", "bin", "deepline-real"),
30145
30221
  (0, import_node_path20.join)(hostDir, "bin", "deepline"),
30146
30222
  (0, import_node_path20.join)(hostDir, "bin", "deepline-real"),
@@ -30458,18 +30534,32 @@ function pendingResult(input2) {
30458
30534
  status: "authorization_pending",
30459
30535
  phases: input2.phases
30460
30536
  });
30537
+ let browserOpenStatus = "failed";
30461
30538
  if (input2.authorizationUrl) {
30462
- openSetupAuthorization(input2.authorizationUrl);
30463
- process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30539
+ browserOpenStatus = openSetupAuthorization(input2.authorizationUrl);
30540
+ if (browserOpenStatus === "opened") {
30541
+ process.stderr.write(
30542
+ "Opened Deepline authorization in your browser. Complete approval there.\n"
30543
+ );
30544
+ } else if (browserOpenStatus === "failed") {
30545
+ process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30464
30546
  `);
30547
+ }
30465
30548
  }
30549
+ const pendingOutput = buildPendingAuthorizationOutput({
30550
+ authorizationUrl: input2.authorizationUrl,
30551
+ browserOpenStatus,
30552
+ resumeCommand: setupResumeCommand(input2.baseUrl, input2.scope)
30553
+ });
30466
30554
  printCommandEnvelope(
30467
30555
  {
30468
30556
  ok: true,
30469
30557
  status: "authorization_pending",
30470
30558
  complete: false,
30471
30559
  scope: input2.scope,
30472
- authorizationUrl: input2.authorizationUrl || null,
30560
+ authorizationUrl: pendingOutput.authorizationUrl,
30561
+ browserOpened: browserOpenStatus === "opened",
30562
+ browserOpenStatus,
30473
30563
  statePath,
30474
30564
  phases: input2.phases,
30475
30565
  currentPhase: "auth",
@@ -30479,15 +30569,12 @@ function pendingResult(input2) {
30479
30569
  scope: input2.scope,
30480
30570
  phase: "auth"
30481
30571
  }),
30482
- next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
30572
+ next: pendingOutput.next,
30483
30573
  render: {
30484
30574
  sections: [
30485
30575
  {
30486
30576
  title: "setup",
30487
- lines: [
30488
- "Authorization is waiting for browser approval.",
30489
- ...input2.authorizationUrl ? [input2.authorizationUrl] : []
30490
- ]
30577
+ lines: pendingOutput.lines
30491
30578
  }
30492
30579
  ]
30493
30580
  }
@@ -30656,10 +30743,9 @@ async function runSetupCommand(options) {
30656
30743
  const pending = readPendingAuthClaim(baseUrl, authScope);
30657
30744
  if (pending) {
30658
30745
  process.stderr.write("Checking pending Deepline authorization...\n");
30659
- const waited = await captureStdout2(
30746
+ await captureStdout2(
30660
30747
  () => handleWait(["--timeout", "1", "--auth-scope", authScope])
30661
30748
  );
30662
- printCapturedAuthorizationUrl(waited.stdout);
30663
30749
  auth = await readAuthStatus(authScope);
30664
30750
  const resumedAuthFailure = reportSetupAuthStatusFailure({
30665
30751
  auth,
@@ -30695,7 +30781,6 @@ async function runSetupCommand(options) {
30695
30781
  const registered = await captureStdout2(
30696
30782
  () => handleRegister(["--wait", waitMode, "--auth-scope", authScope])
30697
30783
  );
30698
- printCapturedAuthorizationUrl(registered.stdout);
30699
30784
  if (registered.exitCode !== 0) {
30700
30785
  return reportSetupPhaseFailure({
30701
30786
  baseUrl,
@@ -703,8 +703,31 @@ var SDK_RELEASE = {
703
703
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
704
704
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
705
705
  // Operators use the checkout-local deepline-admin binary instead.
706
- version: "0.1.266",
707
- apiContract: "2026-07-admin-cli-local-cutover",
706
+ version: "0.1.268",
707
+ contracts: {
708
+ api: {
709
+ name: "sdk-http-api",
710
+ // API v2 is append-only. A breaking public request/response change needs
711
+ // v3 and an explicit v2 support-window decision, never a patch release.
712
+ currentMajor: 2,
713
+ supportedMajors: [2],
714
+ // Accepted only to bridge SDKs released before X-Deepline-API-Major.
715
+ legacyWireIds: [
716
+ "2026-07-admin-cli-local-cutover",
717
+ "2026-07-native-monitor-launch-hard-cutover"
718
+ ]
719
+ },
720
+ playArtifact: {
721
+ name: "play-artifact-runtime",
722
+ currentVersion: 2,
723
+ supportedVersions: [1, 2]
724
+ },
725
+ release: {
726
+ name: "production-sdk-release",
727
+ publishFrom: "latest-successful-production-deployment",
728
+ coalesce: "latest-healthy"
729
+ }
730
+ },
708
731
  supportPolicy: {
709
732
  minimumSupported: "0.1.53",
710
733
  deprecatedBelow: "0.1.219",
@@ -801,7 +824,8 @@ var SDK_RELEASE = {
801
824
 
802
825
  // src/version.ts
803
826
  var SDK_VERSION = SDK_RELEASE.version;
804
- var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
827
+ var SDK_API_MAJOR = SDK_RELEASE.contracts.api.currentMajor;
828
+ var SDK_API_CONTRACT = SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
805
829
 
806
830
  // src/agent-runtime.ts
807
831
  import { homedir as homedir2 } from "os";
@@ -4823,6 +4847,7 @@ function compatibilityCacheKey(baseUrl, command, skillsVersion) {
4823
4847
  baseUrl: baseUrl.replace(/\/$/, ""),
4824
4848
  version: SDK_VERSION,
4825
4849
  apiContract: SDK_API_CONTRACT,
4850
+ apiMajor: SDK_API_MAJOR,
4826
4851
  command: command?.trim() || null,
4827
4852
  skillsVersion: skillsVersion ?? null
4828
4853
  });
@@ -4891,6 +4916,7 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
4891
4916
  headers: {
4892
4917
  "User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
4893
4918
  "X-Deepline-SDK-Version": SDK_VERSION,
4919
+ "X-Deepline-API-Major": String(SDK_API_MAJOR),
4894
4920
  "X-Deepline-API-Contract": SDK_API_CONTRACT
4895
4921
  },
4896
4922
  signal: controller.signal
@@ -5281,26 +5307,29 @@ function browserOpeningDisabled() {
5281
5307
  ).trim().toLowerCase();
5282
5308
  return value === "1" || value === "true" || value === "yes" || value === "on";
5283
5309
  }
5284
- function openInBrowser(url) {
5310
+ function openInBrowser(url, options = {}) {
5285
5311
  try {
5286
- if (browserOpeningDisabled()) return;
5312
+ if (browserOpeningDisabled()) return "failed";
5287
5313
  const targetUrl = String(url || "").trim();
5288
- if (!targetUrl) return;
5289
- if (!claimBrowserOpen(Date.now(), void 0, targetUrl)) return;
5314
+ if (!targetUrl) return "failed";
5315
+ if (options.deduplicate !== false && !claimBrowserOpen(Date.now(), void 0, targetUrl)) {
5316
+ return "suppressed";
5317
+ }
5290
5318
  const allowFocus = true;
5291
5319
  if (process.platform === "darwin") {
5292
- openUrlMacos(targetUrl, allowFocus);
5293
- return;
5320
+ return openUrlMacos(targetUrl, allowFocus) ? "opened" : "failed";
5294
5321
  }
5295
- if (!allowFocus) return;
5322
+ if (!allowFocus) return "failed";
5296
5323
  if (process.platform === "win32") {
5297
5324
  childProcess.execFileSync("cmd.exe", ["/c", "start", "", targetUrl], {
5298
5325
  stdio: "ignore"
5299
5326
  });
5300
- return;
5327
+ return "opened";
5301
5328
  }
5302
5329
  childProcess.execFileSync("xdg-open", [targetUrl], { stdio: "ignore" });
5330
+ return "opened";
5303
5331
  } catch {
5332
+ return "failed";
5304
5333
  }
5305
5334
  }
5306
5335
  function sleep3(ms) {
@@ -29571,6 +29600,18 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
29571
29600
  const prefix = normalized.startsWith("/") && prefixParts[0] !== "" ? `/${prefixParts.join("/")}` : prefixParts.join("/");
29572
29601
  return prefix || null;
29573
29602
  }
29603
+ function isHomebrewFormulaEntrypoint(entrypoint) {
29604
+ const normalized = (() => {
29605
+ try {
29606
+ return realpathSync3(entrypoint);
29607
+ } catch {
29608
+ return resolve13(entrypoint);
29609
+ }
29610
+ })();
29611
+ const parts = normalized.split(/[\\/]+/);
29612
+ const cellarIndex = parts.lastIndexOf("Cellar");
29613
+ return cellarIndex >= 0 && parts[cellarIndex + 1] === "deepline" && parts.slice(cellarIndex + 3).includes("libexec");
29614
+ }
29574
29615
  function resolveUpdatePlan(options = {}) {
29575
29616
  const env = options.env ?? process.env;
29576
29617
  const homeDir2 = options.homeDir ?? homedir12();
@@ -29583,6 +29624,12 @@ function resolveUpdatePlan(options = {}) {
29583
29624
  manualCommand: buildSourceUpdateCommand(sourceRoot)
29584
29625
  };
29585
29626
  }
29627
+ if (entrypoint && isHomebrewFormulaEntrypoint(entrypoint)) {
29628
+ return {
29629
+ kind: "homebrew",
29630
+ manualCommand: "brew upgrade deepline"
29631
+ };
29632
+ }
29586
29633
  const sidecarPlan = resolvePythonSidecarUpdatePlan({
29587
29634
  entrypoint,
29588
29635
  env,
@@ -29614,7 +29661,7 @@ function resolveUpdatePlan(options = {}) {
29614
29661
  }
29615
29662
  var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
29616
29663
  function autoUpdateFailurePath(plan) {
29617
- if (plan.kind === "source") return null;
29664
+ if (plan.kind === "source" || plan.kind === "homebrew") return null;
29618
29665
  if (plan.kind === "python-sidecar") {
29619
29666
  return join15(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
29620
29667
  }
@@ -29627,7 +29674,7 @@ function autoUpdateFailurePath(plan) {
29627
29674
  );
29628
29675
  }
29629
29676
  function autoUpdatePackageSpec(plan) {
29630
- if (plan.kind === "source") return "";
29677
+ if (plan.kind === "source" || plan.kind === "homebrew") return "";
29631
29678
  if (plan.kind === "python-sidecar") return plan.packageSpec;
29632
29679
  return plan.args[plan.args.length - 1] ?? plan.manualCommand;
29633
29680
  }
@@ -29648,7 +29695,7 @@ function readAutoUpdateFailure(plan) {
29648
29695
  }
29649
29696
  function writeAutoUpdateFailure(plan, exitCode) {
29650
29697
  const path = autoUpdateFailurePath(plan);
29651
- if (!path || plan.kind === "source") return;
29698
+ if (!path || plan.kind === "source" || plan.kind === "homebrew") return;
29652
29699
  const marker = {
29653
29700
  kind: plan.kind,
29654
29701
  packageSpec: autoUpdatePackageSpec(plan),
@@ -29673,7 +29720,9 @@ function clearAutoUpdateFailure(plan) {
29673
29720
  }
29674
29721
  function matchingAutoUpdateFailure(plan) {
29675
29722
  const marker = readAutoUpdateFailure(plan);
29676
- if (!marker || plan.kind === "source") return null;
29723
+ if (!marker || plan.kind === "source" || plan.kind === "homebrew") {
29724
+ return null;
29725
+ }
29677
29726
  if (marker.kind !== plan.kind) return null;
29678
29727
  if (marker.packageSpec !== autoUpdatePackageSpec(plan)) return null;
29679
29728
  return marker;
@@ -29931,6 +29980,8 @@ async function runUpdatePlan(plan) {
29931
29980
  });
29932
29981
  } else if (plan.kind === "python-sidecar") {
29933
29982
  exitCode = await runPythonSidecarUpdatePlan(plan);
29983
+ } else if (plan.kind === "homebrew") {
29984
+ exitCode = 0;
29934
29985
  }
29935
29986
  if (exitCode === 0) {
29936
29987
  clearAutoUpdateFailure(plan);
@@ -29969,6 +30020,9 @@ async function runUpdateCommand(options, dependencies = {}) {
29969
30020
  lines: plan.kind === "source" ? [
29970
30021
  "This Deepline CLI is running from SDK source, so it cannot safely update itself like an npm global.",
29971
30022
  `Update the backing checkout with: ${plan.manualCommand}`
30023
+ ] : plan.kind === "homebrew" ? [
30024
+ "This Deepline CLI was installed by Homebrew, which owns its upgrades.",
30025
+ `Update it with: ${plan.manualCommand}`
29972
30026
  ] : plan.kind === "python-sidecar" ? [
29973
30027
  "This Deepline CLI is running from the Python-managed SDK sidecar.",
29974
30028
  "Updating will refresh that sidecar, not a global npm binary."
@@ -29993,7 +30047,7 @@ async function runUpdateCommand(options, dependencies = {}) {
29993
30047
  );
29994
30048
  return 0;
29995
30049
  }
29996
- if (plan.kind === "source") {
30050
+ if (plan.kind === "source" || plan.kind === "homebrew") {
29997
30051
  printCommandEnvelope({ ...plan, render }, { json: false });
29998
30052
  return 0;
29999
30053
  }
@@ -30012,6 +30066,8 @@ function registerUpdateCommand(program) {
30012
30066
  `
30013
30067
  Notes:
30014
30068
  For the published npm CLI, this runs npm install -g deepline@latest.
30069
+ For a Homebrew installation, this prints brew upgrade deepline; Homebrew
30070
+ owns formula upgrades and Deepline never runs npm inside its Cellar.
30015
30071
  For Python-managed SDK sidecars, this refreshes the sidecar that launched
30016
30072
  the current SDK CLI instead of changing a global npm binary.
30017
30073
  For repo-backed SDK wrappers such as cli-env sdk-prod or sdk-worktree, this
@@ -30139,14 +30195,37 @@ function resolveScopeRoot(scope) {
30139
30195
  function authScopeForSetup(scope) {
30140
30196
  return scope === "local" ? "folder" : "global";
30141
30197
  }
30142
- function shouldOpenSetupAuthorization(runtime = detectAgentRuntime()) {
30143
- return runtime !== "claude_cowork";
30144
- }
30145
30198
  function openSetupAuthorization(authorizationUrl, options = {}) {
30146
30199
  const url = authorizationUrl.trim();
30147
- if (!url || !shouldOpenSetupAuthorization(options.runtime)) return false;
30148
- (options.open ?? openInBrowser)(url);
30149
- return true;
30200
+ if (!url) return "failed";
30201
+ if (options.open) return options.open(url);
30202
+ const result = openInBrowser(url, { deduplicate: false });
30203
+ return result === "opened" ? "opened" : "failed";
30204
+ }
30205
+ function buildPendingAuthorizationOutput(input2) {
30206
+ const authorizationUrl = input2.authorizationUrl.trim();
30207
+ if (input2.browserOpenStatus === "opened") {
30208
+ return {
30209
+ authorizationUrl: null,
30210
+ next: `Complete browser approval, then run: ${input2.resumeCommand}`,
30211
+ lines: ["Complete authorization in the browser window Deepline opened."]
30212
+ };
30213
+ }
30214
+ if (authorizationUrl) {
30215
+ return {
30216
+ authorizationUrl,
30217
+ next: `Open the authorization URL, approve it, then run: ${input2.resumeCommand}`,
30218
+ lines: [
30219
+ "Browser launch failed. Open the authorization URL to continue.",
30220
+ authorizationUrl
30221
+ ]
30222
+ };
30223
+ }
30224
+ return {
30225
+ authorizationUrl: null,
30226
+ next: `Authorization is pending without a browser URL. Retry: ${input2.resumeCommand}`,
30227
+ lines: ["Authorization is pending, but no browser URL was returned."]
30228
+ };
30150
30229
  }
30151
30230
  function setupStatePath(baseUrl, scope, root) {
30152
30231
  return scope === "local" && root ? join16(root, ".deepline", "setup", "state.json") : join16(sdkCliStateDirPath(baseUrl), "setup.json");
@@ -30176,15 +30255,6 @@ function parseCapturedJson(stdout) {
30176
30255
  function asRecord2(value) {
30177
30256
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
30178
30257
  }
30179
- function printCapturedAuthorizationUrl(stdout) {
30180
- const urls = stdout.match(/https:\/\/[^\s]+/g) ?? [];
30181
- for (const url of new Set(
30182
- urls.map((value) => value.replace(/[).,]+$/, ""))
30183
- )) {
30184
- process.stderr.write(`Authorize Deepline: ${url}
30185
- `);
30186
- }
30187
- }
30188
30258
  function safeRead(path) {
30189
30259
  try {
30190
30260
  return readFileSync14(path, "utf8");
@@ -30199,13 +30269,19 @@ function isNpmManagedDeeplinePath(path) {
30199
30269
  return false;
30200
30270
  }
30201
30271
  }
30272
+ function isInstallerManagedLegacyLauncher(path) {
30273
+ const content = safeRead(path);
30274
+ return content.includes("DEEPLINE_REAL_BINARY") && content.includes("DEEPLINE_ACTIVE_FILE");
30275
+ }
30202
30276
  function removeKnownLegacyPaths(baseUrl) {
30203
30277
  const home = homedir13();
30204
30278
  const hostDir = join16(home, ".local", "deepline", baseUrlSlug(baseUrl));
30279
+ const legacyLauncherPath = join16(home, ".local", "bin", "deepline");
30205
30280
  const installerCommandPath = safeRead(
30206
30281
  join16(hostDir, "sdk", ".command-path")
30207
30282
  ).trim();
30208
30283
  const candidates = [
30284
+ ...isInstallerManagedLegacyLauncher(legacyLauncherPath) ? [legacyLauncherPath] : [],
30209
30285
  join16(home, ".local", "bin", "deepline-real"),
30210
30286
  join16(hostDir, "bin", "deepline"),
30211
30287
  join16(hostDir, "bin", "deepline-real"),
@@ -30523,18 +30599,32 @@ function pendingResult(input2) {
30523
30599
  status: "authorization_pending",
30524
30600
  phases: input2.phases
30525
30601
  });
30602
+ let browserOpenStatus = "failed";
30526
30603
  if (input2.authorizationUrl) {
30527
- openSetupAuthorization(input2.authorizationUrl);
30528
- process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30604
+ browserOpenStatus = openSetupAuthorization(input2.authorizationUrl);
30605
+ if (browserOpenStatus === "opened") {
30606
+ process.stderr.write(
30607
+ "Opened Deepline authorization in your browser. Complete approval there.\n"
30608
+ );
30609
+ } else if (browserOpenStatus === "failed") {
30610
+ process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30529
30611
  `);
30612
+ }
30530
30613
  }
30614
+ const pendingOutput = buildPendingAuthorizationOutput({
30615
+ authorizationUrl: input2.authorizationUrl,
30616
+ browserOpenStatus,
30617
+ resumeCommand: setupResumeCommand(input2.baseUrl, input2.scope)
30618
+ });
30531
30619
  printCommandEnvelope(
30532
30620
  {
30533
30621
  ok: true,
30534
30622
  status: "authorization_pending",
30535
30623
  complete: false,
30536
30624
  scope: input2.scope,
30537
- authorizationUrl: input2.authorizationUrl || null,
30625
+ authorizationUrl: pendingOutput.authorizationUrl,
30626
+ browserOpened: browserOpenStatus === "opened",
30627
+ browserOpenStatus,
30538
30628
  statePath,
30539
30629
  phases: input2.phases,
30540
30630
  currentPhase: "auth",
@@ -30544,15 +30634,12 @@ function pendingResult(input2) {
30544
30634
  scope: input2.scope,
30545
30635
  phase: "auth"
30546
30636
  }),
30547
- next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
30637
+ next: pendingOutput.next,
30548
30638
  render: {
30549
30639
  sections: [
30550
30640
  {
30551
30641
  title: "setup",
30552
- lines: [
30553
- "Authorization is waiting for browser approval.",
30554
- ...input2.authorizationUrl ? [input2.authorizationUrl] : []
30555
- ]
30642
+ lines: pendingOutput.lines
30556
30643
  }
30557
30644
  ]
30558
30645
  }
@@ -30721,10 +30808,9 @@ async function runSetupCommand(options) {
30721
30808
  const pending = readPendingAuthClaim(baseUrl, authScope);
30722
30809
  if (pending) {
30723
30810
  process.stderr.write("Checking pending Deepline authorization...\n");
30724
- const waited = await captureStdout2(
30811
+ await captureStdout2(
30725
30812
  () => handleWait(["--timeout", "1", "--auth-scope", authScope])
30726
30813
  );
30727
- printCapturedAuthorizationUrl(waited.stdout);
30728
30814
  auth = await readAuthStatus(authScope);
30729
30815
  const resumedAuthFailure = reportSetupAuthStatusFailure({
30730
30816
  auth,
@@ -30760,7 +30846,6 @@ async function runSetupCommand(options) {
30760
30846
  const registered = await captureStdout2(
30761
30847
  () => handleRegister(["--wait", waitMode, "--auth-scope", authScope])
30762
30848
  );
30763
- printCapturedAuthorizationUrl(registered.stdout);
30764
30849
  if (registered.exitCode !== 0) {
30765
30850
  return reportSetupPhaseFailure({
30766
30851
  baseUrl,
package/dist/index.d.mts CHANGED
@@ -2703,6 +2703,7 @@ declare class RunObserveTransportUnavailableError extends Error {
2703
2703
  }
2704
2704
 
2705
2705
  declare const SDK_VERSION: string;
2706
+ /** @deprecated Transitional wire id for pre-major-header SDKs only. */
2706
2707
  declare const SDK_API_CONTRACT: string;
2707
2708
 
2708
2709
  /**
package/dist/index.d.ts CHANGED
@@ -2703,6 +2703,7 @@ declare class RunObserveTransportUnavailableError extends Error {
2703
2703
  }
2704
2704
 
2705
2705
  declare const SDK_VERSION: string;
2706
+ /** @deprecated Transitional wire id for pre-major-header SDKs only. */
2706
2707
  declare const SDK_API_CONTRACT: string;
2707
2708
 
2708
2709
  /**
package/dist/index.js CHANGED
@@ -437,8 +437,31 @@ var SDK_RELEASE = {
437
437
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
438
438
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
439
439
  // Operators use the checkout-local deepline-admin binary instead.
440
- version: "0.1.266",
441
- apiContract: "2026-07-admin-cli-local-cutover",
440
+ version: "0.1.268",
441
+ contracts: {
442
+ api: {
443
+ name: "sdk-http-api",
444
+ // API v2 is append-only. A breaking public request/response change needs
445
+ // v3 and an explicit v2 support-window decision, never a patch release.
446
+ currentMajor: 2,
447
+ supportedMajors: [2],
448
+ // Accepted only to bridge SDKs released before X-Deepline-API-Major.
449
+ legacyWireIds: [
450
+ "2026-07-admin-cli-local-cutover",
451
+ "2026-07-native-monitor-launch-hard-cutover"
452
+ ]
453
+ },
454
+ playArtifact: {
455
+ name: "play-artifact-runtime",
456
+ currentVersion: 2,
457
+ supportedVersions: [1, 2]
458
+ },
459
+ release: {
460
+ name: "production-sdk-release",
461
+ publishFrom: "latest-successful-production-deployment",
462
+ coalesce: "latest-healthy"
463
+ }
464
+ },
442
465
  supportPolicy: {
443
466
  minimumSupported: "0.1.53",
444
467
  deprecatedBelow: "0.1.219",
@@ -535,7 +558,8 @@ var SDK_RELEASE = {
535
558
 
536
559
  // src/version.ts
537
560
  var SDK_VERSION = SDK_RELEASE.version;
538
- var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
561
+ var SDK_API_MAJOR = SDK_RELEASE.contracts.api.currentMajor;
562
+ var SDK_API_CONTRACT = SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
539
563
 
540
564
  // src/agent-runtime.ts
541
565
  var import_node_os2 = require("os");
package/dist/index.mjs CHANGED
@@ -367,8 +367,31 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.266",
371
- apiContract: "2026-07-admin-cli-local-cutover",
370
+ version: "0.1.268",
371
+ contracts: {
372
+ api: {
373
+ name: "sdk-http-api",
374
+ // API v2 is append-only. A breaking public request/response change needs
375
+ // v3 and an explicit v2 support-window decision, never a patch release.
376
+ currentMajor: 2,
377
+ supportedMajors: [2],
378
+ // Accepted only to bridge SDKs released before X-Deepline-API-Major.
379
+ legacyWireIds: [
380
+ "2026-07-admin-cli-local-cutover",
381
+ "2026-07-native-monitor-launch-hard-cutover"
382
+ ]
383
+ },
384
+ playArtifact: {
385
+ name: "play-artifact-runtime",
386
+ currentVersion: 2,
387
+ supportedVersions: [1, 2]
388
+ },
389
+ release: {
390
+ name: "production-sdk-release",
391
+ publishFrom: "latest-successful-production-deployment",
392
+ coalesce: "latest-healthy"
393
+ }
394
+ },
372
395
  supportPolicy: {
373
396
  minimumSupported: "0.1.53",
374
397
  deprecatedBelow: "0.1.219",
@@ -465,7 +488,8 @@ var SDK_RELEASE = {
465
488
 
466
489
  // src/version.ts
467
490
  var SDK_VERSION = SDK_RELEASE.version;
468
- var SDK_API_CONTRACT = SDK_RELEASE.apiContract;
491
+ var SDK_API_MAJOR = SDK_RELEASE.contracts.api.currentMajor;
492
+ var SDK_API_CONTRACT = SDK_RELEASE.contracts.api.legacyWireIds[0] ?? `api-v${SDK_API_MAJOR}`;
469
493
 
470
494
  // src/agent-runtime.ts
471
495
  import { homedir as homedir2 } from "os";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.266",
3
+ "version": "0.1.268",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -62,6 +62,7 @@
62
62
  "typescript": "^6.0.2"
63
63
  },
64
64
  "deepline": {
65
- "apiContract": "2026-07-admin-cli-local-cutover"
65
+ "apiContract": "2026-07-admin-cli-local-cutover",
66
+ "apiMajor": 2
66
67
  }
67
68
  }