@withone/cli 1.44.1 → 1.44.2

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.
Files changed (3) hide show
  1. package/README.md +14 -0
  2. package/dist/index.js +42 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -548,6 +548,20 @@ Settings propagate automatically to all installed agent configs.
548
548
 
549
549
  Auto-sync refuses to resurrect skills if you opted out of skill installation during `one init` — the canonical dir has to already exist.
550
550
 
551
+ ### `one update`
552
+
553
+ Updates the CLI to the latest version (`npm install -g @withone/cli@latest`).
554
+
555
+ The CLI also **auto-updates in the background**: when a newer version has been published for more than 30 minutes, the next `one` command silently kicks off a global install. This is hardened against concurrent runs — a lock file in `~/.one/` ensures at most one install runs at a time (so parallel agent invocations can't collide and wedge npm), and the lock self-heals after 10 minutes if an install ever crashes or hangs.
556
+
557
+ To disable background auto-updates entirely (e.g. on CI or a shared agent host), set:
558
+
559
+ ```bash
560
+ export ONE_NO_AUTO_UPDATE=1
561
+ ```
562
+
563
+ Run `one update` manually whenever you want to upgrade.
564
+
551
565
  ### Project config (`.onerc`)
552
566
 
553
567
  Drop a `.onerc` file in your project root to override global settings per-project. Simple `KEY=VALUE` format; `#` for comments. Read from the current working directory (no parent lookup).
package/dist/index.js CHANGED
@@ -621,14 +621,17 @@ import { fileURLToPath } from "url";
621
621
  // src/commands/update.ts
622
622
  import { createRequire } from "module";
623
623
  import { spawn } from "child_process";
624
- import { readFileSync, writeFileSync, mkdirSync } from "fs";
624
+ import { readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
625
625
  import { homedir } from "os";
626
626
  import { join } from "path";
627
627
  var require2 = createRequire(import.meta.url);
628
628
  var { version: currentVersion } = require2("../package.json");
629
- var CACHE_PATH = join(homedir(), ".one", "update-check.json");
629
+ var ONE_DIR = join(homedir(), ".one");
630
+ var CACHE_PATH = join(ONE_DIR, "update-check.json");
631
+ var LOCK_PATH = join(ONE_DIR, "auto-update.lock");
630
632
  var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
631
633
  var AGE_GATE_MS = 30 * 60 * 1e3;
634
+ var LOCK_TTL_MS = 10 * 60 * 1e3;
632
635
  async function fetchLatestVersionInfo() {
633
636
  try {
634
637
  const res = await fetch("https://registry.npmjs.org/@withone/cli");
@@ -725,16 +728,52 @@ function isNewerVersion(latest, current) {
725
728
  if (lMin !== cMin) return lMin > cMin;
726
729
  return lPat > cPat;
727
730
  }
731
+ function isAutoUpdateDisabled() {
732
+ const v = process.env.ONE_NO_AUTO_UPDATE ?? process.env.ONE_DISABLE_AUTO_UPDATE;
733
+ return v === "1" || v === "true";
734
+ }
735
+ function acquireUpdateLock(targetVersion) {
736
+ try {
737
+ mkdirSync(ONE_DIR, { recursive: true });
738
+ } catch {
739
+ }
740
+ try {
741
+ const lock = JSON.parse(readFileSync(LOCK_PATH, "utf8"));
742
+ const startedAt = typeof lock.startedAt === "number" ? lock.startedAt : 0;
743
+ if (Date.now() - startedAt < LOCK_TTL_MS) return false;
744
+ rmSync(LOCK_PATH, { force: true });
745
+ } catch {
746
+ }
747
+ try {
748
+ writeFileSync(
749
+ LOCK_PATH,
750
+ JSON.stringify({ pid: process.pid, startedAt: Date.now(), targetVersion }),
751
+ { flag: "wx" }
752
+ // fail if another invocation created it first
753
+ );
754
+ return true;
755
+ } catch {
756
+ return false;
757
+ }
758
+ }
728
759
  function autoUpdate(targetVersion, publishedAt) {
760
+ if (isAutoUpdateDisabled()) return;
729
761
  if (publishedAt) {
730
762
  const age = Date.now() - new Date(publishedAt).getTime();
731
763
  if (age < AGE_GATE_MS) return;
732
764
  }
765
+ if (!acquireUpdateLock(targetVersion)) return;
733
766
  const child = spawn("npm", ["install", "-g", `@withone/cli@${targetVersion}`], {
734
767
  detached: true,
735
768
  stdio: "ignore",
736
769
  shell: true
737
770
  });
771
+ child.on("error", () => {
772
+ try {
773
+ rmSync(LOCK_PATH, { force: true });
774
+ } catch {
775
+ }
776
+ });
738
777
  child.unref();
739
778
  }
740
779
 
@@ -11135,7 +11174,7 @@ program.command("guide [topic]").description("Full CLI usage guide for agents (t
11135
11174
  program.command("onboard").description("Agent onboarding \u2014 teaches your agent what the One CLI can do").option("--step <number>", "Run a specific onboarding step (1, 2, or 3)").action(async (options) => {
11136
11175
  await onboardCommand(options.step ? parseInt(options.step, 10) : void 0);
11137
11176
  });
11138
- program.command("update").description("Update the One CLI to the latest version").action(async () => {
11177
+ program.command("update").description("Update the One CLI to the latest version (background auto-update can be disabled with ONE_NO_AUTO_UPDATE=1)").action(async () => {
11139
11178
  await updateCommand();
11140
11179
  });
11141
11180
  program.command("whoami").description("Show the user, organization, and project for the current API key").action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.44.1",
3
+ "version": "1.44.2",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [