abtars 0.2.0 → 0.2.1-alpha.10

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 (146) hide show
  1. package/README.md +15 -18
  2. package/bundle/{_registry.generated-6GO2PAMD.js → _registry.generated-4P6KTBTH.js} +8 -8
  3. package/bundle/_registry.generated-G2FSGHNY.js +36 -0
  4. package/bundle/_registry.generated-G2FSGHNY.js.map +7 -0
  5. package/bundle/_registry.generated-N74SMTUJ.js +36 -0
  6. package/bundle/_registry.generated-N74SMTUJ.js.map +7 -0
  7. package/bundle/_registry.generated-Y4VT5MBX.js +36 -0
  8. package/bundle/_registry.generated-Y4VT5MBX.js.map +7 -0
  9. package/bundle/abtars-browser.js +0 -1
  10. package/bundle/abtars-browser.js.map +2 -2
  11. package/bundle/abtars-cli.js +589 -547
  12. package/bundle/abtars-cli.js.map +4 -4
  13. package/bundle/abtars-restart.js +1 -1
  14. package/bundle/abtars-rss.js +0 -1
  15. package/bundle/abtars-rss.js.map +2 -2
  16. package/bundle/abtars-task.js +1 -2
  17. package/bundle/abtars-task.js.map +2 -2
  18. package/bundle/abtars.js +58 -33
  19. package/bundle/abtars.js.map +2 -2
  20. package/bundle/{agent-registry-SYUFNSVB.js → agent-registry-TM7EISOV.js} +2 -2
  21. package/bundle/{browse-delivery-64GQIUHG.js → browse-delivery-VTLEAVYA.js} +4 -4
  22. package/bundle/{browser-5H2Q7GEC.js → browser-JQGYFZAG.js} +5 -5
  23. package/bundle/browser-M4KDLN75.js +19 -0
  24. package/bundle/browser-REIXOJ6S.js +19 -0
  25. package/bundle/browser-VG2GTEND.js +19 -0
  26. package/bundle/{chunk-KFENC7BM.js → chunk-4YOTNYAE.js} +2 -2
  27. package/bundle/{chunk-KWBGYWDO.js → chunk-7I5C2U3C.js} +1 -1
  28. package/bundle/chunk-7I5C2U3C.js.map +7 -0
  29. package/bundle/{chunk-7STAQF5O.js → chunk-CNWXVXGH.js} +4 -4
  30. package/bundle/{chunk-7STAQF5O.js.map → chunk-CNWXVXGH.js.map} +2 -2
  31. package/bundle/{chunk-JX3ZZU3O.js → chunk-CU3O53U3.js} +28 -14
  32. package/bundle/chunk-CU3O53U3.js.map +7 -0
  33. package/bundle/chunk-EZZBO2QK.js +85 -0
  34. package/bundle/chunk-EZZBO2QK.js.map +7 -0
  35. package/bundle/{chunk-XLLSPBBT.js → chunk-GPL57SRN.js} +2 -2
  36. package/bundle/chunk-GPL57SRN.js.map +7 -0
  37. package/bundle/{chunk-PQ62LZNA.js → chunk-HEHD3GG5.js} +2 -2
  38. package/bundle/{chunk-A5OJYQNU.js → chunk-HTGVYNPE.js} +4 -4
  39. package/bundle/{chunk-WUTCGJDZ.js → chunk-HZRUBJ4Q.js} +148 -9
  40. package/bundle/chunk-HZRUBJ4Q.js.map +7 -0
  41. package/bundle/{chunk-ZVDVNSXK.js → chunk-J7CFCY4U.js} +2 -2
  42. package/bundle/{chunk-HXJRZWKA.js → chunk-JRK3UFBS.js} +106 -58
  43. package/bundle/chunk-JRK3UFBS.js.map +7 -0
  44. package/bundle/{chunk-GZUQQWBZ.js → chunk-KJOCXWJ5.js} +3 -3
  45. package/bundle/chunk-KJOCXWJ5.js.map +7 -0
  46. package/bundle/{chunk-K7P74UNQ.js → chunk-LDKSCXGL.js} +3 -3
  47. package/bundle/{chunk-K7P74UNQ.js.map → chunk-LDKSCXGL.js.map} +2 -2
  48. package/bundle/chunk-MNKLPRGY.js +138 -0
  49. package/bundle/chunk-MNKLPRGY.js.map +7 -0
  50. package/bundle/chunk-O73EZGKR.js +135 -0
  51. package/bundle/chunk-O73EZGKR.js.map +7 -0
  52. package/bundle/{chunk-OZ4IZFV4.js → chunk-Q7F5R2LL.js} +1 -1
  53. package/bundle/{chunk-OZ4IZFV4.js.map → chunk-Q7F5R2LL.js.map} +2 -2
  54. package/bundle/{chunk-XOCP5BMO.js → chunk-URAQLQ2U.js} +2 -2
  55. package/bundle/chunk-URAQLQ2U.js.map +7 -0
  56. package/bundle/{chunk-PPSB2ZIN.js → chunk-VREI2GUO.js} +18 -7
  57. package/bundle/chunk-VREI2GUO.js.map +7 -0
  58. package/bundle/chunk-VYR25H37.js +135 -0
  59. package/bundle/chunk-VYR25H37.js.map +7 -0
  60. package/bundle/{commands-E3Y4QUNF.js → commands-J6JAZ7D2.js} +5 -5
  61. package/bundle/{deploy-lib-import-ODLDL2DB.js → deploy-lib-import-PJXUADPS.js} +18 -16
  62. package/bundle/{direct-api-transport-TRV45NO6.js → direct-api-transport-ZSJHKYBX.js} +1 -1
  63. package/bundle/direct-api-transport-ZSJHKYBX.js.map +7 -0
  64. package/bundle/{discord-adapter-5DS7UTBE.js → discord-adapter-OCWSJTJU.js} +8 -8
  65. package/bundle/{doctor-R54GZPKL.js → doctor-XOGVHA4W.js} +13 -2
  66. package/bundle/{doctor-R54GZPKL.js.map → doctor-XOGVHA4W.js.map} +2 -2
  67. package/bundle/{install-RSLOS3Q5.js → install-6H3APAIJ.js} +3 -3
  68. package/bundle/{irc-adapter-RKRUSZXB.js → irc-adapter-AIEP6OX6.js} +6 -2
  69. package/bundle/irc-adapter-AIEP6OX6.js.map +7 -0
  70. package/bundle/{message-pipeline-CFVO73CK.js → message-pipeline-TCPHRBAK.js} +5 -5
  71. package/bundle/meta.json +4005 -3868
  72. package/bundle/{phase-transport-FEZ4SIJJ.js → phase-transport-ME2XDRR2.js} +3 -3
  73. package/bundle/restore-UH2UE2K5.js +151 -0
  74. package/bundle/restore-UH2UE2K5.js.map +7 -0
  75. package/bundle/rollback-D7AYTC7Z.js +11 -0
  76. package/bundle/{sleep-BPWX3FCN.js → sleep-IOWYTSMK.js} +2 -2
  77. package/bundle/{soul-bundle-BRIUDEQ2.js → soul-bundle-AH5S3MVI.js} +2 -2
  78. package/bundle/{soul-loader-GBXJ7EBH.js → soul-loader-N5FA4I6C.js} +3 -3
  79. package/bundle/soul-loader-N5FA4I6C.js.map +7 -0
  80. package/bundle/{start-4IWBKLWO.js → start-CBVKNEAT.js} +1 -1
  81. package/bundle/{subagent-runtime-MDBO6LHS.js → subagent-runtime-OOJXCKJF.js} +2 -2
  82. package/bundle/subagent-runtime-OOJXCKJF.js.map +7 -0
  83. package/bundle/{system-status-WAY63BYC.js → system-status-4JP36OKC.js} +12 -5
  84. package/bundle/{system-status-WAY63BYC.js.map → system-status-4JP36OKC.js.map} +2 -2
  85. package/bundle/{task-store-KIBFZL5A.js → task-store-LC7ZMS72.js} +2 -2
  86. package/bundle/task-store-LC7ZMS72.js.map +7 -0
  87. package/bundle/{telegram-adapter-MVA33IO2.js → telegram-adapter-QXHJQLLX.js} +5 -5
  88. package/bundle/{update-check-O5MS6B3L.js → update-check-XVY2IK2L.js} +2 -2
  89. package/bundle/update-check-XVY2IK2L.js.map +7 -0
  90. package/core/skills/tools/rss/SKILL.md +51 -0
  91. package/install-manifest.json +4 -3
  92. package/package.json +3 -4
  93. package/scripts/abtars-daemon.service +1 -1
  94. package/scripts/abtars-watchdog.service +1 -1
  95. package/scripts/abtars.sh +3 -5
  96. package/scripts/abtars@.service +1 -1
  97. package/scripts/build-and-deploy.sh +6 -0
  98. package/scripts/com.abtars.daemon.plist +1 -1
  99. package/scripts/com.abtars.watchdog.plist +1 -1
  100. package/scripts/daily-backup.sh +1 -61
  101. package/scripts/doctor.sh +48 -33
  102. package/scripts/watchdog.sh +53 -8
  103. package/bundle/chunk-GZUQQWBZ.js.map +0 -7
  104. package/bundle/chunk-HXJRZWKA.js.map +0 -7
  105. package/bundle/chunk-JX3ZZU3O.js.map +0 -7
  106. package/bundle/chunk-KWBGYWDO.js.map +0 -7
  107. package/bundle/chunk-PPSB2ZIN.js.map +0 -7
  108. package/bundle/chunk-WUTCGJDZ.js.map +0 -7
  109. package/bundle/chunk-XLLSPBBT.js.map +0 -7
  110. package/bundle/chunk-XOCP5BMO.js.map +0 -7
  111. package/bundle/direct-api-transport-TRV45NO6.js.map +0 -7
  112. package/bundle/irc-adapter-RKRUSZXB.js.map +0 -7
  113. package/bundle/passwd-QSHZJ2CG.js +0 -134
  114. package/bundle/passwd-QSHZJ2CG.js.map +0 -7
  115. package/bundle/restore-ROJF22R2.js +0 -47
  116. package/bundle/restore-ROJF22R2.js.map +0 -7
  117. package/core/core_templates/SOUL.md +0 -24
  118. package/core/core_templates/agent_notes.md +0 -7
  119. package/core/core_templates/core_facts.md +0 -10
  120. package/core/core_templates/user_profile.md +0 -7
  121. package/core/skills/tools/fxtwitter/SKILL.md +0 -52
  122. package/core/skills/tools/twitterX/SKILL.md +0 -52
  123. package/core/skills/tools/twitterX/scripts/abtars-tweet.js +0 -532
  124. package/core/skills/tools/twitterX/scripts/package.json +0 -1
  125. /package/bundle/{_registry.generated-6GO2PAMD.js.map → _registry.generated-4P6KTBTH.js.map} +0 -0
  126. /package/bundle/{agent-registry-SYUFNSVB.js.map → agent-registry-TM7EISOV.js.map} +0 -0
  127. /package/bundle/{browse-delivery-64GQIUHG.js.map → browse-delivery-VTLEAVYA.js.map} +0 -0
  128. /package/bundle/{browser-5H2Q7GEC.js.map → browser-JQGYFZAG.js.map} +0 -0
  129. /package/bundle/{commands-E3Y4QUNF.js.map → browser-M4KDLN75.js.map} +0 -0
  130. /package/bundle/{deploy-lib-import-ODLDL2DB.js.map → browser-REIXOJ6S.js.map} +0 -0
  131. /package/bundle/{install-RSLOS3Q5.js.map → browser-VG2GTEND.js.map} +0 -0
  132. /package/bundle/{chunk-KFENC7BM.js.map → chunk-4YOTNYAE.js.map} +0 -0
  133. /package/bundle/{chunk-PQ62LZNA.js.map → chunk-HEHD3GG5.js.map} +0 -0
  134. /package/bundle/{chunk-A5OJYQNU.js.map → chunk-HTGVYNPE.js.map} +0 -0
  135. /package/bundle/{chunk-ZVDVNSXK.js.map → chunk-J7CFCY4U.js.map} +0 -0
  136. /package/bundle/{message-pipeline-CFVO73CK.js.map → commands-J6JAZ7D2.js.map} +0 -0
  137. /package/bundle/{phase-transport-FEZ4SIJJ.js.map → deploy-lib-import-PJXUADPS.js.map} +0 -0
  138. /package/bundle/{discord-adapter-5DS7UTBE.js.map → discord-adapter-OCWSJTJU.js.map} +0 -0
  139. /package/bundle/{sleep-BPWX3FCN.js.map → install-6H3APAIJ.js.map} +0 -0
  140. /package/bundle/{soul-bundle-BRIUDEQ2.js.map → message-pipeline-TCPHRBAK.js.map} +0 -0
  141. /package/bundle/{soul-loader-GBXJ7EBH.js.map → phase-transport-ME2XDRR2.js.map} +0 -0
  142. /package/bundle/{subagent-runtime-MDBO6LHS.js.map → rollback-D7AYTC7Z.js.map} +0 -0
  143. /package/bundle/{task-store-KIBFZL5A.js.map → sleep-IOWYTSMK.js.map} +0 -0
  144. /package/bundle/{update-check-O5MS6B3L.js.map → soul-bundle-AH5S3MVI.js.map} +0 -0
  145. /package/bundle/{start-4IWBKLWO.js.map → start-CBVKNEAT.js.map} +0 -0
  146. /package/bundle/{telegram-adapter-MVA33IO2.js.map → telegram-adapter-QXHJQLLX.js.map} +0 -0
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  loadMinimalSoul,
14
14
  loadSoulBundle
15
- } from "./chunk-KFENC7BM.js";
15
+ } from "./chunk-4YOTNYAE.js";
16
16
  import {
17
17
  loadUsers
18
18
  } from "./chunk-GBBTK6H2.js";
@@ -32,7 +32,7 @@ import {
32
32
  } from "./chunk-UDZIZB5F.js";
33
33
  import {
34
34
  readEntries
35
- } from "./chunk-XLLSPBBT.js";
35
+ } from "./chunk-GPL57SRN.js";
36
36
  import {
37
37
  localTime
38
38
  } from "./chunk-MZWMYN4O.js";
@@ -1059,6 +1059,12 @@ var busyGuardMiddleware = async (ctx, next) => {
1059
1059
  if (entry.busy) {
1060
1060
  const text = ctx.text.trim();
1061
1061
  const lower = text.toLowerCase();
1062
+ const firstWord = lower.split(/\s/)[0];
1063
+ const READONLY = ["/memory", "/models", "/status", "/help", "/tasks", "/usage", "/sleep", "/sessions", "/whoami", "/model"];
1064
+ if (READONLY.includes(firstWord)) {
1065
+ await next();
1066
+ return;
1067
+ }
1062
1068
  if (lower === "/stop" || lower === "/ctrlc") {
1063
1069
  logInfo("busy-guard", `STOP interrupt for ${activeId}`);
1064
1070
  await deps.transport.sendInterrupt();
@@ -1333,11 +1339,15 @@ You are now talking to ${user.userId} (${user.role}, ${CLASS_NAMES[user.maxClass
1333
1339
  if (compSummary && sessionKey) {
1334
1340
  } else {
1335
1341
  const ctxOpts = isCodeSession ? { skipDailies: true, maxAgeMs: 48 * 60 * 60 * 1e3 } : void 0;
1336
- const ctx = abmind()?.buildSessionStartContext(memory, userId, maxContext, ctxOpts);
1342
+ const ctxResult = abmind()?.buildSessionStartContext(memory, userId, maxContext, ctxOpts);
1343
+ const ctx = ctxResult?.text ?? null;
1337
1344
  if (ctx) {
1338
1345
  contextParts.push(ctx);
1339
- logInfo(TAG3, `Injected session-start context (${ctx.length} chars${isCodeSession ? ", Code mode" : ""})`);
1340
- logTrace(TAG3, `session-start content: ${ctx}`);
1346
+ const s = ctxResult.stats;
1347
+ const ctxPct = maxContext ? Math.round(ctx.length / maxContext * 100) : -1;
1348
+ logInfo(TAG3, `Session start: ${s.messages} messages + ${s.dailies} dailies (${(s.usedBytes / 1024).toFixed(1)}KB / ${(s.budget / 1024).toFixed(0)}KB budget, ${ctxPct}% ctx${isCodeSession ? ", Code" : ""})`);
1349
+ logDebug(TAG3, `Session context: ${s.messages} msgs, ${s.dailies} dailies, ${s.usedBytes}B / ${s.budget}B budget, ${ctxPct}% ctx`);
1350
+ logTrace(TAG3, `session-start content: ${ctx.slice(0, 500)}...`);
1341
1351
  }
1342
1352
  try {
1343
1353
  const userRole = loadUsers().byUserId.get(userId)?.role ?? "master";
@@ -2355,9 +2365,10 @@ ${raw || "(no output)"}`);
2355
2365
  }
2356
2366
  return true;
2357
2367
  }
2358
- const { getDoctorReport, renderDoctorText } = await import("./doctor-R54GZPKL.js");
2368
+ const { getDoctorReport, renderDoctorText } = await import("./doctor-XOGVHA4W.js");
2359
2369
  const force = arg === "force";
2360
2370
  const svcStates = ctx.registry?.getStates() ?? {};
2371
+ await ctx.reply("\u{1FA7A} Running diagnostics...");
2361
2372
  const report = await getDoctorReport({
2362
2373
  memory: ctx.memory,
2363
2374
  transport: ctx.transport,
@@ -2370,7 +2381,7 @@ ${raw || "(no output)"}`);
2370
2381
  }
2371
2382
  async function handleStatus(_text, ctx) {
2372
2383
  if (ctx.phaseHealth && ctx.registry) {
2373
- const { getSystemStatus, renderStatusText } = await import("./system-status-WAY63BYC.js");
2384
+ const { getSystemStatus, renderStatusText } = await import("./system-status-4JP36OKC.js");
2374
2385
  const status = await getSystemStatus({
2375
2386
  phaseHealth: ctx.phaseHealth,
2376
2387
  registry: ctx.registry,
@@ -2662,6 +2673,132 @@ async function handleWhoami(_text, ctx) {
2662
2673
  }
2663
2674
  return true;
2664
2675
  }
2676
+ async function handleSoftware(_text, ctx) {
2677
+ const { existsSync } = await import("node:fs");
2678
+ const { abtarsHome: abtarsHome2 } = await import("./paths-ZJYIDND2.js");
2679
+ const home = abtarsHome2();
2680
+ const arg = _text.replace(/^\/(software|update)\s*/i, "").trim();
2681
+ const { loadUsers: loadUsers2 } = await import("./user-registry-NUVNEHJU.js");
2682
+ const user = loadUsers2().byUserId.get(ctx.userId);
2683
+ const isMaster = user?.role === "master";
2684
+ if (arg.startsWith("rollback")) {
2685
+ if (!isMaster) {
2686
+ await ctx.reply("\u274C Requires master role.");
2687
+ return true;
2688
+ }
2689
+ const targetVersion = arg.replace(/^rollback\s*/, "").trim();
2690
+ if (!targetVersion) {
2691
+ await ctx.reply("Usage: /software rollback <version>\nUse /software to see available versions.");
2692
+ return true;
2693
+ }
2694
+ let targetSlot = null;
2695
+ for (let i = 1; i <= 3; i++) {
2696
+ const pkgPath = join2(home, `app.prev.${i}`, "package.json");
2697
+ try {
2698
+ const ver = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
2699
+ if (ver === targetVersion) {
2700
+ targetSlot = i;
2701
+ break;
2702
+ }
2703
+ } catch {
2704
+ }
2705
+ }
2706
+ if (!targetSlot) {
2707
+ await ctx.reply(`\u274C Version ${targetVersion} not found in rollback slots.`);
2708
+ return true;
2709
+ }
2710
+ await ctx.reply(`\u26A0\uFE0F Rolling back to ${targetVersion}...`);
2711
+ try {
2712
+ const { rollback } = await import("./rollback-D7AYTC7Z.js");
2713
+ await rollback({ to: targetSlot });
2714
+ } catch (err) {
2715
+ await ctx.reply(`\u274C Rollback failed: ${err instanceof Error ? err.message : String(err)}`);
2716
+ }
2717
+ return true;
2718
+ }
2719
+ if (arg === "update" || arg === "update local" || arg === "local" || arg === "") {
2720
+ if (arg === "" && _text.match(/^\/software\s*$/i)) {
2721
+ } else if (arg === "update" || arg === "update local" || arg === "local") {
2722
+ if (!isMaster) {
2723
+ await ctx.reply("\u274C Requires master role.");
2724
+ return true;
2725
+ }
2726
+ const isLocal = arg.includes("local");
2727
+ await ctx.reply(`\u23F3 Updating${isLocal ? " (local)" : " (npm)"}...`);
2728
+ try {
2729
+ const { spawnSync } = await import("node:child_process");
2730
+ const args = ["update"];
2731
+ if (isLocal) args.push("--from-local");
2732
+ const { writeFileSync: wf } = await import("node:fs");
2733
+ const reasonPath = join2(home, ".last-restart-reason");
2734
+ wf(reasonPath, `software-update`, "utf-8");
2735
+ spawnSync("abtars", args, { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
2736
+ await ctx.reply("\u26A0\uFE0F Update completed but bridge did not restart. Run /restart.");
2737
+ } catch (err) {
2738
+ await ctx.reply(`\u274C Update failed: ${err instanceof Error ? err.message : String(err)}`);
2739
+ }
2740
+ return true;
2741
+ }
2742
+ }
2743
+ if (arg === "check") {
2744
+ await ctx.reply("\u{1F50D} Checking npm registry...");
2745
+ try {
2746
+ const { spawnSync } = await import("node:child_process");
2747
+ const abtarsLatest = spawnSync("npm", ["view", "abtars", "dist-tags", "--json"], { encoding: "utf-8", timeout: 1e4 });
2748
+ const abmindLatest = spawnSync("npm", ["view", "abmind", "dist-tags", "--json"], { encoding: "utf-8", timeout: 1e4 });
2749
+ const abt = abtarsLatest.status === 0 ? JSON.parse(abtarsLatest.stdout) : null;
2750
+ const abm = abmindLatest.status === 0 ? JSON.parse(abmindLatest.stdout) : null;
2751
+ const lines2 = ["\u{1F4E6} npm registry (fresh):"];
2752
+ if (abt) lines2.push(` abtars: latest=${abt.latest ?? "?"} alpha=${abt.alpha ?? "?"}`);
2753
+ if (abm) lines2.push(` abmind: latest=${abm.latest ?? "?"} alpha=${abm.alpha ?? "?"}`);
2754
+ if (!abt && !abm) lines2.push(" \u26A0\uFE0F npm unreachable");
2755
+ await ctx.reply(lines2.join("\n"));
2756
+ } catch {
2757
+ await ctx.reply("\u274C npm check failed (timeout or network error)");
2758
+ }
2759
+ return true;
2760
+ }
2761
+ const lines = ["\u{1F527} Software"];
2762
+ try {
2763
+ const pkg = JSON.parse(readFileSync(join2(home, "app", "package.json"), "utf-8"));
2764
+ const manifest = existsSync(join2(home, "manifest.json")) ? JSON.parse(readFileSync(join2(home, "manifest.json"), "utf-8")) : null;
2765
+ const deployed = manifest?.activatedAt ? new Date(manifest.activatedAt).toLocaleString() : "unknown";
2766
+ lines.push(` abtars: ${pkg.version} (deployed ${deployed})`);
2767
+ } catch {
2768
+ lines.push(" abtars: unknown");
2769
+ }
2770
+ const abmindHome = process.env["ABMIND_HOME"] ?? join2(home, "..", ".abmind");
2771
+ const abmindManifest = join2(abmindHome, "manifest.json");
2772
+ if (existsSync(abmindManifest)) {
2773
+ try {
2774
+ const m = JSON.parse(readFileSync(abmindManifest, "utf-8"));
2775
+ const deployed = m.activatedAt ? new Date(m.activatedAt).toLocaleString() : "unknown";
2776
+ lines.push(` abmind: ${m.version ?? "?"} (deployed ${deployed})`);
2777
+ } catch {
2778
+ lines.push(" abmind: installed (version unknown)");
2779
+ }
2780
+ }
2781
+ try {
2782
+ const { checkForUpdate } = await import("./update-check-XVY2IK2L.js");
2783
+ const abtResult = checkForUpdate("abtars", "0.0.0");
2784
+ if (abtResult?.latest) lines.push(` Latest stable: abtars@${abtResult.latest}`);
2785
+ } catch {
2786
+ }
2787
+ lines.push(" Rollback:");
2788
+ for (let i = 1; i <= 3; i++) {
2789
+ const pkgPath = join2(home, `app.prev.${i}`, "package.json");
2790
+ try {
2791
+ const ver = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
2792
+ lines.push(` ${i}: ${ver}`);
2793
+ } catch {
2794
+ lines.push(` ${i}: (empty)`);
2795
+ }
2796
+ }
2797
+ lines.push("");
2798
+ lines.push(" /software check | update [local] | rollback <version>");
2799
+ await ctx.reply(lines.join("\n"));
2800
+ return true;
2801
+ }
2665
2802
 
2666
2803
  // src/components/nlm-command-handler.ts
2667
2804
  init_env_schema();
@@ -2976,7 +3113,7 @@ async function handleTasksList(_text, ctx) {
2976
3113
  const now = (/* @__PURE__ */ new Date()).toLocaleString("en-GB", { timeZone: tz, dateStyle: "medium", timeStyle: "medium" });
2977
3114
  let listing;
2978
3115
  try {
2979
- const { readEntries: readEntries2 } = await import("./task-store-KIBFZL5A.js");
3116
+ const { readEntries: readEntries2 } = await import("./task-store-LC7ZMS72.js");
2980
3117
  const entries = readEntries2();
2981
3118
  const active = entries.filter((e) => !e.fired);
2982
3119
  active.sort((a, b) => {
@@ -3652,6 +3789,8 @@ registerExact("/restart", handleRestart);
3652
3789
  registerExact("/full", handleFull);
3653
3790
  registerExact("/short", handleShort);
3654
3791
  registerExact("/healing", handleHealing);
3792
+ registerExact("/software", handleSoftware);
3793
+ registerExact("/update", handleSoftware);
3655
3794
  registerExact("/facts", handleFacts);
3656
3795
  registerExact("/tasks", handleTasksList);
3657
3796
  registerExact("/task", handleTasksList);
@@ -3708,4 +3847,4 @@ export {
3708
3847
  handleInboundMessage,
3709
3848
  startSession
3710
3849
  };
3711
- //# sourceMappingURL=chunk-WUTCGJDZ.js.map
3850
+ //# sourceMappingURL=chunk-HZRUBJ4Q.js.map