deepline 0.3.189 → 0.3.190

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
@@ -1965,7 +1965,7 @@ configureProxyFromEnv();
1965
1965
  // src/cli/index.ts
1966
1966
  var import_promises14 = require("fs/promises");
1967
1967
  var import_node_path32 = require("path");
1968
- var import_node_os19 = require("os");
1968
+ var import_node_os20 = require("os");
1969
1969
  var import_commander5 = require("commander");
1970
1970
 
1971
1971
  // src/pagination.ts
@@ -3051,7 +3051,7 @@ var SDK_RELEASE = {
3051
3051
  // getters keep their established compatibility behavior.
3052
3052
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3053
3053
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3054
- version: "0.3.189",
3054
+ version: "0.3.190",
3055
3055
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3056
3056
  packageCapabilities: {
3057
3057
  updatePreferences: 1
@@ -3276,6 +3276,13 @@ var KNOWN_SKILL_AGENTS = [
3276
3276
  "gemini-cli",
3277
3277
  "windsurf"
3278
3278
  ];
3279
+ var DEFAULT_SKILL_AGENTS = [
3280
+ "codex",
3281
+ "claude-code",
3282
+ "cursor",
3283
+ "gemini-cli",
3284
+ "antigravity"
3285
+ ];
3279
3286
  function skillsAgentPathSegment(agent) {
3280
3287
  if (agent === "*") return "all";
3281
3288
  const slug = agent.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "");
@@ -3288,6 +3295,13 @@ function sdkSkillsVersionPath(baseUrl, agents = []) {
3288
3295
  function legacySdkSkillsVersionPath(baseUrl) {
3289
3296
  return (0, import_node_path2.join)((0, import_node_path2.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
3290
3297
  }
3298
+ function readSkillsVersionFile(path) {
3299
+ try {
3300
+ return (0, import_node_fs2.readFileSync)(path, "utf-8").trim();
3301
+ } catch {
3302
+ return "";
3303
+ }
3304
+ }
3291
3305
  function resolveAutoSyncSkillAgents() {
3292
3306
  switch (detectAgentRuntime()) {
3293
3307
  case "codex":
@@ -3300,6 +3314,8 @@ function resolveAutoSyncSkillAgents() {
3300
3314
  return ["gemini-cli"];
3301
3315
  case "antigravity":
3302
3316
  return ["antigravity"];
3317
+ case "unknown":
3318
+ return [...DEFAULT_SKILL_AGENTS];
3303
3319
  default:
3304
3320
  return [];
3305
3321
  }
@@ -3308,6 +3324,13 @@ function readSdkSkillsLocalVersion(baseUrl) {
3308
3324
  const pluginVersion = readPluginSkillsVersion();
3309
3325
  if (pluginVersion) return pluginVersion;
3310
3326
  const agents = resolveAutoSyncSkillAgents();
3327
+ if (agents.length > 1) {
3328
+ const versions = agents.map(
3329
+ (agent) => readSkillsVersionFile(sdkSkillsVersionPath(baseUrl, [agent]))
3330
+ );
3331
+ const first = versions[0];
3332
+ return first && versions.every((version) => version === first) ? first : "";
3333
+ }
3311
3334
  const scopedPath = sdkSkillsVersionPath(baseUrl, agents);
3312
3335
  if (agents.length > 0 && (0, import_node_fs2.existsSync)(scopedPath)) {
3313
3336
  try {
@@ -3334,10 +3357,19 @@ function readSdkSkillsLocalVersion(baseUrl) {
3334
3357
  }
3335
3358
  }
3336
3359
  function writeSdkSkillsLocalVersion(baseUrl, version, agents) {
3337
- const path = sdkSkillsVersionPath(baseUrl, agents);
3338
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(path), { recursive: true });
3339
- (0, import_node_fs2.writeFileSync)(path, `${version}
3360
+ const targets = agents.length > 1 ? agents.map((agent) => [agent]) : [agents];
3361
+ let complete = true;
3362
+ for (const target of targets) {
3363
+ const path = sdkSkillsVersionPath(baseUrl, target);
3364
+ try {
3365
+ (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(path), { recursive: true });
3366
+ (0, import_node_fs2.writeFileSync)(path, `${version}
3340
3367
  `, "utf-8");
3368
+ } catch {
3369
+ complete = false;
3370
+ }
3371
+ }
3372
+ return complete;
3341
3373
  }
3342
3374
 
3343
3375
  // ../play-runtime/coordinator-headers.ts
@@ -42724,7 +42756,7 @@ Examples:
42724
42756
  // src/cli/commands/setup.ts
42725
42757
  var import_node_child_process5 = require("child_process");
42726
42758
  var import_node_fs20 = require("fs");
42727
- var import_node_os14 = require("os");
42759
+ var import_node_os15 = require("os");
42728
42760
  var import_node_path25 = require("path");
42729
42761
 
42730
42762
  // src/cli/installation-lifecycle.ts
@@ -42852,7 +42884,7 @@ function isOwnedInstallerCommandPath(input2) {
42852
42884
  // src/cli/commands/skills.ts
42853
42885
  var import_node_child_process3 = require("child_process");
42854
42886
  var import_node_fs19 = require("fs");
42855
- var import_node_os13 = require("os");
42887
+ var import_node_os14 = require("os");
42856
42888
  var import_node_path24 = require("path");
42857
42889
 
42858
42890
  // contracts/install-commands.json
@@ -42888,7 +42920,6 @@ var install_commands_default = {
42888
42920
 
42889
42921
  // src/cli/install-commands.ts
42890
42922
  var INSTALL_COMMANDS = install_commands_default;
42891
- var DEFAULT_SKILL_AGENTS = INSTALL_COMMANDS.skills.default_agents;
42892
42923
  var skillsNpxPackage = INSTALL_COMMANDS.skills.npx_add_args_template.find(
42893
42924
  (arg) => /^skills@\d+\.\d+\.\d+$/.test(arg)
42894
42925
  );
@@ -42939,7 +42970,7 @@ function skillsSourceUrl(baseUrl) {
42939
42970
  function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
42940
42971
  const skillNames = Array.isArray(skillName) ? skillName : [skillName];
42941
42972
  const [firstSkillName, ...extraSkillNames] = skillNames;
42942
- const agents = options.agents ?? INSTALL_COMMANDS.skills.default_agents;
42973
+ const agents = options.agents ?? DEFAULT_SKILL_AGENTS;
42943
42974
  const values = {
42944
42975
  skills_index_url: skillsIndexUrl(baseUrl),
42945
42976
  skills_source_url: skillsSourceUrl(baseUrl),
@@ -42968,6 +42999,8 @@ function buildSkillsAddArgs(baseUrl, skillName, options = {}) {
42968
42999
  // src/cli/skills-sync.ts
42969
43000
  var import_node_child_process2 = require("child_process");
42970
43001
  var import_node_crypto11 = require("crypto");
43002
+ var import_node_os13 = require("os");
43003
+ var import_node_zlib2 = require("zlib");
42971
43004
  var import_node_fs18 = require("fs");
42972
43005
  var import_node_path23 = require("path");
42973
43006
 
@@ -43324,6 +43357,8 @@ async function maybeReportSdkCliFailure(input2) {
43324
43357
 
43325
43358
  // src/cli/skills-sync.ts
43326
43359
  var CHECK_TIMEOUT_MS2 = 3e3;
43360
+ var INSTALLER_PROBE_TIMEOUT_MS = 1500;
43361
+ var PUBLISHED_VERIFICATION_RETRY_MS = 5 * 6e4;
43327
43362
  function shouldSkipSkillsSync() {
43328
43363
  if (detectAgentRuntime() === "claude_cowork" || isCiEnvironment()) {
43329
43364
  return true;
@@ -43612,7 +43647,7 @@ function spawnDetachedSkillsSyncChild(argv, onSpawnError) {
43612
43647
  function failedSkillsSyncPath(baseUrl, agents) {
43613
43648
  return (0, import_node_path23.join)(
43614
43649
  sdkCliStateDirPath(baseUrl),
43615
- `skills-sync-failed-${agents.map(agentLeaseSegment).join("-")}-version`
43650
+ `skills-sync-failed-${sortedLeaseAgents(agents).map(agentLeaseSegment).join("-")}-version`
43616
43651
  );
43617
43652
  }
43618
43653
  function hasMarkedSkillsSyncVersion(path, version) {
@@ -43635,13 +43670,15 @@ function writeMarkedSkillsSyncVersion(path, version) {
43635
43670
  return false;
43636
43671
  }
43637
43672
  }
43638
- function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames, notice = writeSdkSkillsStatusLine) {
43673
+ function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames, reason, notice = writeSdkSkillsStatusLine, knownProbes) {
43639
43674
  const path = unavailableSkillsNoticePath(baseUrl);
43640
43675
  if (hasMarkedSkillsSyncVersion(path, remoteVersion)) return;
43641
43676
  writeMarkedSkillsSyncVersion(path, remoteVersion);
43642
- const manualCommand = `npx ${buildSkillsInstallArgs(baseUrl, skillNames).join(" ")}`;
43677
+ const probes = reason === "no-installer" ? knownProbes ?? probeInstallers() : null;
43678
+ const manualCommand = probes?.npx === "missing" && probes.bunx !== "missing" ? `bunx ${buildBunxSkillsInstallArgs(baseUrl, skillNames, DEFAULT_SKILL_AGENTS).map(shellQuote4).join(" ")}` : `npx ${buildSkillsInstallArgs(baseUrl, skillNames).join(" ")}`;
43679
+ const explanation = reason === "unsupported-agent" ? "the detected agent has no automatic skills sync target. Automatic sync was skipped." : probes?.bunx === "missing" && probes.npx === "missing" ? "neither `bunx` nor `npx` was found on PATH. Make one available." : `installer version check failed for ${Object.entries(probes ?? {}).filter(([, result]) => result === "failed").map(([command]) => `\`${command}\``).join(" and ")}. Check those commands with --version.`;
43643
43680
  notice(
43644
- `Deepline agent skills are out of date, but neither \`bunx\` nor \`npx\` is available. Install Node.js/npm or Bun, then run:
43681
+ `Deepline agent skills are out of date, but ${explanation} To install manually, run:
43645
43682
  ${manualCommand}`
43646
43683
  );
43647
43684
  }
@@ -43652,10 +43689,17 @@ function clearUnavailableSkillsNotice(baseUrl) {
43652
43689
  }
43653
43690
  }
43654
43691
  function hasFailedSkillsSync(baseUrl, remoteVersion, agents) {
43655
- return hasMarkedSkillsSyncVersion(
43656
- failedSkillsSyncPath(baseUrl, agents),
43657
- remoteVersion
43692
+ const marked = readMarkedSkillsSyncVersion(
43693
+ failedSkillsSyncPath(baseUrl, agents)
43658
43694
  );
43695
+ if (marked === remoteVersion) return true;
43696
+ try {
43697
+ const retry = JSON.parse(marked);
43698
+ const now = Date.now();
43699
+ return retry.version === remoteVersion && typeof retry.retryAfter === "number" && retry.retryAfter > now && retry.retryAfter <= now + PUBLISHED_VERIFICATION_RETRY_MS;
43700
+ } catch {
43701
+ return false;
43702
+ }
43659
43703
  }
43660
43704
  function hasFailedAutomaticSkillsSync(baseUrl, agents) {
43661
43705
  return (0, import_node_fs18.existsSync)(failedSkillsSyncPath(baseUrl, agents));
@@ -43666,6 +43710,15 @@ function markFailedSkillsSync(baseUrl, remoteVersion, agents) {
43666
43710
  remoteVersion
43667
43711
  );
43668
43712
  }
43713
+ function deferPublishedVerificationRetry(baseUrl, remoteVersion, agents) {
43714
+ return writeMarkedSkillsSyncVersion(
43715
+ failedSkillsSyncPath(baseUrl, agents),
43716
+ JSON.stringify({
43717
+ version: remoteVersion,
43718
+ retryAfter: Date.now() + PUBLISHED_VERIFICATION_RETRY_MS
43719
+ })
43720
+ );
43721
+ }
43669
43722
  function clearFailedSkillsSync(baseUrl, agents) {
43670
43723
  try {
43671
43724
  (0, import_node_fs18.unlinkSync)(failedSkillsSyncPath(baseUrl, agents));
@@ -43680,7 +43733,7 @@ function sortedUniqueSkillNames(names) {
43680
43733
  (a, b) => a.localeCompare(b)
43681
43734
  );
43682
43735
  }
43683
- async function fetchV1SkillNames(baseUrl) {
43736
+ async function fetchV1SkillIndex(baseUrl) {
43684
43737
  const controller = new AbortController();
43685
43738
  const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS2);
43686
43739
  try {
@@ -43688,20 +43741,175 @@ async function fetchV1SkillNames(baseUrl) {
43688
43741
  new URL("/.well-known/skills/index.json", baseUrl),
43689
43742
  { signal: controller.signal }
43690
43743
  );
43691
- if (!response.ok) return [];
43744
+ if (!response.ok) return null;
43692
43745
  const data = await response.json().catch(() => null);
43693
- const names = (data?.skills ?? []).filter((skill) => skill.install_surface === "v1").map((skill) => skill.name).filter(
43694
- (name) => typeof name === "string" && name.length > 0
43695
- );
43696
- return sortedUniqueSkillNames(names);
43746
+ return data;
43697
43747
  } catch {
43698
- return [];
43748
+ return null;
43699
43749
  } finally {
43700
43750
  clearTimeout(timeout);
43701
43751
  }
43702
43752
  }
43703
- function buildSdkSkillNames(v1SkillNames) {
43704
- return sortedUniqueSkillNames(v1SkillNames);
43753
+ function v1SkillNames(index) {
43754
+ const skills = Array.isArray(index?.skills) ? index.skills : [];
43755
+ return sortedUniqueSkillNames(
43756
+ skills.filter((skill) => skill && skill.install_surface === "v1").map((skill) => skill.name).filter(
43757
+ (name) => typeof name === "string" && name.length > 0
43758
+ )
43759
+ );
43760
+ }
43761
+ function buildSdkSkillNames(v1SkillNames2) {
43762
+ return sortedUniqueSkillNames(v1SkillNames2);
43763
+ }
43764
+ function isDefaultAgentSet(agents) {
43765
+ return agents.length === DEFAULT_SKILL_AGENTS.length && agents.every((agent, index) => agent === DEFAULT_SKILL_AGENTS[index]);
43766
+ }
43767
+ function safeSkillFilePath(value) {
43768
+ if (typeof value !== "string" || !value) return false;
43769
+ return value.split("/").every(
43770
+ (part) => /^[a-zA-Z0-9._-]+$/.test(part) && part !== "." && part !== ".."
43771
+ );
43772
+ }
43773
+ function installedSkillFiles(root, prefix = "") {
43774
+ const files = [];
43775
+ for (const entry of (0, import_node_fs18.readdirSync)((0, import_node_path23.join)(root, prefix), {
43776
+ withFileTypes: true
43777
+ })) {
43778
+ const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
43779
+ if (entry.isDirectory()) {
43780
+ files.push(...installedSkillFiles(root, relativePath));
43781
+ } else if (entry.isFile()) {
43782
+ files.push(relativePath);
43783
+ } else {
43784
+ throw new Error(`unexpected installed entry in ${root}`);
43785
+ }
43786
+ }
43787
+ return files.sort((a, b) => a.localeCompare(b));
43788
+ }
43789
+ function publishedArchiveFiles(bytes, expectedFiles, name) {
43790
+ const tar = (0, import_node_zlib2.gunzipSync)(bytes, { maxOutputLength: 128 * 1024 * 1024 });
43791
+ const expected = new Set(expectedFiles);
43792
+ const files = /* @__PURE__ */ new Map();
43793
+ let offset = 0;
43794
+ while (offset + 512 <= tar.length) {
43795
+ const header = tar.subarray(offset, offset + 512);
43796
+ if (header.every((byte) => byte === 0)) {
43797
+ if (!tar.subarray(offset).every((byte) => byte === 0)) {
43798
+ throw new Error(`invalid published archive for ${name}`);
43799
+ }
43800
+ break;
43801
+ }
43802
+ const file = header.toString("utf8", 0, 100).split("\0", 1)[0] ?? "";
43803
+ const sizeText = header.toString("ascii", 124, 136).replace(/\0/g, "").trim();
43804
+ const size = /^[0-7]+$/.test(sizeText) ? Number.parseInt(sizeText, 8) : NaN;
43805
+ const type = header[156];
43806
+ if (!safeSkillFilePath(file) || !expected.has(file) || files.has(file) || !Number.isSafeInteger(size) || size < 0 || type !== 0 && type !== 48 || header.subarray(345, 500).some((byte) => byte !== 0)) {
43807
+ throw new Error(`invalid published archive entry for ${name}`);
43808
+ }
43809
+ const start = offset + 512;
43810
+ const end = start + size;
43811
+ if (end > tar.length) {
43812
+ throw new Error(`incomplete published archive for ${name}`);
43813
+ }
43814
+ files.set(file, tar.subarray(start, end));
43815
+ offset = start + Math.ceil(size / 512) * 512;
43816
+ }
43817
+ if (files.size !== expected.size) {
43818
+ throw new Error(`published archive file list differs for ${name}`);
43819
+ }
43820
+ return files;
43821
+ }
43822
+ var PublishedSkillsVerificationError = class extends Error {
43823
+ };
43824
+ async function verifyDefaultAgentSkillsInstall(baseUrl, remoteVersion, skillNames, index) {
43825
+ if (index?.version !== remoteVersion) {
43826
+ throw new PublishedSkillsVerificationError(
43827
+ "the published skill index version does not match the server version"
43828
+ );
43829
+ }
43830
+ const published = /* @__PURE__ */ new Map();
43831
+ const entries = Array.isArray(index.skills) ? index.skills : [];
43832
+ for (const name of skillNames) {
43833
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(name)) {
43834
+ throw new PublishedSkillsVerificationError(
43835
+ `unsafe published skill name: ${name}`
43836
+ );
43837
+ }
43838
+ const entry = entries.find(
43839
+ (skill) => skill && skill.name === name && skill.install_surface === "v1"
43840
+ );
43841
+ if (!Array.isArray(entry?.files) || !entry.files.length || !entry.files.every(safeSkillFilePath) || new Set(entry.files).size !== entry.files.length || !entry.files.includes("SKILL.md") || entry.type !== "archive" || entry.url !== `./archives/${name}.tar.gz` || typeof entry.digest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(entry.digest)) {
43842
+ throw new PublishedSkillsVerificationError(
43843
+ `invalid published file list for ${name}`
43844
+ );
43845
+ }
43846
+ published.set(name, {
43847
+ files: [...entry.files].sort((a, b) => a.localeCompare(b)),
43848
+ digest: entry.digest
43849
+ });
43850
+ }
43851
+ const expected = /* @__PURE__ */ new Map();
43852
+ const jobs = [...published];
43853
+ const controller = new AbortController();
43854
+ const timeout = setTimeout(() => controller.abort(), 12e4);
43855
+ let cursor = 0;
43856
+ try {
43857
+ await Promise.all(
43858
+ Array.from({ length: Math.min(8, jobs.length) }, async () => {
43859
+ while (cursor < jobs.length) {
43860
+ const job = jobs[cursor++];
43861
+ if (!job) break;
43862
+ const [name, publishedSkill] = job;
43863
+ const url = new URL(
43864
+ `/.well-known/skills/archives/${name}.tar.gz`,
43865
+ baseUrl
43866
+ );
43867
+ const response = await fetch(url, { signal: controller.signal });
43868
+ if (!response.ok) {
43869
+ throw new Error(`published archive is unavailable: ${name}`);
43870
+ }
43871
+ const bytes = Buffer.from(await response.arrayBuffer());
43872
+ const digest = `sha256:${(0, import_node_crypto11.createHash)("sha256").update(bytes).digest("hex")}`;
43873
+ if (digest !== publishedSkill.digest) {
43874
+ throw new Error(`published archive digest differs for ${name}`);
43875
+ }
43876
+ for (const [file, content] of publishedArchiveFiles(
43877
+ bytes,
43878
+ publishedSkill.files,
43879
+ name
43880
+ )) {
43881
+ expected.set(`${name}/${file}`, content);
43882
+ }
43883
+ }
43884
+ })
43885
+ );
43886
+ } catch (error) {
43887
+ throw new PublishedSkillsVerificationError(
43888
+ error instanceof Error ? error.message : String(error)
43889
+ );
43890
+ } finally {
43891
+ clearTimeout(timeout);
43892
+ controller.abort();
43893
+ }
43894
+ const home = (0, import_node_os13.homedir)();
43895
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path23.join)(home, ".claude");
43896
+ for (const [name, { files }] of published) {
43897
+ for (const root of [
43898
+ (0, import_node_path23.join)(home, ".agents", "skills", name),
43899
+ (0, import_node_path23.join)(claudeConfigDir, "skills", name)
43900
+ ]) {
43901
+ const installed = installedSkillFiles(root);
43902
+ if (installed.length !== files.length || installed.some((file, index2) => file !== files[index2])) {
43903
+ throw new Error(`installed file tree differs for ${name}`);
43904
+ }
43905
+ for (const file of files) {
43906
+ const publishedContent = expected.get(`${name}/${file}`);
43907
+ if (!publishedContent || !(0, import_node_fs18.readFileSync)((0, import_node_path23.join)(root, file)).equals(publishedContent)) {
43908
+ throw new Error(`installed content differs for ${name}/${file}`);
43909
+ }
43910
+ }
43911
+ }
43912
+ }
43705
43913
  }
43706
43914
  async function fetchSkillsUpdate(baseUrl, localVersion) {
43707
43915
  const controller = new AbortController();
@@ -43742,13 +43950,58 @@ function buildBunxSkillsInstallArgs(baseUrl, skillNames, agents) {
43742
43950
  agents
43743
43951
  });
43744
43952
  }
43745
- function hasCommand(command) {
43953
+ var NEGATIVE_INSTALLER_PROBE_TTL_MS = 5 * 60 * 1e3;
43954
+ function probeInstallers(timeoutMs) {
43955
+ return {
43956
+ bunx: probeCommand("bunx", timeoutMs),
43957
+ npx: probeCommand("npx", timeoutMs)
43958
+ };
43959
+ }
43960
+ function noInstallerProbePath(baseUrl) {
43961
+ return (0, import_node_path23.join)(
43962
+ sdkCliStateDirPath(baseUrl),
43963
+ "skills-sync-no-installer-unknown.json"
43964
+ );
43965
+ }
43966
+ function dueUnknownInstallerProbes(baseUrl, remoteVersion) {
43967
+ const path = noInstallerProbePath(baseUrl);
43968
+ try {
43969
+ const cached = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf-8"));
43970
+ if (cached.version === remoteVersion && typeof cached.checkedAt === "number" && cached.checkedAt <= Date.now() && Date.now() - cached.checkedAt < NEGATIVE_INSTALLER_PROBE_TTL_MS && (cached.probes?.bunx === "missing" || cached.probes?.bunx === "failed") && (cached.probes?.npx === "missing" || cached.probes?.npx === "failed")) {
43971
+ return cached.probes;
43972
+ }
43973
+ } catch {
43974
+ }
43975
+ const probes = probeInstallers(INSTALLER_PROBE_TIMEOUT_MS);
43976
+ if (probes.bunx !== "available" && probes.npx !== "available") {
43977
+ try {
43978
+ (0, import_node_fs18.mkdirSync)((0, import_node_path23.dirname)(path), { recursive: true });
43979
+ (0, import_node_fs18.writeFileSync)(
43980
+ path,
43981
+ JSON.stringify({
43982
+ version: remoteVersion,
43983
+ checkedAt: Date.now(),
43984
+ probes
43985
+ }),
43986
+ "utf-8"
43987
+ );
43988
+ } catch {
43989
+ }
43990
+ }
43991
+ return probes;
43992
+ }
43993
+ function probeCommand(command, timeoutMs) {
43746
43994
  const plan = resolveShellSpawn(command, ["--version"]);
43747
43995
  const result = (0, import_node_child_process2.spawnSync)(plan.command, plan.args, {
43748
43996
  stdio: "ignore",
43749
- shell: plan.shell
43997
+ shell: plan.shell,
43998
+ timeout: timeoutMs
43750
43999
  });
43751
- return result.status === 0;
44000
+ if (result.status === 0) return "available";
44001
+ return result.error?.code === "ENOENT" ? "missing" : "failed";
44002
+ }
44003
+ function hasCommand(command) {
44004
+ return probeCommand(command) === "available";
43752
44005
  }
43753
44006
  function shellQuote4(arg) {
43754
44007
  return `'${arg.replace(/'/g, `'\\''`)}'`;
@@ -43834,7 +44087,7 @@ async function runSkillsInstall(installs, agents, notice = writeSdkSkillsStatusL
43834
44087
  }
43835
44088
  const details = failures.map((failure) => failure.detail).filter(Boolean).join("\n");
43836
44089
  const attemptedCommands = failures.map((failure) => ` ${failure.manualCommand}`).join("\n");
43837
- const retryAgent = agents.at(0);
44090
+ const retryAgent = agents.length === 1 ? agents[0] : void 0;
43838
44091
  notice(
43839
44092
  `Deepline agent-skills refresh failed for ${agents.join(", ")}. The Deepline command will continue; this only affects optional local agent instructions, not authentication, data, or billing.
43840
44093
  ` + (attemptedCommands ? `Attempted installer command${failures.length === 1 ? "" : "s"}:
@@ -43921,6 +44174,9 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
43921
44174
  if (options.mode === "detached" && agents.length > 0) {
43922
44175
  flushDeferredSkillsNotices(baseUrl, agents);
43923
44176
  }
44177
+ if (options.mode === "detached" && options.update === void 0 && isDefaultAgentSet(agents)) {
44178
+ return;
44179
+ }
43924
44180
  const ownsInProgressMarker = options.mode !== "detached" && agents.length > 0 && Boolean(options.claim);
43925
44181
  const leases = ownsInProgressMarker ? readInProgressSkillsSyncLeases(baseUrl, agents) : null;
43926
44182
  if (leases && [...leases.values()].some((lease) => lease.owner !== options.claim)) {
@@ -43953,11 +44209,33 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
43953
44209
  writeUnavailableSkillsNotice(
43954
44210
  baseUrl,
43955
44211
  update.remoteVersion,
43956
- buildSdkSkillNames(DEFAULT_SDK_SKILL_NAMES)
44212
+ buildSdkSkillNames(DEFAULT_SDK_SKILL_NAMES),
44213
+ "unsupported-agent"
43957
44214
  );
43958
44215
  return;
43959
44216
  }
43960
44217
  if (options.mode === "detached" && agents.length > 0) {
44218
+ if (isDefaultAgentSet(agents)) {
44219
+ if (agents.some(
44220
+ (agent) => isFreshInProgressSkillsSync(
44221
+ readInProgressSkillsSyncLease(baseUrl, agent)
44222
+ )
44223
+ )) {
44224
+ return;
44225
+ }
44226
+ const probes = dueUnknownInstallerProbes(baseUrl, update.remoteVersion);
44227
+ if (probes.bunx !== "available" && probes.npx !== "available") {
44228
+ writeUnavailableSkillsNotice(
44229
+ baseUrl,
44230
+ update.remoteVersion,
44231
+ buildSdkSkillNames(DEFAULT_SDK_SKILL_NAMES),
44232
+ "no-installer",
44233
+ writeSdkSkillsStatusLine,
44234
+ probes
44235
+ );
44236
+ return;
44237
+ }
44238
+ }
43961
44239
  const outcome = claimAndSpawnDetachedSkillsSync(
43962
44240
  baseUrl,
43963
44241
  agents,
@@ -43967,10 +44245,11 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
43967
44245
  if (outcome === "held") return;
43968
44246
  if (outcome === "claimed") {
43969
44247
  writeSdkSkillsStatusLine(
43970
- "Deepline skills changed; refreshing agent skills in the background."
44248
+ "Deepline skills are out of date; updating in the background."
43971
44249
  );
43972
44250
  return;
43973
44251
  }
44252
+ if (isDefaultAgentSet(agents)) return;
43974
44253
  }
43975
44254
  await runInlineSkillsSync(
43976
44255
  baseUrl,
@@ -43987,7 +44266,8 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
43987
44266
  async function runInlineSkillsSync(baseUrl, remoteVersion, agents, notices) {
43988
44267
  const update = { remoteVersion };
43989
44268
  const notice = notices === "defer" ? deferSkillsNotice(baseUrl, agents) : writeSdkSkillsStatusLine;
43990
- const remoteSkillNames = await fetchV1SkillNames(baseUrl);
44269
+ const index = await fetchV1SkillIndex(baseUrl);
44270
+ const remoteSkillNames = v1SkillNames(index);
43991
44271
  const skillNames = buildSdkSkillNames(
43992
44272
  remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
43993
44273
  );
@@ -43997,6 +44277,7 @@ async function runInlineSkillsSync(baseUrl, remoteVersion, agents, notices) {
43997
44277
  baseUrl,
43998
44278
  update.remoteVersion,
43999
44279
  skillNames,
44280
+ "unsupported-agent",
44000
44281
  notice
44001
44282
  );
44002
44283
  return;
@@ -44007,6 +44288,7 @@ async function runInlineSkillsSync(baseUrl, remoteVersion, agents, notices) {
44007
44288
  baseUrl,
44008
44289
  update.remoteVersion,
44009
44290
  skillNames,
44291
+ "no-installer",
44010
44292
  notice
44011
44293
  );
44012
44294
  return;
@@ -44032,10 +44314,47 @@ async function runInlineSkillsSync(baseUrl, remoteVersion, agents, notices) {
44032
44314
  markerWritten,
44033
44315
  attempts: installResult.attempts
44034
44316
  });
44317
+ if (isDefaultAgentSet(agents)) {
44318
+ notice(
44319
+ `After fixing the installer, remove ${failedSkillsSyncPath(baseUrl, agents)} to retry this skills version automatically.`
44320
+ );
44321
+ }
44035
44322
  return;
44036
44323
  }
44324
+ if (isDefaultAgentSet(agents)) {
44325
+ try {
44326
+ await verifyDefaultAgentSkillsInstall(
44327
+ baseUrl,
44328
+ update.remoteVersion,
44329
+ skillNames,
44330
+ index
44331
+ );
44332
+ } catch (error) {
44333
+ const detail = error instanceof Error ? error.message : String(error);
44334
+ const publishedFailure = error instanceof PublishedSkillsVerificationError;
44335
+ const markerWritten = publishedFailure ? deferPublishedVerificationRetry(baseUrl, update.remoteVersion, agents) : markFailedSkillsSync(baseUrl, update.remoteVersion, agents);
44336
+ notice(
44337
+ publishedFailure ? `Deepline could not verify the published skills: ${detail}. The local version remains stale; it will retry automatically on a later command.` : `Deepline agent-skills refresh could not verify the five installed targets: ${detail}. The local version remains stale. After fixing the install, remove ${failedSkillsSyncPath(baseUrl, agents)} to retry this version automatically.`
44338
+ );
44339
+ void maybeReportAutomaticSkillsSyncFailure({
44340
+ baseUrl,
44341
+ remoteSkillsVersion: update.remoteVersion,
44342
+ agents,
44343
+ skillsPackage: SKILLS_NPX_PACKAGE,
44344
+ targetSkillCount: skillNames.length,
44345
+ markerWritten,
44346
+ attempts: []
44347
+ });
44348
+ return;
44349
+ }
44350
+ }
44037
44351
  runLegacySkillsCleanup(agents);
44038
- writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents);
44352
+ if (!writeSdkSkillsLocalVersion(baseUrl, update.remoteVersion, agents)) {
44353
+ notice(
44354
+ "Deepline agent skills installed, but the local skills version could not be recorded. A later command will retry the refresh."
44355
+ );
44356
+ return;
44357
+ }
44039
44358
  clearUnavailableSkillsNotice(baseUrl);
44040
44359
  clearFailedSkillsSync(baseUrl, agents);
44041
44360
  notice("Deepline agent skills are up to date.");
@@ -44104,7 +44423,7 @@ function detectSkillsAgents(input2) {
44104
44423
  if (knownAgent) return [knownAgent];
44105
44424
  const roots = [
44106
44425
  ...input2.scope === "local" && input2.root ? [input2.root] : [],
44107
- input2.homeDir ?? (0, import_node_os13.homedir)()
44426
+ input2.homeDir ?? (0, import_node_os14.homedir)()
44108
44427
  ];
44109
44428
  const detected = AGENT_MARKERS.filter(
44110
44429
  (marker) => roots.some(
@@ -44688,7 +45007,7 @@ function safeRead(path) {
44688
45007
  function removeKnownLegacyPaths(baseUrl) {
44689
45008
  return CliInstallation.forUser({
44690
45009
  baseUrlSlug: baseUrlSlug(baseUrl),
44691
- home: (0, import_node_os14.homedir)()
45010
+ home: (0, import_node_os15.homedir)()
44692
45011
  }).removeRetiredArtifacts();
44693
45012
  }
44694
45013
  function resolvePathCommands(command) {
@@ -45444,7 +45763,7 @@ var import_node_fs24 = require("fs");
45444
45763
 
45445
45764
  // src/cli/update-preferences.ts
45446
45765
  var import_node_fs21 = require("fs");
45447
- var import_node_os15 = require("os");
45766
+ var import_node_os16 = require("os");
45448
45767
  var import_node_path26 = require("path");
45449
45768
  var UPDATE_PREFERENCES_SCHEMA_VERSION = 1;
45450
45769
  var CLI_UPDATE_MESSAGES = [
@@ -45473,7 +45792,7 @@ function unreadablePreferences(path, error) {
45473
45792
  acknowledgedMessages: CLI_UPDATE_MESSAGES.map(({ id }) => id)
45474
45793
  };
45475
45794
  }
45476
- function cliUpdatePreferencesPath(homeDir2 = (0, import_node_os15.homedir)()) {
45795
+ function cliUpdatePreferencesPath(homeDir2 = (0, import_node_os16.homedir)()) {
45477
45796
  return (0, import_node_path26.join)(
45478
45797
  homeDir2,
45479
45798
  ".local",
@@ -45482,7 +45801,7 @@ function cliUpdatePreferencesPath(homeDir2 = (0, import_node_os15.homedir)()) {
45482
45801
  "update-preferences.json"
45483
45802
  );
45484
45803
  }
45485
- function readCliUpdatePreferences(homeDir2 = (0, import_node_os15.homedir)()) {
45804
+ function readCliUpdatePreferences(homeDir2 = (0, import_node_os16.homedir)()) {
45486
45805
  const path = cliUpdatePreferencesPath(homeDir2);
45487
45806
  if (!(0, import_node_fs21.existsSync)(path)) return defaultPreferences();
45488
45807
  try {
@@ -45499,7 +45818,7 @@ function readCliUpdatePreferences(homeDir2 = (0, import_node_os15.homedir)()) {
45499
45818
  return unreadablePreferences(path, error);
45500
45819
  }
45501
45820
  }
45502
- function writeCliUpdatePreferences(preferences, homeDir2 = (0, import_node_os15.homedir)()) {
45821
+ function writeCliUpdatePreferences(preferences, homeDir2 = (0, import_node_os16.homedir)()) {
45503
45822
  const path = cliUpdatePreferencesPath(homeDir2);
45504
45823
  const tempPath = `${path}.${process.pid}.tmp`;
45505
45824
  (0, import_node_fs21.mkdirSync)((0, import_node_path26.dirname)(path), { recursive: true });
@@ -45514,7 +45833,7 @@ function writeCliUpdatePreferences(preferences, homeDir2 = (0, import_node_os15.
45514
45833
  (0, import_node_fs21.rmSync)(tempPath, { force: true });
45515
45834
  }
45516
45835
  }
45517
- function setCliAutoUpdateEnabled(enabled, homeDir2 = (0, import_node_os15.homedir)()) {
45836
+ function setCliAutoUpdateEnabled(enabled, homeDir2 = (0, import_node_os16.homedir)()) {
45518
45837
  const current = readCliUpdatePreferences(homeDir2);
45519
45838
  const next = {
45520
45839
  ...current,
@@ -45524,7 +45843,7 @@ function setCliAutoUpdateEnabled(enabled, homeDir2 = (0, import_node_os15.homedi
45524
45843
  writeCliUpdatePreferences(next, homeDir2);
45525
45844
  return next;
45526
45845
  }
45527
- function setCliPinnedVersion(version, homeDir2 = (0, import_node_os15.homedir)()) {
45846
+ function setCliPinnedVersion(version, homeDir2 = (0, import_node_os16.homedir)()) {
45528
45847
  const next = {
45529
45848
  ...readCliUpdatePreferences(homeDir2),
45530
45849
  pinnedVersion: version
@@ -45532,18 +45851,18 @@ function setCliPinnedVersion(version, homeDir2 = (0, import_node_os15.homedir)()
45532
45851
  writeCliUpdatePreferences(next, homeDir2);
45533
45852
  return next;
45534
45853
  }
45535
- function clearCliPinnedVersion(homeDir2 = (0, import_node_os15.homedir)()) {
45854
+ function clearCliPinnedVersion(homeDir2 = (0, import_node_os16.homedir)()) {
45536
45855
  const current = readCliUpdatePreferences(homeDir2);
45537
45856
  if (current.pinnedVersion === null) return current;
45538
45857
  const next = { ...current, pinnedVersion: null };
45539
45858
  writeCliUpdatePreferences(next, homeDir2);
45540
45859
  return next;
45541
45860
  }
45542
- function shouldRunCliAutoUpdate(homeDir2 = (0, import_node_os15.homedir)()) {
45861
+ function shouldRunCliAutoUpdate(homeDir2 = (0, import_node_os16.homedir)()) {
45543
45862
  const preferences = readCliUpdatePreferences(homeDir2);
45544
45863
  return preferences.autoUpdateEnabled && preferences.pinnedVersion === null;
45545
45864
  }
45546
- function consumePendingCliUpdateMessages(homeDir2 = (0, import_node_os15.homedir)()) {
45865
+ function consumePendingCliUpdateMessages(homeDir2 = (0, import_node_os16.homedir)()) {
45547
45866
  const preferences = readCliUpdatePreferences(homeDir2);
45548
45867
  const acknowledged = new Set(preferences.acknowledgedMessages);
45549
45868
  const pending = CLI_UPDATE_MESSAGES.filter(({ id }) => !acknowledged.has(id));
@@ -45562,7 +45881,7 @@ function consumePendingCliUpdateMessages(homeDir2 = (0, import_node_os15.homedir
45562
45881
  // src/cli/commands/update.ts
45563
45882
  var import_node_child_process6 = require("child_process");
45564
45883
  var import_node_fs23 = require("fs");
45565
- var import_node_os16 = require("os");
45884
+ var import_node_os17 = require("os");
45566
45885
  var import_node_path28 = require("path");
45567
45886
 
45568
45887
  // src/cli/install-integrity.ts
@@ -45937,7 +46256,7 @@ function isHomebrewFormulaEntrypoint(entrypoint) {
45937
46256
  }
45938
46257
  function resolveUpdatePlan(options = {}) {
45939
46258
  const env = options.env ?? process.env;
45940
- const homeDir2 = options.homeDir ?? (0, import_node_os16.homedir)();
46259
+ const homeDir2 = options.homeDir ?? (0, import_node_os17.homedir)();
45941
46260
  const entrypoint = options.entrypoint ?? (process.argv[1] ? (0, import_node_path28.resolve)(process.argv[1]) : "");
45942
46261
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path28.dirname)(entrypoint)) : null;
45943
46262
  if (sourceRoot) {
@@ -45995,7 +46314,7 @@ function autoUpdateFailurePath(plan) {
45995
46314
  return (0, import_node_path28.join)(plan.stateDir, AUTO_UPDATE_FAILURE_FILE);
45996
46315
  }
45997
46316
  return (0, import_node_path28.join)(
45998
- (0, import_node_os16.homedir)(),
46317
+ (0, import_node_os17.homedir)(),
45999
46318
  ".local",
46000
46319
  "deepline",
46001
46320
  "sdk-cli",
@@ -47497,12 +47816,12 @@ function stableStringify(value) {
47497
47816
 
47498
47817
  // src/cli/commands/tools.ts
47499
47818
  var import_node_fs26 = require("fs");
47500
- var import_node_os18 = require("os");
47819
+ var import_node_os19 = require("os");
47501
47820
  var import_node_path30 = require("path");
47502
47821
 
47503
47822
  // src/tool-output.ts
47504
47823
  var import_node_fs25 = require("fs");
47505
- var import_node_os17 = require("os");
47824
+ var import_node_os18 = require("os");
47506
47825
  var import_node_path29 = require("path");
47507
47826
  function isPlainObject(value) {
47508
47827
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -47630,7 +47949,7 @@ function projectRowOutput(conversion) {
47630
47949
  };
47631
47950
  }
47632
47951
  function ensureOutputDir() {
47633
- const outputDir = (0, import_node_path29.join)((0, import_node_os17.homedir)(), ".local", "share", "deepline", "data");
47952
+ const outputDir = (0, import_node_path29.join)((0, import_node_os18.homedir)(), ".local", "share", "deepline", "data");
47634
47953
  (0, import_node_fs25.mkdirSync)(outputDir, { recursive: true });
47635
47954
  return outputDir;
47636
47955
  }
@@ -50069,7 +50388,7 @@ function starterScriptJson(script) {
50069
50388
  function seedToolListScript(input2) {
50070
50389
  const stem = safeFileStem(input2.toolId);
50071
50390
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
50072
- const scriptDir = (0, import_node_fs26.mkdtempSync)((0, import_node_path30.join)((0, import_node_os18.tmpdir)(), "deepline-workflow-seed-"));
50391
+ const scriptDir = (0, import_node_fs26.mkdtempSync)((0, import_node_path30.join)((0, import_node_os19.tmpdir)(), "deepline-workflow-seed-"));
50073
50392
  (0, import_node_fs26.chmodSync)(scriptDir, 448);
50074
50393
  const scriptPath = (0, import_node_path30.join)(scriptDir, fileName);
50075
50394
  const projectDir = `deepline/projects/${stem}-workflow`;
@@ -51367,7 +51686,7 @@ function topLevelCommandKnown(program, commandName) {
51367
51686
  );
51368
51687
  }
51369
51688
  async function runPlayRunnerHealthCheck() {
51370
- const dir = await (0, import_promises14.mkdtemp)((0, import_node_path32.join)((0, import_node_os19.tmpdir)(), "deepline-health-play-"));
51689
+ const dir = await (0, import_promises14.mkdtemp)((0, import_node_path32.join)((0, import_node_os20.tmpdir)(), "deepline-health-play-"));
51371
51690
  const file = (0, import_node_path32.join)(dir, "health-check.play.ts");
51372
51691
  try {
51373
51692
  await (0, import_promises14.writeFile)(