deepline 0.1.125 → 0.1.127

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
@@ -404,10 +404,10 @@ var SDK_RELEASE = {
404
404
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
405
405
  // the SDK enrich generator's one-second stale policy.
406
406
  // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
407
- version: "0.1.125",
407
+ version: "0.1.127",
408
408
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
409
409
  supportPolicy: {
410
- latest: "0.1.125",
410
+ latest: "0.1.127",
411
411
  minimumSupported: "0.1.53",
412
412
  deprecatedBelow: "0.1.53",
413
413
  commandMinimumSupported: [
@@ -21248,24 +21248,362 @@ Notes:
21248
21248
  }
21249
21249
 
21250
21250
  // src/cli/commands/update.ts
21251
+ var import_node_child_process3 = require("child_process");
21252
+ var import_node_fs15 = require("fs");
21253
+ var import_node_os13 = require("os");
21254
+ var import_node_path18 = require("path");
21255
+
21256
+ // src/cli/skills-sync.ts
21251
21257
  var import_node_child_process2 = require("child_process");
21252
21258
  var import_node_fs14 = require("fs");
21253
21259
  var import_node_os12 = require("os");
21254
21260
  var import_node_path17 = require("path");
21261
+
21262
+ // ../shared_libs/cli/install-commands.json
21263
+ var install_commands_default = {
21264
+ skills: {
21265
+ index_path: "/.well-known/skills/index.json",
21266
+ default_agents: [
21267
+ "codex",
21268
+ "claude-code",
21269
+ "cursor",
21270
+ "gemini-cli",
21271
+ "antigravity"
21272
+ ],
21273
+ npx_binary: "npx",
21274
+ npx_add_args_template: [
21275
+ "--yes",
21276
+ "skills",
21277
+ "add",
21278
+ "{skills_index_url}",
21279
+ "--agent",
21280
+ "{agents}",
21281
+ "--global",
21282
+ "--yes",
21283
+ "--skill",
21284
+ "{skill_name}",
21285
+ "--full-depth"
21286
+ ]
21287
+ },
21288
+ cli: {
21289
+ legacy_python_shell_template: "curl -s {base_url}/api/v2/cli/install | bash",
21290
+ sdk_npm_global: "npm install -g deepline@latest"
21291
+ }
21292
+ };
21293
+
21294
+ // src/cli/install-commands.ts
21295
+ var INSTALL_COMMANDS = install_commands_default;
21296
+ var DEFAULT_V1_SKILL_NAMES = [
21297
+ "build-tam",
21298
+ "clay-to-deepline",
21299
+ "deepline-analytics",
21300
+ "deepline-feedback",
21301
+ "deepline-gtm",
21302
+ "deepline-quickstart",
21303
+ "find-qualified-titles",
21304
+ "linkedin-url-lookup",
21305
+ "niche-signal-discovery",
21306
+ "portfolio-prospecting",
21307
+ "workflow-hello-world"
21308
+ ];
21309
+ var DEFAULT_SDK_SKILL_NAMES = [
21310
+ ...DEFAULT_V1_SKILL_NAMES,
21311
+ "deepline-plays"
21312
+ ];
21313
+ function normalizeBaseUrl2(baseUrl) {
21314
+ return baseUrl.replace(/\/$/, "");
21315
+ }
21316
+ function renderTemplate(template, values) {
21317
+ return template.replace(/\{([a-z_]+)\}/g, (match, key) => {
21318
+ return values[key] ?? match;
21319
+ });
21320
+ }
21321
+ function shellJoin(args) {
21322
+ return args.join(" ");
21323
+ }
21324
+ function skillsIndexUrl(baseUrl) {
21325
+ return `${normalizeBaseUrl2(baseUrl)}${INSTALL_COMMANDS.skills.index_path}`;
21326
+ }
21327
+ function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
21328
+ const skillNames = Array.isArray(skillName) ? skillName : [skillName];
21329
+ const [firstSkillName, ...extraSkillNames] = skillNames;
21330
+ const values = {
21331
+ skills_index_url: skillsIndexUrl(baseUrl),
21332
+ agents: INSTALL_COMMANDS.skills.default_agents.join(" "),
21333
+ skill_name: firstSkillName ?? ""
21334
+ };
21335
+ const rendered = INSTALL_COMMANDS.skills.npx_add_args_template.flatMap(
21336
+ (arg, index) => {
21337
+ const next = index === 0 && options.firstArg ? options.firstArg : arg;
21338
+ const value = renderTemplate(next, values);
21339
+ if (arg === "{agents}") {
21340
+ return INSTALL_COMMANDS.skills.default_agents;
21341
+ }
21342
+ if (arg === "{skill_name}") {
21343
+ return [value, ...extraSkillNames.flatMap((name) => ["--skill", name])];
21344
+ }
21345
+ return value;
21346
+ }
21347
+ );
21348
+ return rendered;
21349
+ }
21350
+ function skillsInstallCommand(baseUrl, skillName) {
21351
+ return `${INSTALL_COMMANDS.skills.npx_binary} ${shellJoin(
21352
+ buildSkillsAddArgs(baseUrl, skillName)
21353
+ )}`;
21354
+ }
21355
+ function legacyPythonInstallCommand(baseUrl) {
21356
+ return renderTemplate(INSTALL_COMMANDS.cli.legacy_python_shell_template, {
21357
+ base_url: normalizeBaseUrl2(baseUrl)
21358
+ });
21359
+ }
21360
+ function sdkNpmGlobalInstallCommand() {
21361
+ return INSTALL_COMMANDS.cli.sdk_npm_global;
21362
+ }
21363
+
21364
+ // src/cli/skills-sync.ts
21365
+ var CHECK_TIMEOUT_MS2 = 3e3;
21366
+ var SDK_PLAY_SKILL_NAME = "deepline-plays";
21367
+ var attemptedSync = false;
21368
+ function shouldSkipSkillsSync() {
21369
+ const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
21370
+ return value === "1" || value === "true" || value === "yes" || value === "on";
21371
+ }
21372
+ function activePluginSkillsDir() {
21373
+ const pluginMode = process.env.DEEPLINE_PLUGIN_MODE?.trim().toLowerCase();
21374
+ if (pluginMode !== "true" && pluginMode !== "1" && pluginMode !== "yes" && pluginMode !== "on") {
21375
+ return "";
21376
+ }
21377
+ const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
21378
+ return dir && (0, import_node_fs14.existsSync)(dir) ? dir : "";
21379
+ }
21380
+ function readPluginSkillsVersion() {
21381
+ const dir = activePluginSkillsDir();
21382
+ if (!dir) return "";
21383
+ try {
21384
+ return (0, import_node_fs14.readFileSync)((0, import_node_path17.join)(dir, ".version"), "utf-8").trim();
21385
+ } catch {
21386
+ return "";
21387
+ }
21388
+ }
21389
+ function sdkSkillsVersionPath(baseUrl) {
21390
+ const home = process.env.HOME?.trim() || (0, import_node_os12.homedir)();
21391
+ return (0, import_node_path17.join)(
21392
+ home,
21393
+ ".local",
21394
+ "deepline",
21395
+ baseUrlSlug(baseUrl),
21396
+ "sdk-skills",
21397
+ ".version"
21398
+ );
21399
+ }
21400
+ function readLocalSkillsVersion(baseUrl) {
21401
+ const pluginVersion = readPluginSkillsVersion();
21402
+ if (pluginVersion) return pluginVersion;
21403
+ const path = sdkSkillsVersionPath(baseUrl);
21404
+ if (!(0, import_node_fs14.existsSync)(path)) return "";
21405
+ try {
21406
+ return (0, import_node_fs14.readFileSync)(path, "utf-8").trim();
21407
+ } catch {
21408
+ return "";
21409
+ }
21410
+ }
21411
+ function writeLocalSkillsVersion(baseUrl, version) {
21412
+ const path = sdkSkillsVersionPath(baseUrl);
21413
+ (0, import_node_fs14.mkdirSync)((0, import_node_path17.dirname)(path), { recursive: true });
21414
+ (0, import_node_fs14.writeFileSync)(path, `${version}
21415
+ `, "utf-8");
21416
+ }
21417
+ function sortedUniqueSkillNames(names) {
21418
+ return [...new Set(names.map((name) => name.trim()).filter(Boolean))].sort(
21419
+ (a, b) => a.localeCompare(b)
21420
+ );
21421
+ }
21422
+ async function fetchV1SkillNames(baseUrl) {
21423
+ const controller = new AbortController();
21424
+ const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
21425
+ try {
21426
+ const response = await fetch(
21427
+ new URL("/.well-known/skills/index.json", baseUrl),
21428
+ { signal: controller.signal }
21429
+ );
21430
+ if (!response.ok) return [];
21431
+ const data = await response.json().catch(() => null);
21432
+ const names = (data?.skills ?? []).filter((skill) => skill.install_surface === "v1").map((skill) => skill.name).filter(
21433
+ (name) => typeof name === "string" && name.length > 0
21434
+ );
21435
+ return sortedUniqueSkillNames(names);
21436
+ } catch {
21437
+ return [];
21438
+ } finally {
21439
+ clearTimeout(timeout);
21440
+ }
21441
+ }
21442
+ function buildSdkSkillNames(v1SkillNames) {
21443
+ return sortedUniqueSkillNames([...v1SkillNames, SDK_PLAY_SKILL_NAME]);
21444
+ }
21445
+ async function fetchSkillsUpdate(baseUrl, localVersion) {
21446
+ const controller = new AbortController();
21447
+ const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
21448
+ try {
21449
+ const response = await fetch(new URL("/api/v2/cli/update-check", baseUrl), {
21450
+ method: "POST",
21451
+ headers: { "Content-Type": "application/json" },
21452
+ body: JSON.stringify({
21453
+ skills: {
21454
+ version: localVersion
21455
+ }
21456
+ }),
21457
+ signal: controller.signal
21458
+ });
21459
+ if (!response.ok) return null;
21460
+ const data = await response.json().catch(() => null);
21461
+ const skills = data?.skills;
21462
+ if (!skills) return null;
21463
+ return {
21464
+ needsUpdate: skills.needs_update === true,
21465
+ remoteVersion: typeof skills.remote?.version === "string" ? skills.remote.version.trim() : ""
21466
+ };
21467
+ } catch {
21468
+ return null;
21469
+ } finally {
21470
+ clearTimeout(timeout);
21471
+ }
21472
+ }
21473
+ function buildSkillsInstallArgs(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
21474
+ return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames));
21475
+ }
21476
+ function buildBunxSkillsInstallArgs(baseUrl, skillNames) {
21477
+ return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames), {
21478
+ firstArg: "--bun"
21479
+ });
21480
+ }
21481
+ function hasCommand(command) {
21482
+ const result = (0, import_node_child_process2.spawnSync)(command, ["--version"], {
21483
+ stdio: "ignore",
21484
+ shell: process.platform === "win32"
21485
+ });
21486
+ return result.status === 0;
21487
+ }
21488
+ function shellQuote3(arg) {
21489
+ return `'${arg.replace(/'/g, `'\\''`)}'`;
21490
+ }
21491
+ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
21492
+ const npxArgs = buildSkillsInstallArgs(baseUrl, skillNames);
21493
+ const npxInstall = {
21494
+ command: "npx",
21495
+ args: npxArgs,
21496
+ manualCommand: `npx ${npxArgs.map(shellQuote3).join(" ")}`
21497
+ };
21498
+ if (hasCommand("bunx")) {
21499
+ const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
21500
+ return [
21501
+ {
21502
+ command: "bunx",
21503
+ args: bunxArgs,
21504
+ manualCommand: `bunx ${bunxArgs.map(shellQuote3).join(" ")}`
21505
+ },
21506
+ npxInstall
21507
+ ];
21508
+ }
21509
+ return [npxInstall];
21510
+ }
21511
+ function runOneSkillsInstall(install) {
21512
+ return new Promise((resolve13) => {
21513
+ const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
21514
+ stdio: ["ignore", "ignore", "pipe"],
21515
+ env: process.env
21516
+ });
21517
+ let stderr = "";
21518
+ child.stderr.on("data", (chunk) => {
21519
+ stderr += chunk.toString("utf-8");
21520
+ });
21521
+ child.on("error", (error) => {
21522
+ resolve13({
21523
+ ok: false,
21524
+ detail: `failed to start ${install.command}: ${error.message}`,
21525
+ manualCommand: install.manualCommand
21526
+ });
21527
+ });
21528
+ child.on("close", (code) => {
21529
+ if (code === 0) {
21530
+ resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
21531
+ return;
21532
+ }
21533
+ const detail = stderr.trim();
21534
+ resolve13({
21535
+ ok: false,
21536
+ detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
21537
+ manualCommand: install.manualCommand
21538
+ });
21539
+ });
21540
+ });
21541
+ }
21542
+ async function runSkillsInstall(baseUrl, skillNames) {
21543
+ const failures = [];
21544
+ for (const install of resolveSkillsInstallCommands(baseUrl, skillNames)) {
21545
+ const result = await runOneSkillsInstall(install);
21546
+ if (result.ok) return true;
21547
+ failures.push(result);
21548
+ }
21549
+ const details = failures.map((failure) => failure.detail).filter(Boolean).join("\n");
21550
+ const manualCommand = failures.at(-1)?.manualCommand;
21551
+ process.stderr.write(
21552
+ `SDK skills sync failed${details ? `:
21553
+ ${details}` : ""}
21554
+ ` + (manualCommand ? `Run manually: ${manualCommand}
21555
+ ` : "")
21556
+ );
21557
+ return false;
21558
+ }
21559
+ function writeSdkSkillsStatusLine(line) {
21560
+ const progress = getActiveCliProgress();
21561
+ if (progress) {
21562
+ progress.writeLine(line);
21563
+ return;
21564
+ }
21565
+ process.stderr.write(`${line}
21566
+ `);
21567
+ }
21568
+ async function syncSdkSkillsIfNeeded(baseUrl) {
21569
+ if (attemptedSync || shouldSkipSkillsSync()) return;
21570
+ attemptedSync = true;
21571
+ const usingPluginSkills = Boolean(activePluginSkillsDir());
21572
+ const localVersion = readLocalSkillsVersion(baseUrl);
21573
+ const update = await fetchSkillsUpdate(baseUrl, localVersion);
21574
+ if (usingPluginSkills) {
21575
+ return;
21576
+ }
21577
+ if (!update?.needsUpdate || !update.remoteVersion) {
21578
+ return;
21579
+ }
21580
+ const remoteSkillNames = await fetchV1SkillNames(baseUrl);
21581
+ const skillNames = buildSdkSkillNames(
21582
+ remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
21583
+ );
21584
+ if (skillNames.length === 0) return;
21585
+ writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
21586
+ const installed = await runSkillsInstall(baseUrl, skillNames);
21587
+ if (!installed) return;
21588
+ writeLocalSkillsVersion(baseUrl, update.remoteVersion);
21589
+ writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
21590
+ }
21591
+
21592
+ // src/cli/commands/update.ts
21255
21593
  function posixShellQuote(value) {
21256
21594
  return `'${value.replace(/'/g, `'\\''`)}'`;
21257
21595
  }
21258
21596
  function windowsCmdQuote(value) {
21259
21597
  return `"${value.replace(/"/g, '""')}"`;
21260
21598
  }
21261
- function shellQuote3(value) {
21599
+ function shellQuote4(value) {
21262
21600
  if (process.platform === "win32") {
21263
21601
  return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
21264
21602
  }
21265
21603
  return posixShellQuote(value);
21266
21604
  }
21267
21605
  function buildSourceUpdateCommand(sourceRoot) {
21268
- const quotedRoot = shellQuote3(sourceRoot);
21606
+ const quotedRoot = shellQuote4(sourceRoot);
21269
21607
  const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
21270
21608
  return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
21271
21609
  }
@@ -21274,11 +21612,11 @@ function sidecarStateDir(input2) {
21274
21612
  if (!scope || scope.includes("/") || scope.includes("\\")) {
21275
21613
  return null;
21276
21614
  }
21277
- return (0, import_node_path17.join)(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
21615
+ return (0, import_node_path18.join)(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
21278
21616
  }
21279
21617
  function readOptionalText(path) {
21280
21618
  try {
21281
- return (0, import_node_fs14.readFileSync)(path, "utf8").trim();
21619
+ return (0, import_node_fs15.readFileSync)(path, "utf8").trim();
21282
21620
  } catch {
21283
21621
  return "";
21284
21622
  }
@@ -21286,26 +21624,26 @@ function readOptionalText(path) {
21286
21624
  function resolvePythonSidecarUpdatePlan(options) {
21287
21625
  const stateDir = sidecarStateDir(options);
21288
21626
  if (!stateDir) return null;
21289
- const relativeEntrypoint = (0, import_node_path17.relative)(
21290
- (0, import_node_path17.resolve)(stateDir),
21291
- (0, import_node_path17.resolve)(options.entrypoint)
21627
+ const relativeEntrypoint = (0, import_node_path18.relative)(
21628
+ (0, import_node_path18.resolve)(stateDir),
21629
+ (0, import_node_path18.resolve)(options.entrypoint)
21292
21630
  );
21293
- if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || (0, import_node_path17.isAbsolute)(relativeEntrypoint)) {
21631
+ if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || (0, import_node_path18.isAbsolute)(relativeEntrypoint)) {
21294
21632
  return null;
21295
21633
  }
21296
- const installMethod = readOptionalText((0, import_node_path17.join)(stateDir, ".install-method"));
21634
+ const installMethod = readOptionalText((0, import_node_path18.join)(stateDir, ".install-method"));
21297
21635
  if (installMethod !== "python-sidecar") return null;
21298
21636
  const scope = options.env.DEEPLINE_CONFIG_SCOPE?.trim() || "";
21299
21637
  const hostUrl = options.env.DEEPLINE_HOST_URL?.trim() || "";
21300
- const nodeBin = readOptionalText((0, import_node_path17.join)(stateDir, ".node-bin")) || process.execPath;
21301
- const sidecarPath = readOptionalText((0, import_node_path17.join)(stateDir, ".command-path")) || (0, import_node_path17.join)(
21638
+ const nodeBin = readOptionalText((0, import_node_path18.join)(stateDir, ".node-bin")) || process.execPath;
21639
+ const sidecarPath = readOptionalText((0, import_node_path18.join)(stateDir, ".command-path")) || (0, import_node_path18.join)(
21302
21640
  stateDir,
21303
21641
  "bin",
21304
21642
  process.platform === "win32" ? "deepline-sdk.cmd" : "deepline-sdk"
21305
21643
  );
21306
21644
  const packageSpec = options.packageSpec || "deepline@latest";
21307
21645
  const npmCommand = "npm";
21308
- const manualCommand = `${npmCommand} install --prefix ${shellQuote3((0, import_node_path17.join)(stateDir, "versions", "<version>"))} --no-audit --no-fund ${shellQuote3(packageSpec)}`;
21646
+ const manualCommand = `${npmCommand} install --prefix ${shellQuote4((0, import_node_path18.join)(stateDir, "versions", "<version>"))} --no-audit --no-fund ${shellQuote4(packageSpec)}`;
21309
21647
  return {
21310
21648
  kind: "python-sidecar",
21311
21649
  stateDir,
@@ -21319,12 +21657,12 @@ function resolvePythonSidecarUpdatePlan(options) {
21319
21657
  };
21320
21658
  }
21321
21659
  function findRepoBackedSdkRoot(startPath) {
21322
- let current = (0, import_node_path17.resolve)(startPath);
21660
+ let current = (0, import_node_path18.resolve)(startPath);
21323
21661
  while (true) {
21324
- if ((0, import_node_fs14.existsSync)((0, import_node_path17.join)(current, "sdk", "package.json")) && (0, import_node_fs14.existsSync)((0, import_node_path17.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
21662
+ if ((0, import_node_fs15.existsSync)((0, import_node_path18.join)(current, "sdk", "package.json")) && (0, import_node_fs15.existsSync)((0, import_node_path18.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
21325
21663
  return current;
21326
21664
  }
21327
- const parent = (0, import_node_path17.dirname)(current);
21665
+ const parent = (0, import_node_path18.dirname)(current);
21328
21666
  if (parent === current) return null;
21329
21667
  current = parent;
21330
21668
  }
@@ -21332,9 +21670,9 @@ function findRepoBackedSdkRoot(startPath) {
21332
21670
  function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
21333
21671
  const normalized = (() => {
21334
21672
  try {
21335
- return (0, import_node_fs14.realpathSync)(entrypoint);
21673
+ return (0, import_node_fs15.realpathSync)(entrypoint);
21336
21674
  } catch {
21337
- return (0, import_node_path17.resolve)(entrypoint);
21675
+ return (0, import_node_path18.resolve)(entrypoint);
21338
21676
  }
21339
21677
  })();
21340
21678
  const parts = normalized.split(/[\\/]+/);
@@ -21352,9 +21690,9 @@ function inferNpmGlobalPrefixFromEntrypoint(entrypoint) {
21352
21690
  }
21353
21691
  function resolveUpdatePlan(options = {}) {
21354
21692
  const env = options.env ?? process.env;
21355
- const homeDir2 = options.homeDir ?? (0, import_node_os12.homedir)();
21356
- const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path17.resolve)(process.argv[1]) : "");
21357
- const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path17.dirname)(entrypoint)) : null;
21693
+ const homeDir2 = options.homeDir ?? (0, import_node_os13.homedir)();
21694
+ const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path18.resolve)(process.argv[1]) : "");
21695
+ const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path18.dirname)(entrypoint)) : null;
21358
21696
  if (sourceRoot) {
21359
21697
  return {
21360
21698
  kind: "source",
@@ -21378,15 +21716,101 @@ function resolveUpdatePlan(options = {}) {
21378
21716
  command,
21379
21717
  args,
21380
21718
  ...installPrefix ? { installPrefix } : {},
21381
- manualCommand: `${command} ${args.map(shellQuote3).join(" ")}`
21719
+ manualCommand: `${command} ${args.map(shellQuote4).join(" ")}`
21720
+ };
21721
+ }
21722
+ var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
21723
+ function autoUpdateFailurePath(plan) {
21724
+ if (plan.kind === "source") return null;
21725
+ if (plan.kind === "python-sidecar") {
21726
+ return (0, import_node_path18.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
21727
+ }
21728
+ return (0, import_node_path18.join)(
21729
+ (0, import_node_os13.homedir)(),
21730
+ ".local",
21731
+ "deepline",
21732
+ "sdk-cli",
21733
+ AUTO_UPDATE_FAILURE_FILE
21734
+ );
21735
+ }
21736
+ function autoUpdatePackageSpec(plan) {
21737
+ if (plan.kind === "source") return "";
21738
+ if (plan.kind === "python-sidecar") return plan.packageSpec;
21739
+ return plan.args[plan.args.length - 1] ?? plan.manualCommand;
21740
+ }
21741
+ function readAutoUpdateFailure(plan) {
21742
+ const path = autoUpdateFailurePath(plan);
21743
+ if (!path) return null;
21744
+ try {
21745
+ const parsed = JSON.parse(
21746
+ (0, import_node_fs15.readFileSync)(path, "utf8")
21747
+ );
21748
+ if ((parsed.kind === "npm-global" || parsed.kind === "python-sidecar") && typeof parsed.packageSpec === "string" && typeof parsed.failedAt === "string" && typeof parsed.exitCode === "number" && typeof parsed.manualCommand === "string") {
21749
+ return parsed;
21750
+ }
21751
+ } catch {
21752
+ return null;
21753
+ }
21754
+ return null;
21755
+ }
21756
+ function writeAutoUpdateFailure(plan, exitCode) {
21757
+ const path = autoUpdateFailurePath(plan);
21758
+ if (!path || plan.kind === "source") return;
21759
+ const marker = {
21760
+ kind: plan.kind,
21761
+ packageSpec: autoUpdatePackageSpec(plan),
21762
+ failedAt: (/* @__PURE__ */ new Date()).toISOString(),
21763
+ exitCode,
21764
+ manualCommand: plan.manualCommand
21382
21765
  };
21766
+ try {
21767
+ (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
21768
+ (0, import_node_fs15.writeFileSync)(path, `${JSON.stringify(marker, null, 2)}
21769
+ `, "utf8");
21770
+ } catch {
21771
+ }
21772
+ }
21773
+ function clearAutoUpdateFailure(plan) {
21774
+ const path = autoUpdateFailurePath(plan);
21775
+ if (!path) return;
21776
+ try {
21777
+ (0, import_node_fs15.unlinkSync)(path);
21778
+ } catch {
21779
+ }
21780
+ }
21781
+ function matchingAutoUpdateFailure(plan) {
21782
+ const marker = readAutoUpdateFailure(plan);
21783
+ if (!marker || plan.kind === "source") return null;
21784
+ if (marker.kind !== plan.kind) return null;
21785
+ if (marker.packageSpec !== autoUpdatePackageSpec(plan)) return null;
21786
+ return marker;
21787
+ }
21788
+ async function runAutomaticUpdatePlan(plan) {
21789
+ const previousFailure = matchingAutoUpdateFailure(plan);
21790
+ if (previousFailure) {
21791
+ process.stderr.write(
21792
+ [
21793
+ "Skipping Deepline SDK/CLI auto-update because this same update already failed on this machine.",
21794
+ `Fix Node/npm native package installation issues, then run: ${previousFailure.manualCommand}`,
21795
+ "Common causes include broken esbuild installs, node-gyp build toolchain errors, npm cache corruption, or registry/network failures.",
21796
+ ""
21797
+ ].join("\n")
21798
+ );
21799
+ return {
21800
+ status: "skipped_previous_failure",
21801
+ exitCode: previousFailure.exitCode || 1,
21802
+ previousFailure
21803
+ };
21804
+ }
21805
+ const exitCode = await runUpdatePlan(plan);
21806
+ return exitCode === 0 ? { status: "updated", exitCode: 0 } : { status: "failed", exitCode };
21383
21807
  }
21384
21808
  function safeVersionSegment(value) {
21385
21809
  const normalized = value.trim();
21386
21810
  return /^[0-9A-Za-z._-]+$/.test(normalized) ? normalized : "";
21387
21811
  }
21388
21812
  function entryPathInVersionDir(versionDir) {
21389
- return (0, import_node_path17.join)(
21813
+ return (0, import_node_path18.join)(
21390
21814
  versionDir,
21391
21815
  "node_modules",
21392
21816
  "deepline",
@@ -21396,14 +21820,14 @@ function entryPathInVersionDir(versionDir) {
21396
21820
  );
21397
21821
  }
21398
21822
  function installedPackageVersion(versionDir) {
21399
- const packageJsonPath = (0, import_node_path17.join)(
21823
+ const packageJsonPath = (0, import_node_path18.join)(
21400
21824
  versionDir,
21401
21825
  "node_modules",
21402
21826
  "deepline",
21403
21827
  "package.json"
21404
21828
  );
21405
21829
  try {
21406
- const parsed = JSON.parse((0, import_node_fs14.readFileSync)(packageJsonPath, "utf8"));
21830
+ const parsed = JSON.parse((0, import_node_fs15.readFileSync)(packageJsonPath, "utf8"));
21407
21831
  return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
21408
21832
  } catch {
21409
21833
  return "";
@@ -21411,7 +21835,7 @@ function installedPackageVersion(versionDir) {
21411
21835
  }
21412
21836
  function runCommand(command, args, env = process.env) {
21413
21837
  return new Promise((resolveExitCode) => {
21414
- const child = (0, import_node_child_process2.spawn)(command, args, {
21838
+ const child = (0, import_node_child_process3.spawn)(command, args, {
21415
21839
  stdio: "inherit",
21416
21840
  shell: process.platform === "win32",
21417
21841
  env
@@ -21427,9 +21851,9 @@ function runCommand(command, args, env = process.env) {
21427
21851
  });
21428
21852
  }
21429
21853
  function writeSidecarLauncher(input2) {
21430
- (0, import_node_fs14.mkdirSync)((0, import_node_path17.dirname)(input2.path), { recursive: true });
21854
+ (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(input2.path), { recursive: true });
21431
21855
  if (process.platform === "win32") {
21432
- (0, import_node_fs14.writeFileSync)(
21856
+ (0, import_node_fs15.writeFileSync)(
21433
21857
  input2.path,
21434
21858
  [
21435
21859
  `@set DEEPLINE_HOST_URL=${input2.hostUrl.replace(/\r?\n/g, "")}`,
@@ -21441,30 +21865,30 @@ function writeSidecarLauncher(input2) {
21441
21865
  );
21442
21866
  return;
21443
21867
  }
21444
- (0, import_node_fs14.writeFileSync)(
21868
+ (0, import_node_fs15.writeFileSync)(
21445
21869
  input2.path,
21446
21870
  [
21447
21871
  "#!/usr/bin/env sh",
21448
- `export DEEPLINE_HOST_URL=${shellQuote3(input2.hostUrl)}`,
21449
- `export DEEPLINE_CONFIG_SCOPE=${shellQuote3(input2.scope)}`,
21450
- `exec ${shellQuote3(input2.nodeBin)} ${shellQuote3(input2.entryPath)} "$@"`,
21872
+ `export DEEPLINE_HOST_URL=${shellQuote4(input2.hostUrl)}`,
21873
+ `export DEEPLINE_CONFIG_SCOPE=${shellQuote4(input2.scope)}`,
21874
+ `exec ${shellQuote4(input2.nodeBin)} ${shellQuote4(input2.entryPath)} "$@"`,
21451
21875
  ""
21452
21876
  ].join("\n"),
21453
21877
  { encoding: "utf8", mode: 493 }
21454
21878
  );
21455
21879
  }
21456
21880
  async function runPythonSidecarUpdatePlan(plan) {
21457
- const versionsDir = (0, import_node_path17.join)(plan.stateDir, "versions");
21458
- const tempDir = (0, import_node_path17.join)(
21881
+ const versionsDir = (0, import_node_path18.join)(plan.stateDir, "versions");
21882
+ const tempDir = (0, import_node_path18.join)(
21459
21883
  versionsDir,
21460
21884
  `.tmp-sdk-update-${process.pid}-${Date.now()}`
21461
21885
  );
21462
- (0, import_node_fs14.rmSync)(tempDir, { recursive: true, force: true });
21463
- (0, import_node_fs14.mkdirSync)(tempDir, { recursive: true });
21464
- (0, import_node_fs14.writeFileSync)((0, import_node_path17.join)(tempDir, "package.json"), '{"private":true}\n', "utf8");
21886
+ (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
21887
+ (0, import_node_fs15.mkdirSync)(tempDir, { recursive: true });
21888
+ (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(tempDir, "package.json"), '{"private":true}\n', "utf8");
21465
21889
  const env = {
21466
21890
  ...process.env,
21467
- PATH: `${(0, import_node_path17.dirname)(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
21891
+ PATH: `${(0, import_node_path18.dirname)(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
21468
21892
  };
21469
21893
  const installExitCode = await runCommand(
21470
21894
  plan.npmCommand,
@@ -21479,7 +21903,7 @@ async function runPythonSidecarUpdatePlan(plan) {
21479
21903
  env
21480
21904
  );
21481
21905
  if (installExitCode !== 0) {
21482
- (0, import_node_fs14.rmSync)(tempDir, { recursive: true, force: true });
21906
+ (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
21483
21907
  return installExitCode;
21484
21908
  }
21485
21909
  const installedVersion = installedPackageVersion(tempDir);
@@ -21487,19 +21911,19 @@ async function runPythonSidecarUpdatePlan(plan) {
21487
21911
  process.stderr.write(
21488
21912
  "Updated Deepline SDK package did not report a version.\n"
21489
21913
  );
21490
- (0, import_node_fs14.rmSync)(tempDir, { recursive: true, force: true });
21914
+ (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
21491
21915
  return 1;
21492
21916
  }
21493
- const finalDir = (0, import_node_path17.join)(versionsDir, installedVersion);
21917
+ const finalDir = (0, import_node_path18.join)(versionsDir, installedVersion);
21494
21918
  const finalEntryPath = entryPathInVersionDir(finalDir);
21495
- if ((0, import_node_fs14.existsSync)(finalEntryPath)) {
21496
- (0, import_node_fs14.rmSync)(tempDir, { recursive: true, force: true });
21919
+ if ((0, import_node_fs15.existsSync)(finalEntryPath)) {
21920
+ (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
21497
21921
  } else {
21498
- (0, import_node_fs14.rmSync)(finalDir, { recursive: true, force: true });
21922
+ (0, import_node_fs15.rmSync)(finalDir, { recursive: true, force: true });
21499
21923
  try {
21500
- (0, import_node_fs14.renameSync)(tempDir, finalDir);
21924
+ (0, import_node_fs15.renameSync)(tempDir, finalDir);
21501
21925
  } catch (error) {
21502
- (0, import_node_fs14.rmSync)(tempDir, { recursive: true, force: true });
21926
+ (0, import_node_fs15.rmSync)(tempDir, { recursive: true, force: true });
21503
21927
  process.stderr.write(
21504
21928
  `Failed to publish Deepline SDK sidecar update: ${error.message}
21505
21929
  `
@@ -21507,7 +21931,7 @@ async function runPythonSidecarUpdatePlan(plan) {
21507
21931
  return 1;
21508
21932
  }
21509
21933
  }
21510
- if (!(0, import_node_fs14.existsSync)(finalEntryPath)) {
21934
+ if (!(0, import_node_fs15.existsSync)(finalEntryPath)) {
21511
21935
  process.stderr.write(
21512
21936
  `Updated Deepline SDK CLI entrypoint missing: ${finalEntryPath}
21513
21937
  `
@@ -21521,28 +21945,28 @@ async function runPythonSidecarUpdatePlan(plan) {
21521
21945
  nodeBin: plan.nodeBin,
21522
21946
  entryPath: finalEntryPath
21523
21947
  });
21524
- (0, import_node_fs14.writeFileSync)(
21525
- (0, import_node_path17.join)(plan.stateDir, ".version"),
21948
+ (0, import_node_fs15.writeFileSync)(
21949
+ (0, import_node_path18.join)(plan.stateDir, ".version"),
21526
21950
  `${installedVersion}
21527
21951
  `,
21528
21952
  "utf8"
21529
21953
  );
21530
- (0, import_node_fs14.writeFileSync)(
21531
- (0, import_node_path17.join)(plan.stateDir, ".install-method"),
21954
+ (0, import_node_fs15.writeFileSync)(
21955
+ (0, import_node_path18.join)(plan.stateDir, ".install-method"),
21532
21956
  "python-sidecar\n",
21533
21957
  "utf8"
21534
21958
  );
21535
- (0, import_node_fs14.writeFileSync)(
21536
- (0, import_node_path17.join)(plan.stateDir, ".command-path"),
21959
+ (0, import_node_fs15.writeFileSync)(
21960
+ (0, import_node_path18.join)(plan.stateDir, ".command-path"),
21537
21961
  `${plan.sidecarPath}
21538
21962
  `,
21539
21963
  "utf8"
21540
21964
  );
21541
- (0, import_node_fs14.writeFileSync)((0, import_node_path17.join)(plan.stateDir, ".runner"), "node\n", "utf8");
21542
- (0, import_node_fs14.writeFileSync)((0, import_node_path17.join)(plan.stateDir, ".node-bin"), `${plan.nodeBin}
21965
+ (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(plan.stateDir, ".runner"), "node\n", "utf8");
21966
+ (0, import_node_fs15.writeFileSync)((0, import_node_path18.join)(plan.stateDir, ".node-bin"), `${plan.nodeBin}
21543
21967
  `, "utf8");
21544
- (0, import_node_fs14.writeFileSync)(
21545
- (0, import_node_path17.join)(plan.stateDir, ".entry-path"),
21968
+ (0, import_node_fs15.writeFileSync)(
21969
+ (0, import_node_path18.join)(plan.stateDir, ".entry-path"),
21546
21970
  `${finalEntryPath}
21547
21971
  `,
21548
21972
  "utf8"
@@ -21550,16 +21974,29 @@ async function runPythonSidecarUpdatePlan(plan) {
21550
21974
  return 0;
21551
21975
  }
21552
21976
  async function runUpdatePlan(plan) {
21977
+ let exitCode = 1;
21553
21978
  if (plan.kind === "npm-global") {
21554
- return runCommand(plan.command, plan.args);
21979
+ exitCode = await runCommand(plan.command, plan.args);
21980
+ } else if (plan.kind === "python-sidecar") {
21981
+ exitCode = await runPythonSidecarUpdatePlan(plan);
21555
21982
  }
21556
- if (plan.kind === "python-sidecar") {
21557
- return runPythonSidecarUpdatePlan(plan);
21983
+ if (exitCode === 0) {
21984
+ clearAutoUpdateFailure(plan);
21985
+ } else {
21986
+ writeAutoUpdateFailure(plan, exitCode);
21558
21987
  }
21559
- return 1;
21988
+ return exitCode;
21989
+ }
21990
+ function normalizeBaseUrl3(value) {
21991
+ return value.replace(/\/$/, "");
21560
21992
  }
21561
- async function handleUpdate(options) {
21562
- const plan = resolveUpdatePlan();
21993
+ async function runUpdateCommand(options, dependencies = {}) {
21994
+ const detectBaseUrl = dependencies.detectBaseUrl ?? autoDetectBaseUrl;
21995
+ const resolvePlan = dependencies.resolvePlan ?? resolveUpdatePlan;
21996
+ const runPlan = dependencies.runPlan ?? runUpdatePlan;
21997
+ const syncSkills = dependencies.syncSkillsIfNeeded ?? syncSdkSkillsIfNeeded;
21998
+ const stderr = dependencies.stderr ?? process.stderr;
21999
+ const plan = resolvePlan();
21563
22000
  const render = {
21564
22001
  sections: [
21565
22002
  {
@@ -21595,11 +22032,14 @@ async function handleUpdate(options) {
21595
22032
  printCommandEnvelope({ ...plan, render }, { json: false });
21596
22033
  return 0;
21597
22034
  }
21598
- process.stderr.write(
21599
- `Updating Deepline SDK/CLI with: ${plan.manualCommand}
21600
- `
21601
- );
21602
- return runUpdatePlan(plan);
22035
+ stderr.write(`Updating Deepline SDK/CLI with: ${plan.manualCommand}
22036
+ `);
22037
+ const updateExitCode = await runPlan(plan);
22038
+ if (updateExitCode !== 0) {
22039
+ return updateExitCode;
22040
+ }
22041
+ await syncSkills(normalizeBaseUrl3(detectBaseUrl()));
22042
+ return 0;
21603
22043
  }
21604
22044
  function registerUpdateCommand(program) {
21605
22045
  program.command("update").description("Update the Deepline SDK/CLI.").addHelpText(
@@ -21618,7 +22058,7 @@ Examples:
21618
22058
  deepline update --json
21619
22059
  `
21620
22060
  ).option("--print-command", "Print the update command without running it").option("--json", "Emit the resolved update plan as JSON").action(async (options) => {
21621
- process.exitCode = await handleUpdate(options);
22061
+ process.exitCode = await runUpdateCommand(options);
21622
22062
  });
21623
22063
  }
21624
22064
 
@@ -21631,138 +22071,36 @@ var command_compatibility_default = {
21631
22071
  },
21632
22072
  session: {
21633
22073
  family: "python",
21634
- label: "a legacy Python CLI session/playground command",
21635
- sdk_alternative: "Use `deepline sessions send ...` or `deepline sessions render ...` for transcript workflows."
21636
- },
21637
- workflows: {
21638
- family: "python",
21639
- label: "a legacy Python CLI workflow command",
21640
- sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
21641
- },
21642
- events: {
21643
- family: "python",
21644
- label: "a legacy Python CLI event command"
21645
- },
21646
- plays: {
21647
- family: "sdk",
21648
- label: "an SDK CLI play command",
21649
- python_alternative: "Use `deepline workflows ...` only for legacy workflows."
21650
- },
21651
- runs: {
21652
- family: "sdk",
21653
- label: "an SDK CLI run inspection command"
21654
- },
21655
- sessions: {
21656
- family: "sdk",
21657
- label: "an SDK CLI session transcript command"
21658
- },
21659
- health: {
21660
- family: "sdk",
21661
- label: "an SDK CLI health command"
21662
- }
21663
- };
21664
-
21665
- // ../shared_libs/cli/install-commands.json
21666
- var install_commands_default = {
21667
- skills: {
21668
- index_path: "/.well-known/skills/index.json",
21669
- default_agents: [
21670
- "codex",
21671
- "claude-code",
21672
- "cursor",
21673
- "gemini-cli",
21674
- "antigravity"
21675
- ],
21676
- npx_binary: "npx",
21677
- npx_add_args_template: [
21678
- "--yes",
21679
- "skills",
21680
- "add",
21681
- "{skills_index_url}",
21682
- "--agent",
21683
- "{agents}",
21684
- "--global",
21685
- "--yes",
21686
- "--skill",
21687
- "{skill_name}",
21688
- "--full-depth"
21689
- ]
21690
- },
21691
- cli: {
21692
- legacy_python_shell_template: "curl -s {base_url}/api/v2/cli/install | bash",
21693
- sdk_npm_global: "npm install -g deepline@latest"
21694
- }
21695
- };
21696
-
21697
- // src/cli/install-commands.ts
21698
- var INSTALL_COMMANDS = install_commands_default;
21699
- var DEFAULT_V1_SKILL_NAMES = [
21700
- "build-tam",
21701
- "clay-to-deepline",
21702
- "deepline-analytics",
21703
- "deepline-feedback",
21704
- "deepline-gtm",
21705
- "deepline-quickstart",
21706
- "find-qualified-titles",
21707
- "linkedin-url-lookup",
21708
- "niche-signal-discovery",
21709
- "portfolio-prospecting",
21710
- "workflow-hello-world"
21711
- ];
21712
- var DEFAULT_SDK_SKILL_NAMES = [
21713
- ...DEFAULT_V1_SKILL_NAMES,
21714
- "deepline-plays"
21715
- ];
21716
- function normalizeBaseUrl2(baseUrl) {
21717
- return baseUrl.replace(/\/$/, "");
21718
- }
21719
- function renderTemplate(template, values) {
21720
- return template.replace(/\{([a-z_]+)\}/g, (match, key) => {
21721
- return values[key] ?? match;
21722
- });
21723
- }
21724
- function shellJoin(args) {
21725
- return args.join(" ");
21726
- }
21727
- function skillsIndexUrl(baseUrl) {
21728
- return `${normalizeBaseUrl2(baseUrl)}${INSTALL_COMMANDS.skills.index_path}`;
21729
- }
21730
- function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
21731
- const skillNames = Array.isArray(skillName) ? skillName : [skillName];
21732
- const [firstSkillName, ...extraSkillNames] = skillNames;
21733
- const values = {
21734
- skills_index_url: skillsIndexUrl(baseUrl),
21735
- agents: INSTALL_COMMANDS.skills.default_agents.join(" "),
21736
- skill_name: firstSkillName ?? ""
21737
- };
21738
- const rendered = INSTALL_COMMANDS.skills.npx_add_args_template.flatMap(
21739
- (arg, index) => {
21740
- const next = index === 0 && options.firstArg ? options.firstArg : arg;
21741
- const value = renderTemplate(next, values);
21742
- if (arg === "{agents}") {
21743
- return INSTALL_COMMANDS.skills.default_agents;
21744
- }
21745
- if (arg === "{skill_name}") {
21746
- return [value, ...extraSkillNames.flatMap((name) => ["--skill", name])];
21747
- }
21748
- return value;
21749
- }
21750
- );
21751
- return rendered;
21752
- }
21753
- function skillsInstallCommand(baseUrl, skillName) {
21754
- return `${INSTALL_COMMANDS.skills.npx_binary} ${shellJoin(
21755
- buildSkillsAddArgs(baseUrl, skillName)
21756
- )}`;
21757
- }
21758
- function legacyPythonInstallCommand(baseUrl) {
21759
- return renderTemplate(INSTALL_COMMANDS.cli.legacy_python_shell_template, {
21760
- base_url: normalizeBaseUrl2(baseUrl)
21761
- });
21762
- }
21763
- function sdkNpmGlobalInstallCommand() {
21764
- return INSTALL_COMMANDS.cli.sdk_npm_global;
21765
- }
22074
+ label: "a legacy Python CLI session/playground command",
22075
+ sdk_alternative: "Use `deepline sessions send ...` or `deepline sessions render ...` for transcript workflows."
22076
+ },
22077
+ workflows: {
22078
+ family: "python",
22079
+ label: "a legacy Python CLI workflow command",
22080
+ sdk_alternative: "Use `deepline plays ...` in the SDK CLI."
22081
+ },
22082
+ events: {
22083
+ family: "python",
22084
+ label: "a legacy Python CLI event command"
22085
+ },
22086
+ plays: {
22087
+ family: "sdk",
22088
+ label: "an SDK CLI play command",
22089
+ python_alternative: "Use `deepline workflows ...` only for legacy workflows."
22090
+ },
22091
+ runs: {
22092
+ family: "sdk",
22093
+ label: "an SDK CLI run inspection command"
22094
+ },
22095
+ sessions: {
22096
+ family: "sdk",
22097
+ label: "an SDK CLI session transcript command"
22098
+ },
22099
+ health: {
22100
+ family: "sdk",
22101
+ label: "an SDK CLI health command"
22102
+ }
22103
+ };
21766
22104
 
21767
22105
  // src/cli/command-compatibility.ts
21768
22106
  var COMMAND_COMPATIBILITY = command_compatibility_default;
@@ -21817,7 +22155,7 @@ function unknownCommandNameFromMessage(message) {
21817
22155
  }
21818
22156
 
21819
22157
  // src/cli/self-update.ts
21820
- var import_node_child_process3 = require("child_process");
22158
+ var import_node_child_process4 = require("child_process");
21821
22159
  function envTruthy(name) {
21822
22160
  const value = process.env[name]?.trim().toLowerCase();
21823
22161
  return value === "1" || value === "true" || value === "yes";
@@ -21832,7 +22170,7 @@ function relaunchCurrentCommand(plan) {
21832
22170
  return new Promise((resolve13) => {
21833
22171
  const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
21834
22172
  const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
21835
- const child = (0, import_node_child_process3.spawn)(command, args, {
22173
+ const child = (0, import_node_child_process4.spawn)(command, args, {
21836
22174
  stdio: "inherit",
21837
22175
  shell: process.platform === "win32",
21838
22176
  env: {
@@ -21865,15 +22203,18 @@ async function maybeAutoUpdateAndRelaunch(response) {
21865
22203
  `Deepline SDK/CLI ${label}; running ${plan.manualCommand}
21866
22204
  `
21867
22205
  );
21868
- const updateExitCode = await runUpdatePlan(plan);
21869
- if (updateExitCode !== 0) {
22206
+ const updateResult = await runAutomaticUpdatePlan(plan);
22207
+ if (updateResult.status === "skipped_previous_failure") {
22208
+ return false;
22209
+ }
22210
+ if (updateResult.exitCode !== 0) {
21870
22211
  if (autoUpdate.required) {
21871
22212
  throw new Error(
21872
- `Automatic Deepline SDK/CLI update failed with exit code ${updateExitCode}. ${response.message}`
22213
+ `Automatic Deepline SDK/CLI update failed with exit code ${updateResult.exitCode}. ${response.message}`
21873
22214
  );
21874
22215
  }
21875
22216
  process.stderr.write(
21876
- `Deepline SDK/CLI auto-update failed with exit code ${updateExitCode}; continuing with ${response.current ?? "current version"}.
22217
+ `Deepline SDK/CLI auto-update failed with exit code ${updateResult.exitCode}; continuing with ${response.current ?? "current version"}.
21877
22218
  `
21878
22219
  );
21879
22220
  return false;
@@ -21884,238 +22225,6 @@ async function maybeAutoUpdateAndRelaunch(response) {
21884
22225
  return true;
21885
22226
  }
21886
22227
 
21887
- // src/cli/skills-sync.ts
21888
- var import_node_child_process4 = require("child_process");
21889
- var import_node_fs15 = require("fs");
21890
- var import_node_os13 = require("os");
21891
- var import_node_path18 = require("path");
21892
- var CHECK_TIMEOUT_MS2 = 3e3;
21893
- var SDK_PLAY_SKILL_NAME = "deepline-plays";
21894
- var attemptedSync = false;
21895
- function shouldSkipSkillsSync() {
21896
- const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
21897
- return value === "1" || value === "true" || value === "yes" || value === "on";
21898
- }
21899
- function activePluginSkillsDir() {
21900
- const pluginMode = process.env.DEEPLINE_PLUGIN_MODE?.trim().toLowerCase();
21901
- if (pluginMode !== "true" && pluginMode !== "1" && pluginMode !== "yes" && pluginMode !== "on") {
21902
- return "";
21903
- }
21904
- const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
21905
- return dir && (0, import_node_fs15.existsSync)(dir) ? dir : "";
21906
- }
21907
- function readPluginSkillsVersion() {
21908
- const dir = activePluginSkillsDir();
21909
- if (!dir) return "";
21910
- try {
21911
- return (0, import_node_fs15.readFileSync)((0, import_node_path18.join)(dir, ".version"), "utf-8").trim();
21912
- } catch {
21913
- return "";
21914
- }
21915
- }
21916
- function sdkSkillsVersionPath(baseUrl) {
21917
- const home = process.env.HOME?.trim() || (0, import_node_os13.homedir)();
21918
- return (0, import_node_path18.join)(
21919
- home,
21920
- ".local",
21921
- "deepline",
21922
- baseUrlSlug(baseUrl),
21923
- "sdk-skills",
21924
- ".version"
21925
- );
21926
- }
21927
- function readLocalSkillsVersion(baseUrl) {
21928
- const pluginVersion = readPluginSkillsVersion();
21929
- if (pluginVersion) return pluginVersion;
21930
- const path = sdkSkillsVersionPath(baseUrl);
21931
- if (!(0, import_node_fs15.existsSync)(path)) return "";
21932
- try {
21933
- return (0, import_node_fs15.readFileSync)(path, "utf-8").trim();
21934
- } catch {
21935
- return "";
21936
- }
21937
- }
21938
- function writeLocalSkillsVersion(baseUrl, version) {
21939
- const path = sdkSkillsVersionPath(baseUrl);
21940
- (0, import_node_fs15.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
21941
- (0, import_node_fs15.writeFileSync)(path, `${version}
21942
- `, "utf-8");
21943
- }
21944
- function sortedUniqueSkillNames(names) {
21945
- return [...new Set(names.map((name) => name.trim()).filter(Boolean))].sort(
21946
- (a, b) => a.localeCompare(b)
21947
- );
21948
- }
21949
- async function fetchV1SkillNames(baseUrl) {
21950
- const controller = new AbortController();
21951
- const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
21952
- try {
21953
- const response = await fetch(
21954
- new URL("/.well-known/skills/index.json", baseUrl),
21955
- { signal: controller.signal }
21956
- );
21957
- if (!response.ok) return [];
21958
- const data = await response.json().catch(() => null);
21959
- const names = (data?.skills ?? []).filter((skill) => skill.install_surface === "v1").map((skill) => skill.name).filter(
21960
- (name) => typeof name === "string" && name.length > 0
21961
- );
21962
- return sortedUniqueSkillNames(names);
21963
- } catch {
21964
- return [];
21965
- } finally {
21966
- clearTimeout(timeout);
21967
- }
21968
- }
21969
- function buildSdkSkillNames(v1SkillNames) {
21970
- return sortedUniqueSkillNames([...v1SkillNames, SDK_PLAY_SKILL_NAME]);
21971
- }
21972
- async function fetchSkillsUpdate(baseUrl, localVersion) {
21973
- const controller = new AbortController();
21974
- const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
21975
- try {
21976
- const response = await fetch(new URL("/api/v2/cli/update-check", baseUrl), {
21977
- method: "POST",
21978
- headers: { "Content-Type": "application/json" },
21979
- body: JSON.stringify({
21980
- skills: {
21981
- version: localVersion
21982
- }
21983
- }),
21984
- signal: controller.signal
21985
- });
21986
- if (!response.ok) return null;
21987
- const data = await response.json().catch(() => null);
21988
- const skills = data?.skills;
21989
- if (!skills) return null;
21990
- return {
21991
- needsUpdate: skills.needs_update === true,
21992
- remoteVersion: typeof skills.remote?.version === "string" ? skills.remote.version.trim() : ""
21993
- };
21994
- } catch {
21995
- return null;
21996
- } finally {
21997
- clearTimeout(timeout);
21998
- }
21999
- }
22000
- function buildSkillsInstallArgs(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
22001
- return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames));
22002
- }
22003
- function buildBunxSkillsInstallArgs(baseUrl, skillNames) {
22004
- return buildSkillsAddArgs(baseUrl, sortedUniqueSkillNames(skillNames), {
22005
- firstArg: "--bun"
22006
- });
22007
- }
22008
- function hasCommand(command) {
22009
- const result = (0, import_node_child_process4.spawnSync)(command, ["--version"], {
22010
- stdio: "ignore",
22011
- shell: process.platform === "win32"
22012
- });
22013
- return result.status === 0;
22014
- }
22015
- function shellQuote4(arg) {
22016
- return `'${arg.replace(/'/g, `'\\''`)}'`;
22017
- }
22018
- function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
22019
- const npxArgs = buildSkillsInstallArgs(baseUrl, skillNames);
22020
- const npxInstall = {
22021
- command: "npx",
22022
- args: npxArgs,
22023
- manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
22024
- };
22025
- if (hasCommand("bunx")) {
22026
- const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
22027
- return [
22028
- {
22029
- command: "bunx",
22030
- args: bunxArgs,
22031
- manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
22032
- },
22033
- npxInstall
22034
- ];
22035
- }
22036
- return [npxInstall];
22037
- }
22038
- function runOneSkillsInstall(install) {
22039
- return new Promise((resolve13) => {
22040
- const child = (0, import_node_child_process4.spawn)(install.command, install.args, {
22041
- stdio: ["ignore", "ignore", "pipe"],
22042
- env: process.env
22043
- });
22044
- let stderr = "";
22045
- child.stderr.on("data", (chunk) => {
22046
- stderr += chunk.toString("utf-8");
22047
- });
22048
- child.on("error", (error) => {
22049
- resolve13({
22050
- ok: false,
22051
- detail: `failed to start ${install.command}: ${error.message}`,
22052
- manualCommand: install.manualCommand
22053
- });
22054
- });
22055
- child.on("close", (code) => {
22056
- if (code === 0) {
22057
- resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
22058
- return;
22059
- }
22060
- const detail = stderr.trim();
22061
- resolve13({
22062
- ok: false,
22063
- detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
22064
- manualCommand: install.manualCommand
22065
- });
22066
- });
22067
- });
22068
- }
22069
- async function runSkillsInstall(baseUrl, skillNames) {
22070
- const failures = [];
22071
- for (const install of resolveSkillsInstallCommands(baseUrl, skillNames)) {
22072
- const result = await runOneSkillsInstall(install);
22073
- if (result.ok) return true;
22074
- failures.push(result);
22075
- }
22076
- const details = failures.map((failure) => failure.detail).filter(Boolean).join("\n");
22077
- const manualCommand = failures.at(-1)?.manualCommand;
22078
- process.stderr.write(
22079
- `SDK skills sync failed${details ? `:
22080
- ${details}` : ""}
22081
- ` + (manualCommand ? `Run manually: ${manualCommand}
22082
- ` : "")
22083
- );
22084
- return false;
22085
- }
22086
- function writeSdkSkillsStatusLine(line) {
22087
- const progress = getActiveCliProgress();
22088
- if (progress) {
22089
- progress.writeLine(line);
22090
- return;
22091
- }
22092
- process.stderr.write(`${line}
22093
- `);
22094
- }
22095
- async function syncSdkSkillsIfNeeded(baseUrl) {
22096
- if (attemptedSync || shouldSkipSkillsSync()) return;
22097
- attemptedSync = true;
22098
- const usingPluginSkills = Boolean(activePluginSkillsDir());
22099
- const localVersion = readLocalSkillsVersion(baseUrl);
22100
- const update = await fetchSkillsUpdate(baseUrl, localVersion);
22101
- if (usingPluginSkills) {
22102
- return;
22103
- }
22104
- if (!update?.needsUpdate || !update.remoteVersion) {
22105
- return;
22106
- }
22107
- const remoteSkillNames = await fetchV1SkillNames(baseUrl);
22108
- const skillNames = buildSdkSkillNames(
22109
- remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
22110
- );
22111
- if (skillNames.length === 0) return;
22112
- writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
22113
- const installed = await runSkillsInstall(baseUrl, skillNames);
22114
- if (!installed) return;
22115
- writeLocalSkillsVersion(baseUrl, update.remoteVersion);
22116
- writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
22117
- }
22118
-
22119
22228
  // src/cli/failure-reporting.ts
22120
22229
  var import_node_os14 = require("os");
22121
22230
  var FAILURE_REPORT_DISABLE_ENV = "DEEPLINE_DISABLE_FAILURE_REPORTING";