@0dai-dev/cli 3.1.5 → 3.1.7

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 (2) hide show
  1. package/bin/0dai.js +129 -1
  2. package/package.json +1 -1
package/bin/0dai.js CHANGED
@@ -416,6 +416,11 @@ async function cmdInit(target, args = []) {
416
416
  }
417
417
  writeFiles(target, result.files || {});
418
418
 
419
+ // Ensure ai/VERSION matches CLI version
420
+ const versionFile = path.join(target, "ai", "VERSION");
421
+ fs.mkdirSync(path.dirname(versionFile), { recursive: true });
422
+ fs.writeFileSync(versionFile, VERSION + "\n", "utf8");
423
+
419
424
  // Add to .gitignore
420
425
  const gi = path.join(target, ".gitignore");
421
426
  try {
@@ -539,6 +544,15 @@ async function cmdSync(target, args = []) {
539
544
  log("already up to date");
540
545
  }
541
546
 
547
+ // Ensure ai/VERSION matches CLI version after successful sync
548
+ const versionFile = path.join(target, "ai", "VERSION");
549
+ try {
550
+ const current = fs.existsSync(versionFile) ? fs.readFileSync(versionFile, "utf8").trim() : "";
551
+ if (current !== VERSION) {
552
+ fs.writeFileSync(versionFile, VERSION + "\n", "utf8");
553
+ }
554
+ } catch {}
555
+
542
556
  // Update portfolio registry
543
557
  registerProject(target, path.basename(target), stack);
544
558
  }
@@ -793,6 +807,50 @@ function cmdDoctor(target) {
793
807
  console.log(` ${mark.padEnd(22)} ${c.name}${hint}`);
794
808
  }
795
809
 
810
+ // --- agent CLIs check ---
811
+ const AGENT_CLIS = [
812
+ { name: "claude", pkg: "@anthropic-ai/claude-code", bin: "claude", install: "npm i -g @anthropic-ai/claude-code", altAuth: "Pro/Team subscription" },
813
+ { name: "codex", pkg: "@openai/codex", bin: "codex", install: "npm i -g @openai/codex", altAuth: "ChatGPT Pro subscription" },
814
+ { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", install: "npm i -g @google/gemini-cli", altAuth: null },
815
+ { name: "aider", pkg: null, bin: "aider", install: "pip install aider-chat", altAuth: null },
816
+ { name: "opencode", pkg: null, bin: "opencode", install: "go install github.com/nichochar/opencode@latest", altAuth: null },
817
+ ];
818
+ const { execFileSync: _ef2 } = require("child_process");
819
+ let updatesAvailable = 0;
820
+ console.log("\n agent CLIs:");
821
+ for (const cli of AGENT_CLIS) {
822
+ let installed = false, ver = null;
823
+ try {
824
+ const out = _ef2(cli.bin, ["--version"], { timeout: 3000 }).toString().trim();
825
+ installed = true;
826
+ const m = out.match(/(\d+\.\d+\.\d+)/);
827
+ if (m) ver = m[1];
828
+ } catch {}
829
+
830
+ if (installed) {
831
+ let latest = null;
832
+ if (cli.pkg) {
833
+ try {
834
+ const npmOut = _ef2("npm", ["view", cli.pkg, "version"], { timeout: 5000 }).toString().trim();
835
+ if (npmOut.match(/^\d+\.\d+\.\d+$/)) latest = npmOut;
836
+ } catch {}
837
+ }
838
+ if (latest && ver && latest !== ver) {
839
+ updatesAvailable++;
840
+ console.log(` ${W}update${R2} ${cli.name} ${D}${ver} → ${latest}${R2}`);
841
+ console.log(` ${D}→ ${cli.install}${R2}`);
842
+ } else {
843
+ console.log(` ${G}ok${R2} ${cli.name}${ver ? ` ${D}v${ver}${R2}` : ""}`);
844
+ }
845
+ } else {
846
+ console.log(` ${D}—${R2} ${cli.name} ${D}not installed${R2}`);
847
+ console.log(` ${D}→ ${cli.install}${cli.altAuth ? ` (or ${cli.altAuth})` : ""}${R2}`);
848
+ }
849
+ }
850
+ if (updatesAvailable) {
851
+ console.log(`\n ${D}Run: 0dai update${R2} to update all`);
852
+ }
853
+
796
854
  // --- swarm check ---
797
855
  const swarmDir = path.join(ai, "swarm");
798
856
  const countDir = (d) => { try { return fs.readdirSync(d).filter(f => f.endsWith(".json")).length; } catch { return 0; } };
@@ -874,6 +932,74 @@ function cmdValidate(target) {
874
932
  }
875
933
  }
876
934
 
935
+ // --- Update agent CLIs ---
936
+ function cmdUpdate(args) {
937
+ const { execFileSync: _ef3, execSync } = require("child_process");
938
+ const dryRun = args.includes("--dry-run");
939
+
940
+ const CLIS = [
941
+ { name: "0dai", pkg: "@0dai-dev/cli", bin: "0dai", type: "npm" },
942
+ { name: "claude", pkg: "@anthropic-ai/claude-code",bin: "claude", type: "npm" },
943
+ { name: "codex", pkg: "@openai/codex", bin: "codex", type: "npm" },
944
+ { name: "gemini", pkg: "@google/gemini-cli", bin: "gemini", type: "npm" },
945
+ { name: "aider", pkg: "aider-chat", bin: "aider", type: "pip" },
946
+ { name: "opencode",pkg: null, bin: "opencode",type: "go" },
947
+ ];
948
+
949
+ let updated = 0;
950
+ for (const cli of CLIS) {
951
+ let installed = false, ver = null;
952
+ try {
953
+ const out = _ef3(cli.bin, ["--version"], { timeout: 3000 }).toString().trim();
954
+ installed = true;
955
+ const m = out.match(/(\d+\.\d+\.\d+)/);
956
+ if (m) ver = m[1];
957
+ } catch {}
958
+
959
+ if (!installed) continue;
960
+
961
+ let latest = null;
962
+ if (cli.type === "npm" && cli.pkg) {
963
+ try { latest = _ef3("npm", ["view", cli.pkg, "version"], { timeout: 5000 }).toString().trim(); } catch {}
964
+ } else if (cli.type === "pip" && cli.pkg) {
965
+ try {
966
+ const out = _ef3("pip", ["index", "versions", cli.pkg], { timeout: 8000, encoding: "utf8" });
967
+ const m = out.match(/LATEST:\s*(\d+\.\d+\.\d+)/i) || out.match(/(\d+\.\d+\.\d+)/);
968
+ if (m) latest = m[1];
969
+ } catch {}
970
+ }
971
+
972
+ if (!latest || latest === ver) {
973
+ console.log(` ${cli.name} ${ver || ""} — up to date`);
974
+ continue;
975
+ }
976
+
977
+ console.log(` ${cli.name} ${ver} → ${latest}`);
978
+ if (dryRun) { updated++; continue; }
979
+
980
+ try {
981
+ if (cli.type === "npm") {
982
+ log(`updating ${cli.name}...`);
983
+ execSync(`npm install -g ${cli.pkg}@latest`, { timeout: 60000, stdio: "pipe" });
984
+ log(`${cli.name} updated to ${latest}`);
985
+ updated++;
986
+ } else if (cli.type === "pip") {
987
+ log(`updating ${cli.name}...`);
988
+ execSync(`pip install --upgrade ${cli.pkg}`, { timeout: 60000, stdio: "pipe" });
989
+ log(`${cli.name} updated to ${latest}`);
990
+ updated++;
991
+ }
992
+ } catch (e) {
993
+ log(`failed to update ${cli.name}: ${e.message.split("\n")[0]}`);
994
+ }
995
+ }
996
+ if (updated) {
997
+ log(`${dryRun ? "would update" : "updated"} ${updated} CLI(s)`);
998
+ } else {
999
+ log("all CLIs are up to date");
1000
+ }
1001
+ }
1002
+
877
1003
  // --- Session reflection --- (dogfood feedback #36)
878
1004
  function cmdReflect(target, args) {
879
1005
  const ai = path.join(target, "ai");
@@ -1898,6 +2024,7 @@ async function main() {
1898
2024
  case "doctor": cmdDoctor(target); break;
1899
2025
  case "validate": cmdValidate(target); break;
1900
2026
  case "reflect": cmdReflect(target, args); break;
2027
+ case "update": cmdUpdate(args); break;
1901
2028
  case "metrics": cmdMetrics(target); break;
1902
2029
  case "portfolio": cmdPortfolio(); break;
1903
2030
  case "status": cmdStatus(target); break;
@@ -1946,7 +2073,8 @@ async function main() {
1946
2073
  console.log(" sync Update ai/ layer (via API) [--dry-run] [--quiet]");
1947
2074
  console.log(" detect Show detected stack");
1948
2075
  console.log(" doctor Check health + credentials checklist");
1949
- console.log(" validate Validate ai/ layer completeness");
2076
+ console.log(" update Update all installed agent CLIs to latest [--dry-run]");
2077
+ console.log(" validate Validate ai/ layer completeness");
1950
2078
  console.log(" reflect Session reflection: delivered, delegation rate, blockers");
1951
2079
  console.log(" metrics Effectiveness score: adoption funnel, sessions, delegation");
1952
2080
  console.log(" portfolio All tracked projects: score, sessions, agents, last activity");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0dai-dev/cli",
3
- "version": "3.1.5",
3
+ "version": "3.1.7",
4
4
  "description": "One config layer for 5 AI agent CLIs — Claude Code, Codex, OpenCode, Gemini, Aider",
5
5
  "bin": {
6
6
  "0dai": "./bin/0dai.js"