deepline 0.1.265 → 0.1.267

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.
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.265",
722
- apiContract: "2026-07-admin-cli-local-cutover",
721
+ version: "0.1.267",
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) {
@@ -14256,6 +14285,26 @@ function withOrdinaryRunAgainCommand(status, options, resolvedRevisionId) {
14256
14285
  rerunCommand: buildOrdinaryPlayRunCommand(options, resolvedRevisionId)
14257
14286
  } : status;
14258
14287
  }
14288
+ function buildBillingRollupTextLines(status) {
14289
+ const billing = status.billing;
14290
+ const rollup = billing?.rollup;
14291
+ if (!rollup) return [];
14292
+ const total = formatCreditAmount(rollup.totalCreditsRollup);
14293
+ if (rollup.childCredits > 0 && rollup.descendantRunCount > 0) {
14294
+ const own = formatCreditAmount(rollup.ownCredits);
14295
+ const child = formatCreditAmount(rollup.childCredits);
14296
+ const suffix = rollup.rollupComplete ? "" : " (incomplete: child billing could not be fully resolved)";
14297
+ return [
14298
+ ` cost: ${total} credits total \u2014 ${own} this run + ${child} across ${rollup.descendantRunCount} child run${rollup.descendantRunCount === 1 ? "" : "s"}${suffix}`
14299
+ ];
14300
+ }
14301
+ if (!rollup.rollupComplete) {
14302
+ return [
14303
+ ` cost: ${total} credits (incomplete: child billing could not be fully resolved${rollup.rollupError ? ` \u2014 ${rollup.rollupError}` : ""})`
14304
+ ];
14305
+ }
14306
+ return [` cost: ${total} credits`];
14307
+ }
14259
14308
  function writePlayResult(status, jsonOutput, options) {
14260
14309
  const packaged = getPlayRunPackage(status);
14261
14310
  if (jsonOutput) {
@@ -14318,6 +14367,7 @@ function writePlayResult(status, jsonOutput, options) {
14318
14367
  lines.push(...renderedServerView.lines);
14319
14368
  }
14320
14369
  lines.push(...renderedServerView.actions);
14370
+ lines.push(...buildBillingRollupTextLines(status));
14321
14371
  const compact = compactPlayStatus(status);
14322
14372
  const payload = options?.fullJson ? status : compact;
14323
14373
  printCommandEnvelope(
@@ -29493,6 +29543,18 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
29493
29543
  const prefix = normalized.startsWith("/") && prefixParts[0] !== "" ? `/${prefixParts.join("/")}` : prefixParts.join("/");
29494
29544
  return prefix || null;
29495
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
+ }
29496
29558
  function resolveUpdatePlan(options = {}) {
29497
29559
  const env = options.env ?? process.env;
29498
29560
  const homeDir2 = options.homeDir ?? (0, import_node_os14.homedir)();
@@ -29505,6 +29567,12 @@ function resolveUpdatePlan(options = {}) {
29505
29567
  manualCommand: buildSourceUpdateCommand(sourceRoot)
29506
29568
  };
29507
29569
  }
29570
+ if (entrypoint && isHomebrewFormulaEntrypoint(entrypoint)) {
29571
+ return {
29572
+ kind: "homebrew",
29573
+ manualCommand: "brew upgrade deepline"
29574
+ };
29575
+ }
29508
29576
  const sidecarPlan = resolvePythonSidecarUpdatePlan({
29509
29577
  entrypoint,
29510
29578
  env,
@@ -29536,7 +29604,7 @@ function resolveUpdatePlan(options = {}) {
29536
29604
  }
29537
29605
  var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
29538
29606
  function autoUpdateFailurePath(plan) {
29539
- if (plan.kind === "source") return null;
29607
+ if (plan.kind === "source" || plan.kind === "homebrew") return null;
29540
29608
  if (plan.kind === "python-sidecar") {
29541
29609
  return (0, import_node_path19.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
29542
29610
  }
@@ -29549,7 +29617,7 @@ function autoUpdateFailurePath(plan) {
29549
29617
  );
29550
29618
  }
29551
29619
  function autoUpdatePackageSpec(plan) {
29552
- if (plan.kind === "source") return "";
29620
+ if (plan.kind === "source" || plan.kind === "homebrew") return "";
29553
29621
  if (plan.kind === "python-sidecar") return plan.packageSpec;
29554
29622
  return plan.args[plan.args.length - 1] ?? plan.manualCommand;
29555
29623
  }
@@ -29570,7 +29638,7 @@ function readAutoUpdateFailure(plan) {
29570
29638
  }
29571
29639
  function writeAutoUpdateFailure(plan, exitCode) {
29572
29640
  const path = autoUpdateFailurePath(plan);
29573
- if (!path || plan.kind === "source") return;
29641
+ if (!path || plan.kind === "source" || plan.kind === "homebrew") return;
29574
29642
  const marker = {
29575
29643
  kind: plan.kind,
29576
29644
  packageSpec: autoUpdatePackageSpec(plan),
@@ -29595,7 +29663,9 @@ function clearAutoUpdateFailure(plan) {
29595
29663
  }
29596
29664
  function matchingAutoUpdateFailure(plan) {
29597
29665
  const marker = readAutoUpdateFailure(plan);
29598
- if (!marker || plan.kind === "source") return null;
29666
+ if (!marker || plan.kind === "source" || plan.kind === "homebrew") {
29667
+ return null;
29668
+ }
29599
29669
  if (marker.kind !== plan.kind) return null;
29600
29670
  if (marker.packageSpec !== autoUpdatePackageSpec(plan)) return null;
29601
29671
  return marker;
@@ -29853,6 +29923,8 @@ async function runUpdatePlan(plan) {
29853
29923
  });
29854
29924
  } else if (plan.kind === "python-sidecar") {
29855
29925
  exitCode = await runPythonSidecarUpdatePlan(plan);
29926
+ } else if (plan.kind === "homebrew") {
29927
+ exitCode = 0;
29856
29928
  }
29857
29929
  if (exitCode === 0) {
29858
29930
  clearAutoUpdateFailure(plan);
@@ -29891,6 +29963,9 @@ async function runUpdateCommand(options, dependencies = {}) {
29891
29963
  lines: plan.kind === "source" ? [
29892
29964
  "This Deepline CLI is running from SDK source, so it cannot safely update itself like an npm global.",
29893
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}`
29894
29969
  ] : plan.kind === "python-sidecar" ? [
29895
29970
  "This Deepline CLI is running from the Python-managed SDK sidecar.",
29896
29971
  "Updating will refresh that sidecar, not a global npm binary."
@@ -29915,7 +29990,7 @@ async function runUpdateCommand(options, dependencies = {}) {
29915
29990
  );
29916
29991
  return 0;
29917
29992
  }
29918
- if (plan.kind === "source") {
29993
+ if (plan.kind === "source" || plan.kind === "homebrew") {
29919
29994
  printCommandEnvelope({ ...plan, render }, { json: false });
29920
29995
  return 0;
29921
29996
  }
@@ -29934,6 +30009,8 @@ function registerUpdateCommand(program) {
29934
30009
  `
29935
30010
  Notes:
29936
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.
29937
30014
  For Python-managed SDK sidecars, this refreshes the sidecar that launched
29938
30015
  the current SDK CLI instead of changing a global npm binary.
29939
30016
  For repo-backed SDK wrappers such as cli-env sdk-prod or sdk-worktree, this
@@ -30053,14 +30130,37 @@ function resolveScopeRoot(scope) {
30053
30130
  function authScopeForSetup(scope) {
30054
30131
  return scope === "local" ? "folder" : "global";
30055
30132
  }
30056
- function shouldOpenSetupAuthorization(runtime = detectAgentRuntime()) {
30057
- return runtime !== "claude_cowork";
30058
- }
30059
30133
  function openSetupAuthorization(authorizationUrl, options = {}) {
30060
30134
  const url = authorizationUrl.trim();
30061
- if (!url || !shouldOpenSetupAuthorization(options.runtime)) return false;
30062
- (options.open ?? openInBrowser)(url);
30063
- 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
+ };
30064
30164
  }
30065
30165
  function setupStatePath(baseUrl, scope, root) {
30066
30166
  return scope === "local" && root ? (0, import_node_path20.join)(root, ".deepline", "setup", "state.json") : (0, import_node_path20.join)(sdkCliStateDirPath(baseUrl), "setup.json");
@@ -30090,15 +30190,6 @@ function parseCapturedJson(stdout) {
30090
30190
  function asRecord2(value) {
30091
30191
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
30092
30192
  }
30093
- function printCapturedAuthorizationUrl(stdout) {
30094
- const urls = stdout.match(/https:\/\/[^\s]+/g) ?? [];
30095
- for (const url of new Set(
30096
- urls.map((value) => value.replace(/[).,]+$/, ""))
30097
- )) {
30098
- process.stderr.write(`Authorize Deepline: ${url}
30099
- `);
30100
- }
30101
- }
30102
30193
  function safeRead(path) {
30103
30194
  try {
30104
30195
  return (0, import_node_fs18.readFileSync)(path, "utf8");
@@ -30437,18 +30528,32 @@ function pendingResult(input2) {
30437
30528
  status: "authorization_pending",
30438
30529
  phases: input2.phases
30439
30530
  });
30531
+ let browserOpenStatus = "failed";
30440
30532
  if (input2.authorizationUrl) {
30441
- openSetupAuthorization(input2.authorizationUrl);
30442
- process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30533
+ browserOpenStatus = openSetupAuthorization(input2.authorizationUrl);
30534
+ if (browserOpenStatus === "opened") {
30535
+ process.stderr.write(
30536
+ "Opened Deepline authorization in your browser. Complete approval there.\n"
30537
+ );
30538
+ } else if (browserOpenStatus === "failed") {
30539
+ process.stderr.write(`Authorize Deepline: ${input2.authorizationUrl}
30443
30540
  `);
30541
+ }
30444
30542
  }
30543
+ const pendingOutput = buildPendingAuthorizationOutput({
30544
+ authorizationUrl: input2.authorizationUrl,
30545
+ browserOpenStatus,
30546
+ resumeCommand: setupResumeCommand(input2.baseUrl, input2.scope)
30547
+ });
30445
30548
  printCommandEnvelope(
30446
30549
  {
30447
30550
  ok: true,
30448
30551
  status: "authorization_pending",
30449
30552
  complete: false,
30450
30553
  scope: input2.scope,
30451
- authorizationUrl: input2.authorizationUrl || null,
30554
+ authorizationUrl: pendingOutput.authorizationUrl,
30555
+ browserOpened: browserOpenStatus === "opened",
30556
+ browserOpenStatus,
30452
30557
  statePath,
30453
30558
  phases: input2.phases,
30454
30559
  currentPhase: "auth",
@@ -30458,15 +30563,12 @@ function pendingResult(input2) {
30458
30563
  scope: input2.scope,
30459
30564
  phase: "auth"
30460
30565
  }),
30461
- next: `Approve the link, then run: ${setupResumeCommand(input2.baseUrl, input2.scope)}`,
30566
+ next: pendingOutput.next,
30462
30567
  render: {
30463
30568
  sections: [
30464
30569
  {
30465
30570
  title: "setup",
30466
- lines: [
30467
- "Authorization is waiting for browser approval.",
30468
- ...input2.authorizationUrl ? [input2.authorizationUrl] : []
30469
- ]
30571
+ lines: pendingOutput.lines
30470
30572
  }
30471
30573
  ]
30472
30574
  }
@@ -30635,10 +30737,9 @@ async function runSetupCommand(options) {
30635
30737
  const pending = readPendingAuthClaim(baseUrl, authScope);
30636
30738
  if (pending) {
30637
30739
  process.stderr.write("Checking pending Deepline authorization...\n");
30638
- const waited = await captureStdout2(
30740
+ await captureStdout2(
30639
30741
  () => handleWait(["--timeout", "1", "--auth-scope", authScope])
30640
30742
  );
30641
- printCapturedAuthorizationUrl(waited.stdout);
30642
30743
  auth = await readAuthStatus(authScope);
30643
30744
  const resumedAuthFailure = reportSetupAuthStatusFailure({
30644
30745
  auth,
@@ -30674,7 +30775,6 @@ async function runSetupCommand(options) {
30674
30775
  const registered = await captureStdout2(
30675
30776
  () => handleRegister(["--wait", waitMode, "--auth-scope", authScope])
30676
30777
  );
30677
- printCapturedAuthorizationUrl(registered.stdout);
30678
30778
  if (registered.exitCode !== 0) {
30679
30779
  return reportSetupPhaseFailure({
30680
30780
  baseUrl,