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.
- package/README.md +15 -18
- package/bundle/{_registry.generated-6GO2PAMD.js → _registry.generated-4P6KTBTH.js} +8 -8
- package/bundle/_registry.generated-G2FSGHNY.js +36 -0
- package/bundle/_registry.generated-G2FSGHNY.js.map +7 -0
- package/bundle/_registry.generated-N74SMTUJ.js +36 -0
- package/bundle/_registry.generated-N74SMTUJ.js.map +7 -0
- package/bundle/_registry.generated-Y4VT5MBX.js +36 -0
- package/bundle/_registry.generated-Y4VT5MBX.js.map +7 -0
- package/bundle/abtars-browser.js +0 -1
- package/bundle/abtars-browser.js.map +2 -2
- package/bundle/abtars-cli.js +589 -547
- package/bundle/abtars-cli.js.map +4 -4
- package/bundle/abtars-restart.js +1 -1
- package/bundle/abtars-rss.js +0 -1
- package/bundle/abtars-rss.js.map +2 -2
- package/bundle/abtars-task.js +1 -2
- package/bundle/abtars-task.js.map +2 -2
- package/bundle/abtars.js +58 -33
- package/bundle/abtars.js.map +2 -2
- package/bundle/{agent-registry-SYUFNSVB.js → agent-registry-TM7EISOV.js} +2 -2
- package/bundle/{browse-delivery-64GQIUHG.js → browse-delivery-VTLEAVYA.js} +4 -4
- package/bundle/{browser-5H2Q7GEC.js → browser-JQGYFZAG.js} +5 -5
- package/bundle/browser-M4KDLN75.js +19 -0
- package/bundle/browser-REIXOJ6S.js +19 -0
- package/bundle/browser-VG2GTEND.js +19 -0
- package/bundle/{chunk-KFENC7BM.js → chunk-4YOTNYAE.js} +2 -2
- package/bundle/{chunk-KWBGYWDO.js → chunk-7I5C2U3C.js} +1 -1
- package/bundle/chunk-7I5C2U3C.js.map +7 -0
- package/bundle/{chunk-7STAQF5O.js → chunk-CNWXVXGH.js} +4 -4
- package/bundle/{chunk-7STAQF5O.js.map → chunk-CNWXVXGH.js.map} +2 -2
- package/bundle/{chunk-JX3ZZU3O.js → chunk-CU3O53U3.js} +28 -14
- package/bundle/chunk-CU3O53U3.js.map +7 -0
- package/bundle/chunk-EZZBO2QK.js +85 -0
- package/bundle/chunk-EZZBO2QK.js.map +7 -0
- package/bundle/{chunk-XLLSPBBT.js → chunk-GPL57SRN.js} +2 -2
- package/bundle/chunk-GPL57SRN.js.map +7 -0
- package/bundle/{chunk-PQ62LZNA.js → chunk-HEHD3GG5.js} +2 -2
- package/bundle/{chunk-A5OJYQNU.js → chunk-HTGVYNPE.js} +4 -4
- package/bundle/{chunk-WUTCGJDZ.js → chunk-HZRUBJ4Q.js} +148 -9
- package/bundle/chunk-HZRUBJ4Q.js.map +7 -0
- package/bundle/{chunk-ZVDVNSXK.js → chunk-J7CFCY4U.js} +2 -2
- package/bundle/{chunk-HXJRZWKA.js → chunk-JRK3UFBS.js} +106 -58
- package/bundle/chunk-JRK3UFBS.js.map +7 -0
- package/bundle/{chunk-GZUQQWBZ.js → chunk-KJOCXWJ5.js} +3 -3
- package/bundle/chunk-KJOCXWJ5.js.map +7 -0
- package/bundle/{chunk-K7P74UNQ.js → chunk-LDKSCXGL.js} +3 -3
- package/bundle/{chunk-K7P74UNQ.js.map → chunk-LDKSCXGL.js.map} +2 -2
- package/bundle/chunk-MNKLPRGY.js +138 -0
- package/bundle/chunk-MNKLPRGY.js.map +7 -0
- package/bundle/chunk-O73EZGKR.js +135 -0
- package/bundle/chunk-O73EZGKR.js.map +7 -0
- package/bundle/{chunk-OZ4IZFV4.js → chunk-Q7F5R2LL.js} +1 -1
- package/bundle/{chunk-OZ4IZFV4.js.map → chunk-Q7F5R2LL.js.map} +2 -2
- package/bundle/{chunk-XOCP5BMO.js → chunk-URAQLQ2U.js} +2 -2
- package/bundle/chunk-URAQLQ2U.js.map +7 -0
- package/bundle/{chunk-PPSB2ZIN.js → chunk-VREI2GUO.js} +18 -7
- package/bundle/chunk-VREI2GUO.js.map +7 -0
- package/bundle/chunk-VYR25H37.js +135 -0
- package/bundle/chunk-VYR25H37.js.map +7 -0
- package/bundle/{commands-E3Y4QUNF.js → commands-J6JAZ7D2.js} +5 -5
- package/bundle/{deploy-lib-import-ODLDL2DB.js → deploy-lib-import-PJXUADPS.js} +18 -16
- package/bundle/{direct-api-transport-TRV45NO6.js → direct-api-transport-ZSJHKYBX.js} +1 -1
- package/bundle/direct-api-transport-ZSJHKYBX.js.map +7 -0
- package/bundle/{discord-adapter-5DS7UTBE.js → discord-adapter-OCWSJTJU.js} +8 -8
- package/bundle/{doctor-R54GZPKL.js → doctor-XOGVHA4W.js} +13 -2
- package/bundle/{doctor-R54GZPKL.js.map → doctor-XOGVHA4W.js.map} +2 -2
- package/bundle/{install-RSLOS3Q5.js → install-6H3APAIJ.js} +3 -3
- package/bundle/{irc-adapter-RKRUSZXB.js → irc-adapter-AIEP6OX6.js} +6 -2
- package/bundle/irc-adapter-AIEP6OX6.js.map +7 -0
- package/bundle/{message-pipeline-CFVO73CK.js → message-pipeline-TCPHRBAK.js} +5 -5
- package/bundle/meta.json +4005 -3868
- package/bundle/{phase-transport-FEZ4SIJJ.js → phase-transport-ME2XDRR2.js} +3 -3
- package/bundle/restore-UH2UE2K5.js +151 -0
- package/bundle/restore-UH2UE2K5.js.map +7 -0
- package/bundle/rollback-D7AYTC7Z.js +11 -0
- package/bundle/{sleep-BPWX3FCN.js → sleep-IOWYTSMK.js} +2 -2
- package/bundle/{soul-bundle-BRIUDEQ2.js → soul-bundle-AH5S3MVI.js} +2 -2
- package/bundle/{soul-loader-GBXJ7EBH.js → soul-loader-N5FA4I6C.js} +3 -3
- package/bundle/soul-loader-N5FA4I6C.js.map +7 -0
- package/bundle/{start-4IWBKLWO.js → start-CBVKNEAT.js} +1 -1
- package/bundle/{subagent-runtime-MDBO6LHS.js → subagent-runtime-OOJXCKJF.js} +2 -2
- package/bundle/subagent-runtime-OOJXCKJF.js.map +7 -0
- package/bundle/{system-status-WAY63BYC.js → system-status-4JP36OKC.js} +12 -5
- package/bundle/{system-status-WAY63BYC.js.map → system-status-4JP36OKC.js.map} +2 -2
- package/bundle/{task-store-KIBFZL5A.js → task-store-LC7ZMS72.js} +2 -2
- package/bundle/task-store-LC7ZMS72.js.map +7 -0
- package/bundle/{telegram-adapter-MVA33IO2.js → telegram-adapter-QXHJQLLX.js} +5 -5
- package/bundle/{update-check-O5MS6B3L.js → update-check-XVY2IK2L.js} +2 -2
- package/bundle/update-check-XVY2IK2L.js.map +7 -0
- package/core/skills/tools/rss/SKILL.md +51 -0
- package/install-manifest.json +4 -3
- package/package.json +3 -4
- package/scripts/abtars-daemon.service +1 -1
- package/scripts/abtars-watchdog.service +1 -1
- package/scripts/abtars.sh +3 -5
- package/scripts/abtars@.service +1 -1
- package/scripts/build-and-deploy.sh +6 -0
- package/scripts/com.abtars.daemon.plist +1 -1
- package/scripts/com.abtars.watchdog.plist +1 -1
- package/scripts/daily-backup.sh +1 -61
- package/scripts/doctor.sh +48 -33
- package/scripts/watchdog.sh +53 -8
- package/bundle/chunk-GZUQQWBZ.js.map +0 -7
- package/bundle/chunk-HXJRZWKA.js.map +0 -7
- package/bundle/chunk-JX3ZZU3O.js.map +0 -7
- package/bundle/chunk-KWBGYWDO.js.map +0 -7
- package/bundle/chunk-PPSB2ZIN.js.map +0 -7
- package/bundle/chunk-WUTCGJDZ.js.map +0 -7
- package/bundle/chunk-XLLSPBBT.js.map +0 -7
- package/bundle/chunk-XOCP5BMO.js.map +0 -7
- package/bundle/direct-api-transport-TRV45NO6.js.map +0 -7
- package/bundle/irc-adapter-RKRUSZXB.js.map +0 -7
- package/bundle/passwd-QSHZJ2CG.js +0 -134
- package/bundle/passwd-QSHZJ2CG.js.map +0 -7
- package/bundle/restore-ROJF22R2.js +0 -47
- package/bundle/restore-ROJF22R2.js.map +0 -7
- package/core/core_templates/SOUL.md +0 -24
- package/core/core_templates/agent_notes.md +0 -7
- package/core/core_templates/core_facts.md +0 -10
- package/core/core_templates/user_profile.md +0 -7
- package/core/skills/tools/fxtwitter/SKILL.md +0 -52
- package/core/skills/tools/twitterX/SKILL.md +0 -52
- package/core/skills/tools/twitterX/scripts/abtars-tweet.js +0 -532
- package/core/skills/tools/twitterX/scripts/package.json +0 -1
- /package/bundle/{_registry.generated-6GO2PAMD.js.map → _registry.generated-4P6KTBTH.js.map} +0 -0
- /package/bundle/{agent-registry-SYUFNSVB.js.map → agent-registry-TM7EISOV.js.map} +0 -0
- /package/bundle/{browse-delivery-64GQIUHG.js.map → browse-delivery-VTLEAVYA.js.map} +0 -0
- /package/bundle/{browser-5H2Q7GEC.js.map → browser-JQGYFZAG.js.map} +0 -0
- /package/bundle/{commands-E3Y4QUNF.js.map → browser-M4KDLN75.js.map} +0 -0
- /package/bundle/{deploy-lib-import-ODLDL2DB.js.map → browser-REIXOJ6S.js.map} +0 -0
- /package/bundle/{install-RSLOS3Q5.js.map → browser-VG2GTEND.js.map} +0 -0
- /package/bundle/{chunk-KFENC7BM.js.map → chunk-4YOTNYAE.js.map} +0 -0
- /package/bundle/{chunk-PQ62LZNA.js.map → chunk-HEHD3GG5.js.map} +0 -0
- /package/bundle/{chunk-A5OJYQNU.js.map → chunk-HTGVYNPE.js.map} +0 -0
- /package/bundle/{chunk-ZVDVNSXK.js.map → chunk-J7CFCY4U.js.map} +0 -0
- /package/bundle/{message-pipeline-CFVO73CK.js.map → commands-J6JAZ7D2.js.map} +0 -0
- /package/bundle/{phase-transport-FEZ4SIJJ.js.map → deploy-lib-import-PJXUADPS.js.map} +0 -0
- /package/bundle/{discord-adapter-5DS7UTBE.js.map → discord-adapter-OCWSJTJU.js.map} +0 -0
- /package/bundle/{sleep-BPWX3FCN.js.map → install-6H3APAIJ.js.map} +0 -0
- /package/bundle/{soul-bundle-BRIUDEQ2.js.map → message-pipeline-TCPHRBAK.js.map} +0 -0
- /package/bundle/{soul-loader-GBXJ7EBH.js.map → phase-transport-ME2XDRR2.js.map} +0 -0
- /package/bundle/{subagent-runtime-MDBO6LHS.js.map → rollback-D7AYTC7Z.js.map} +0 -0
- /package/bundle/{task-store-KIBFZL5A.js.map → sleep-IOWYTSMK.js.map} +0 -0
- /package/bundle/{update-check-O5MS6B3L.js.map → soul-bundle-AH5S3MVI.js.map} +0 -0
- /package/bundle/{start-4IWBKLWO.js.map → start-CBVKNEAT.js.map} +0 -0
- /package/bundle/{telegram-adapter-MVA33IO2.js.map → telegram-adapter-QXHJQLLX.js.map} +0 -0
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
buildTransport,
|
|
5
5
|
phaseTransport,
|
|
6
6
|
rebuildTransport
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-HTGVYNPE.js";
|
|
8
|
+
import "./chunk-J7CFCY4U.js";
|
|
9
9
|
import "./chunk-RV54J75Q.js";
|
|
10
10
|
import "./chunk-GBBTK6H2.js";
|
|
11
11
|
import "./chunk-UDZIZB5F.js";
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
phaseTransport,
|
|
21
21
|
rebuildTransport
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=phase-transport-
|
|
23
|
+
//# sourceMappingURL=phase-transport-ME2XDRR2.js.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
|
|
3
|
+
import {
|
|
4
|
+
abtarsHome,
|
|
5
|
+
init_paths
|
|
6
|
+
} from "./chunk-MJ6PHMOK.js";
|
|
7
|
+
import "./chunk-7K2YZTLD.js";
|
|
8
|
+
|
|
9
|
+
// src/cli/commands/restore.ts
|
|
10
|
+
init_paths();
|
|
11
|
+
import { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { join, dirname, basename } from "node:path";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
import { createDecipheriv, hkdfSync } from "node:crypto";
|
|
15
|
+
async function restore(archivePath, opts = {}) {
|
|
16
|
+
if (!archivePath) {
|
|
17
|
+
process.stderr.write("Usage: abtars restore <file.zip|.7z|.abm|.enc> [--config] [--passphrase <p>]\n");
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
if (!existsSync(archivePath)) {
|
|
21
|
+
process.stderr.write(`File not found: ${archivePath}
|
|
22
|
+
`);
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
if (archivePath.endsWith(".abm")) {
|
|
26
|
+
return restoreAbmind(archivePath, opts.passphrase);
|
|
27
|
+
}
|
|
28
|
+
if (archivePath.endsWith(".enc")) {
|
|
29
|
+
const date = extractDate(archivePath);
|
|
30
|
+
const dir = dirname(archivePath);
|
|
31
|
+
const sibling = findSiblingAbm(dir, date);
|
|
32
|
+
if (!opts.config && sibling) {
|
|
33
|
+
const rc2 = restoreAbmind(sibling, opts.passphrase);
|
|
34
|
+
if (rc2 !== 0) return rc2;
|
|
35
|
+
}
|
|
36
|
+
const abmindHome = process.env["ABMIND_HOME"] ?? join(dirname(abtarsHome()), ".abmind");
|
|
37
|
+
const keyPath = join(abmindHome, "secret", "abmind.key");
|
|
38
|
+
if (!existsSync(keyPath)) {
|
|
39
|
+
process.stderr.write("Error: abmind.key not found \u2014 run `abmind restore <file.abm>` first to recreate it, then retry.\n");
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
const tmpZip = join(process.env["TMPDIR"] ?? "/tmp", `abtars-restore-${Date.now()}.zip`);
|
|
43
|
+
const ok = decryptFile(archivePath, tmpZip, keyPath);
|
|
44
|
+
if (!ok) return 1;
|
|
45
|
+
process.stdout.write("\u2713 decrypted\n");
|
|
46
|
+
const rc = extractZip(tmpZip, abtarsHome());
|
|
47
|
+
try {
|
|
48
|
+
unlinkSync(tmpZip);
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return rc;
|
|
52
|
+
}
|
|
53
|
+
if (!opts.config) {
|
|
54
|
+
const date = extractDate(archivePath);
|
|
55
|
+
const dir = dirname(archivePath);
|
|
56
|
+
const sibling = findSiblingAbm(dir, date);
|
|
57
|
+
if (sibling) {
|
|
58
|
+
const rc = restoreAbmind(sibling, opts.passphrase);
|
|
59
|
+
if (rc !== 0) return rc;
|
|
60
|
+
} else {
|
|
61
|
+
process.stdout.write("\u2139 no sibling .abm found \u2014 memory not restored\n");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return extractZip(archivePath, abtarsHome());
|
|
65
|
+
}
|
|
66
|
+
function restoreAbmind(abmPath, passphrase) {
|
|
67
|
+
const args = ["restore", "--input", abmPath, "--mode", "merge"];
|
|
68
|
+
if (passphrase) args.push("--passphrase", passphrase);
|
|
69
|
+
const envPassphrase = process.env["ABMIND_BACKUP_PASSPHRASE"];
|
|
70
|
+
const env = { ...process.env };
|
|
71
|
+
if (!passphrase && envPassphrase) {
|
|
72
|
+
env["ABMIND_BACKUP_PASSPHRASE"] = envPassphrase;
|
|
73
|
+
}
|
|
74
|
+
const result = spawnSync("abmind", args, { encoding: "utf-8", stdio: "inherit", env });
|
|
75
|
+
if (result.status !== 0) {
|
|
76
|
+
process.stderr.write("abmind restore failed\n");
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
process.stdout.write("\u2713 abmind memory restored\n");
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
function extractZip(archivePath, destDir) {
|
|
83
|
+
const is7z = archivePath.endsWith(".7z");
|
|
84
|
+
const listCmd = is7z ? spawnSync("7z", ["l", archivePath], { encoding: "utf-8" }) : spawnSync("unzip", ["-l", archivePath], { encoding: "utf-8" });
|
|
85
|
+
if (!listCmd.stdout?.includes("config/")) {
|
|
86
|
+
process.stderr.write("Error: archive does not contain config/ \u2014 not a valid abtars backup\n");
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
let result;
|
|
90
|
+
if (is7z) {
|
|
91
|
+
result = spawnSync(
|
|
92
|
+
"7z",
|
|
93
|
+
["x", `-o${destDir}`, "-aoa", "-xr!releases", "-xr!current", "-xr!bin", "-xr!manifest.json", archivePath],
|
|
94
|
+
{ encoding: "utf-8", stdio: "inherit" }
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
result = spawnSync(
|
|
98
|
+
"unzip",
|
|
99
|
+
["-o", archivePath, "-d", destDir, "-x", "releases/*", "current/*", "bin/*", "manifest.json"],
|
|
100
|
+
{ encoding: "utf-8", stdio: "inherit" }
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (result.status !== 0) {
|
|
104
|
+
process.stderr.write("Restore extract failed\n");
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
process.stdout.write(`\u2713 Restored to ${destDir}
|
|
108
|
+
`);
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
function extractDate(filePath) {
|
|
112
|
+
const name = basename(filePath);
|
|
113
|
+
const match = name.match(/(\d{4}-\d{2}-\d{2})/);
|
|
114
|
+
return match?.[1] ?? null;
|
|
115
|
+
}
|
|
116
|
+
function findSiblingAbm(dir, date) {
|
|
117
|
+
if (!existsSync(dir)) return null;
|
|
118
|
+
const files = readdirSync(dir).filter((f) => f.endsWith(".abm"));
|
|
119
|
+
if (date) {
|
|
120
|
+
const exact = files.find((f) => f.includes(date));
|
|
121
|
+
if (exact) return join(dir, exact);
|
|
122
|
+
}
|
|
123
|
+
const sorted = files.sort().reverse();
|
|
124
|
+
return sorted[0] ? join(dir, sorted[0]) : null;
|
|
125
|
+
}
|
|
126
|
+
function decryptFile(inputPath, outputPath, keyPath) {
|
|
127
|
+
const master = Buffer.from(readFileSync(keyPath, "utf-8").trim(), "hex");
|
|
128
|
+
const key = Buffer.from(hkdfSync("sha256", master, "", "abtars-backup-v1", 32));
|
|
129
|
+
const buf = readFileSync(inputPath);
|
|
130
|
+
if (buf.length < 28) {
|
|
131
|
+
process.stderr.write("Error: encrypted file too small\n");
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
const iv = buf.subarray(0, 12);
|
|
135
|
+
const tag = buf.subarray(buf.length - 16);
|
|
136
|
+
const ciphertext = buf.subarray(12, buf.length - 16);
|
|
137
|
+
try {
|
|
138
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
139
|
+
decipher.setAuthTag(tag);
|
|
140
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
141
|
+
writeFileSync(outputPath, decrypted);
|
|
142
|
+
return true;
|
|
143
|
+
} catch {
|
|
144
|
+
process.stderr.write("Error: decryption failed \u2014 wrong key or corrupted file\n");
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
restore
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=restore-UH2UE2K5.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/commands/restore.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * `abtars restore` \u2014 restore from backup archive, auto-detect type.\n *\n * .abm \u2192 delegate to abmind restore\n * .zip/.7z \u2192 extract to ~/.abtars/ + find sibling .abm \u2192 restore both\n * .enc \u2192 find sibling .abm first (restore \u2192 key exists) \u2192 decrypt \u2192 extract\n * --config \u2192 zip only, skip abmind\n * --passphrase \u2192 passed through to abmind restore\n */\n\nimport { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join, dirname, basename } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport { createDecipheriv, hkdfSync } from \"node:crypto\";\nimport { abtarsHome } from \"../../paths.js\";\n\nexport interface RestoreOpts {\n config?: boolean;\n passphrase?: string;\n}\n\nexport async function restore(archivePath: string, opts: RestoreOpts = {}): Promise<number> {\n if (!archivePath) {\n process.stderr.write(\"Usage: abtars restore <file.zip|.7z|.abm|.enc> [--config] [--passphrase <p>]\\n\");\n return 1;\n }\n if (!existsSync(archivePath)) {\n process.stderr.write(`File not found: ${archivePath}\\n`);\n return 1;\n }\n\n // Direct .abm \u2192 delegate entirely to abmind restore\n if (archivePath.endsWith(\".abm\")) {\n return restoreAbmind(archivePath, opts.passphrase);\n }\n\n // .enc \u2192 restore sibling .abm first (ensures key exists), then decrypt\n if (archivePath.endsWith(\".enc\")) {\n // Find sibling .abm\n const date = extractDate(archivePath);\n const dir = dirname(archivePath);\n const sibling = findSiblingAbm(dir, date);\n\n if (!opts.config && sibling) {\n const rc = restoreAbmind(sibling, opts.passphrase);\n if (rc !== 0) return rc;\n }\n\n // Decrypt .enc \u2192 temp zip\n const abmindHome = process.env[\"ABMIND_HOME\"] ?? join(dirname(abtarsHome()), \".abmind\");\n const keyPath = join(abmindHome, \"secret\", \"abmind.key\");\n if (!existsSync(keyPath)) {\n process.stderr.write(\"Error: abmind.key not found \u2014 run `abmind restore <file.abm>` first to recreate it, then retry.\\n\");\n return 1;\n }\n\n const tmpZip = join(process.env[\"TMPDIR\"] ?? \"/tmp\", `abtars-restore-${Date.now()}.zip`);\n const ok = decryptFile(archivePath, tmpZip, keyPath);\n if (!ok) return 1;\n process.stdout.write(\"\u2713 decrypted\\n\");\n\n // Extract the decrypted zip\n const rc = extractZip(tmpZip, abtarsHome());\n try { unlinkSync(tmpZip); } catch { /* ignore */ }\n return rc;\n }\n\n // .zip/.7z\n if (!opts.config) {\n // Restore sibling .abm first\n const date = extractDate(archivePath);\n const dir = dirname(archivePath);\n const sibling = findSiblingAbm(dir, date);\n if (sibling) {\n const rc = restoreAbmind(sibling, opts.passphrase);\n if (rc !== 0) return rc;\n } else {\n process.stdout.write(\"\u2139 no sibling .abm found \u2014 memory not restored\\n\");\n }\n }\n\n // Extract zip to ~/.abtars/\n return extractZip(archivePath, abtarsHome());\n}\n\nfunction restoreAbmind(abmPath: string, passphrase?: string): number {\n const args = [\"restore\", \"--input\", abmPath, \"--mode\", \"merge\"];\n if (passphrase) args.push(\"--passphrase\", passphrase);\n\n const envPassphrase = process.env[\"ABMIND_BACKUP_PASSPHRASE\"];\n const env = { ...process.env };\n if (!passphrase && envPassphrase) {\n env[\"ABMIND_BACKUP_PASSPHRASE\"] = envPassphrase;\n }\n\n const result = spawnSync(\"abmind\", args, { encoding: \"utf-8\", stdio: \"inherit\", env });\n if (result.status !== 0) {\n process.stderr.write(\"abmind restore failed\\n\");\n return 1;\n }\n process.stdout.write(\"\u2713 abmind memory restored\\n\");\n return 0;\n}\n\nfunction extractZip(archivePath: string, destDir: string): number {\n const is7z = archivePath.endsWith(\".7z\");\n\n // Sanity check\n const listCmd = is7z\n ? spawnSync(\"7z\", [\"l\", archivePath], { encoding: \"utf-8\" })\n : spawnSync(\"unzip\", [\"-l\", archivePath], { encoding: \"utf-8\" });\n if (!listCmd.stdout?.includes(\"config/\")) {\n process.stderr.write(\"Error: archive does not contain config/ \u2014 not a valid abtars backup\\n\");\n return 1;\n }\n\n // Extract, excluding binary dirs + manifest (install state, not user data)\n let result;\n if (is7z) {\n result = spawnSync(\"7z\", [\"x\", `-o${destDir}`, \"-aoa\", \"-xr!releases\", \"-xr!current\", \"-xr!bin\", \"-xr!manifest.json\", archivePath],\n { encoding: \"utf-8\", stdio: \"inherit\" });\n } else {\n result = spawnSync(\"unzip\", [\"-o\", archivePath, \"-d\", destDir, \"-x\", \"releases/*\", \"current/*\", \"bin/*\", \"manifest.json\"],\n { encoding: \"utf-8\", stdio: \"inherit\" });\n }\n\n if (result.status !== 0) {\n process.stderr.write(\"Restore extract failed\\n\");\n return 1;\n }\n\n process.stdout.write(`\u2713 Restored to ${destDir}\\n`);\n return 0;\n}\n\nfunction extractDate(filePath: string): string | null {\n const name = basename(filePath);\n const match = name.match(/(\\d{4}-\\d{2}-\\d{2})/);\n return match?.[1] ?? null;\n}\n\nfunction findSiblingAbm(dir: string, date: string | null): string | null {\n if (!existsSync(dir)) return null;\n const files = readdirSync(dir).filter(f => f.endsWith(\".abm\"));\n if (date) {\n const exact = files.find(f => f.includes(date));\n if (exact) return join(dir, exact);\n }\n // Fallback: latest .abm in the dir\n const sorted = files.sort().reverse();\n return sorted[0] ? join(dir, sorted[0]) : null;\n}\n\nfunction decryptFile(inputPath: string, outputPath: string, keyPath: string): boolean {\n const master = Buffer.from(readFileSync(keyPath, \"utf-8\").trim(), \"hex\");\n const key = Buffer.from(hkdfSync(\"sha256\", master, \"\", \"abtars-backup-v1\", 32));\n\n const buf = readFileSync(inputPath);\n if (buf.length < 28) { // 12 iv + 16 tag minimum\n process.stderr.write(\"Error: encrypted file too small\\n\");\n return false;\n }\n\n const iv = buf.subarray(0, 12);\n const tag = buf.subarray(buf.length - 16);\n const ciphertext = buf.subarray(12, buf.length - 16);\n\n try {\n const decipher = createDecipheriv(\"aes-256-gcm\", key, iv);\n decipher.setAuthTag(tag);\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n writeFileSync(outputPath, decrypted);\n return true;\n } catch {\n process.stderr.write(\"Error: decryption failed \u2014 wrong key or corrupted file\\n\");\n return false;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["rc"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
|
|
3
|
+
import {
|
|
4
|
+
rollback
|
|
5
|
+
} from "./chunk-EZZBO2QK.js";
|
|
6
|
+
import "./chunk-JRK3UFBS.js";
|
|
7
|
+
import "./chunk-7K2YZTLD.js";
|
|
8
|
+
export {
|
|
9
|
+
rollback
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=rollback-D7AYTC7Z.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
createSleepHandle,
|
|
5
5
|
register
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7I5C2U3C.js";
|
|
7
7
|
import "./chunk-JAJ3DUQ2.js";
|
|
8
8
|
import "./chunk-BYDUMHXT.js";
|
|
9
9
|
import "./chunk-UDZIZB5F.js";
|
|
@@ -17,4 +17,4 @@ export {
|
|
|
17
17
|
createSleepHandle,
|
|
18
18
|
register
|
|
19
19
|
};
|
|
20
|
-
//# sourceMappingURL=sleep-
|
|
20
|
+
//# sourceMappingURL=sleep-IOWYTSMK.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
|
|
3
3
|
import {
|
|
4
4
|
buildSoulBundle
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-Q7F5R2LL.js";
|
|
6
6
|
import "./chunk-GBBTK6H2.js";
|
|
7
7
|
import "./chunk-EX2SRTUE.js";
|
|
8
8
|
import "./chunk-PZE3J7ER.js";
|
|
@@ -12,4 +12,4 @@ import "./chunk-7K2YZTLD.js";
|
|
|
12
12
|
export {
|
|
13
13
|
buildSoulBundle
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=soul-bundle-
|
|
15
|
+
//# sourceMappingURL=soul-bundle-AH5S3MVI.js.map
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import {
|
|
4
4
|
loadMinimalSoul,
|
|
5
5
|
loadSoulBundle
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-4YOTNYAE.js";
|
|
7
|
+
import "./chunk-Q7F5R2LL.js";
|
|
8
8
|
import "./chunk-GBBTK6H2.js";
|
|
9
9
|
import "./chunk-EX2SRTUE.js";
|
|
10
10
|
import "./chunk-PZE3J7ER.js";
|
|
@@ -15,4 +15,4 @@ export {
|
|
|
15
15
|
loadMinimalSoul,
|
|
16
16
|
loadSoulBundle
|
|
17
17
|
};
|
|
18
|
-
//# sourceMappingURL=soul-loader-
|
|
18
|
+
//# sourceMappingURL=soul-loader-N5FA4I6C.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
|
|
3
3
|
import {
|
|
4
4
|
SubagentRuntime
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-CNWXVXGH.js";
|
|
6
6
|
import "./chunk-EX2SRTUE.js";
|
|
7
7
|
import "./chunk-2BY6I4P5.js";
|
|
8
8
|
import "./chunk-MJ6PHMOK.js";
|
|
@@ -10,4 +10,4 @@ import "./chunk-7K2YZTLD.js";
|
|
|
10
10
|
export {
|
|
11
11
|
SubagentRuntime
|
|
12
12
|
};
|
|
13
|
-
//# sourceMappingURL=subagent-runtime-
|
|
13
|
+
//# sourceMappingURL=subagent-runtime-OOJXCKJF.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
init_update_check,
|
|
5
5
|
update_check_exports
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CU3O53U3.js";
|
|
7
7
|
import {
|
|
8
8
|
init_log_and_swallow,
|
|
9
9
|
logAndSwallow
|
|
@@ -81,7 +81,7 @@ async function getSystemStatus(ctx) {
|
|
|
81
81
|
}
|
|
82
82
|
let tasks = { recurring: 0, pending: 0, paused: 0 };
|
|
83
83
|
try {
|
|
84
|
-
const { readEntries } = await import("./task-store-
|
|
84
|
+
const { readEntries } = await import("./task-store-LC7ZMS72.js");
|
|
85
85
|
const entries = readEntries();
|
|
86
86
|
tasks = {
|
|
87
87
|
recurring: entries.filter((e) => e.schedule && !e.paused).length,
|
|
@@ -164,9 +164,16 @@ function renderStatusText(status) {
|
|
|
164
164
|
"\u{1F3E5} Subsystems:"
|
|
165
165
|
);
|
|
166
166
|
for (const s of status.subsystems) {
|
|
167
|
-
|
|
167
|
+
let icon = s.status === "ok" ? "\u2713" : s.status === "skipped" ? "\u25CB" : "\u2717";
|
|
168
168
|
const label = s.name.replace("phase", "").replace(/([A-Z])/g, " $1").trim().toLowerCase();
|
|
169
|
-
|
|
169
|
+
let detail = s.detail ? ` \u2014 ${s.detail}` : "";
|
|
170
|
+
if (s.status === "ok" && (s.name === "phaseMemory" || s.name === "phaseMemoryIpc")) {
|
|
171
|
+
const abmindManifest = join(homedir(), ".abmind", "manifest.json");
|
|
172
|
+
if (!existsSync(abmindManifest) && status.transportType === "acp") {
|
|
173
|
+
icon = "\u26A0\uFE0F";
|
|
174
|
+
if (s.name === "phaseMemory") detail = " \u2014 agent tools unavailable (install abmind)";
|
|
175
|
+
}
|
|
176
|
+
}
|
|
170
177
|
lines.push(` ${icon} ${label}${detail}`);
|
|
171
178
|
}
|
|
172
179
|
lines.push("");
|
|
@@ -187,4 +194,4 @@ export {
|
|
|
187
194
|
getSystemStatus,
|
|
188
195
|
renderStatusText
|
|
189
196
|
};
|
|
190
|
-
//# sourceMappingURL=system-status-
|
|
197
|
+
//# sourceMappingURL=system-status-4JP36OKC.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/components/system-status.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * system-status.ts \u2014 Single source of truth for bridge status.\n * One collector, many renderers. Used by /status (text), dashboard (HTML), future API (JSON).\n */\n\nimport { logAndSwallow } from \"./log-and-swallow.js\";\nimport { readFileSync, readlinkSync, existsSync } from \"node:fs\";\nimport { join, basename } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ServiceState } from \"./service-registry.js\";\n\nconst TAG = \"system_status\";\n\nexport interface SubsystemHealth {\n name: string;\n status: \"ok\" | \"failed\" | \"skipped\" | \"stopped\" | \"retrying\";\n detail?: string;\n}\n\nexport interface SystemStatus {\n version: string;\n commit: string;\n model: string;\n transportType: string;\n transportProvider: string;\n transportReady: boolean;\n uptimeMs: number;\n subsystems: SubsystemHealth[];\n tasks: { recurring: number; pending: number; paused: number };\n lastBackup: string | null;\n}\n\nexport interface StatusContext {\n phaseHealth: Map<string, { status: \"ok\" | \"failed\" | \"skipped\"; error?: string }>;\n registry: { getStates(): Record<string, ServiceState> };\n transport: { isReady: boolean } | null;\n startedAt: number;\n bridgeLockPath: string;\n heartbeat: { intervalMs: number } | null;\n}\n\nexport async function getSystemStatus(ctx: StatusContext): Promise<SystemStatus> {\n // Version + commit from release symlink\n let version = \"?\";\n let commit = \"?\";\n try {\n const target = basename(readlinkSync(join(homedir(), \".abtars\", \"current\")));\n const dash = target.lastIndexOf(\"-\");\n if (dash > 0) { version = target.slice(0, dash); commit = target.slice(dash + 1); }\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Model + transport\n let model = \"unknown\";\n let transportType = \"unknown\";\n let transportProvider = \"unknown\";\n try {\n const { loadTransport, resolveAgent } = await import(\"./transport-config.js\");\n const tc = loadTransport();\n const prof = tc ? resolveAgent(\"professor\", tc) : null;\n if (prof) {\n model = prof.model;\n transportType = (prof.provider.transport ?? \"acp\").toUpperCase();\n transportProvider = prof.providerName ?? \"unknown\";\n }\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Subsystem health: merge phaseHealth + ServiceRegistry live state\n const serviceStates = ctx.registry.getStates();\n const subsystems: SubsystemHealth[] = [];\n\n for (const [name, health] of ctx.phaseHealth) {\n const entry: SubsystemHealth = { name, status: health.status };\n\n // For platform services, override with live ServiceRegistry state\n const svcName = phaseToService(name);\n if (svcName && serviceStates[svcName]) {\n const svc = serviceStates[svcName] as ServiceState;\n if (health.status === \"ok\" && !svc.running) {\n entry.status = svc.retrying ? \"retrying\" : \"stopped\";\n }\n if (svc.retrying) {\n entry.detail = `retry #${svc.retrying.attempt}`;\n }\n }\n\n // Add contextual detail for specific phases\n if (name === \"phaseTransport\" && health.status === \"ok\" && ctx.transport) {\n entry.detail = `${transportType} (${transportProvider}), ${ctx.transport.isReady ? \"ready\" : \"not ready\"}`;\n }\n if (name === \"phaseHeartbeat\" && health.status === \"ok\" && ctx.heartbeat) {\n try {\n const lock = JSON.parse(readFileSync(ctx.bridgeLockPath, \"utf-8\"));\n const ago = Math.round((Date.now() - (lock.lastHeartbeat || 0)) / 60000);\n entry.detail = `${Math.round(ctx.heartbeat.intervalMs / 1000)}s, last tick ${ago}m ago`;\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n }\n if (name === \"phaseDashboard\" && health.status === \"ok\") {\n entry.detail = `:${process.env[\"WEB_PORT\"] || \"3000\"}`;\n }\n\n subsystems.push(entry);\n }\n\n // Tasks\n let tasks = { recurring: 0, pending: 0, paused: 0 };\n try {\n const { readEntries } = await import(\"./tasks/task-store.js\");\n const entries = readEntries();\n tasks = {\n recurring: entries.filter((e: any) => e.schedule && !e.paused).length,\n pending: entries.filter((e: any) => !e.fired && !e.schedule).length,\n paused: entries.filter((e: any) => e.paused).length,\n };\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Last backup\n let lastBackup: string | null = null;\n try {\n const { readdirSync } = await import(\"node:fs\");\n const bd = join(homedir(), \".backup-abtars\");\n const bk = readdirSync(bd).filter((f: string) => f.startsWith(\"abtars-\")).sort();\n if (bk.length > 0) lastBackup = bk[bk.length - 1] ?? null;\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n return {\n version,\n commit,\n model,\n transportType,\n transportProvider,\n transportReady: ctx.transport?.isReady ?? false,\n uptimeMs: Date.now() - ctx.startedAt,\n subsystems,\n tasks,\n lastBackup,\n };\n}\n\n/** Map phase names to ServiceRegistry service names (for live state merge). */\nfunction phaseToService(phaseName: string): string | null {\n switch (phaseName) {\n case \"phasePlatforms\": return null; // platforms registers telegram + discord separately\n case \"phaseDashboard\": return null;\n case \"phaseAgentApi\": return \"agent-api\";\n default: return null;\n }\n}\n\n/** Render SystemStatus as plain text for Telegram/Discord /status command. */\nexport function renderStatusText(status: SystemStatus): string {\n const uptime = formatUptime(status.uptimeMs);\n const lines: string[] = [\n `abTARS v${status.version} (${status.commit})`,\n ];\n\n // abmind version\n try {\n const abmindManifest = join(homedir(), \".abmind\", \"manifest.json\");\n if (existsSync(abmindManifest)) {\n const m = JSON.parse(readFileSync(abmindManifest, \"utf-8\"));\n const ver = m.version?.replace(/-[a-f0-9]{7,}$/, \"\") || null;\n const commit = m.commit?.slice(0, 7) ?? \"\";\n if (ver) {\n lines.push(`abmind v${ver}${commit ? ` (${commit})` : \"\"}`);\n } else {\n lines.push(\"abmind: installed (version unknown)\");\n }\n } else {\n lines.push(\"abmind: not installed\");\n }\n } catch (err) { logAndSwallow(TAG, \"read abmind manifest\", err); }\n\n // Update check (#440)\n try {\n const { checkForUpdate } = require(\"./update-check.js\") as typeof import(\"./update-check.js\");\n const result = checkForUpdate(\"abtars\", status.version);\n if (result?.updateAvailable) {\n lines.push(`\uD83D\uDCE6 Update available: ${result.current} \u2192 ${result.latest}`);\n }\n } catch (err) { logAndSwallow(TAG, \"update check\", err); }\n\n lines.push(\n `\uD83E\uDD16 Model: ${status.model}`,\n `\u23F1\uFE0F Uptime: ${uptime}`,\n \"\",\n \"\uD83C\uDFE5 Subsystems:\",\n );\n\n for (const s of status.subsystems) {\n
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * system-status.ts \u2014 Single source of truth for bridge status.\n * One collector, many renderers. Used by /status (text), dashboard (HTML), future API (JSON).\n */\n\nimport { logAndSwallow } from \"./log-and-swallow.js\";\nimport { readFileSync, readlinkSync, existsSync } from \"node:fs\";\nimport { join, basename } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ServiceState } from \"./service-registry.js\";\n\nconst TAG = \"system_status\";\n\nexport interface SubsystemHealth {\n name: string;\n status: \"ok\" | \"failed\" | \"skipped\" | \"stopped\" | \"retrying\";\n detail?: string;\n}\n\nexport interface SystemStatus {\n version: string;\n commit: string;\n model: string;\n transportType: string;\n transportProvider: string;\n transportReady: boolean;\n uptimeMs: number;\n subsystems: SubsystemHealth[];\n tasks: { recurring: number; pending: number; paused: number };\n lastBackup: string | null;\n}\n\nexport interface StatusContext {\n phaseHealth: Map<string, { status: \"ok\" | \"failed\" | \"skipped\"; error?: string }>;\n registry: { getStates(): Record<string, ServiceState> };\n transport: { isReady: boolean } | null;\n startedAt: number;\n bridgeLockPath: string;\n heartbeat: { intervalMs: number } | null;\n}\n\nexport async function getSystemStatus(ctx: StatusContext): Promise<SystemStatus> {\n // Version + commit from release symlink\n let version = \"?\";\n let commit = \"?\";\n try {\n const target = basename(readlinkSync(join(homedir(), \".abtars\", \"current\")));\n const dash = target.lastIndexOf(\"-\");\n if (dash > 0) { version = target.slice(0, dash); commit = target.slice(dash + 1); }\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Model + transport\n let model = \"unknown\";\n let transportType = \"unknown\";\n let transportProvider = \"unknown\";\n try {\n const { loadTransport, resolveAgent } = await import(\"./transport-config.js\");\n const tc = loadTransport();\n const prof = tc ? resolveAgent(\"professor\", tc) : null;\n if (prof) {\n model = prof.model;\n transportType = (prof.provider.transport ?? \"acp\").toUpperCase();\n transportProvider = prof.providerName ?? \"unknown\";\n }\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Subsystem health: merge phaseHealth + ServiceRegistry live state\n const serviceStates = ctx.registry.getStates();\n const subsystems: SubsystemHealth[] = [];\n\n for (const [name, health] of ctx.phaseHealth) {\n const entry: SubsystemHealth = { name, status: health.status };\n\n // For platform services, override with live ServiceRegistry state\n const svcName = phaseToService(name);\n if (svcName && serviceStates[svcName]) {\n const svc = serviceStates[svcName] as ServiceState;\n if (health.status === \"ok\" && !svc.running) {\n entry.status = svc.retrying ? \"retrying\" : \"stopped\";\n }\n if (svc.retrying) {\n entry.detail = `retry #${svc.retrying.attempt}`;\n }\n }\n\n // Add contextual detail for specific phases\n if (name === \"phaseTransport\" && health.status === \"ok\" && ctx.transport) {\n entry.detail = `${transportType} (${transportProvider}), ${ctx.transport.isReady ? \"ready\" : \"not ready\"}`;\n }\n if (name === \"phaseHeartbeat\" && health.status === \"ok\" && ctx.heartbeat) {\n try {\n const lock = JSON.parse(readFileSync(ctx.bridgeLockPath, \"utf-8\"));\n const ago = Math.round((Date.now() - (lock.lastHeartbeat || 0)) / 60000);\n entry.detail = `${Math.round(ctx.heartbeat.intervalMs / 1000)}s, last tick ${ago}m ago`;\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n }\n if (name === \"phaseDashboard\" && health.status === \"ok\") {\n entry.detail = `:${process.env[\"WEB_PORT\"] || \"3000\"}`;\n }\n\n subsystems.push(entry);\n }\n\n // Tasks\n let tasks = { recurring: 0, pending: 0, paused: 0 };\n try {\n const { readEntries } = await import(\"./tasks/task-store.js\");\n const entries = readEntries();\n tasks = {\n recurring: entries.filter((e: any) => e.schedule && !e.paused).length,\n pending: entries.filter((e: any) => !e.fired && !e.schedule).length,\n paused: entries.filter((e: any) => e.paused).length,\n };\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n // Last backup\n let lastBackup: string | null = null;\n try {\n const { readdirSync } = await import(\"node:fs\");\n const bd = join(homedir(), \".backup-abtars\");\n const bk = readdirSync(bd).filter((f: string) => f.startsWith(\"abtars-\")).sort();\n if (bk.length > 0) lastBackup = bk[bk.length - 1] ?? null;\n } catch (err) { logAndSwallow(\"system_status\", \"op\", err); }\n\n return {\n version,\n commit,\n model,\n transportType,\n transportProvider,\n transportReady: ctx.transport?.isReady ?? false,\n uptimeMs: Date.now() - ctx.startedAt,\n subsystems,\n tasks,\n lastBackup,\n };\n}\n\n/** Map phase names to ServiceRegistry service names (for live state merge). */\nfunction phaseToService(phaseName: string): string | null {\n switch (phaseName) {\n case \"phasePlatforms\": return null; // platforms registers telegram + discord separately\n case \"phaseDashboard\": return null;\n case \"phaseAgentApi\": return \"agent-api\";\n default: return null;\n }\n}\n\n/** Render SystemStatus as plain text for Telegram/Discord /status command. */\nexport function renderStatusText(status: SystemStatus): string {\n const uptime = formatUptime(status.uptimeMs);\n const lines: string[] = [\n `abTARS v${status.version} (${status.commit})`,\n ];\n\n // abmind version\n try {\n const abmindManifest = join(homedir(), \".abmind\", \"manifest.json\");\n if (existsSync(abmindManifest)) {\n const m = JSON.parse(readFileSync(abmindManifest, \"utf-8\"));\n const ver = m.version?.replace(/-[a-f0-9]{7,}$/, \"\") || null;\n const commit = m.commit?.slice(0, 7) ?? \"\";\n if (ver) {\n lines.push(`abmind v${ver}${commit ? ` (${commit})` : \"\"}`);\n } else {\n lines.push(\"abmind: installed (version unknown)\");\n }\n } else {\n lines.push(\"abmind: not installed\");\n }\n } catch (err) { logAndSwallow(TAG, \"read abmind manifest\", err); }\n\n // Update check (#440)\n try {\n const { checkForUpdate } = require(\"./update-check.js\") as typeof import(\"./update-check.js\");\n const result = checkForUpdate(\"abtars\", status.version);\n if (result?.updateAvailable) {\n lines.push(`\uD83D\uDCE6 Update available: ${result.current} \u2192 ${result.latest}`);\n }\n } catch (err) { logAndSwallow(TAG, \"update check\", err); }\n\n lines.push(\n `\uD83E\uDD16 Model: ${status.model}`,\n `\u23F1\uFE0F Uptime: ${uptime}`,\n \"\",\n \"\uD83C\uDFE5 Subsystems:\",\n );\n\n for (const s of status.subsystems) {\n let icon = s.status === \"ok\" ? \"\u2713\" : s.status === \"skipped\" ? \"\u25CB\" : \"\u2717\";\n const label = s.name.replace(\"phase\", \"\").replace(/([A-Z])/g, \" $1\").trim().toLowerCase();\n let detail = s.detail ? ` \u2014 ${s.detail}` : \"\";\n\n // #799: warn if memory is \"ok\" but abmind CLI unavailable (ACP transport only)\n if (s.status === \"ok\" && (s.name === \"phaseMemory\" || s.name === \"phaseMemoryIpc\")) {\n const abmindManifest = join(homedir(), \".abmind\", \"manifest.json\");\n if (!existsSync(abmindManifest) && status.transportType === \"acp\") {\n icon = \"\u26A0\uFE0F\";\n if (s.name === \"phaseMemory\") detail = \" \u2014 agent tools unavailable (install abmind)\";\n }\n }\n\n lines.push(` ${icon} ${label}${detail}`);\n }\n\n lines.push(\"\");\n lines.push(`\u23F0 Tasks: ${status.tasks.recurring} recurring, ${status.tasks.pending} pending${status.tasks.paused ? `, ${status.tasks.paused} paused` : \"\"}`);\n if (status.lastBackup) lines.push(`\uD83D\uDCBE Last backup: ${status.lastBackup}`);\n\n return lines.join(\"\\n\");\n}\n\nfunction formatUptime(ms: number): string {\n const s = Math.floor(ms / 1000);\n const m = Math.floor(s / 60) % 60;\n const h = Math.floor(s / 3600) % 24;\n const d = Math.floor(s / 86400);\n if (d > 0) return `${d}d ${h}h ${m}m`;\n if (h > 0) return `${h}h ${m}m`;\n return `${m}m`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
recordRun,
|
|
8
8
|
removeEntry,
|
|
9
9
|
writeEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GPL57SRN.js";
|
|
11
11
|
import "./chunk-EX2SRTUE.js";
|
|
12
12
|
import "./chunk-2BY6I4P5.js";
|
|
13
13
|
import "./chunk-MJ6PHMOK.js";
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
removeEntry,
|
|
21
21
|
writeEntry
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=task-store-
|
|
23
|
+
//# sourceMappingURL=task-store-LC7ZMS72.js.map
|
|
@@ -12,19 +12,19 @@ import {
|
|
|
12
12
|
handleInboundMessage,
|
|
13
13
|
resetAndPrepare,
|
|
14
14
|
routeReaction
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HZRUBJ4Q.js";
|
|
16
16
|
import "./chunk-NIRYBWUW.js";
|
|
17
17
|
import "./chunk-3MO2MDXJ.js";
|
|
18
18
|
import "./chunk-RV54J75Q.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-4YOTNYAE.js";
|
|
20
|
+
import "./chunk-Q7F5R2LL.js";
|
|
21
21
|
import {
|
|
22
22
|
loadUsers
|
|
23
23
|
} from "./chunk-GBBTK6H2.js";
|
|
24
24
|
import "./chunk-JAJ3DUQ2.js";
|
|
25
25
|
import "./chunk-G6IXMYIO.js";
|
|
26
26
|
import "./chunk-UDZIZB5F.js";
|
|
27
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-GPL57SRN.js";
|
|
28
28
|
import "./chunk-MZWMYN4O.js";
|
|
29
29
|
import {
|
|
30
30
|
init_log_and_swallow,
|
|
@@ -1059,4 +1059,4 @@ export {
|
|
|
1059
1059
|
TELEGRAM_CAPABILITIES,
|
|
1060
1060
|
TelegramAdapter
|
|
1061
1061
|
};
|
|
1062
|
-
//# sourceMappingURL=telegram-adapter-
|
|
1062
|
+
//# sourceMappingURL=telegram-adapter-QXHJQLLX.js.map
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import {
|
|
4
4
|
checkForUpdate,
|
|
5
5
|
init_update_check
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CU3O53U3.js";
|
|
7
7
|
import "./chunk-MJ6PHMOK.js";
|
|
8
8
|
import "./chunk-7K2YZTLD.js";
|
|
9
9
|
init_update_check();
|
|
10
10
|
export {
|
|
11
11
|
checkForUpdate
|
|
12
12
|
};
|
|
13
|
-
//# sourceMappingURL=update-check-
|
|
13
|
+
//# sourceMappingURL=update-check-XVY2IK2L.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rss
|
|
3
|
+
description: Fetch RSS/Atom feeds via abtars-rss CLI. Use when a task needs to pull news, articles, or structured feed data.
|
|
4
|
+
requires:
|
|
5
|
+
bins: [abtars-rss]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# RSS Feed Fetcher
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
abtars-rss --feeds <path-to-feeds.json> [--hours N]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- `--feeds` (required): path to a JSON file containing feed configs
|
|
17
|
+
- `--hours` (optional, default 24): only include items from the last N hours
|
|
18
|
+
|
|
19
|
+
## Feeds file format
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
[
|
|
23
|
+
{ "url": "https://example.com/rss", "name": "Example Feed" },
|
|
24
|
+
{ "url": "https://other.com/atom.xml", "name": "Other Feed", "keywords": ["AI", "finance"] }
|
|
25
|
+
]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `url`: RSS/Atom feed URL (or SEC EDGAR JSON endpoint)
|
|
29
|
+
- `name`: display name for the source
|
|
30
|
+
- `keywords` (optional): only keep items matching these keywords
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
Writes to `~/.abtars/workspace/rss/<feedname>/<date>.json` and prints JSON to stdout.
|
|
35
|
+
|
|
36
|
+
## Task integration
|
|
37
|
+
|
|
38
|
+
Place your feeds file alongside your task with the `_feeds.json` suffix:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
tasks/
|
|
42
|
+
daily-ai-report.md
|
|
43
|
+
daily-ai-report_feeds.json ← auto-injected into task context
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
In your task `.md`, instruct: "Run `abtars-rss --feeds tasks/daily-ai-report_feeds.json`"
|
|
47
|
+
|
|
48
|
+
## Do not
|
|
49
|
+
|
|
50
|
+
- Do not hardcode feed URLs in task instructions — put them in the `_feeds.json` file
|
|
51
|
+
- Do not parse HTML pages with this tool — it only handles RSS/Atom XML and SEC EDGAR JSON
|
package/install-manifest.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"path": "bin"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"path": "
|
|
18
|
+
"path": "app"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
"path": "skills/core"
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
"source": "tasks.default.json",
|
|
77
|
-
"dest": "
|
|
77
|
+
"dest": "tasks/tasks.json"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"source": "config/peers.json.example",
|
|
@@ -126,7 +126,8 @@
|
|
|
126
126
|
"abtars-browser",
|
|
127
127
|
"abtars-restart",
|
|
128
128
|
"abtars-task",
|
|
129
|
-
"abtars-tweet"
|
|
129
|
+
"abtars-tweet",
|
|
130
|
+
"abtars-todo"
|
|
130
131
|
],
|
|
131
132
|
"postInstall": [
|
|
132
133
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abtars",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-alpha.10",
|
|
4
4
|
"description": "Standalone agent bridging Telegram to Kiro CLI via tmux/ACP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bundle/abtars.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"start": "node dist/main.js",
|
|
12
12
|
"typecheck": "tsc --noEmit",
|
|
13
13
|
"check-imports": "bash -c '! grep -rE \"from \\\"abmind/|from '\\''abmind/\" src --include=*.ts | grep -vE \"abmind/deploy-lib\\\"|abmind/deploy-lib'\\''\"'",
|
|
14
|
-
"test": "vitest --run",
|
|
14
|
+
"test": "vitest --run && node src/cli/commands/install-smoke.mjs",
|
|
15
15
|
"test:watch": "vitest",
|
|
16
16
|
"prepublishOnly": "node -e \"const p=require('./package.json');const d=JSON.stringify(p.dependencies||{});if(d.includes('file:')){console.error('ERROR: file: dependency found');process.exit(1)}\""
|
|
17
17
|
},
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"@types/node": "^22.19.17",
|
|
26
26
|
"@types/pdf-parse": "^1.1.5",
|
|
27
27
|
"@types/ws": "^8.18.1",
|
|
28
|
-
"abmind": "file:../abmind",
|
|
29
28
|
"cron-parser": "^5.5.0",
|
|
30
29
|
"discord.js": "^14.26.3",
|
|
31
30
|
"dotenv": "^16.6.1",
|
|
@@ -57,4 +56,4 @@
|
|
|
57
56
|
"install-manifest.json",
|
|
58
57
|
"config/"
|
|
59
58
|
]
|
|
60
|
-
}
|
|
59
|
+
}
|
package/scripts/abtars.sh
CHANGED
|
@@ -3,12 +3,10 @@
|
|
|
3
3
|
set -euo pipefail
|
|
4
4
|
|
|
5
5
|
ABTARS_HOME="${ABTARS_HOME:-$HOME/.abtars}"
|
|
6
|
-
CURRENT="$ABTARS_HOME/current/bundle"
|
|
7
6
|
|
|
8
|
-
# Make
|
|
9
|
-
GLOBAL_MODULES="$(npm root -g 2>/dev/null || true)"
|
|
7
|
+
# Make native addons (better-sqlite3) resolvable
|
|
10
8
|
ABMIND_LIB="${ABMIND_HOME:-$HOME/.abmind}/lib/node_modules"
|
|
11
|
-
NODE_PATH="${
|
|
9
|
+
NODE_PATH="${ABMIND_LIB:+$ABMIND_LIB:}${NODE_PATH:-}"
|
|
12
10
|
export NODE_PATH
|
|
13
11
|
|
|
14
|
-
exec node "$
|
|
12
|
+
exec node "$ABTARS_HOME/app/bundle/abtars.js" "$@"
|