@askexenow/exe-os 0.9.53 → 0.9.55
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/dist/bin/backfill-conversations.js +103 -0
- package/dist/bin/backfill-responses.js +103 -0
- package/dist/bin/backfill-vectors.js +103 -0
- package/dist/bin/cleanup-stale-review-tasks.js +103 -0
- package/dist/bin/cli.js +121 -10
- package/dist/bin/exe-assign.js +103 -0
- package/dist/bin/exe-boot.js +96 -10
- package/dist/bin/exe-call.js +25 -0
- package/dist/bin/exe-cloud.js +31 -10
- package/dist/bin/exe-dispatch.js +103 -0
- package/dist/bin/exe-doctor.js +152 -3
- package/dist/bin/exe-export-behaviors.js +103 -0
- package/dist/bin/exe-forget.js +103 -0
- package/dist/bin/exe-gateway.js +103 -0
- package/dist/bin/exe-heartbeat.js +103 -0
- package/dist/bin/exe-kill.js +103 -0
- package/dist/bin/exe-launch-agent.js +103 -0
- package/dist/bin/exe-link.js +31 -10
- package/dist/bin/exe-new-employee.js +25 -0
- package/dist/bin/exe-pending-messages.js +103 -0
- package/dist/bin/exe-pending-notifications.js +103 -0
- package/dist/bin/exe-pending-reviews.js +103 -0
- package/dist/bin/exe-rename.js +103 -0
- package/dist/bin/exe-review.js +103 -0
- package/dist/bin/exe-search.js +103 -0
- package/dist/bin/exe-session-cleanup.js +103 -0
- package/dist/bin/exe-start-codex.js +103 -0
- package/dist/bin/exe-start-opencode.js +103 -0
- package/dist/bin/exe-status.js +103 -0
- package/dist/bin/exe-team.js +103 -0
- package/dist/bin/git-sweep.js +103 -0
- package/dist/bin/graph-backfill.js +103 -0
- package/dist/bin/graph-export.js +103 -0
- package/dist/bin/intercom-check.js +103 -0
- package/dist/bin/scan-tasks.js +103 -0
- package/dist/bin/setup.js +56 -10
- package/dist/bin/shard-migrate.js +103 -0
- package/dist/gateway/index.js +103 -0
- package/dist/hooks/bug-report-worker.js +103 -0
- package/dist/hooks/codex-stop-task-finalizer.js +103 -0
- package/dist/hooks/commit-complete.js +103 -0
- package/dist/hooks/error-recall.js +103 -0
- package/dist/hooks/ingest.js +103 -0
- package/dist/hooks/instructions-loaded.js +103 -0
- package/dist/hooks/notification.js +103 -0
- package/dist/hooks/post-compact.js +103 -0
- package/dist/hooks/post-tool-combined.js +103 -0
- package/dist/hooks/pre-compact.js +103 -0
- package/dist/hooks/pre-tool-use.js +103 -0
- package/dist/hooks/prompt-submit.js +103 -0
- package/dist/hooks/session-end.js +103 -0
- package/dist/hooks/session-start.js +103 -0
- package/dist/hooks/stop.js +103 -0
- package/dist/hooks/subagent-stop.js +103 -0
- package/dist/hooks/summary-worker.js +96 -10
- package/dist/index.js +103 -0
- package/dist/lib/cloud-sync.js +31 -10
- package/dist/lib/employee-templates.js +25 -0
- package/dist/lib/exe-daemon.js +165 -14
- package/dist/lib/hybrid-search.js +103 -0
- package/dist/lib/keychain.js +31 -10
- package/dist/lib/schedules.js +103 -0
- package/dist/lib/store.js +103 -0
- package/dist/mcp/server.js +164 -13
- package/dist/runtime/index.js +103 -0
- package/dist/tui/App.js +96 -10
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -6686,6 +6686,15 @@ function readMachineId() {
|
|
|
6686
6686
|
return "";
|
|
6687
6687
|
}
|
|
6688
6688
|
}
|
|
6689
|
+
function encryptWithMachineKey(plaintext, machineKey) {
|
|
6690
|
+
const crypto8 = __require("crypto");
|
|
6691
|
+
const iv = crypto8.randomBytes(12);
|
|
6692
|
+
const cipher = crypto8.createCipheriv("aes-256-gcm", machineKey, iv);
|
|
6693
|
+
let encrypted = cipher.update(plaintext, "utf-8", "base64");
|
|
6694
|
+
encrypted += cipher.final("base64");
|
|
6695
|
+
const authTag = cipher.getAuthTag().toString("base64");
|
|
6696
|
+
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${authTag}:${encrypted}`;
|
|
6697
|
+
}
|
|
6689
6698
|
function decryptWithMachineKey(encrypted, machineKey) {
|
|
6690
6699
|
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
6691
6700
|
try {
|
|
@@ -6704,6 +6713,21 @@ function decryptWithMachineKey(encrypted, machineKey) {
|
|
|
6704
6713
|
return null;
|
|
6705
6714
|
}
|
|
6706
6715
|
}
|
|
6716
|
+
async function writeMachineBoundFileFallback(b64) {
|
|
6717
|
+
const dir = getKeyDir();
|
|
6718
|
+
await mkdir4(dir, { recursive: true });
|
|
6719
|
+
const keyPath = getKeyPath();
|
|
6720
|
+
const machineKey = deriveMachineKey();
|
|
6721
|
+
if (machineKey) {
|
|
6722
|
+
const encrypted = encryptWithMachineKey(b64, machineKey);
|
|
6723
|
+
await writeFile5(keyPath, encrypted + "\n", "utf-8");
|
|
6724
|
+
await chmod2(keyPath, 384);
|
|
6725
|
+
return "encrypted";
|
|
6726
|
+
}
|
|
6727
|
+
await writeFile5(keyPath, b64 + "\n", "utf-8");
|
|
6728
|
+
await chmod2(keyPath, 384);
|
|
6729
|
+
return "plaintext";
|
|
6730
|
+
}
|
|
6707
6731
|
async function getMasterKey() {
|
|
6708
6732
|
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
6709
6733
|
if (nativeValue) {
|
|
@@ -6755,6 +6779,20 @@ async function getMasterKey() {
|
|
|
6755
6779
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
6756
6780
|
if (migrated) {
|
|
6757
6781
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
6782
|
+
try {
|
|
6783
|
+
await unlink(keyPath);
|
|
6784
|
+
process.stderr.write("[keychain] Removed legacy master.key file after native keychain migration.\n");
|
|
6785
|
+
} catch {
|
|
6786
|
+
}
|
|
6787
|
+
} else if (!content.startsWith(ENCRYPTED_PREFIX)) {
|
|
6788
|
+
const fallback = await writeMachineBoundFileFallback(b64Value);
|
|
6789
|
+
if (fallback === "encrypted") {
|
|
6790
|
+
process.stderr.write("[keychain] Upgraded legacy plaintext master.key to machine-bound encrypted fallback.\n");
|
|
6791
|
+
} else {
|
|
6792
|
+
process.stderr.write(
|
|
6793
|
+
"[keychain] WARNING: Could not encrypt legacy master.key \u2014 plaintext fallback remains.\n"
|
|
6794
|
+
);
|
|
6795
|
+
}
|
|
6758
6796
|
}
|
|
6759
6797
|
return key;
|
|
6760
6798
|
} catch (err) {
|
|
@@ -6972,6 +7010,7 @@ var init_memory_write_governor = __esm({
|
|
|
6972
7010
|
// src/lib/shard-manager.ts
|
|
6973
7011
|
var shard_manager_exports = {};
|
|
6974
7012
|
__export(shard_manager_exports, {
|
|
7013
|
+
auditShardHealth: () => auditShardHealth,
|
|
6975
7014
|
disposeShards: () => disposeShards,
|
|
6976
7015
|
ensureShardSchema: () => ensureShardSchema,
|
|
6977
7016
|
getOpenShardCount: () => getOpenShardCount,
|
|
@@ -7038,6 +7077,70 @@ function listShards() {
|
|
|
7038
7077
|
if (!existsSync16(SHARDS_DIR)) return [];
|
|
7039
7078
|
return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7040
7079
|
}
|
|
7080
|
+
async function auditShardHealth(options = {}) {
|
|
7081
|
+
if (!_encryptionKey) {
|
|
7082
|
+
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
7083
|
+
}
|
|
7084
|
+
const repair = options.repair === true;
|
|
7085
|
+
const dryRun = options.dryRun === true;
|
|
7086
|
+
const names = listShards();
|
|
7087
|
+
const shards = [];
|
|
7088
|
+
for (const name of names) {
|
|
7089
|
+
const dbPath = path20.join(SHARDS_DIR, `${name}.db`);
|
|
7090
|
+
const stat = statSync2(dbPath);
|
|
7091
|
+
const item = {
|
|
7092
|
+
name,
|
|
7093
|
+
path: dbPath,
|
|
7094
|
+
ok: false,
|
|
7095
|
+
unreadable: false,
|
|
7096
|
+
error: null,
|
|
7097
|
+
size: stat.size,
|
|
7098
|
+
mtime: stat.mtime.toISOString(),
|
|
7099
|
+
memoryCount: null
|
|
7100
|
+
};
|
|
7101
|
+
const client = createClient2({
|
|
7102
|
+
url: `file:${dbPath}`,
|
|
7103
|
+
encryptionKey: _encryptionKey
|
|
7104
|
+
});
|
|
7105
|
+
try {
|
|
7106
|
+
await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
|
|
7107
|
+
const hasMemories = await client.execute(
|
|
7108
|
+
"SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
|
|
7109
|
+
);
|
|
7110
|
+
if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
|
|
7111
|
+
const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
7112
|
+
item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
|
|
7113
|
+
}
|
|
7114
|
+
item.ok = true;
|
|
7115
|
+
} catch (err) {
|
|
7116
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7117
|
+
item.error = message;
|
|
7118
|
+
item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
|
|
7119
|
+
if (item.unreadable && repair && !dryRun) {
|
|
7120
|
+
client.close();
|
|
7121
|
+
_shards.delete(name);
|
|
7122
|
+
_shardLastAccess.delete(name);
|
|
7123
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7124
|
+
const archivedPath = path20.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
7125
|
+
renameSync4(dbPath, archivedPath);
|
|
7126
|
+
item.archivedPath = archivedPath;
|
|
7127
|
+
}
|
|
7128
|
+
} finally {
|
|
7129
|
+
try {
|
|
7130
|
+
client.close();
|
|
7131
|
+
} catch {
|
|
7132
|
+
}
|
|
7133
|
+
}
|
|
7134
|
+
shards.push(item);
|
|
7135
|
+
}
|
|
7136
|
+
return {
|
|
7137
|
+
total: shards.length,
|
|
7138
|
+
ok: shards.filter((s) => s.ok).length,
|
|
7139
|
+
unreadable: shards.filter((s) => s.unreadable).length,
|
|
7140
|
+
archived: shards.filter((s) => Boolean(s.archivedPath)).length,
|
|
7141
|
+
shards
|
|
7142
|
+
};
|
|
7143
|
+
}
|
|
7041
7144
|
async function ensureShardSchema(client) {
|
|
7042
7145
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
7043
7146
|
await client.execute("PRAGMA busy_timeout = 30000");
|
package/dist/tui/App.js
CHANGED
|
@@ -10555,6 +10555,21 @@ function decryptWithMachineKey(encrypted, machineKey) {
|
|
|
10555
10555
|
return null;
|
|
10556
10556
|
}
|
|
10557
10557
|
}
|
|
10558
|
+
async function writeMachineBoundFileFallback(b64) {
|
|
10559
|
+
const dir = getKeyDir();
|
|
10560
|
+
await mkdir4(dir, { recursive: true });
|
|
10561
|
+
const keyPath = getKeyPath();
|
|
10562
|
+
const machineKey = deriveMachineKey();
|
|
10563
|
+
if (machineKey) {
|
|
10564
|
+
const encrypted = encryptWithMachineKey(b64, machineKey);
|
|
10565
|
+
await writeFile5(keyPath, encrypted + "\n", "utf-8");
|
|
10566
|
+
await chmod2(keyPath, 384);
|
|
10567
|
+
return "encrypted";
|
|
10568
|
+
}
|
|
10569
|
+
await writeFile5(keyPath, b64 + "\n", "utf-8");
|
|
10570
|
+
await chmod2(keyPath, 384);
|
|
10571
|
+
return "plaintext";
|
|
10572
|
+
}
|
|
10558
10573
|
async function getMasterKey() {
|
|
10559
10574
|
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
10560
10575
|
if (nativeValue) {
|
|
@@ -10606,6 +10621,20 @@ async function getMasterKey() {
|
|
|
10606
10621
|
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
10607
10622
|
if (migrated) {
|
|
10608
10623
|
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
10624
|
+
try {
|
|
10625
|
+
await unlink(keyPath);
|
|
10626
|
+
process.stderr.write("[keychain] Removed legacy master.key file after native keychain migration.\n");
|
|
10627
|
+
} catch {
|
|
10628
|
+
}
|
|
10629
|
+
} else if (!content.startsWith(ENCRYPTED_PREFIX)) {
|
|
10630
|
+
const fallback = await writeMachineBoundFileFallback(b64Value);
|
|
10631
|
+
if (fallback === "encrypted") {
|
|
10632
|
+
process.stderr.write("[keychain] Upgraded legacy plaintext master.key to machine-bound encrypted fallback.\n");
|
|
10633
|
+
} else {
|
|
10634
|
+
process.stderr.write(
|
|
10635
|
+
"[keychain] WARNING: Could not encrypt legacy master.key \u2014 plaintext fallback remains.\n"
|
|
10636
|
+
);
|
|
10637
|
+
}
|
|
10609
10638
|
}
|
|
10610
10639
|
return key;
|
|
10611
10640
|
} catch (err) {
|
|
@@ -10629,18 +10658,10 @@ async function setMasterKey(key) {
|
|
|
10629
10658
|
} catch {
|
|
10630
10659
|
}
|
|
10631
10660
|
}
|
|
10632
|
-
const
|
|
10633
|
-
|
|
10634
|
-
const keyPath = getKeyPath();
|
|
10635
|
-
const machineKey = deriveMachineKey();
|
|
10636
|
-
if (machineKey) {
|
|
10637
|
-
const encrypted = encryptWithMachineKey(b64, machineKey);
|
|
10638
|
-
await writeFile5(keyPath, encrypted + "\n", "utf-8");
|
|
10639
|
-
await chmod2(keyPath, 384);
|
|
10661
|
+
const fallback = await writeMachineBoundFileFallback(b64);
|
|
10662
|
+
if (fallback === "encrypted") {
|
|
10640
10663
|
process.stderr.write("[keychain] Key stored encrypted (machine-bound).\n");
|
|
10641
10664
|
} else {
|
|
10642
|
-
await writeFile5(keyPath, b64 + "\n", "utf-8");
|
|
10643
|
-
await chmod2(keyPath, 384);
|
|
10644
10665
|
process.stderr.write(
|
|
10645
10666
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
10646
10667
|
);
|
|
@@ -11288,6 +11309,7 @@ var init_memory_write_governor = __esm({
|
|
|
11288
11309
|
// src/lib/shard-manager.ts
|
|
11289
11310
|
var shard_manager_exports = {};
|
|
11290
11311
|
__export(shard_manager_exports, {
|
|
11312
|
+
auditShardHealth: () => auditShardHealth,
|
|
11291
11313
|
disposeShards: () => disposeShards,
|
|
11292
11314
|
ensureShardSchema: () => ensureShardSchema,
|
|
11293
11315
|
getOpenShardCount: () => getOpenShardCount,
|
|
@@ -11354,6 +11376,70 @@ function listShards() {
|
|
|
11354
11376
|
if (!existsSync17(SHARDS_DIR)) return [];
|
|
11355
11377
|
return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
11356
11378
|
}
|
|
11379
|
+
async function auditShardHealth(options = {}) {
|
|
11380
|
+
if (!_encryptionKey) {
|
|
11381
|
+
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
11382
|
+
}
|
|
11383
|
+
const repair = options.repair === true;
|
|
11384
|
+
const dryRun = options.dryRun === true;
|
|
11385
|
+
const names = listShards();
|
|
11386
|
+
const shards = [];
|
|
11387
|
+
for (const name of names) {
|
|
11388
|
+
const dbPath = path27.join(SHARDS_DIR, `${name}.db`);
|
|
11389
|
+
const stat = statSync2(dbPath);
|
|
11390
|
+
const item = {
|
|
11391
|
+
name,
|
|
11392
|
+
path: dbPath,
|
|
11393
|
+
ok: false,
|
|
11394
|
+
unreadable: false,
|
|
11395
|
+
error: null,
|
|
11396
|
+
size: stat.size,
|
|
11397
|
+
mtime: stat.mtime.toISOString(),
|
|
11398
|
+
memoryCount: null
|
|
11399
|
+
};
|
|
11400
|
+
const client = createClient2({
|
|
11401
|
+
url: `file:${dbPath}`,
|
|
11402
|
+
encryptionKey: _encryptionKey
|
|
11403
|
+
});
|
|
11404
|
+
try {
|
|
11405
|
+
await client.execute("SELECT COUNT(*) as cnt FROM sqlite_schema");
|
|
11406
|
+
const hasMemories = await client.execute(
|
|
11407
|
+
"SELECT COUNT(*) as cnt FROM sqlite_schema WHERE type = 'table' AND name = 'memories'"
|
|
11408
|
+
);
|
|
11409
|
+
if (Number(hasMemories.rows[0]?.cnt ?? 0) > 0) {
|
|
11410
|
+
const mem = await client.execute("SELECT COUNT(*) as cnt FROM memories");
|
|
11411
|
+
item.memoryCount = Number(mem.rows[0]?.cnt ?? 0);
|
|
11412
|
+
}
|
|
11413
|
+
item.ok = true;
|
|
11414
|
+
} catch (err) {
|
|
11415
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11416
|
+
item.error = message;
|
|
11417
|
+
item.unreadable = /SQLITE_NOTADB|file is not a database/i.test(message);
|
|
11418
|
+
if (item.unreadable && repair && !dryRun) {
|
|
11419
|
+
client.close();
|
|
11420
|
+
_shards.delete(name);
|
|
11421
|
+
_shardLastAccess.delete(name);
|
|
11422
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
11423
|
+
const archivedPath = path27.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
11424
|
+
renameSync4(dbPath, archivedPath);
|
|
11425
|
+
item.archivedPath = archivedPath;
|
|
11426
|
+
}
|
|
11427
|
+
} finally {
|
|
11428
|
+
try {
|
|
11429
|
+
client.close();
|
|
11430
|
+
} catch {
|
|
11431
|
+
}
|
|
11432
|
+
}
|
|
11433
|
+
shards.push(item);
|
|
11434
|
+
}
|
|
11435
|
+
return {
|
|
11436
|
+
total: shards.length,
|
|
11437
|
+
ok: shards.filter((s) => s.ok).length,
|
|
11438
|
+
unreadable: shards.filter((s) => s.unreadable).length,
|
|
11439
|
+
archived: shards.filter((s) => Boolean(s.archivedPath)).length,
|
|
11440
|
+
shards
|
|
11441
|
+
};
|
|
11442
|
+
}
|
|
11357
11443
|
async function ensureShardSchema(client) {
|
|
11358
11444
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
11359
11445
|
await client.execute("PRAGMA busy_timeout = 30000");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.55",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|