meetsoma 0.3.6 → 0.4.0

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/dist/thin-cli.js +143 -3
  2. package/package.json +1 -1
package/dist/thin-cli.js CHANGED
@@ -213,6 +213,7 @@ import { join as join3, dirname as dirname3 } from "path";
213
213
  import { homedir as homedir3, platform as platform2 } from "os";
214
214
  import { fileURLToPath } from "url";
215
215
  import { execSync as execSync2, execFileSync } from "child_process";
216
+ import { randomBytes } from "crypto";
216
217
 
217
218
  // personality.js
218
219
  var _state = {
@@ -1222,7 +1223,7 @@ function showHelp() {
1222
1223
  console.log("");
1223
1224
  console.log(` ${bold("Maintenance")}`);
1224
1225
  console.log(` ${green("soma doctor")} Verify installation + project health`);
1225
- console.log(` ${green("soma update")} Update the Soma runtime`);
1226
+ console.log(` ${green("soma update")} Update the Soma runtime ${dim("(--yes / -y to skip prompt)")}`);
1226
1227
  console.log(` ${green("soma check-updates")} Check for updates without installing`);
1227
1228
  console.log(` ${green("soma status")} Show installation status`);
1228
1229
  console.log("");
@@ -1454,13 +1455,17 @@ async function checkAndUpdate() {
1454
1455
  }
1455
1456
  } catch {
1456
1457
  }
1457
- const shouldUpdate = await confirmYN(` ${dim("\u2192")} Update now?`);
1458
+ const autoYes = process.argv.includes("--yes") || process.argv.includes("-y");
1459
+ const shouldUpdate = autoYes ? true : await confirmYN(` ${dim("\u2192")} Update now?`);
1458
1460
  if (!shouldUpdate) {
1459
1461
  console.log("");
1460
1462
  console.log(` ${dim("Skipped. Run")} ${green("soma update")} ${dim("anytime to update.")}`);
1461
1463
  console.log("");
1462
1464
  return;
1463
1465
  }
1466
+ if (autoYes) {
1467
+ console.log(` ${dim("\u2192")} Auto-confirmed via --yes`);
1468
+ }
1464
1469
  console.log("");
1465
1470
  try {
1466
1471
  execSync2("git pull --ff-only", { cwd: installPath, stdio: "ignore" });
@@ -1734,6 +1739,107 @@ async function projectDoctor() {
1734
1739
  console.log("");
1735
1740
  return;
1736
1741
  }
1742
+ try {
1743
+ const softSomaDir = join3(process.cwd(), ".soma");
1744
+ const softSettings = join3(softSomaDir, "settings.json");
1745
+ if (existsSync3(softSettings)) {
1746
+ const templateRoots = [CORE_DIR, join3(CORE_DIR, "dist")];
1747
+ try {
1748
+ const devCore = readlinkSync2(join3(CORE_DIR, "core"));
1749
+ if (devCore) {
1750
+ const devRoot = dirname3(devCore);
1751
+ templateRoots.push(devRoot, join3(devRoot, "dist"));
1752
+ }
1753
+ } catch {
1754
+ }
1755
+ const phaseDirsSeen = /* @__PURE__ */ new Set();
1756
+ const phaseDirs = [];
1757
+ for (const root of templateRoots) {
1758
+ const d = join3(root, "migrations", "phases");
1759
+ if (existsSync3(d) && !phaseDirsSeen.has(d)) {
1760
+ phaseDirs.push(d);
1761
+ phaseDirsSeen.add(d);
1762
+ }
1763
+ }
1764
+ const seenMaps = /* @__PURE__ */ new Set();
1765
+ const maps = [];
1766
+ for (const dir of phaseDirs) {
1767
+ for (const f of readdirSync(dir).filter((f2) => f2.endsWith(".md"))) {
1768
+ if (seenMaps.has(f)) continue;
1769
+ seenMaps.add(f);
1770
+ maps.push(join3(dir, f));
1771
+ }
1772
+ }
1773
+ let obj = JSON.parse(readFileSync3(softSettings, "utf-8"));
1774
+ let objChanged = false;
1775
+ let replayFixes = 0;
1776
+ for (const mapPath of maps) {
1777
+ let raw;
1778
+ try {
1779
+ raw = readFileSync3(mapPath, "utf-8");
1780
+ } catch {
1781
+ continue;
1782
+ }
1783
+ const fmMatch = raw.match(/^---\n([\s\S]*?)\n---/);
1784
+ if (!fmMatch) continue;
1785
+ const replayLine = fmMatch[1].match(/^replay-until:\s*["']?([^"'\n]+?)["']?\s*$/m);
1786
+ if (!replayLine) continue;
1787
+ const replayUntil = replayLine[1].trim();
1788
+ if (agentV && semverCmp2(agentV, replayUntil) >= 0) continue;
1789
+ const actionsBlock = raw.match(/^## Doctor Actions[\s\S]*?```json\s*\n([\s\S]*?)```/m);
1790
+ if (!actionsBlock) continue;
1791
+ let actions;
1792
+ try {
1793
+ actions = JSON.parse(actionsBlock[1]);
1794
+ } catch {
1795
+ continue;
1796
+ }
1797
+ if (actions["settings-defaults"] && typeof actions["settings-defaults"] === "object") {
1798
+ for (const [k, v] of Object.entries(actions["settings-defaults"])) {
1799
+ if (!(k in obj)) {
1800
+ obj[k] = v;
1801
+ objChanged = true;
1802
+ replayFixes++;
1803
+ }
1804
+ }
1805
+ }
1806
+ if (actions["settings-subkeys"] && typeof actions["settings-subkeys"] === "object") {
1807
+ for (const [parent, sub] of Object.entries(actions["settings-subkeys"])) {
1808
+ if (!obj[parent] || typeof obj[parent] !== "object") continue;
1809
+ for (const [k, v] of Object.entries(sub)) {
1810
+ if (obj[parent][k] === void 0) {
1811
+ obj[parent][k] = v;
1812
+ objChanged = true;
1813
+ replayFixes++;
1814
+ }
1815
+ }
1816
+ }
1817
+ }
1818
+ if (Array.isArray(actions["scaffold-files"])) {
1819
+ for (const entry of actions["scaffold-files"]) {
1820
+ if (!entry || !entry.target || !entry.template) continue;
1821
+ const target = join3(softSomaDir, entry.target);
1822
+ if (existsSync3(target)) continue;
1823
+ for (const root of templateRoots) {
1824
+ const src = join3(root, entry.template);
1825
+ if (!existsSync3(src)) continue;
1826
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1827
+ mkdirSync2(dirname3(target), { recursive: true });
1828
+ writeFileSync2(target, readFileSync3(src, "utf-8").replace(/\{\{today\}\}/g, today));
1829
+ replayFixes++;
1830
+ break;
1831
+ }
1832
+ }
1833
+ }
1834
+ }
1835
+ if (objChanged) writeFileSync2(softSettings, JSON.stringify(obj, null, " ") + "\n");
1836
+ if (replayFixes > 0) {
1837
+ console.log(` ${green("\u2713")} Migration replay applied ${replayFixes} backfill(s)`);
1838
+ console.log("");
1839
+ }
1840
+ }
1841
+ } catch {
1842
+ }
1737
1843
  if (agentV && semverCmp2(projectV, agentV) === 0) {
1738
1844
  console.log(` ${green("\u2713")} Project is up to date.`);
1739
1845
  console.log("");
@@ -1758,14 +1864,21 @@ async function projectDoctor() {
1758
1864
  }
1759
1865
  };
1760
1866
  add("doctor", { autoUpdate: true, declinedVersion: null });
1867
+ add("keepalive", { maxPings: 5, autoExhale: true, autoExhaleMinTokens: 75e3 });
1761
1868
  add("breathe", { auto: false, triggerAt: 50, rotateAt: 70, graceSeconds: 30 });
1762
1869
  add("context", { notifyAt: 50, warnAt: 70, urgentAt: 80, autoExhaleAt: 85 });
1763
- add("preload", { staleAfterHours: 48, lastSessionLogs: 0 });
1870
+ add("preload", { staleAfterHours: 48, lastSessionLogs: 0, recentNotesCount: 3 });
1764
1871
  add("scratch", { autoInject: false });
1765
1872
  add("guard", { coreFiles: "warn", bashCommands: "warn", gitIdentity: null });
1766
1873
  add("checkpoints", { enabled: true, intervalMinutes: 5, squashOnPush: true });
1874
+ add("cache", { retention: null });
1767
1875
  add("persona", { name: null, emoji: "\u03C3" });
1768
1876
  add("inherit", { identity: true, protocols: true, muscles: true, tools: true });
1877
+ if (current.preload && typeof current.preload === "object" && current.preload.recentNotesCount === void 0) {
1878
+ current.preload.recentNotesCount = 3;
1879
+ changed = true;
1880
+ fixes++;
1881
+ }
1769
1882
  if (changed) writeFileSync2(settingsPath, JSON.stringify(current, null, " ") + "\n");
1770
1883
  } catch {
1771
1884
  }
@@ -1818,6 +1931,25 @@ async function projectDoctor() {
1818
1931
  }
1819
1932
  }
1820
1933
  }
1934
+ try {
1935
+ const notesTarget = join3(somaDir, "memory", "notes", "soma-log.md");
1936
+ if (!existsSync3(notesTarget)) {
1937
+ const candidates = [
1938
+ join3(agentRoot, "templates", "default", "memory", "notes", "soma-log.md"),
1939
+ join3(agentRoot, "dist", "templates", "default", "memory", "notes", "soma-log.md")
1940
+ ];
1941
+ for (const src of candidates) {
1942
+ if (!existsSync3(src)) continue;
1943
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1944
+ const content = readFileSync3(src, "utf-8").replace(/\{\{today\}\}/g, today);
1945
+ mkdirSync2(dirname3(notesTarget), { recursive: true });
1946
+ writeFileSync2(notesTarget, content);
1947
+ fixes++;
1948
+ break;
1949
+ }
1950
+ }
1951
+ } catch {
1952
+ }
1821
1953
  if (fixes > 0) {
1822
1954
  try {
1823
1955
  const s = JSON.parse(readFileSync3(settingsPath, "utf-8"));
@@ -1976,6 +2108,14 @@ try {
1976
2108
  }
1977
2109
  } catch {
1978
2110
  }
2111
+ try {
2112
+ const tokenPath = join3(SOMA_HOME, "somadian-token");
2113
+ if (!existsSync3(tokenPath)) {
2114
+ mkdirSync2(SOMA_HOME, { recursive: true, mode: 448 });
2115
+ writeFileSync2(tokenPath, randomBytes(24).toString("hex"), { mode: 384 });
2116
+ }
2117
+ } catch {
2118
+ }
1979
2119
  if (cmd === "--version" || cmd === "-v" || cmd === "-V" || cmd === "version") {
1980
2120
  showVersion();
1981
2121
  } else if (cmd === "--help" || cmd === "-h" || cmd === "help") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meetsoma",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "description": "Soma — the AI coding agent with self-growing memory",
5
5
  "type": "module",
6
6
  "bin": {