@askexenow/exe-os 0.9.30 → 0.9.32
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 +135 -7
- package/dist/bin/backfill-responses.js +135 -7
- package/dist/bin/backfill-vectors.js +135 -7
- package/dist/bin/cleanup-stale-review-tasks.js +139 -11
- package/dist/bin/cli.js +812 -486
- package/dist/bin/exe-assign.js +135 -7
- package/dist/bin/exe-boot.js +422 -113
- package/dist/bin/exe-cloud.js +160 -9
- package/dist/bin/exe-dispatch.js +136 -8
- package/dist/bin/exe-doctor.js +255 -13
- package/dist/bin/exe-export-behaviors.js +136 -8
- package/dist/bin/exe-forget.js +136 -8
- package/dist/bin/exe-gateway.js +171 -24
- package/dist/bin/exe-heartbeat.js +141 -13
- package/dist/bin/exe-kill.js +140 -12
- package/dist/bin/exe-launch-agent.js +143 -15
- package/dist/bin/exe-link.js +357 -48
- package/dist/bin/exe-pending-messages.js +136 -8
- package/dist/bin/exe-pending-notifications.js +136 -8
- package/dist/bin/exe-pending-reviews.js +138 -10
- package/dist/bin/exe-review.js +136 -8
- package/dist/bin/exe-search.js +155 -20
- package/dist/bin/exe-session-cleanup.js +166 -38
- package/dist/bin/exe-start-codex.js +142 -14
- package/dist/bin/exe-start-opencode.js +140 -12
- package/dist/bin/exe-status.js +148 -20
- package/dist/bin/exe-team.js +136 -8
- package/dist/bin/git-sweep.js +138 -10
- package/dist/bin/graph-backfill.js +135 -7
- package/dist/bin/graph-export.js +136 -8
- package/dist/bin/intercom-check.js +153 -25
- package/dist/bin/scan-tasks.js +138 -10
- package/dist/bin/setup.js +447 -121
- package/dist/bin/shard-migrate.js +135 -7
- package/dist/gateway/index.js +151 -23
- package/dist/hooks/bug-report-worker.js +151 -23
- package/dist/hooks/codex-stop-task-finalizer.js +145 -17
- package/dist/hooks/commit-complete.js +138 -10
- package/dist/hooks/error-recall.js +159 -24
- package/dist/hooks/ingest.js +142 -14
- package/dist/hooks/instructions-loaded.js +136 -8
- package/dist/hooks/notification.js +136 -8
- package/dist/hooks/post-compact.js +136 -8
- package/dist/hooks/post-tool-combined.js +159 -24
- package/dist/hooks/pre-compact.js +136 -8
- package/dist/hooks/pre-tool-use.js +144 -16
- package/dist/hooks/prompt-submit.js +195 -55
- package/dist/hooks/session-end.js +141 -13
- package/dist/hooks/session-start.js +165 -30
- package/dist/hooks/stop.js +136 -8
- package/dist/hooks/subagent-stop.js +136 -8
- package/dist/hooks/summary-worker.js +374 -65
- package/dist/index.js +136 -8
- package/dist/lib/cloud-sync.js +355 -46
- package/dist/lib/consolidation.js +1 -0
- package/dist/lib/exe-daemon.js +469 -127
- package/dist/lib/hybrid-search.js +155 -20
- package/dist/lib/keychain.js +191 -7
- package/dist/lib/schedules.js +138 -10
- package/dist/lib/store.js +135 -7
- package/dist/mcp/server.js +706 -213
- package/dist/runtime/index.js +136 -8
- package/dist/tui/App.js +208 -31
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -1654,8 +1654,8 @@ function findPackageRoot() {
|
|
|
1654
1654
|
function getAvailableMemoryGB() {
|
|
1655
1655
|
if (process.platform === "darwin") {
|
|
1656
1656
|
try {
|
|
1657
|
-
const { execSync:
|
|
1658
|
-
const vmstat =
|
|
1657
|
+
const { execSync: execSync9 } = __require("child_process");
|
|
1658
|
+
const vmstat = execSync9("vm_stat", { encoding: "utf8" });
|
|
1659
1659
|
const pageSize = 16384;
|
|
1660
1660
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1661
1661
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -6564,6 +6564,7 @@ var init_tmux_routing = __esm({
|
|
|
6564
6564
|
// src/lib/keychain.ts
|
|
6565
6565
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6566
6566
|
import { existsSync as existsSync15 } from "fs";
|
|
6567
|
+
import { execSync as execSync8 } from "child_process";
|
|
6567
6568
|
import path19 from "path";
|
|
6568
6569
|
import os12 from "os";
|
|
6569
6570
|
function getKeyDir() {
|
|
@@ -6572,6 +6573,59 @@ function getKeyDir() {
|
|
|
6572
6573
|
function getKeyPath() {
|
|
6573
6574
|
return path19.join(getKeyDir(), "master.key");
|
|
6574
6575
|
}
|
|
6576
|
+
function macKeychainGet() {
|
|
6577
|
+
if (process.platform !== "darwin") return null;
|
|
6578
|
+
try {
|
|
6579
|
+
return execSync8(
|
|
6580
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
6581
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
6582
|
+
).trim();
|
|
6583
|
+
} catch {
|
|
6584
|
+
return null;
|
|
6585
|
+
}
|
|
6586
|
+
}
|
|
6587
|
+
function macKeychainSet(value) {
|
|
6588
|
+
if (process.platform !== "darwin") return false;
|
|
6589
|
+
try {
|
|
6590
|
+
try {
|
|
6591
|
+
execSync8(
|
|
6592
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
6593
|
+
{ timeout: 5e3 }
|
|
6594
|
+
);
|
|
6595
|
+
} catch {
|
|
6596
|
+
}
|
|
6597
|
+
execSync8(
|
|
6598
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
6599
|
+
{ timeout: 5e3 }
|
|
6600
|
+
);
|
|
6601
|
+
return true;
|
|
6602
|
+
} catch {
|
|
6603
|
+
return false;
|
|
6604
|
+
}
|
|
6605
|
+
}
|
|
6606
|
+
function linuxSecretGet() {
|
|
6607
|
+
if (process.platform !== "linux") return null;
|
|
6608
|
+
try {
|
|
6609
|
+
return execSync8(
|
|
6610
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
6611
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
6612
|
+
).trim();
|
|
6613
|
+
} catch {
|
|
6614
|
+
return null;
|
|
6615
|
+
}
|
|
6616
|
+
}
|
|
6617
|
+
function linuxSecretSet(value) {
|
|
6618
|
+
if (process.platform !== "linux") return false;
|
|
6619
|
+
try {
|
|
6620
|
+
execSync8(
|
|
6621
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
6622
|
+
{ timeout: 5e3 }
|
|
6623
|
+
);
|
|
6624
|
+
return true;
|
|
6625
|
+
} catch {
|
|
6626
|
+
return false;
|
|
6627
|
+
}
|
|
6628
|
+
}
|
|
6575
6629
|
async function tryKeytar() {
|
|
6576
6630
|
try {
|
|
6577
6631
|
return await import("keytar");
|
|
@@ -6579,13 +6633,63 @@ async function tryKeytar() {
|
|
|
6579
6633
|
return null;
|
|
6580
6634
|
}
|
|
6581
6635
|
}
|
|
6636
|
+
function deriveMachineKey() {
|
|
6637
|
+
try {
|
|
6638
|
+
const crypto8 = __require("crypto");
|
|
6639
|
+
const material = [
|
|
6640
|
+
os12.hostname(),
|
|
6641
|
+
os12.userInfo().username,
|
|
6642
|
+
os12.arch(),
|
|
6643
|
+
os12.platform(),
|
|
6644
|
+
// Machine ID on Linux (stable across reboots)
|
|
6645
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
6646
|
+
].join("|");
|
|
6647
|
+
return crypto8.createHash("sha256").update(material).digest();
|
|
6648
|
+
} catch {
|
|
6649
|
+
return null;
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
function readMachineId() {
|
|
6653
|
+
try {
|
|
6654
|
+
const { readFileSync: readFileSync13 } = __require("fs");
|
|
6655
|
+
return readFileSync13("/etc/machine-id", "utf-8").trim();
|
|
6656
|
+
} catch {
|
|
6657
|
+
return "";
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
6661
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
6662
|
+
try {
|
|
6663
|
+
const crypto8 = __require("crypto");
|
|
6664
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
6665
|
+
if (parts.length !== 3) return null;
|
|
6666
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
6667
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
6668
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
6669
|
+
const decipher = crypto8.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
6670
|
+
decipher.setAuthTag(authTag);
|
|
6671
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
6672
|
+
decrypted += decipher.final("utf-8");
|
|
6673
|
+
return decrypted;
|
|
6674
|
+
} catch {
|
|
6675
|
+
return null;
|
|
6676
|
+
}
|
|
6677
|
+
}
|
|
6582
6678
|
async function getMasterKey() {
|
|
6679
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
6680
|
+
if (nativeValue) {
|
|
6681
|
+
return Buffer.from(nativeValue, "base64");
|
|
6682
|
+
}
|
|
6583
6683
|
const keytar = await tryKeytar();
|
|
6584
6684
|
if (keytar) {
|
|
6585
6685
|
try {
|
|
6586
|
-
const
|
|
6587
|
-
if (
|
|
6588
|
-
|
|
6686
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
6687
|
+
if (keytarValue) {
|
|
6688
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
6689
|
+
if (migrated) {
|
|
6690
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
6691
|
+
}
|
|
6692
|
+
return Buffer.from(keytarValue, "base64");
|
|
6589
6693
|
}
|
|
6590
6694
|
} catch {
|
|
6591
6695
|
}
|
|
@@ -6599,8 +6703,31 @@ async function getMasterKey() {
|
|
|
6599
6703
|
return null;
|
|
6600
6704
|
}
|
|
6601
6705
|
try {
|
|
6602
|
-
const content = await readFile4(keyPath, "utf-8");
|
|
6603
|
-
|
|
6706
|
+
const content = (await readFile4(keyPath, "utf-8")).trim();
|
|
6707
|
+
let b64Value;
|
|
6708
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
6709
|
+
const machineKey = deriveMachineKey();
|
|
6710
|
+
if (!machineKey) {
|
|
6711
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
6712
|
+
return null;
|
|
6713
|
+
}
|
|
6714
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
6715
|
+
if (!decrypted) {
|
|
6716
|
+
process.stderr.write(
|
|
6717
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
6718
|
+
);
|
|
6719
|
+
return null;
|
|
6720
|
+
}
|
|
6721
|
+
b64Value = decrypted;
|
|
6722
|
+
} else {
|
|
6723
|
+
b64Value = content;
|
|
6724
|
+
}
|
|
6725
|
+
const key = Buffer.from(b64Value, "base64");
|
|
6726
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
6727
|
+
if (migrated) {
|
|
6728
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
6729
|
+
}
|
|
6730
|
+
return key;
|
|
6604
6731
|
} catch (err) {
|
|
6605
6732
|
process.stderr.write(
|
|
6606
6733
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -6609,12 +6736,13 @@ async function getMasterKey() {
|
|
|
6609
6736
|
return null;
|
|
6610
6737
|
}
|
|
6611
6738
|
}
|
|
6612
|
-
var SERVICE, ACCOUNT;
|
|
6739
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
6613
6740
|
var init_keychain = __esm({
|
|
6614
6741
|
"src/lib/keychain.ts"() {
|
|
6615
6742
|
"use strict";
|
|
6616
6743
|
SERVICE = "exe-mem";
|
|
6617
6744
|
ACCOUNT = "master-key";
|
|
6745
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
6618
6746
|
}
|
|
6619
6747
|
});
|
|
6620
6748
|
|
package/dist/tui/App.js
CHANGED
|
@@ -1905,8 +1905,8 @@ function findPackageRoot() {
|
|
|
1905
1905
|
function getAvailableMemoryGB() {
|
|
1906
1906
|
if (process.platform === "darwin") {
|
|
1907
1907
|
try {
|
|
1908
|
-
const { execSync:
|
|
1909
|
-
const vmstat =
|
|
1908
|
+
const { execSync: execSync11 } = __require("child_process");
|
|
1909
|
+
const vmstat = execSync11("vm_stat", { encoding: "utf8" });
|
|
1910
1910
|
const pageSize = 16384;
|
|
1911
1911
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1912
1912
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -10375,6 +10375,7 @@ __export(keychain_exports, {
|
|
|
10375
10375
|
});
|
|
10376
10376
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
10377
10377
|
import { existsSync as existsSync16 } from "fs";
|
|
10378
|
+
import { execSync as execSync9 } from "child_process";
|
|
10378
10379
|
import path26 from "path";
|
|
10379
10380
|
import os12 from "os";
|
|
10380
10381
|
function getKeyDir() {
|
|
@@ -10383,6 +10384,83 @@ function getKeyDir() {
|
|
|
10383
10384
|
function getKeyPath() {
|
|
10384
10385
|
return path26.join(getKeyDir(), "master.key");
|
|
10385
10386
|
}
|
|
10387
|
+
function macKeychainGet() {
|
|
10388
|
+
if (process.platform !== "darwin") return null;
|
|
10389
|
+
try {
|
|
10390
|
+
return execSync9(
|
|
10391
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
10392
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
10393
|
+
).trim();
|
|
10394
|
+
} catch {
|
|
10395
|
+
return null;
|
|
10396
|
+
}
|
|
10397
|
+
}
|
|
10398
|
+
function macKeychainSet(value) {
|
|
10399
|
+
if (process.platform !== "darwin") return false;
|
|
10400
|
+
try {
|
|
10401
|
+
try {
|
|
10402
|
+
execSync9(
|
|
10403
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
10404
|
+
{ timeout: 5e3 }
|
|
10405
|
+
);
|
|
10406
|
+
} catch {
|
|
10407
|
+
}
|
|
10408
|
+
execSync9(
|
|
10409
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
10410
|
+
{ timeout: 5e3 }
|
|
10411
|
+
);
|
|
10412
|
+
return true;
|
|
10413
|
+
} catch {
|
|
10414
|
+
return false;
|
|
10415
|
+
}
|
|
10416
|
+
}
|
|
10417
|
+
function macKeychainDelete() {
|
|
10418
|
+
if (process.platform !== "darwin") return false;
|
|
10419
|
+
try {
|
|
10420
|
+
execSync9(
|
|
10421
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
10422
|
+
{ timeout: 5e3 }
|
|
10423
|
+
);
|
|
10424
|
+
return true;
|
|
10425
|
+
} catch {
|
|
10426
|
+
return false;
|
|
10427
|
+
}
|
|
10428
|
+
}
|
|
10429
|
+
function linuxSecretGet() {
|
|
10430
|
+
if (process.platform !== "linux") return null;
|
|
10431
|
+
try {
|
|
10432
|
+
return execSync9(
|
|
10433
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
10434
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
10435
|
+
).trim();
|
|
10436
|
+
} catch {
|
|
10437
|
+
return null;
|
|
10438
|
+
}
|
|
10439
|
+
}
|
|
10440
|
+
function linuxSecretSet(value) {
|
|
10441
|
+
if (process.platform !== "linux") return false;
|
|
10442
|
+
try {
|
|
10443
|
+
execSync9(
|
|
10444
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
10445
|
+
{ timeout: 5e3 }
|
|
10446
|
+
);
|
|
10447
|
+
return true;
|
|
10448
|
+
} catch {
|
|
10449
|
+
return false;
|
|
10450
|
+
}
|
|
10451
|
+
}
|
|
10452
|
+
function linuxSecretDelete() {
|
|
10453
|
+
if (process.platform !== "linux") return false;
|
|
10454
|
+
try {
|
|
10455
|
+
execSync9(
|
|
10456
|
+
`secret-tool clear service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
10457
|
+
{ timeout: 5e3 }
|
|
10458
|
+
);
|
|
10459
|
+
return true;
|
|
10460
|
+
} catch {
|
|
10461
|
+
return false;
|
|
10462
|
+
}
|
|
10463
|
+
}
|
|
10386
10464
|
async function tryKeytar() {
|
|
10387
10465
|
try {
|
|
10388
10466
|
return await import("keytar");
|
|
@@ -10390,13 +10468,72 @@ async function tryKeytar() {
|
|
|
10390
10468
|
return null;
|
|
10391
10469
|
}
|
|
10392
10470
|
}
|
|
10471
|
+
function deriveMachineKey() {
|
|
10472
|
+
try {
|
|
10473
|
+
const crypto8 = __require("crypto");
|
|
10474
|
+
const material = [
|
|
10475
|
+
os12.hostname(),
|
|
10476
|
+
os12.userInfo().username,
|
|
10477
|
+
os12.arch(),
|
|
10478
|
+
os12.platform(),
|
|
10479
|
+
// Machine ID on Linux (stable across reboots)
|
|
10480
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
10481
|
+
].join("|");
|
|
10482
|
+
return crypto8.createHash("sha256").update(material).digest();
|
|
10483
|
+
} catch {
|
|
10484
|
+
return null;
|
|
10485
|
+
}
|
|
10486
|
+
}
|
|
10487
|
+
function readMachineId() {
|
|
10488
|
+
try {
|
|
10489
|
+
const { readFileSync: readFileSync14 } = __require("fs");
|
|
10490
|
+
return readFileSync14("/etc/machine-id", "utf-8").trim();
|
|
10491
|
+
} catch {
|
|
10492
|
+
return "";
|
|
10493
|
+
}
|
|
10494
|
+
}
|
|
10495
|
+
function encryptWithMachineKey(plaintext, machineKey) {
|
|
10496
|
+
const crypto8 = __require("crypto");
|
|
10497
|
+
const iv = crypto8.randomBytes(12);
|
|
10498
|
+
const cipher = crypto8.createCipheriv("aes-256-gcm", machineKey, iv);
|
|
10499
|
+
let encrypted = cipher.update(plaintext, "utf-8", "base64");
|
|
10500
|
+
encrypted += cipher.final("base64");
|
|
10501
|
+
const authTag = cipher.getAuthTag().toString("base64");
|
|
10502
|
+
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${authTag}:${encrypted}`;
|
|
10503
|
+
}
|
|
10504
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
10505
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
10506
|
+
try {
|
|
10507
|
+
const crypto8 = __require("crypto");
|
|
10508
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
10509
|
+
if (parts.length !== 3) return null;
|
|
10510
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
10511
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
10512
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
10513
|
+
const decipher = crypto8.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
10514
|
+
decipher.setAuthTag(authTag);
|
|
10515
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
10516
|
+
decrypted += decipher.final("utf-8");
|
|
10517
|
+
return decrypted;
|
|
10518
|
+
} catch {
|
|
10519
|
+
return null;
|
|
10520
|
+
}
|
|
10521
|
+
}
|
|
10393
10522
|
async function getMasterKey() {
|
|
10523
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
10524
|
+
if (nativeValue) {
|
|
10525
|
+
return Buffer.from(nativeValue, "base64");
|
|
10526
|
+
}
|
|
10394
10527
|
const keytar = await tryKeytar();
|
|
10395
10528
|
if (keytar) {
|
|
10396
10529
|
try {
|
|
10397
|
-
const
|
|
10398
|
-
if (
|
|
10399
|
-
|
|
10530
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
10531
|
+
if (keytarValue) {
|
|
10532
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
10533
|
+
if (migrated) {
|
|
10534
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
10535
|
+
}
|
|
10536
|
+
return Buffer.from(keytarValue, "base64");
|
|
10400
10537
|
}
|
|
10401
10538
|
} catch {
|
|
10402
10539
|
}
|
|
@@ -10410,8 +10547,31 @@ async function getMasterKey() {
|
|
|
10410
10547
|
return null;
|
|
10411
10548
|
}
|
|
10412
10549
|
try {
|
|
10413
|
-
const content = await readFile4(keyPath, "utf-8");
|
|
10414
|
-
|
|
10550
|
+
const content = (await readFile4(keyPath, "utf-8")).trim();
|
|
10551
|
+
let b64Value;
|
|
10552
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
10553
|
+
const machineKey = deriveMachineKey();
|
|
10554
|
+
if (!machineKey) {
|
|
10555
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
10556
|
+
return null;
|
|
10557
|
+
}
|
|
10558
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
10559
|
+
if (!decrypted) {
|
|
10560
|
+
process.stderr.write(
|
|
10561
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
10562
|
+
);
|
|
10563
|
+
return null;
|
|
10564
|
+
}
|
|
10565
|
+
b64Value = decrypted;
|
|
10566
|
+
} else {
|
|
10567
|
+
b64Value = content;
|
|
10568
|
+
}
|
|
10569
|
+
const key = Buffer.from(b64Value, "base64");
|
|
10570
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
10571
|
+
if (migrated) {
|
|
10572
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
10573
|
+
}
|
|
10574
|
+
return key;
|
|
10415
10575
|
} catch (err) {
|
|
10416
10576
|
process.stderr.write(
|
|
10417
10577
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -10422,6 +10582,9 @@ async function getMasterKey() {
|
|
|
10422
10582
|
}
|
|
10423
10583
|
async function setMasterKey(key) {
|
|
10424
10584
|
const b64 = key.toString("base64");
|
|
10585
|
+
if (macKeychainSet(b64) || linuxSecretSet(b64)) {
|
|
10586
|
+
return;
|
|
10587
|
+
}
|
|
10425
10588
|
const keytar = await tryKeytar();
|
|
10426
10589
|
if (keytar) {
|
|
10427
10590
|
try {
|
|
@@ -10433,10 +10596,23 @@ async function setMasterKey(key) {
|
|
|
10433
10596
|
const dir = getKeyDir();
|
|
10434
10597
|
await mkdir4(dir, { recursive: true });
|
|
10435
10598
|
const keyPath = getKeyPath();
|
|
10436
|
-
|
|
10437
|
-
|
|
10599
|
+
const machineKey = deriveMachineKey();
|
|
10600
|
+
if (machineKey) {
|
|
10601
|
+
const encrypted = encryptWithMachineKey(b64, machineKey);
|
|
10602
|
+
await writeFile5(keyPath, encrypted + "\n", "utf-8");
|
|
10603
|
+
await chmod2(keyPath, 384);
|
|
10604
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound).\n");
|
|
10605
|
+
} else {
|
|
10606
|
+
await writeFile5(keyPath, b64 + "\n", "utf-8");
|
|
10607
|
+
await chmod2(keyPath, 384);
|
|
10608
|
+
process.stderr.write(
|
|
10609
|
+
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
10610
|
+
);
|
|
10611
|
+
}
|
|
10438
10612
|
}
|
|
10439
10613
|
async function deleteMasterKey() {
|
|
10614
|
+
macKeychainDelete();
|
|
10615
|
+
linuxSecretDelete();
|
|
10440
10616
|
const keytar = await tryKeytar();
|
|
10441
10617
|
if (keytar) {
|
|
10442
10618
|
try {
|
|
@@ -10478,12 +10654,13 @@ async function importMnemonic(mnemonic) {
|
|
|
10478
10654
|
const entropy = mnemonicToEntropy(trimmed);
|
|
10479
10655
|
return Buffer.from(entropy, "hex");
|
|
10480
10656
|
}
|
|
10481
|
-
var SERVICE, ACCOUNT;
|
|
10657
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
10482
10658
|
var init_keychain = __esm({
|
|
10483
10659
|
"src/lib/keychain.ts"() {
|
|
10484
10660
|
"use strict";
|
|
10485
10661
|
SERVICE = "exe-mem";
|
|
10486
10662
|
ACCOUNT = "master-key";
|
|
10663
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
10487
10664
|
}
|
|
10488
10665
|
});
|
|
10489
10666
|
|
|
@@ -17751,8 +17928,8 @@ function Footer() {
|
|
|
17751
17928
|
setSessions(allSessions.length);
|
|
17752
17929
|
if (!currentSession) {
|
|
17753
17930
|
try {
|
|
17754
|
-
const { execSync:
|
|
17755
|
-
const name =
|
|
17931
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
17932
|
+
const name = execSync11("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
17756
17933
|
encoding: "utf8",
|
|
17757
17934
|
timeout: 2e3
|
|
17758
17935
|
}).trim();
|
|
@@ -19186,8 +19363,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
19186
19363
|
}
|
|
19187
19364
|
const capture = () => {
|
|
19188
19365
|
try {
|
|
19189
|
-
const { execSync:
|
|
19190
|
-
const output =
|
|
19366
|
+
const { execSync: execSync11 } = __require("child_process");
|
|
19367
|
+
const output = execSync11(
|
|
19191
19368
|
`tmux capture-pane -t ${JSON.stringify(sessionName)} -p -e 2>/dev/null | tail -${CAPTURE_LINES}`,
|
|
19192
19369
|
{ encoding: "utf8", timeout: 3e3 }
|
|
19193
19370
|
);
|
|
@@ -19211,8 +19388,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
19211
19388
|
if (key.return) {
|
|
19212
19389
|
if (!demo && inputBuffer.trim()) {
|
|
19213
19390
|
try {
|
|
19214
|
-
const { execSync:
|
|
19215
|
-
|
|
19391
|
+
const { execSync: execSync11 } = __require("child_process");
|
|
19392
|
+
execSync11(
|
|
19216
19393
|
`tmux send-keys -t ${JSON.stringify(sessionName)} ${JSON.stringify(inputBuffer)} Enter`,
|
|
19217
19394
|
{ timeout: 2e3 }
|
|
19218
19395
|
);
|
|
@@ -19220,8 +19397,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
19220
19397
|
}
|
|
19221
19398
|
} else if (!demo) {
|
|
19222
19399
|
try {
|
|
19223
|
-
const { execSync:
|
|
19224
|
-
|
|
19400
|
+
const { execSync: execSync11 } = __require("child_process");
|
|
19401
|
+
execSync11(`tmux send-keys -t ${JSON.stringify(sessionName)} Enter`, { timeout: 2e3 });
|
|
19225
19402
|
} catch {
|
|
19226
19403
|
}
|
|
19227
19404
|
}
|
|
@@ -19524,12 +19701,12 @@ function SessionsView({
|
|
|
19524
19701
|
return;
|
|
19525
19702
|
}
|
|
19526
19703
|
} else {
|
|
19527
|
-
const { execSync:
|
|
19704
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
19528
19705
|
const dir = projectDir || process.cwd();
|
|
19529
|
-
|
|
19530
|
-
|
|
19706
|
+
execSync11(`tmux new-session -d -s ${JSON.stringify(entry.sessionName)} -c ${JSON.stringify(dir)}`, { timeout: 5e3 });
|
|
19707
|
+
execSync11(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "claude --dangerously-skip-permissions" Enter`, { timeout: 3e3 });
|
|
19531
19708
|
await new Promise((r) => setTimeout(r, 3e3));
|
|
19532
|
-
|
|
19709
|
+
execSync11(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "/exe" Enter`, { timeout: 3e3 });
|
|
19533
19710
|
}
|
|
19534
19711
|
const updated = { ...entry, status: "active", activity: "Starting...", attached: false };
|
|
19535
19712
|
setViewingEmployee(updated);
|
|
@@ -19632,7 +19809,7 @@ function SessionsView({
|
|
|
19632
19809
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
19633
19810
|
const { getCoordinatorName: getCoordinatorName2, isCoordinatorRole: isCoordinatorRole2, loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
19634
19811
|
const { isExeSession: isExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
19635
|
-
const { execSync:
|
|
19812
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
19636
19813
|
if (!inTmux2()) {
|
|
19637
19814
|
setTmuxAvailable(false);
|
|
19638
19815
|
setProjects([]);
|
|
@@ -19641,7 +19818,7 @@ function SessionsView({
|
|
|
19641
19818
|
setTmuxAvailable(true);
|
|
19642
19819
|
const attachedMap = /* @__PURE__ */ new Map();
|
|
19643
19820
|
try {
|
|
19644
|
-
const out =
|
|
19821
|
+
const out = execSync11("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
|
|
19645
19822
|
encoding: "utf8",
|
|
19646
19823
|
timeout: 3e3
|
|
19647
19824
|
});
|
|
@@ -20343,8 +20520,8 @@ function upsertConversation(conversations, platform, senderId, message) {
|
|
|
20343
20520
|
async function loadGatewayConfig() {
|
|
20344
20521
|
const state = { running: false, port: 3100, adapters: [], agents: [], gatewayUrl: "" };
|
|
20345
20522
|
try {
|
|
20346
|
-
const { execSync:
|
|
20347
|
-
const ps =
|
|
20523
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
20524
|
+
const ps = execSync11("pgrep -f exe-gateway 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
|
|
20348
20525
|
state.running = ps.trim().length > 0;
|
|
20349
20526
|
} catch {
|
|
20350
20527
|
state.running = false;
|
|
@@ -20728,10 +20905,10 @@ function GatewayView({ onBack }) {
|
|
|
20728
20905
|
import React22, { useState as useState12, useEffect as useEffect14 } from "react";
|
|
20729
20906
|
|
|
20730
20907
|
// src/tui/utils/agent-status.ts
|
|
20731
|
-
import { execSync as
|
|
20908
|
+
import { execSync as execSync10 } from "child_process";
|
|
20732
20909
|
function getAgentStatus(agentId) {
|
|
20733
20910
|
try {
|
|
20734
|
-
const sessions =
|
|
20911
|
+
const sessions = execSync10("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
20735
20912
|
encoding: "utf8",
|
|
20736
20913
|
timeout: 2e3
|
|
20737
20914
|
}).trim().split("\n");
|
|
@@ -20742,7 +20919,7 @@ function getAgentStatus(agentId) {
|
|
|
20742
20919
|
return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
|
|
20743
20920
|
});
|
|
20744
20921
|
if (!agentSession) return { label: "offline", color: "gray" };
|
|
20745
|
-
const pane =
|
|
20922
|
+
const pane = execSync10(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
|
|
20746
20923
|
encoding: "utf8",
|
|
20747
20924
|
timeout: 2e3
|
|
20748
20925
|
});
|
|
@@ -21500,8 +21677,8 @@ function SettingsView({ onBack }) {
|
|
|
21500
21677
|
};
|
|
21501
21678
|
});
|
|
21502
21679
|
try {
|
|
21503
|
-
const { execSync:
|
|
21504
|
-
|
|
21680
|
+
const { execSync: execSync11 } = await import("child_process");
|
|
21681
|
+
execSync11("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
|
|
21505
21682
|
providerList.push({ name: "Ollama", configured: true, detail: "localhost:11434" });
|
|
21506
21683
|
} catch {
|
|
21507
21684
|
providerList.push({ name: "Ollama", configured: false, detail: "not running" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.32",
|
|
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",
|