@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/bin/cli.js
CHANGED
|
@@ -1638,6 +1638,7 @@ __export(keychain_exports, {
|
|
|
1638
1638
|
});
|
|
1639
1639
|
import { readFile as readFile4, writeFile as writeFile4, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
1640
1640
|
import { existsSync as existsSync8 } from "fs";
|
|
1641
|
+
import { execSync as execSync3 } from "child_process";
|
|
1641
1642
|
import path7 from "path";
|
|
1642
1643
|
import os6 from "os";
|
|
1643
1644
|
function getKeyDir() {
|
|
@@ -1646,6 +1647,83 @@ function getKeyDir() {
|
|
|
1646
1647
|
function getKeyPath() {
|
|
1647
1648
|
return path7.join(getKeyDir(), "master.key");
|
|
1648
1649
|
}
|
|
1650
|
+
function macKeychainGet() {
|
|
1651
|
+
if (process.platform !== "darwin") return null;
|
|
1652
|
+
try {
|
|
1653
|
+
return execSync3(
|
|
1654
|
+
`security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
1655
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
1656
|
+
).trim();
|
|
1657
|
+
} catch {
|
|
1658
|
+
return null;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
function macKeychainSet(value) {
|
|
1662
|
+
if (process.platform !== "darwin") return false;
|
|
1663
|
+
try {
|
|
1664
|
+
try {
|
|
1665
|
+
execSync3(
|
|
1666
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
1667
|
+
{ timeout: 5e3 }
|
|
1668
|
+
);
|
|
1669
|
+
} catch {
|
|
1670
|
+
}
|
|
1671
|
+
execSync3(
|
|
1672
|
+
`security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
|
|
1673
|
+
{ timeout: 5e3 }
|
|
1674
|
+
);
|
|
1675
|
+
return true;
|
|
1676
|
+
} catch {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
function macKeychainDelete() {
|
|
1681
|
+
if (process.platform !== "darwin") return false;
|
|
1682
|
+
try {
|
|
1683
|
+
execSync3(
|
|
1684
|
+
`security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
1685
|
+
{ timeout: 5e3 }
|
|
1686
|
+
);
|
|
1687
|
+
return true;
|
|
1688
|
+
} catch {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
function linuxSecretGet() {
|
|
1693
|
+
if (process.platform !== "linux") return null;
|
|
1694
|
+
try {
|
|
1695
|
+
return execSync3(
|
|
1696
|
+
`secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
1697
|
+
{ encoding: "utf-8", timeout: 5e3 }
|
|
1698
|
+
).trim();
|
|
1699
|
+
} catch {
|
|
1700
|
+
return null;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
function linuxSecretSet(value) {
|
|
1704
|
+
if (process.platform !== "linux") return false;
|
|
1705
|
+
try {
|
|
1706
|
+
execSync3(
|
|
1707
|
+
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
|
|
1708
|
+
{ timeout: 5e3 }
|
|
1709
|
+
);
|
|
1710
|
+
return true;
|
|
1711
|
+
} catch {
|
|
1712
|
+
return false;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
function linuxSecretDelete() {
|
|
1716
|
+
if (process.platform !== "linux") return false;
|
|
1717
|
+
try {
|
|
1718
|
+
execSync3(
|
|
1719
|
+
`secret-tool clear service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
|
|
1720
|
+
{ timeout: 5e3 }
|
|
1721
|
+
);
|
|
1722
|
+
return true;
|
|
1723
|
+
} catch {
|
|
1724
|
+
return false;
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1649
1727
|
async function tryKeytar() {
|
|
1650
1728
|
try {
|
|
1651
1729
|
return await import("keytar");
|
|
@@ -1653,13 +1731,72 @@ async function tryKeytar() {
|
|
|
1653
1731
|
return null;
|
|
1654
1732
|
}
|
|
1655
1733
|
}
|
|
1734
|
+
function deriveMachineKey() {
|
|
1735
|
+
try {
|
|
1736
|
+
const crypto13 = __require("crypto");
|
|
1737
|
+
const material = [
|
|
1738
|
+
os6.hostname(),
|
|
1739
|
+
os6.userInfo().username,
|
|
1740
|
+
os6.arch(),
|
|
1741
|
+
os6.platform(),
|
|
1742
|
+
// Machine ID on Linux (stable across reboots)
|
|
1743
|
+
process.platform === "linux" ? readMachineId() : ""
|
|
1744
|
+
].join("|");
|
|
1745
|
+
return crypto13.createHash("sha256").update(material).digest();
|
|
1746
|
+
} catch {
|
|
1747
|
+
return null;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
function readMachineId() {
|
|
1751
|
+
try {
|
|
1752
|
+
const { readFileSync: readFileSync28 } = __require("fs");
|
|
1753
|
+
return readFileSync28("/etc/machine-id", "utf-8").trim();
|
|
1754
|
+
} catch {
|
|
1755
|
+
return "";
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
function encryptWithMachineKey(plaintext, machineKey) {
|
|
1759
|
+
const crypto13 = __require("crypto");
|
|
1760
|
+
const iv = crypto13.randomBytes(12);
|
|
1761
|
+
const cipher = crypto13.createCipheriv("aes-256-gcm", machineKey, iv);
|
|
1762
|
+
let encrypted = cipher.update(plaintext, "utf-8", "base64");
|
|
1763
|
+
encrypted += cipher.final("base64");
|
|
1764
|
+
const authTag = cipher.getAuthTag().toString("base64");
|
|
1765
|
+
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${authTag}:${encrypted}`;
|
|
1766
|
+
}
|
|
1767
|
+
function decryptWithMachineKey(encrypted, machineKey) {
|
|
1768
|
+
if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
|
|
1769
|
+
try {
|
|
1770
|
+
const crypto13 = __require("crypto");
|
|
1771
|
+
const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
|
|
1772
|
+
if (parts.length !== 3) return null;
|
|
1773
|
+
const [ivB64, tagB64, cipherB64] = parts;
|
|
1774
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
1775
|
+
const authTag = Buffer.from(tagB64, "base64");
|
|
1776
|
+
const decipher = crypto13.createDecipheriv("aes-256-gcm", machineKey, iv);
|
|
1777
|
+
decipher.setAuthTag(authTag);
|
|
1778
|
+
let decrypted = decipher.update(cipherB64, "base64", "utf-8");
|
|
1779
|
+
decrypted += decipher.final("utf-8");
|
|
1780
|
+
return decrypted;
|
|
1781
|
+
} catch {
|
|
1782
|
+
return null;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1656
1785
|
async function getMasterKey() {
|
|
1786
|
+
const nativeValue = macKeychainGet() ?? linuxSecretGet();
|
|
1787
|
+
if (nativeValue) {
|
|
1788
|
+
return Buffer.from(nativeValue, "base64");
|
|
1789
|
+
}
|
|
1657
1790
|
const keytar = await tryKeytar();
|
|
1658
1791
|
if (keytar) {
|
|
1659
1792
|
try {
|
|
1660
|
-
const
|
|
1661
|
-
if (
|
|
1662
|
-
|
|
1793
|
+
const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
1794
|
+
if (keytarValue) {
|
|
1795
|
+
const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
|
|
1796
|
+
if (migrated) {
|
|
1797
|
+
process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
|
|
1798
|
+
}
|
|
1799
|
+
return Buffer.from(keytarValue, "base64");
|
|
1663
1800
|
}
|
|
1664
1801
|
} catch {
|
|
1665
1802
|
}
|
|
@@ -1673,8 +1810,31 @@ async function getMasterKey() {
|
|
|
1673
1810
|
return null;
|
|
1674
1811
|
}
|
|
1675
1812
|
try {
|
|
1676
|
-
const content = await readFile4(keyPath, "utf-8");
|
|
1677
|
-
|
|
1813
|
+
const content = (await readFile4(keyPath, "utf-8")).trim();
|
|
1814
|
+
let b64Value;
|
|
1815
|
+
if (content.startsWith(ENCRYPTED_PREFIX)) {
|
|
1816
|
+
const machineKey = deriveMachineKey();
|
|
1817
|
+
if (!machineKey) {
|
|
1818
|
+
process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
|
|
1819
|
+
return null;
|
|
1820
|
+
}
|
|
1821
|
+
const decrypted = decryptWithMachineKey(content, machineKey);
|
|
1822
|
+
if (!decrypted) {
|
|
1823
|
+
process.stderr.write(
|
|
1824
|
+
"[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
|
|
1825
|
+
);
|
|
1826
|
+
return null;
|
|
1827
|
+
}
|
|
1828
|
+
b64Value = decrypted;
|
|
1829
|
+
} else {
|
|
1830
|
+
b64Value = content;
|
|
1831
|
+
}
|
|
1832
|
+
const key = Buffer.from(b64Value, "base64");
|
|
1833
|
+
const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
|
|
1834
|
+
if (migrated) {
|
|
1835
|
+
process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
|
|
1836
|
+
}
|
|
1837
|
+
return key;
|
|
1678
1838
|
} catch (err) {
|
|
1679
1839
|
process.stderr.write(
|
|
1680
1840
|
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -1685,6 +1845,9 @@ async function getMasterKey() {
|
|
|
1685
1845
|
}
|
|
1686
1846
|
async function setMasterKey(key) {
|
|
1687
1847
|
const b64 = key.toString("base64");
|
|
1848
|
+
if (macKeychainSet(b64) || linuxSecretSet(b64)) {
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1688
1851
|
const keytar = await tryKeytar();
|
|
1689
1852
|
if (keytar) {
|
|
1690
1853
|
try {
|
|
@@ -1696,10 +1859,23 @@ async function setMasterKey(key) {
|
|
|
1696
1859
|
const dir = getKeyDir();
|
|
1697
1860
|
await mkdir4(dir, { recursive: true });
|
|
1698
1861
|
const keyPath = getKeyPath();
|
|
1699
|
-
|
|
1700
|
-
|
|
1862
|
+
const machineKey = deriveMachineKey();
|
|
1863
|
+
if (machineKey) {
|
|
1864
|
+
const encrypted = encryptWithMachineKey(b64, machineKey);
|
|
1865
|
+
await writeFile4(keyPath, encrypted + "\n", "utf-8");
|
|
1866
|
+
await chmod2(keyPath, 384);
|
|
1867
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound).\n");
|
|
1868
|
+
} else {
|
|
1869
|
+
await writeFile4(keyPath, b64 + "\n", "utf-8");
|
|
1870
|
+
await chmod2(keyPath, 384);
|
|
1871
|
+
process.stderr.write(
|
|
1872
|
+
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1701
1875
|
}
|
|
1702
1876
|
async function deleteMasterKey() {
|
|
1877
|
+
macKeychainDelete();
|
|
1878
|
+
linuxSecretDelete();
|
|
1703
1879
|
const keytar = await tryKeytar();
|
|
1704
1880
|
if (keytar) {
|
|
1705
1881
|
try {
|
|
@@ -1741,12 +1917,13 @@ async function importMnemonic(mnemonic) {
|
|
|
1741
1917
|
const entropy = mnemonicToEntropy(trimmed);
|
|
1742
1918
|
return Buffer.from(entropy, "hex");
|
|
1743
1919
|
}
|
|
1744
|
-
var SERVICE, ACCOUNT;
|
|
1920
|
+
var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
|
|
1745
1921
|
var init_keychain = __esm({
|
|
1746
1922
|
"src/lib/keychain.ts"() {
|
|
1747
1923
|
"use strict";
|
|
1748
1924
|
SERVICE = "exe-mem";
|
|
1749
1925
|
ACCOUNT = "master-key";
|
|
1926
|
+
ENCRYPTED_PREFIX = "enc:";
|
|
1750
1927
|
}
|
|
1751
1928
|
});
|
|
1752
1929
|
|
|
@@ -2550,8 +2727,8 @@ function findPackageRoot() {
|
|
|
2550
2727
|
function getAvailableMemoryGB() {
|
|
2551
2728
|
if (process.platform === "darwin") {
|
|
2552
2729
|
try {
|
|
2553
|
-
const { execSync:
|
|
2554
|
-
const vmstat =
|
|
2730
|
+
const { execSync: execSync16 } = __require("child_process");
|
|
2731
|
+
const vmstat = execSync16("vm_stat", { encoding: "utf8" });
|
|
2555
2732
|
const pageSize = 16384;
|
|
2556
2733
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
2557
2734
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -4572,8 +4749,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
4572
4749
|
}
|
|
4573
4750
|
function getCacheAgeMs() {
|
|
4574
4751
|
try {
|
|
4575
|
-
const { statSync:
|
|
4576
|
-
const s =
|
|
4752
|
+
const { statSync: statSync3 } = __require("fs");
|
|
4753
|
+
const s = statSync3(CACHE_PATH);
|
|
4577
4754
|
return Date.now() - s.mtimeMs;
|
|
4578
4755
|
} catch {
|
|
4579
4756
|
return Infinity;
|
|
@@ -5003,6 +5180,109 @@ var init_crdt_sync = __esm({
|
|
|
5003
5180
|
}
|
|
5004
5181
|
});
|
|
5005
5182
|
|
|
5183
|
+
// src/lib/db-backup.ts
|
|
5184
|
+
var db_backup_exports = {};
|
|
5185
|
+
__export(db_backup_exports, {
|
|
5186
|
+
createBackup: () => createBackup,
|
|
5187
|
+
findActiveDb: () => findActiveDb,
|
|
5188
|
+
getBackupDir: () => getBackupDir,
|
|
5189
|
+
getLatestBackup: () => getLatestBackup,
|
|
5190
|
+
hasBackupToday: () => hasBackupToday,
|
|
5191
|
+
listBackups: () => listBackups,
|
|
5192
|
+
rotateBackups: () => rotateBackups
|
|
5193
|
+
});
|
|
5194
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync, unlinkSync as unlinkSync4, statSync as statSync2 } from "fs";
|
|
5195
|
+
import path13 from "path";
|
|
5196
|
+
function findActiveDb() {
|
|
5197
|
+
for (const name of DB_NAMES) {
|
|
5198
|
+
const p = path13.join(EXE_AI_DIR, name);
|
|
5199
|
+
if (existsSync13(p)) return p;
|
|
5200
|
+
}
|
|
5201
|
+
return null;
|
|
5202
|
+
}
|
|
5203
|
+
function createBackup(reason = "manual") {
|
|
5204
|
+
const dbPath = findActiveDb();
|
|
5205
|
+
if (!dbPath) return null;
|
|
5206
|
+
mkdirSync6(BACKUP_DIR, { recursive: true });
|
|
5207
|
+
const dbName = path13.basename(dbPath, ".db");
|
|
5208
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
5209
|
+
const backupName = `${dbName}-${reason}-${timestamp}.db`;
|
|
5210
|
+
const backupPath = path13.join(BACKUP_DIR, backupName);
|
|
5211
|
+
copyFileSync2(dbPath, backupPath);
|
|
5212
|
+
const walPath = dbPath + "-wal";
|
|
5213
|
+
if (existsSync13(walPath)) {
|
|
5214
|
+
try {
|
|
5215
|
+
copyFileSync2(walPath, backupPath + "-wal");
|
|
5216
|
+
} catch {
|
|
5217
|
+
}
|
|
5218
|
+
}
|
|
5219
|
+
const shmPath = dbPath + "-shm";
|
|
5220
|
+
if (existsSync13(shmPath)) {
|
|
5221
|
+
try {
|
|
5222
|
+
copyFileSync2(shmPath, backupPath + "-shm");
|
|
5223
|
+
} catch {
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
return backupPath;
|
|
5227
|
+
}
|
|
5228
|
+
function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
5229
|
+
if (!existsSync13(BACKUP_DIR)) return 0;
|
|
5230
|
+
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
|
|
5231
|
+
let deleted = 0;
|
|
5232
|
+
try {
|
|
5233
|
+
const files = readdirSync(BACKUP_DIR);
|
|
5234
|
+
for (const file of files) {
|
|
5235
|
+
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
5236
|
+
const filePath = path13.join(BACKUP_DIR, file);
|
|
5237
|
+
try {
|
|
5238
|
+
const stat2 = statSync2(filePath);
|
|
5239
|
+
if (stat2.mtimeMs < cutoff) {
|
|
5240
|
+
unlinkSync4(filePath);
|
|
5241
|
+
deleted++;
|
|
5242
|
+
}
|
|
5243
|
+
} catch {
|
|
5244
|
+
}
|
|
5245
|
+
}
|
|
5246
|
+
} catch {
|
|
5247
|
+
}
|
|
5248
|
+
return deleted;
|
|
5249
|
+
}
|
|
5250
|
+
function listBackups() {
|
|
5251
|
+
if (!existsSync13(BACKUP_DIR)) return [];
|
|
5252
|
+
try {
|
|
5253
|
+
const files = readdirSync(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
5254
|
+
return files.map((name) => {
|
|
5255
|
+
const p = path13.join(BACKUP_DIR, name);
|
|
5256
|
+
const stat2 = statSync2(p);
|
|
5257
|
+
return { path: p, name, size: stat2.size, date: stat2.mtime };
|
|
5258
|
+
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
5259
|
+
} catch {
|
|
5260
|
+
return [];
|
|
5261
|
+
}
|
|
5262
|
+
}
|
|
5263
|
+
function hasBackupToday(reason) {
|
|
5264
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
5265
|
+
const backups = listBackups();
|
|
5266
|
+
return backups.some((b) => b.name.includes(reason) && b.name.includes(today.replace(/-/g, "-")));
|
|
5267
|
+
}
|
|
5268
|
+
function getLatestBackup() {
|
|
5269
|
+
const backups = listBackups();
|
|
5270
|
+
return backups.length > 0 ? backups[0].path : null;
|
|
5271
|
+
}
|
|
5272
|
+
function getBackupDir() {
|
|
5273
|
+
return BACKUP_DIR;
|
|
5274
|
+
}
|
|
5275
|
+
var BACKUP_DIR, DEFAULT_KEEP_DAYS, DB_NAMES;
|
|
5276
|
+
var init_db_backup = __esm({
|
|
5277
|
+
"src/lib/db-backup.ts"() {
|
|
5278
|
+
"use strict";
|
|
5279
|
+
init_config();
|
|
5280
|
+
BACKUP_DIR = path13.join(EXE_AI_DIR, "backups");
|
|
5281
|
+
DEFAULT_KEEP_DAYS = 3;
|
|
5282
|
+
DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
|
|
5283
|
+
}
|
|
5284
|
+
});
|
|
5285
|
+
|
|
5006
5286
|
// src/lib/cloud-sync.ts
|
|
5007
5287
|
var cloud_sync_exports = {};
|
|
5008
5288
|
__export(cloud_sync_exports, {
|
|
@@ -5032,16 +5312,16 @@ __export(cloud_sync_exports, {
|
|
|
5032
5312
|
pushToPostgres: () => pushToPostgres,
|
|
5033
5313
|
recordRosterDeletion: () => recordRosterDeletion
|
|
5034
5314
|
});
|
|
5035
|
-
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, existsSync as
|
|
5315
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, existsSync as existsSync14, readdirSync as readdirSync2, mkdirSync as mkdirSync7, appendFileSync, unlinkSync as unlinkSync5, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
5036
5316
|
import crypto4 from "crypto";
|
|
5037
|
-
import
|
|
5317
|
+
import path14 from "path";
|
|
5038
5318
|
import { homedir as homedir2 } from "os";
|
|
5039
5319
|
function sqlSafe(v) {
|
|
5040
5320
|
return v === void 0 ? null : v;
|
|
5041
5321
|
}
|
|
5042
5322
|
function logError(msg) {
|
|
5043
5323
|
try {
|
|
5044
|
-
const logPath =
|
|
5324
|
+
const logPath = path14.join(homedir2(), ".exe-os", "workers.log");
|
|
5045
5325
|
appendFileSync(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
5046
5326
|
`);
|
|
5047
5327
|
} catch {
|
|
@@ -5050,10 +5330,10 @@ function logError(msg) {
|
|
|
5050
5330
|
function loadPgClient() {
|
|
5051
5331
|
if (_pgFailed) return null;
|
|
5052
5332
|
const postgresUrl = process.env.DATABASE_URL;
|
|
5053
|
-
const configPath =
|
|
5333
|
+
const configPath = path14.join(EXE_AI_DIR, "config.json");
|
|
5054
5334
|
let cloudPostgresUrl;
|
|
5055
5335
|
try {
|
|
5056
|
-
if (
|
|
5336
|
+
if (existsSync14(configPath)) {
|
|
5057
5337
|
const cfg = JSON.parse(readFileSync10(configPath, "utf8"));
|
|
5058
5338
|
cloudPostgresUrl = cfg.cloud?.postgresUrl;
|
|
5059
5339
|
if (cfg.cloud?.syncToPostgres === false) {
|
|
@@ -5072,8 +5352,8 @@ function loadPgClient() {
|
|
|
5072
5352
|
_pgPromise = (async () => {
|
|
5073
5353
|
const { createRequire: createRequire3 } = await import("module");
|
|
5074
5354
|
const { pathToFileURL: pathToFileURL3 } = await import("url");
|
|
5075
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
5076
|
-
const req = createRequire3(
|
|
5355
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path14.join(homedir2(), "exe-db");
|
|
5356
|
+
const req = createRequire3(path14.join(exeDbRoot, "package.json"));
|
|
5077
5357
|
const entry = req.resolve("@prisma/client");
|
|
5078
5358
|
const mod = await import(pathToFileURL3(entry).href);
|
|
5079
5359
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -5126,7 +5406,7 @@ async function withRosterLock(fn) {
|
|
|
5126
5406
|
if (Date.now() - ts < LOCK_STALE_MS) {
|
|
5127
5407
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
5128
5408
|
}
|
|
5129
|
-
|
|
5409
|
+
unlinkSync5(ROSTER_LOCK_PATH);
|
|
5130
5410
|
const fd = openSync2(ROSTER_LOCK_PATH, "wx");
|
|
5131
5411
|
closeSync2(fd);
|
|
5132
5412
|
writeFileSync8(ROSTER_LOCK_PATH, String(Date.now()));
|
|
@@ -5142,7 +5422,7 @@ async function withRosterLock(fn) {
|
|
|
5142
5422
|
return await fn();
|
|
5143
5423
|
} finally {
|
|
5144
5424
|
try {
|
|
5145
|
-
|
|
5425
|
+
unlinkSync5(ROSTER_LOCK_PATH);
|
|
5146
5426
|
} catch {
|
|
5147
5427
|
}
|
|
5148
5428
|
}
|
|
@@ -5513,13 +5793,42 @@ async function cloudSync(config) {
|
|
|
5513
5793
|
try {
|
|
5514
5794
|
const employees = await loadEmployees();
|
|
5515
5795
|
rosterResult.employees = employees.length;
|
|
5516
|
-
const idDir =
|
|
5517
|
-
if (
|
|
5518
|
-
rosterResult.identities =
|
|
5796
|
+
const idDir = path14.join(EXE_AI_DIR, "identity");
|
|
5797
|
+
if (existsSync14(idDir)) {
|
|
5798
|
+
rosterResult.identities = readdirSync2(idDir).filter((f) => f.endsWith(".md")).length;
|
|
5519
5799
|
}
|
|
5520
5800
|
} catch {
|
|
5521
5801
|
}
|
|
5522
5802
|
const totalMemories = await countRows("SELECT COUNT(*) as cnt FROM memories WHERE status = 'active' OR status IS NULL");
|
|
5803
|
+
try {
|
|
5804
|
+
const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
|
|
5805
|
+
const { statSync: statFile } = await import("fs");
|
|
5806
|
+
const latestBackup = getLatestBackup2();
|
|
5807
|
+
if (latestBackup) {
|
|
5808
|
+
const backupSize = statFile(latestBackup).size;
|
|
5809
|
+
const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
|
|
5810
|
+
if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
|
|
5811
|
+
const backupData = readFileSync10(latestBackup);
|
|
5812
|
+
const deviceId = loadDeviceId() ?? "unknown";
|
|
5813
|
+
const encrypted = encryptSyncBlob(backupData);
|
|
5814
|
+
const backupRes = await fetchWithRetry(`${config.endpoint}/sync/push-db-backup`, {
|
|
5815
|
+
method: "POST",
|
|
5816
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${config.apiKey}` },
|
|
5817
|
+
body: JSON.stringify({
|
|
5818
|
+
device_id: deviceId,
|
|
5819
|
+
filename: path14.basename(latestBackup),
|
|
5820
|
+
blob: encrypted,
|
|
5821
|
+
size: backupData.length
|
|
5822
|
+
})
|
|
5823
|
+
});
|
|
5824
|
+
if (backupRes && !backupRes.ok) {
|
|
5825
|
+
logError(`[cloud-sync] DB backup upload failed: ${backupRes.status}`);
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
} catch (err) {
|
|
5830
|
+
logError(`[cloud-sync] DB backup upload error: ${err instanceof Error ? err.message : String(err)}`);
|
|
5831
|
+
}
|
|
5523
5832
|
return {
|
|
5524
5833
|
pushed,
|
|
5525
5834
|
pulled,
|
|
@@ -5535,7 +5844,7 @@ async function cloudSync(config) {
|
|
|
5535
5844
|
function recordRosterDeletion(name) {
|
|
5536
5845
|
let deletions = [];
|
|
5537
5846
|
try {
|
|
5538
|
-
if (
|
|
5847
|
+
if (existsSync14(ROSTER_DELETIONS_PATH)) {
|
|
5539
5848
|
deletions = JSON.parse(readFileSync10(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
5540
5849
|
}
|
|
5541
5850
|
} catch {
|
|
@@ -5545,7 +5854,7 @@ function recordRosterDeletion(name) {
|
|
|
5545
5854
|
}
|
|
5546
5855
|
function consumeRosterDeletions() {
|
|
5547
5856
|
try {
|
|
5548
|
-
if (!
|
|
5857
|
+
if (!existsSync14(ROSTER_DELETIONS_PATH)) return [];
|
|
5549
5858
|
const deletions = JSON.parse(readFileSync10(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
5550
5859
|
writeFileSync8(ROSTER_DELETIONS_PATH, "[]");
|
|
5551
5860
|
return deletions;
|
|
@@ -5554,35 +5863,35 @@ function consumeRosterDeletions() {
|
|
|
5554
5863
|
}
|
|
5555
5864
|
}
|
|
5556
5865
|
function buildRosterBlob(paths) {
|
|
5557
|
-
const rosterPath = paths?.rosterPath ??
|
|
5558
|
-
const identityDir = paths?.identityDir ??
|
|
5559
|
-
const configPath = paths?.configPath ??
|
|
5866
|
+
const rosterPath = paths?.rosterPath ?? path14.join(EXE_AI_DIR, "exe-employees.json");
|
|
5867
|
+
const identityDir = paths?.identityDir ?? path14.join(EXE_AI_DIR, "identity");
|
|
5868
|
+
const configPath = paths?.configPath ?? path14.join(EXE_AI_DIR, "config.json");
|
|
5560
5869
|
let roster = [];
|
|
5561
|
-
if (
|
|
5870
|
+
if (existsSync14(rosterPath)) {
|
|
5562
5871
|
try {
|
|
5563
5872
|
roster = JSON.parse(readFileSync10(rosterPath, "utf-8"));
|
|
5564
5873
|
} catch {
|
|
5565
5874
|
}
|
|
5566
5875
|
}
|
|
5567
5876
|
const identities = {};
|
|
5568
|
-
if (
|
|
5569
|
-
for (const file of
|
|
5877
|
+
if (existsSync14(identityDir)) {
|
|
5878
|
+
for (const file of readdirSync2(identityDir).filter((f) => f.endsWith(".md"))) {
|
|
5570
5879
|
try {
|
|
5571
|
-
identities[file] = readFileSync10(
|
|
5880
|
+
identities[file] = readFileSync10(path14.join(identityDir, file), "utf-8");
|
|
5572
5881
|
} catch {
|
|
5573
5882
|
}
|
|
5574
5883
|
}
|
|
5575
5884
|
}
|
|
5576
5885
|
let config;
|
|
5577
|
-
if (
|
|
5886
|
+
if (existsSync14(configPath)) {
|
|
5578
5887
|
try {
|
|
5579
5888
|
config = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
5580
5889
|
} catch {
|
|
5581
5890
|
}
|
|
5582
5891
|
}
|
|
5583
5892
|
let agentConfig;
|
|
5584
|
-
const agentConfigPath =
|
|
5585
|
-
if (
|
|
5893
|
+
const agentConfigPath = path14.join(EXE_AI_DIR, "agent-config.json");
|
|
5894
|
+
if (existsSync14(agentConfigPath)) {
|
|
5586
5895
|
try {
|
|
5587
5896
|
agentConfig = JSON.parse(readFileSync10(agentConfigPath, "utf-8"));
|
|
5588
5897
|
} catch {
|
|
@@ -5660,16 +5969,16 @@ async function cloudPullRoster(config) {
|
|
|
5660
5969
|
}
|
|
5661
5970
|
}
|
|
5662
5971
|
function mergeConfig(remoteConfig, configPath) {
|
|
5663
|
-
const cfgPath = configPath ??
|
|
5972
|
+
const cfgPath = configPath ?? path14.join(EXE_AI_DIR, "config.json");
|
|
5664
5973
|
let local = {};
|
|
5665
|
-
if (
|
|
5974
|
+
if (existsSync14(cfgPath)) {
|
|
5666
5975
|
try {
|
|
5667
5976
|
local = JSON.parse(readFileSync10(cfgPath, "utf-8"));
|
|
5668
5977
|
} catch {
|
|
5669
5978
|
}
|
|
5670
5979
|
}
|
|
5671
5980
|
const merged = { ...remoteConfig, ...local };
|
|
5672
|
-
const dir =
|
|
5981
|
+
const dir = path14.dirname(cfgPath);
|
|
5673
5982
|
ensurePrivateDirSync(dir);
|
|
5674
5983
|
writeFileSync8(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
5675
5984
|
enforcePrivateFileSync(cfgPath);
|
|
@@ -5677,7 +5986,7 @@ function mergeConfig(remoteConfig, configPath) {
|
|
|
5677
5986
|
async function mergeRosterFromRemote(remote, paths) {
|
|
5678
5987
|
return withRosterLock(async () => {
|
|
5679
5988
|
const rosterPath = paths?.rosterPath ?? void 0;
|
|
5680
|
-
const identityDir = paths?.identityDir ??
|
|
5989
|
+
const identityDir = paths?.identityDir ?? path14.join(EXE_AI_DIR, "identity");
|
|
5681
5990
|
const localEmployees = await loadEmployees(rosterPath);
|
|
5682
5991
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
5683
5992
|
let added = 0;
|
|
@@ -5698,11 +6007,11 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
5698
6007
|
) ?? lookupKey;
|
|
5699
6008
|
const remoteIdentity = remote.identities[matchedKey];
|
|
5700
6009
|
if (remoteIdentity) {
|
|
5701
|
-
if (!
|
|
5702
|
-
const idPath =
|
|
6010
|
+
if (!existsSync14(identityDir)) mkdirSync7(identityDir, { recursive: true });
|
|
6011
|
+
const idPath = path14.join(identityDir, `${remoteEmp.name}.md`);
|
|
5703
6012
|
let localIdentity = null;
|
|
5704
6013
|
try {
|
|
5705
|
-
localIdentity =
|
|
6014
|
+
localIdentity = existsSync14(idPath) ? readFileSync10(idPath, "utf-8") : null;
|
|
5706
6015
|
} catch {
|
|
5707
6016
|
}
|
|
5708
6017
|
if (localIdentity !== remoteIdentity) {
|
|
@@ -5732,16 +6041,16 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
5732
6041
|
}
|
|
5733
6042
|
if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
|
|
5734
6043
|
try {
|
|
5735
|
-
const agentConfigPath =
|
|
6044
|
+
const agentConfigPath = path14.join(EXE_AI_DIR, "agent-config.json");
|
|
5736
6045
|
let local = {};
|
|
5737
|
-
if (
|
|
6046
|
+
if (existsSync14(agentConfigPath)) {
|
|
5738
6047
|
try {
|
|
5739
6048
|
local = JSON.parse(readFileSync10(agentConfigPath, "utf-8"));
|
|
5740
6049
|
} catch {
|
|
5741
6050
|
}
|
|
5742
6051
|
}
|
|
5743
6052
|
const merged = { ...remote.agentConfig, ...local };
|
|
5744
|
-
ensurePrivateDirSync(
|
|
6053
|
+
ensurePrivateDirSync(path14.dirname(agentConfigPath));
|
|
5745
6054
|
writeFileSync8(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
5746
6055
|
enforcePrivateFileSync(agentConfigPath);
|
|
5747
6056
|
} catch {
|
|
@@ -6182,11 +6491,11 @@ var init_cloud_sync = __esm({
|
|
|
6182
6491
|
LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
|
|
6183
6492
|
FETCH_TIMEOUT_MS = 3e4;
|
|
6184
6493
|
PUSH_BATCH_SIZE = 5e3;
|
|
6185
|
-
ROSTER_LOCK_PATH =
|
|
6494
|
+
ROSTER_LOCK_PATH = path14.join(EXE_AI_DIR, "roster-merge.lock");
|
|
6186
6495
|
LOCK_STALE_MS = 3e4;
|
|
6187
6496
|
_pgPromise = null;
|
|
6188
6497
|
_pgFailed = false;
|
|
6189
|
-
ROSTER_DELETIONS_PATH =
|
|
6498
|
+
ROSTER_DELETIONS_PATH = path14.join(EXE_AI_DIR, "roster-deletions.json");
|
|
6190
6499
|
}
|
|
6191
6500
|
});
|
|
6192
6501
|
|
|
@@ -6484,13 +6793,13 @@ __export(shard_manager_exports, {
|
|
|
6484
6793
|
listShards: () => listShards,
|
|
6485
6794
|
shardExists: () => shardExists
|
|
6486
6795
|
});
|
|
6487
|
-
import
|
|
6488
|
-
import { existsSync as
|
|
6796
|
+
import path15 from "path";
|
|
6797
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync3 } from "fs";
|
|
6489
6798
|
import { createClient as createClient2 } from "@libsql/client";
|
|
6490
6799
|
function initShardManager(encryptionKey) {
|
|
6491
6800
|
_encryptionKey = encryptionKey;
|
|
6492
|
-
if (!
|
|
6493
|
-
|
|
6801
|
+
if (!existsSync15(SHARDS_DIR)) {
|
|
6802
|
+
mkdirSync8(SHARDS_DIR, { recursive: true });
|
|
6494
6803
|
}
|
|
6495
6804
|
_shardingEnabled = true;
|
|
6496
6805
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
@@ -6519,7 +6828,7 @@ function getShardClient(projectName) {
|
|
|
6519
6828
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
6520
6829
|
evictLRU();
|
|
6521
6830
|
}
|
|
6522
|
-
const dbPath =
|
|
6831
|
+
const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
|
|
6523
6832
|
const client = createClient2({
|
|
6524
6833
|
url: `file:${dbPath}`,
|
|
6525
6834
|
encryptionKey: _encryptionKey
|
|
@@ -6530,11 +6839,11 @@ function getShardClient(projectName) {
|
|
|
6530
6839
|
}
|
|
6531
6840
|
function shardExists(projectName) {
|
|
6532
6841
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6533
|
-
return
|
|
6842
|
+
return existsSync15(path15.join(SHARDS_DIR, `${safeName}.db`));
|
|
6534
6843
|
}
|
|
6535
6844
|
function listShards() {
|
|
6536
|
-
if (!
|
|
6537
|
-
return
|
|
6845
|
+
if (!existsSync15(SHARDS_DIR)) return [];
|
|
6846
|
+
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
6538
6847
|
}
|
|
6539
6848
|
async function ensureShardSchema(client) {
|
|
6540
6849
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
@@ -6780,7 +7089,7 @@ var init_shard_manager = __esm({
|
|
|
6780
7089
|
"src/lib/shard-manager.ts"() {
|
|
6781
7090
|
"use strict";
|
|
6782
7091
|
init_config();
|
|
6783
|
-
SHARDS_DIR =
|
|
7092
|
+
SHARDS_DIR = path15.join(EXE_AI_DIR, "shards");
|
|
6784
7093
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
6785
7094
|
MAX_OPEN_SHARDS = 10;
|
|
6786
7095
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -7650,12 +7959,12 @@ __export(backfill_conversations_exports, {
|
|
|
7650
7959
|
import crypto5 from "crypto";
|
|
7651
7960
|
import { createReadStream } from "fs";
|
|
7652
7961
|
import { readdir as readdir2, stat } from "fs/promises";
|
|
7653
|
-
import
|
|
7962
|
+
import path16 from "path";
|
|
7654
7963
|
import { createInterface as createInterface2 } from "readline";
|
|
7655
7964
|
import { homedir as homedir3 } from "os";
|
|
7656
7965
|
import { parseArgs } from "util";
|
|
7657
7966
|
async function findJsonlFiles(sinceDate, projectFilter) {
|
|
7658
|
-
const projectsDir =
|
|
7967
|
+
const projectsDir = path16.join(homedir3(), ".claude", "projects");
|
|
7659
7968
|
const files = [];
|
|
7660
7969
|
async function walk(dir, depth = 0) {
|
|
7661
7970
|
if (depth > MAX_WALK_DEPTH) return;
|
|
@@ -7666,7 +7975,7 @@ async function findJsonlFiles(sinceDate, projectFilter) {
|
|
|
7666
7975
|
return;
|
|
7667
7976
|
}
|
|
7668
7977
|
for (const entry of entries) {
|
|
7669
|
-
const full =
|
|
7978
|
+
const full = path16.join(dir, entry.name);
|
|
7670
7979
|
if (entry.isDirectory()) {
|
|
7671
7980
|
if (entry.name === "subagents" || entry.name === "tool-results") continue;
|
|
7672
7981
|
await walk(full, depth + 1);
|
|
@@ -7691,7 +8000,7 @@ async function findJsonlFiles(sinceDate, projectFilter) {
|
|
|
7691
8000
|
if (!entry.isDirectory()) continue;
|
|
7692
8001
|
const decoded = decodeProjectDir(entry.name);
|
|
7693
8002
|
if (decoded.toLowerCase().includes(projectFilter.toLowerCase())) {
|
|
7694
|
-
await walk(
|
|
8003
|
+
await walk(path16.join(projectsDir, entry.name));
|
|
7695
8004
|
}
|
|
7696
8005
|
}
|
|
7697
8006
|
} else {
|
|
@@ -7708,14 +8017,14 @@ function decodeProjectDir(dirName) {
|
|
|
7708
8017
|
return dirName;
|
|
7709
8018
|
}
|
|
7710
8019
|
function projectNameFromPath(filePath) {
|
|
7711
|
-
const projectsDir =
|
|
7712
|
-
const relative =
|
|
7713
|
-
const projectDir = relative.split(
|
|
8020
|
+
const projectsDir = path16.join(homedir3(), ".claude", "projects");
|
|
8021
|
+
const relative = path16.relative(projectsDir, filePath);
|
|
8022
|
+
const projectDir = relative.split(path16.sep)[0] ?? "unknown";
|
|
7714
8023
|
return decodeProjectDir(projectDir);
|
|
7715
8024
|
}
|
|
7716
8025
|
async function parseConversation(filePath) {
|
|
7717
8026
|
const conv = {
|
|
7718
|
-
sessionId:
|
|
8027
|
+
sessionId: path16.basename(filePath, ".jsonl"),
|
|
7719
8028
|
projectName: projectNameFromPath(filePath),
|
|
7720
8029
|
cwd: void 0,
|
|
7721
8030
|
startTime: void 0,
|
|
@@ -7779,7 +8088,7 @@ async function parseConversation(filePath) {
|
|
|
7779
8088
|
}
|
|
7780
8089
|
}
|
|
7781
8090
|
if (conv.cwd) {
|
|
7782
|
-
conv.projectName =
|
|
8091
|
+
conv.projectName = path16.basename(conv.cwd);
|
|
7783
8092
|
const worktreeMatch = conv.cwd.match(/\.worktrees\/([^/]+)/);
|
|
7784
8093
|
if (worktreeMatch?.[1]) {
|
|
7785
8094
|
conv.agentId = worktreeMatch[1];
|
|
@@ -8431,9 +8740,9 @@ Unclassified: ${unclassified}
|
|
|
8431
8740
|
}
|
|
8432
8741
|
async function exportBatches(options) {
|
|
8433
8742
|
const fs8 = await import("fs");
|
|
8434
|
-
const
|
|
8743
|
+
const path48 = await import("path");
|
|
8435
8744
|
const client = getClient();
|
|
8436
|
-
const outDir =
|
|
8745
|
+
const outDir = path48.join(process.cwd(), "exe/output/classifications/input");
|
|
8437
8746
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
8438
8747
|
const countResult = await client.execute({
|
|
8439
8748
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -8457,7 +8766,7 @@ async function exportBatches(options) {
|
|
|
8457
8766
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
8458
8767
|
return JSON.stringify({ id: row.id, text });
|
|
8459
8768
|
});
|
|
8460
|
-
const batchFile =
|
|
8769
|
+
const batchFile = path48.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
8461
8770
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
8462
8771
|
exported += batch.rows.length;
|
|
8463
8772
|
offset += options.batchSize;
|
|
@@ -8473,7 +8782,7 @@ async function exportBatches(options) {
|
|
|
8473
8782
|
}
|
|
8474
8783
|
async function importClassifications(importDir) {
|
|
8475
8784
|
const fs8 = await import("fs");
|
|
8476
|
-
const
|
|
8785
|
+
const path48 = await import("path");
|
|
8477
8786
|
const client = getClient();
|
|
8478
8787
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
8479
8788
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -8481,7 +8790,7 @@ async function importClassifications(importDir) {
|
|
|
8481
8790
|
let imported = 0;
|
|
8482
8791
|
let invalid = 0;
|
|
8483
8792
|
for (const file of files) {
|
|
8484
|
-
const lines = fs8.readFileSync(
|
|
8793
|
+
const lines = fs8.readFileSync(path48.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
8485
8794
|
for (const line of lines) {
|
|
8486
8795
|
try {
|
|
8487
8796
|
const rec = JSON.parse(line);
|
|
@@ -8622,17 +8931,17 @@ __export(identity_exports, {
|
|
|
8622
8931
|
listIdentities: () => listIdentities,
|
|
8623
8932
|
updateIdentity: () => updateIdentity
|
|
8624
8933
|
});
|
|
8625
|
-
import { existsSync as
|
|
8626
|
-
import { readdirSync as
|
|
8627
|
-
import
|
|
8934
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
8935
|
+
import { readdirSync as readdirSync4 } from "fs";
|
|
8936
|
+
import path17 from "path";
|
|
8628
8937
|
import { createHash as createHash2 } from "crypto";
|
|
8629
8938
|
function ensureDir() {
|
|
8630
|
-
if (!
|
|
8631
|
-
|
|
8939
|
+
if (!existsSync16(IDENTITY_DIR2)) {
|
|
8940
|
+
mkdirSync9(IDENTITY_DIR2, { recursive: true });
|
|
8632
8941
|
}
|
|
8633
8942
|
}
|
|
8634
8943
|
function identityPath(agentId) {
|
|
8635
|
-
return
|
|
8944
|
+
return path17.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
8636
8945
|
}
|
|
8637
8946
|
function parseFrontmatter(raw) {
|
|
8638
8947
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
@@ -8673,7 +8982,7 @@ function contentHash(content) {
|
|
|
8673
8982
|
}
|
|
8674
8983
|
function getIdentity(agentId) {
|
|
8675
8984
|
const filePath = identityPath(agentId);
|
|
8676
|
-
if (!
|
|
8985
|
+
if (!existsSync16(filePath)) return null;
|
|
8677
8986
|
const raw = readFileSync11(filePath, "utf-8");
|
|
8678
8987
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
8679
8988
|
return {
|
|
@@ -8705,7 +9014,7 @@ async function updateIdentity(agentId, content, updatedBy) {
|
|
|
8705
9014
|
}
|
|
8706
9015
|
function listIdentities() {
|
|
8707
9016
|
ensureDir();
|
|
8708
|
-
const files =
|
|
9017
|
+
const files = readdirSync4(IDENTITY_DIR2).filter((f) => f.endsWith(".md"));
|
|
8709
9018
|
const results = [];
|
|
8710
9019
|
for (const file of files) {
|
|
8711
9020
|
const agentId = file.replace(".md", "");
|
|
@@ -8744,15 +9053,15 @@ var init_identity = __esm({
|
|
|
8744
9053
|
"use strict";
|
|
8745
9054
|
init_config();
|
|
8746
9055
|
init_database();
|
|
8747
|
-
IDENTITY_DIR2 =
|
|
9056
|
+
IDENTITY_DIR2 = path17.join(EXE_AI_DIR, "identity");
|
|
8748
9057
|
}
|
|
8749
9058
|
});
|
|
8750
9059
|
|
|
8751
9060
|
// src/lib/orchestration-package.ts
|
|
8752
9061
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
8753
|
-
import { copyFileSync as
|
|
9062
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
8754
9063
|
import os10 from "os";
|
|
8755
|
-
import
|
|
9064
|
+
import path18 from "path";
|
|
8756
9065
|
function ensureObject(value, label) {
|
|
8757
9066
|
if (value == null || Array.isArray(value) || typeof value !== "object") {
|
|
8758
9067
|
throw new Error(`${label} must be an object`);
|
|
@@ -8811,14 +9120,14 @@ function validateProcedureEntry(value, index) {
|
|
|
8811
9120
|
};
|
|
8812
9121
|
}
|
|
8813
9122
|
function getRosterPath() {
|
|
8814
|
-
return
|
|
9123
|
+
return path18.join(os10.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
|
|
8815
9124
|
}
|
|
8816
9125
|
function getBackupPath() {
|
|
8817
|
-
return
|
|
9126
|
+
return path18.join(os10.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
|
|
8818
9127
|
}
|
|
8819
9128
|
function readRosterFile() {
|
|
8820
9129
|
const rosterPath = getRosterPath();
|
|
8821
|
-
if (!
|
|
9130
|
+
if (!existsSync17(rosterPath)) return [];
|
|
8822
9131
|
const raw = readFileSync12(rosterPath, "utf-8");
|
|
8823
9132
|
const parsed = JSON.parse(raw);
|
|
8824
9133
|
if (!Array.isArray(parsed)) {
|
|
@@ -8831,15 +9140,15 @@ function writeRosterFile(roster) {
|
|
|
8831
9140
|
throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
|
|
8832
9141
|
}
|
|
8833
9142
|
const rosterPath = getRosterPath();
|
|
8834
|
-
|
|
8835
|
-
if (
|
|
9143
|
+
mkdirSync10(path18.dirname(rosterPath), { recursive: true });
|
|
9144
|
+
if (existsSync17(rosterPath)) {
|
|
8836
9145
|
const currentRoster = readRosterFile();
|
|
8837
9146
|
if (roster.length < currentRoster.length) {
|
|
8838
9147
|
throw new Error(
|
|
8839
9148
|
`Refusing to write roster with ${roster.length} entries \u2014 current roster has ${currentRoster.length}. Import would delete ${currentRoster.length - roster.length} employee(s). Use merge strategy instead, or add the missing entries to the package.`
|
|
8840
9149
|
);
|
|
8841
9150
|
}
|
|
8842
|
-
|
|
9151
|
+
copyFileSync3(rosterPath, getBackupPath());
|
|
8843
9152
|
}
|
|
8844
9153
|
writeFileSync10(rosterPath, `${JSON.stringify(roster, null, 2)}
|
|
8845
9154
|
`, "utf-8");
|
|
@@ -9108,8 +9417,8 @@ var exe_export_exports = {};
|
|
|
9108
9417
|
__export(exe_export_exports, {
|
|
9109
9418
|
runExeExport: () => runExeExport
|
|
9110
9419
|
});
|
|
9111
|
-
import { mkdirSync as
|
|
9112
|
-
import
|
|
9420
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
9421
|
+
import path19 from "path";
|
|
9113
9422
|
function printUsage() {
|
|
9114
9423
|
process.stdout.write("Usage: exe-os export --output <path>\n");
|
|
9115
9424
|
}
|
|
@@ -9130,7 +9439,7 @@ async function runExeExport(argv = process.argv.slice(2)) {
|
|
|
9130
9439
|
await initStore();
|
|
9131
9440
|
try {
|
|
9132
9441
|
const pkg = await exportOrchestration("cli");
|
|
9133
|
-
|
|
9442
|
+
mkdirSync11(path19.dirname(outputPath), { recursive: true });
|
|
9134
9443
|
writeFileSync11(outputPath, `${JSON.stringify(pkg, null, 2)}
|
|
9135
9444
|
`, "utf-8");
|
|
9136
9445
|
process.stdout.write(
|
|
@@ -9231,14 +9540,14 @@ __export(session_registry_exports, {
|
|
|
9231
9540
|
refreshSessionProject: () => refreshSessionProject,
|
|
9232
9541
|
registerSession: () => registerSession
|
|
9233
9542
|
});
|
|
9234
|
-
import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, mkdirSync as
|
|
9235
|
-
import { execSync as
|
|
9236
|
-
import
|
|
9543
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, existsSync as existsSync18 } from "fs";
|
|
9544
|
+
import { execSync as execSync4 } from "child_process";
|
|
9545
|
+
import path20 from "path";
|
|
9237
9546
|
import os11 from "os";
|
|
9238
9547
|
function registerSession(entry) {
|
|
9239
|
-
const dir =
|
|
9240
|
-
if (!
|
|
9241
|
-
|
|
9548
|
+
const dir = path20.dirname(REGISTRY_PATH);
|
|
9549
|
+
if (!existsSync18(dir)) {
|
|
9550
|
+
mkdirSync12(dir, { recursive: true });
|
|
9242
9551
|
}
|
|
9243
9552
|
const sessions = listSessions();
|
|
9244
9553
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -9272,7 +9581,7 @@ function pruneStaleSessions() {
|
|
|
9272
9581
|
if (sessions.length === 0) return 0;
|
|
9273
9582
|
let liveSessions = [];
|
|
9274
9583
|
try {
|
|
9275
|
-
liveSessions =
|
|
9584
|
+
liveSessions = execSync4("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
9276
9585
|
encoding: "utf8"
|
|
9277
9586
|
}).trim().split("\n").filter(Boolean);
|
|
9278
9587
|
} catch {
|
|
@@ -9290,12 +9599,12 @@ var REGISTRY_PATH;
|
|
|
9290
9599
|
var init_session_registry = __esm({
|
|
9291
9600
|
"src/lib/session-registry.ts"() {
|
|
9292
9601
|
"use strict";
|
|
9293
|
-
REGISTRY_PATH =
|
|
9602
|
+
REGISTRY_PATH = path20.join(os11.homedir(), ".exe-os", "session-registry.json");
|
|
9294
9603
|
}
|
|
9295
9604
|
});
|
|
9296
9605
|
|
|
9297
9606
|
// src/lib/session-key.ts
|
|
9298
|
-
import { execSync as
|
|
9607
|
+
import { execSync as execSync5 } from "child_process";
|
|
9299
9608
|
function normalizeCommand(command) {
|
|
9300
9609
|
const trimmed = command.trim().toLowerCase();
|
|
9301
9610
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -9314,7 +9623,7 @@ function resolveRuntimeProcess() {
|
|
|
9314
9623
|
let pid = process.ppid;
|
|
9315
9624
|
for (let i = 0; i < 10; i++) {
|
|
9316
9625
|
try {
|
|
9317
|
-
const info =
|
|
9626
|
+
const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
|
|
9318
9627
|
encoding: "utf8",
|
|
9319
9628
|
timeout: 2e3
|
|
9320
9629
|
}).trim();
|
|
@@ -9488,14 +9797,14 @@ var init_transport = __esm({
|
|
|
9488
9797
|
});
|
|
9489
9798
|
|
|
9490
9799
|
// src/lib/cc-agent-support.ts
|
|
9491
|
-
import { execSync as
|
|
9800
|
+
import { execSync as execSync6 } from "child_process";
|
|
9492
9801
|
function _resetCcAgentSupportCache() {
|
|
9493
9802
|
_cachedSupport = null;
|
|
9494
9803
|
}
|
|
9495
9804
|
function claudeSupportsAgentFlag() {
|
|
9496
9805
|
if (_cachedSupport !== null) return _cachedSupport;
|
|
9497
9806
|
try {
|
|
9498
|
-
const helpOutput =
|
|
9807
|
+
const helpOutput = execSync6("claude --help 2>&1", {
|
|
9499
9808
|
encoding: "utf-8",
|
|
9500
9809
|
timeout: 5e3
|
|
9501
9810
|
});
|
|
@@ -9546,16 +9855,16 @@ __export(intercom_queue_exports, {
|
|
|
9546
9855
|
queueIntercom: () => queueIntercom,
|
|
9547
9856
|
readQueue: () => readQueue
|
|
9548
9857
|
});
|
|
9549
|
-
import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as renameSync3, existsSync as
|
|
9550
|
-
import
|
|
9858
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as renameSync3, existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
|
|
9859
|
+
import path21 from "path";
|
|
9551
9860
|
import os12 from "os";
|
|
9552
9861
|
function ensureDir2() {
|
|
9553
|
-
const dir =
|
|
9554
|
-
if (!
|
|
9862
|
+
const dir = path21.dirname(QUEUE_PATH);
|
|
9863
|
+
if (!existsSync19(dir)) mkdirSync13(dir, { recursive: true });
|
|
9555
9864
|
}
|
|
9556
9865
|
function readQueue() {
|
|
9557
9866
|
try {
|
|
9558
|
-
if (!
|
|
9867
|
+
if (!existsSync19(QUEUE_PATH)) return [];
|
|
9559
9868
|
return JSON.parse(readFileSync15(QUEUE_PATH, "utf8"));
|
|
9560
9869
|
} catch {
|
|
9561
9870
|
return [];
|
|
@@ -9656,19 +9965,19 @@ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
|
9656
9965
|
var init_intercom_queue = __esm({
|
|
9657
9966
|
"src/lib/intercom-queue.ts"() {
|
|
9658
9967
|
"use strict";
|
|
9659
|
-
QUEUE_PATH =
|
|
9968
|
+
QUEUE_PATH = path21.join(os12.homedir(), ".exe-os", "intercom-queue.json");
|
|
9660
9969
|
MAX_RETRIES2 = 5;
|
|
9661
9970
|
TTL_MS = 60 * 60 * 1e3;
|
|
9662
|
-
INTERCOM_LOG =
|
|
9971
|
+
INTERCOM_LOG = path21.join(os12.homedir(), ".exe-os", "intercom.log");
|
|
9663
9972
|
}
|
|
9664
9973
|
});
|
|
9665
9974
|
|
|
9666
9975
|
// src/lib/plan-limits.ts
|
|
9667
|
-
import { readFileSync as readFileSync16, existsSync as
|
|
9668
|
-
import
|
|
9976
|
+
import { readFileSync as readFileSync16, existsSync as existsSync20 } from "fs";
|
|
9977
|
+
import path22 from "path";
|
|
9669
9978
|
function getLicenseSync() {
|
|
9670
9979
|
try {
|
|
9671
|
-
if (!
|
|
9980
|
+
if (!existsSync20(CACHE_PATH2)) return freeLicense();
|
|
9672
9981
|
const raw = JSON.parse(readFileSync16(CACHE_PATH2, "utf8"));
|
|
9673
9982
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
9674
9983
|
const parts = raw.token.split(".");
|
|
@@ -9707,7 +10016,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
9707
10016
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
9708
10017
|
let count = 0;
|
|
9709
10018
|
try {
|
|
9710
|
-
if (
|
|
10019
|
+
if (existsSync20(filePath)) {
|
|
9711
10020
|
const raw = readFileSync16(filePath, "utf8");
|
|
9712
10021
|
const employees = JSON.parse(raw);
|
|
9713
10022
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
@@ -9737,7 +10046,7 @@ var init_plan_limits = __esm({
|
|
|
9737
10046
|
this.name = "PlanLimitError";
|
|
9738
10047
|
}
|
|
9739
10048
|
};
|
|
9740
|
-
CACHE_PATH2 =
|
|
10049
|
+
CACHE_PATH2 = path22.join(EXE_AI_DIR, "license-cache.json");
|
|
9741
10050
|
}
|
|
9742
10051
|
});
|
|
9743
10052
|
|
|
@@ -9782,13 +10091,13 @@ var init_task_scope = __esm({
|
|
|
9782
10091
|
|
|
9783
10092
|
// src/lib/notifications.ts
|
|
9784
10093
|
import crypto6 from "crypto";
|
|
9785
|
-
import
|
|
10094
|
+
import path23 from "path";
|
|
9786
10095
|
import os13 from "os";
|
|
9787
10096
|
import {
|
|
9788
10097
|
readFileSync as readFileSync17,
|
|
9789
|
-
readdirSync as
|
|
9790
|
-
unlinkSync as
|
|
9791
|
-
existsSync as
|
|
10098
|
+
readdirSync as readdirSync5,
|
|
10099
|
+
unlinkSync as unlinkSync6,
|
|
10100
|
+
existsSync as existsSync21,
|
|
9792
10101
|
rmdirSync
|
|
9793
10102
|
} from "fs";
|
|
9794
10103
|
async function writeNotification(notification) {
|
|
@@ -9872,34 +10181,34 @@ var init_session_kill_telemetry = __esm({
|
|
|
9872
10181
|
});
|
|
9873
10182
|
|
|
9874
10183
|
// src/lib/project-name.ts
|
|
9875
|
-
import { execSync as
|
|
9876
|
-
import
|
|
10184
|
+
import { execSync as execSync7 } from "child_process";
|
|
10185
|
+
import path24 from "path";
|
|
9877
10186
|
function getProjectName(cwd2) {
|
|
9878
10187
|
const dir = cwd2 ?? process.cwd();
|
|
9879
10188
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
9880
10189
|
try {
|
|
9881
10190
|
let repoRoot;
|
|
9882
10191
|
try {
|
|
9883
|
-
const gitCommonDir =
|
|
10192
|
+
const gitCommonDir = execSync7("git rev-parse --path-format=absolute --git-common-dir", {
|
|
9884
10193
|
cwd: dir,
|
|
9885
10194
|
encoding: "utf8",
|
|
9886
10195
|
timeout: 2e3,
|
|
9887
10196
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9888
10197
|
}).trim();
|
|
9889
|
-
repoRoot =
|
|
10198
|
+
repoRoot = path24.dirname(gitCommonDir);
|
|
9890
10199
|
} catch {
|
|
9891
|
-
repoRoot =
|
|
10200
|
+
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
9892
10201
|
cwd: dir,
|
|
9893
10202
|
encoding: "utf8",
|
|
9894
10203
|
timeout: 2e3,
|
|
9895
10204
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9896
10205
|
}).trim();
|
|
9897
10206
|
}
|
|
9898
|
-
_cached2 =
|
|
10207
|
+
_cached2 = path24.basename(repoRoot);
|
|
9899
10208
|
_cachedCwd = dir;
|
|
9900
10209
|
return _cached2;
|
|
9901
10210
|
} catch {
|
|
9902
|
-
_cached2 =
|
|
10211
|
+
_cached2 = path24.basename(dir);
|
|
9903
10212
|
_cachedCwd = dir;
|
|
9904
10213
|
return _cached2;
|
|
9905
10214
|
}
|
|
@@ -9993,11 +10302,11 @@ __export(tasks_crud_exports, {
|
|
|
9993
10302
|
writeCheckpoint: () => writeCheckpoint
|
|
9994
10303
|
});
|
|
9995
10304
|
import crypto8 from "crypto";
|
|
9996
|
-
import
|
|
10305
|
+
import path25 from "path";
|
|
9997
10306
|
import os14 from "os";
|
|
9998
|
-
import { execSync as
|
|
10307
|
+
import { execSync as execSync8 } from "child_process";
|
|
9999
10308
|
import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
10000
|
-
import { existsSync as
|
|
10309
|
+
import { existsSync as existsSync22, readFileSync as readFileSync18 } from "fs";
|
|
10001
10310
|
async function writeCheckpoint(input) {
|
|
10002
10311
|
const client = getClient();
|
|
10003
10312
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -10196,8 +10505,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
10196
10505
|
}
|
|
10197
10506
|
if (input.baseDir) {
|
|
10198
10507
|
try {
|
|
10199
|
-
await mkdir5(
|
|
10200
|
-
await mkdir5(
|
|
10508
|
+
await mkdir5(path25.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
10509
|
+
await mkdir5(path25.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
10201
10510
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
10202
10511
|
await ensureGitignoreExe(input.baseDir);
|
|
10203
10512
|
} catch {
|
|
@@ -10233,10 +10542,10 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
10233
10542
|
});
|
|
10234
10543
|
if (input.baseDir) {
|
|
10235
10544
|
try {
|
|
10236
|
-
const EXE_OS_DIR =
|
|
10237
|
-
const mdPath =
|
|
10238
|
-
const mdDir =
|
|
10239
|
-
if (!
|
|
10545
|
+
const EXE_OS_DIR = path25.join(os14.homedir(), ".exe-os");
|
|
10546
|
+
const mdPath = path25.join(EXE_OS_DIR, taskFile);
|
|
10547
|
+
const mdDir = path25.dirname(mdPath);
|
|
10548
|
+
if (!existsSync22(mdDir)) await mkdir5(mdDir, { recursive: true });
|
|
10240
10549
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
10241
10550
|
const mdContent = `# ${input.title}
|
|
10242
10551
|
|
|
@@ -10340,14 +10649,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
10340
10649
|
if (!identifier || identifier === "unknown") return true;
|
|
10341
10650
|
try {
|
|
10342
10651
|
if (identifier.startsWith("%")) {
|
|
10343
|
-
const output =
|
|
10652
|
+
const output = execSync8("tmux list-panes -a -F '#{pane_id}'", {
|
|
10344
10653
|
timeout: 2e3,
|
|
10345
10654
|
encoding: "utf8",
|
|
10346
10655
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10347
10656
|
});
|
|
10348
10657
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
10349
10658
|
} else {
|
|
10350
|
-
|
|
10659
|
+
execSync8(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
10351
10660
|
timeout: 2e3,
|
|
10352
10661
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10353
10662
|
});
|
|
@@ -10356,7 +10665,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
10356
10665
|
} catch {
|
|
10357
10666
|
if (identifier.startsWith("%")) return true;
|
|
10358
10667
|
try {
|
|
10359
|
-
|
|
10668
|
+
execSync8("tmux list-sessions", {
|
|
10360
10669
|
timeout: 2e3,
|
|
10361
10670
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10362
10671
|
});
|
|
@@ -10371,12 +10680,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
10371
10680
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
10372
10681
|
try {
|
|
10373
10682
|
const since = new Date(taskCreatedAt).toISOString();
|
|
10374
|
-
const branch =
|
|
10683
|
+
const branch = execSync8(
|
|
10375
10684
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
10376
10685
|
{ encoding: "utf8", timeout: 3e3 }
|
|
10377
10686
|
).trim();
|
|
10378
10687
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
10379
|
-
const commitCount =
|
|
10688
|
+
const commitCount = execSync8(
|
|
10380
10689
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
10381
10690
|
{ encoding: "utf8", timeout: 5e3 }
|
|
10382
10691
|
).trim();
|
|
@@ -10536,9 +10845,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
10536
10845
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
10537
10846
|
}
|
|
10538
10847
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
10539
|
-
const archPath =
|
|
10848
|
+
const archPath = path25.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
10540
10849
|
try {
|
|
10541
|
-
if (
|
|
10850
|
+
if (existsSync22(archPath)) return;
|
|
10542
10851
|
const template = [
|
|
10543
10852
|
`# ${projectName} \u2014 System Architecture`,
|
|
10544
10853
|
"",
|
|
@@ -10571,9 +10880,9 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
10571
10880
|
}
|
|
10572
10881
|
}
|
|
10573
10882
|
async function ensureGitignoreExe(baseDir) {
|
|
10574
|
-
const gitignorePath =
|
|
10883
|
+
const gitignorePath = path25.join(baseDir, ".gitignore");
|
|
10575
10884
|
try {
|
|
10576
|
-
if (
|
|
10885
|
+
if (existsSync22(gitignorePath)) {
|
|
10577
10886
|
const content = readFileSync18(gitignorePath, "utf-8");
|
|
10578
10887
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
10579
10888
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
@@ -10617,8 +10926,8 @@ __export(tasks_review_exports, {
|
|
|
10617
10926
|
isStale: () => isStale,
|
|
10618
10927
|
listPendingReviews: () => listPendingReviews
|
|
10619
10928
|
});
|
|
10620
|
-
import
|
|
10621
|
-
import { existsSync as
|
|
10929
|
+
import path26 from "path";
|
|
10930
|
+
import { existsSync as existsSync23, readdirSync as readdirSync6, unlinkSync as unlinkSync7 } from "fs";
|
|
10622
10931
|
function formatAge(isoTimestamp) {
|
|
10623
10932
|
if (!isoTimestamp) return "";
|
|
10624
10933
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -10887,11 +11196,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
10887
11196
|
);
|
|
10888
11197
|
}
|
|
10889
11198
|
try {
|
|
10890
|
-
const cacheDir =
|
|
10891
|
-
if (
|
|
10892
|
-
for (const f of
|
|
11199
|
+
const cacheDir = path26.join(EXE_AI_DIR, "session-cache");
|
|
11200
|
+
if (existsSync23(cacheDir)) {
|
|
11201
|
+
for (const f of readdirSync6(cacheDir)) {
|
|
10893
11202
|
if (f.startsWith("review-notified-")) {
|
|
10894
|
-
|
|
11203
|
+
unlinkSync7(path26.join(cacheDir, f));
|
|
10895
11204
|
}
|
|
10896
11205
|
}
|
|
10897
11206
|
}
|
|
@@ -10913,7 +11222,7 @@ var init_tasks_review = __esm({
|
|
|
10913
11222
|
});
|
|
10914
11223
|
|
|
10915
11224
|
// src/lib/tasks-chain.ts
|
|
10916
|
-
import
|
|
11225
|
+
import path27 from "path";
|
|
10917
11226
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
10918
11227
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
10919
11228
|
const client = getClient();
|
|
@@ -10930,7 +11239,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
10930
11239
|
});
|
|
10931
11240
|
for (const ur of unblockedRows.rows) {
|
|
10932
11241
|
try {
|
|
10933
|
-
const ubFile =
|
|
11242
|
+
const ubFile = path27.join(baseDir, String(ur.task_file));
|
|
10934
11243
|
let ubContent = await readFile5(ubFile, "utf-8");
|
|
10935
11244
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
10936
11245
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -11114,10 +11423,10 @@ async function disposeEmbedder() {
|
|
|
11114
11423
|
async function embedDirect(text) {
|
|
11115
11424
|
const llamaCpp = await import("node-llama-cpp");
|
|
11116
11425
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11117
|
-
const { existsSync:
|
|
11118
|
-
const
|
|
11119
|
-
const modelPath =
|
|
11120
|
-
if (!
|
|
11426
|
+
const { existsSync: existsSync34 } = await import("fs");
|
|
11427
|
+
const path48 = await import("path");
|
|
11428
|
+
const modelPath = path48.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
11429
|
+
if (!existsSync34(modelPath)) {
|
|
11121
11430
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11122
11431
|
}
|
|
11123
11432
|
const llama = await llamaCpp.getLlama();
|
|
@@ -11483,8 +11792,8 @@ __export(tasks_exports, {
|
|
|
11483
11792
|
updateTaskStatus: () => updateTaskStatus,
|
|
11484
11793
|
writeCheckpoint: () => writeCheckpoint
|
|
11485
11794
|
});
|
|
11486
|
-
import
|
|
11487
|
-
import { writeFileSync as writeFileSync14, mkdirSync as
|
|
11795
|
+
import path28 from "path";
|
|
11796
|
+
import { writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, unlinkSync as unlinkSync8 } from "fs";
|
|
11488
11797
|
async function createTask(input) {
|
|
11489
11798
|
const result = await createTaskCore(input);
|
|
11490
11799
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -11503,14 +11812,14 @@ async function updateTask(input) {
|
|
|
11503
11812
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
11504
11813
|
try {
|
|
11505
11814
|
const agent = String(row.assigned_to);
|
|
11506
|
-
const cacheDir =
|
|
11507
|
-
const cachePath =
|
|
11815
|
+
const cacheDir = path28.join(EXE_AI_DIR, "session-cache");
|
|
11816
|
+
const cachePath = path28.join(cacheDir, `current-task-${agent}.json`);
|
|
11508
11817
|
if (input.status === "in_progress") {
|
|
11509
|
-
|
|
11818
|
+
mkdirSync14(cacheDir, { recursive: true });
|
|
11510
11819
|
writeFileSync14(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
11511
11820
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
11512
11821
|
try {
|
|
11513
|
-
|
|
11822
|
+
unlinkSync8(cachePath);
|
|
11514
11823
|
} catch {
|
|
11515
11824
|
}
|
|
11516
11825
|
}
|
|
@@ -11974,14 +12283,14 @@ __export(tmux_routing_exports, {
|
|
|
11974
12283
|
spawnEmployee: () => spawnEmployee,
|
|
11975
12284
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
11976
12285
|
});
|
|
11977
|
-
import { execFileSync as execFileSync2, execSync as
|
|
11978
|
-
import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, mkdirSync as
|
|
11979
|
-
import
|
|
12286
|
+
import { execFileSync as execFileSync2, execSync as execSync9 } from "child_process";
|
|
12287
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15, existsSync as existsSync24, appendFileSync as appendFileSync2, readdirSync as readdirSync7 } from "fs";
|
|
12288
|
+
import path29 from "path";
|
|
11980
12289
|
import os15 from "os";
|
|
11981
12290
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11982
|
-
import { unlinkSync as
|
|
12291
|
+
import { unlinkSync as unlinkSync9 } from "fs";
|
|
11983
12292
|
function spawnLockPath(sessionName) {
|
|
11984
|
-
return
|
|
12293
|
+
return path29.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
11985
12294
|
}
|
|
11986
12295
|
function isProcessAlive(pid) {
|
|
11987
12296
|
try {
|
|
@@ -11992,11 +12301,11 @@ function isProcessAlive(pid) {
|
|
|
11992
12301
|
}
|
|
11993
12302
|
}
|
|
11994
12303
|
function acquireSpawnLock2(sessionName) {
|
|
11995
|
-
if (!
|
|
11996
|
-
|
|
12304
|
+
if (!existsSync24(SPAWN_LOCK_DIR)) {
|
|
12305
|
+
mkdirSync15(SPAWN_LOCK_DIR, { recursive: true });
|
|
11997
12306
|
}
|
|
11998
12307
|
const lockFile = spawnLockPath(sessionName);
|
|
11999
|
-
if (
|
|
12308
|
+
if (existsSync24(lockFile)) {
|
|
12000
12309
|
try {
|
|
12001
12310
|
const lock = JSON.parse(readFileSync19(lockFile, "utf8"));
|
|
12002
12311
|
const age = Date.now() - lock.timestamp;
|
|
@@ -12011,20 +12320,20 @@ function acquireSpawnLock2(sessionName) {
|
|
|
12011
12320
|
}
|
|
12012
12321
|
function releaseSpawnLock2(sessionName) {
|
|
12013
12322
|
try {
|
|
12014
|
-
|
|
12323
|
+
unlinkSync9(spawnLockPath(sessionName));
|
|
12015
12324
|
} catch {
|
|
12016
12325
|
}
|
|
12017
12326
|
}
|
|
12018
12327
|
function resolveBehaviorsExporterScript() {
|
|
12019
12328
|
try {
|
|
12020
12329
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
12021
|
-
const scriptPath =
|
|
12022
|
-
|
|
12330
|
+
const scriptPath = path29.join(
|
|
12331
|
+
path29.dirname(thisFile),
|
|
12023
12332
|
"..",
|
|
12024
12333
|
"bin",
|
|
12025
12334
|
"exe-export-behaviors.js"
|
|
12026
12335
|
);
|
|
12027
|
-
return
|
|
12336
|
+
return existsSync24(scriptPath) ? scriptPath : null;
|
|
12028
12337
|
} catch {
|
|
12029
12338
|
return null;
|
|
12030
12339
|
}
|
|
@@ -12090,11 +12399,11 @@ function extractRootExe(name) {
|
|
|
12090
12399
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
12091
12400
|
}
|
|
12092
12401
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
12093
|
-
if (!
|
|
12094
|
-
|
|
12402
|
+
if (!existsSync24(SESSION_CACHE)) {
|
|
12403
|
+
mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
12095
12404
|
}
|
|
12096
12405
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
12097
|
-
const filePath =
|
|
12406
|
+
const filePath = path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
12098
12407
|
writeFileSync15(filePath, JSON.stringify({
|
|
12099
12408
|
parentExe: rootExe,
|
|
12100
12409
|
dispatchedBy: dispatchedBy || rootExe,
|
|
@@ -12103,7 +12412,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
12103
12412
|
}
|
|
12104
12413
|
function getParentExe(sessionKey) {
|
|
12105
12414
|
try {
|
|
12106
|
-
const data = JSON.parse(readFileSync19(
|
|
12415
|
+
const data = JSON.parse(readFileSync19(path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
12107
12416
|
return data.parentExe || null;
|
|
12108
12417
|
} catch {
|
|
12109
12418
|
return null;
|
|
@@ -12112,7 +12421,7 @@ function getParentExe(sessionKey) {
|
|
|
12112
12421
|
function getDispatchedBy(sessionKey) {
|
|
12113
12422
|
try {
|
|
12114
12423
|
const data = JSON.parse(readFileSync19(
|
|
12115
|
-
|
|
12424
|
+
path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
12116
12425
|
"utf8"
|
|
12117
12426
|
));
|
|
12118
12427
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -12182,7 +12491,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
12182
12491
|
}
|
|
12183
12492
|
function readDebounceState() {
|
|
12184
12493
|
try {
|
|
12185
|
-
if (!
|
|
12494
|
+
if (!existsSync24(DEBOUNCE_FILE)) return {};
|
|
12186
12495
|
const raw = JSON.parse(readFileSync19(DEBOUNCE_FILE, "utf8"));
|
|
12187
12496
|
const state = {};
|
|
12188
12497
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -12199,7 +12508,7 @@ function readDebounceState() {
|
|
|
12199
12508
|
}
|
|
12200
12509
|
function writeDebounceState(state) {
|
|
12201
12510
|
try {
|
|
12202
|
-
if (!
|
|
12511
|
+
if (!existsSync24(SESSION_CACHE)) mkdirSync15(SESSION_CACHE, { recursive: true });
|
|
12203
12512
|
writeFileSync15(DEBOUNCE_FILE, JSON.stringify(state));
|
|
12204
12513
|
} catch {
|
|
12205
12514
|
}
|
|
@@ -12299,8 +12608,8 @@ function sendIntercom(targetSession) {
|
|
|
12299
12608
|
try {
|
|
12300
12609
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
12301
12610
|
const agent = baseAgentName(rawAgent);
|
|
12302
|
-
const markerPath =
|
|
12303
|
-
if (
|
|
12611
|
+
const markerPath = path29.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
12612
|
+
if (existsSync24(markerPath)) {
|
|
12304
12613
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
12305
12614
|
return "debounced";
|
|
12306
12615
|
}
|
|
@@ -12310,9 +12619,9 @@ function sendIntercom(targetSession) {
|
|
|
12310
12619
|
try {
|
|
12311
12620
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
12312
12621
|
const agent = baseAgentName(rawAgent);
|
|
12313
|
-
const taskDir =
|
|
12314
|
-
if (
|
|
12315
|
-
const files =
|
|
12622
|
+
const taskDir = path29.join(process.cwd(), "exe", agent);
|
|
12623
|
+
if (existsSync24(taskDir)) {
|
|
12624
|
+
const files = readdirSync7(taskDir).filter(
|
|
12316
12625
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
12317
12626
|
);
|
|
12318
12627
|
if (files.length === 0) {
|
|
@@ -12470,23 +12779,23 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12470
12779
|
const transport = getTransport();
|
|
12471
12780
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
12472
12781
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
12473
|
-
const logDir =
|
|
12474
|
-
const logFile =
|
|
12475
|
-
if (!
|
|
12476
|
-
|
|
12782
|
+
const logDir = path29.join(os15.homedir(), ".exe-os", "session-logs");
|
|
12783
|
+
const logFile = path29.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
12784
|
+
if (!existsSync24(logDir)) {
|
|
12785
|
+
mkdirSync15(logDir, { recursive: true });
|
|
12477
12786
|
}
|
|
12478
12787
|
transport.kill(sessionName);
|
|
12479
12788
|
let cleanupSuffix = "";
|
|
12480
12789
|
try {
|
|
12481
12790
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
12482
|
-
const cleanupScript =
|
|
12483
|
-
if (
|
|
12791
|
+
const cleanupScript = path29.join(path29.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
12792
|
+
if (existsSync24(cleanupScript)) {
|
|
12484
12793
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
12485
12794
|
}
|
|
12486
12795
|
} catch {
|
|
12487
12796
|
}
|
|
12488
12797
|
try {
|
|
12489
|
-
const claudeJsonPath =
|
|
12798
|
+
const claudeJsonPath = path29.join(os15.homedir(), ".claude.json");
|
|
12490
12799
|
let claudeJson = {};
|
|
12491
12800
|
try {
|
|
12492
12801
|
claudeJson = JSON.parse(readFileSync19(claudeJsonPath, "utf8"));
|
|
@@ -12501,10 +12810,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12501
12810
|
} catch {
|
|
12502
12811
|
}
|
|
12503
12812
|
try {
|
|
12504
|
-
const settingsDir =
|
|
12813
|
+
const settingsDir = path29.join(os15.homedir(), ".claude", "projects");
|
|
12505
12814
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
12506
|
-
const projSettingsDir =
|
|
12507
|
-
const settingsPath =
|
|
12815
|
+
const projSettingsDir = path29.join(settingsDir, normalizedKey);
|
|
12816
|
+
const settingsPath = path29.join(projSettingsDir, "settings.json");
|
|
12508
12817
|
let settings = {};
|
|
12509
12818
|
try {
|
|
12510
12819
|
settings = JSON.parse(readFileSync19(settingsPath, "utf8"));
|
|
@@ -12535,7 +12844,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12535
12844
|
if (changed) {
|
|
12536
12845
|
perms.allow = allow;
|
|
12537
12846
|
settings.permissions = perms;
|
|
12538
|
-
|
|
12847
|
+
mkdirSync15(projSettingsDir, { recursive: true });
|
|
12539
12848
|
writeFileSync15(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
12540
12849
|
}
|
|
12541
12850
|
} catch {
|
|
@@ -12551,7 +12860,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12551
12860
|
let behaviorsFlag = "";
|
|
12552
12861
|
let legacyFallbackWarned = false;
|
|
12553
12862
|
if (!useExeAgent && !useBinSymlink) {
|
|
12554
|
-
const identityPath2 =
|
|
12863
|
+
const identityPath2 = path29.join(
|
|
12555
12864
|
os15.homedir(),
|
|
12556
12865
|
".exe-os",
|
|
12557
12866
|
"identity",
|
|
@@ -12561,13 +12870,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12561
12870
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
12562
12871
|
if (hasAgentFlag) {
|
|
12563
12872
|
identityFlag = ` --agent ${employeeName}`;
|
|
12564
|
-
} else if (
|
|
12873
|
+
} else if (existsSync24(identityPath2)) {
|
|
12565
12874
|
identityFlag = ` --append-system-prompt-file ${identityPath2}`;
|
|
12566
12875
|
legacyFallbackWarned = true;
|
|
12567
12876
|
}
|
|
12568
12877
|
const behaviorsFile = exportBehaviorsSync(
|
|
12569
12878
|
employeeName,
|
|
12570
|
-
|
|
12879
|
+
path29.basename(spawnCwd),
|
|
12571
12880
|
sessionName
|
|
12572
12881
|
);
|
|
12573
12882
|
if (behaviorsFile) {
|
|
@@ -12582,9 +12891,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12582
12891
|
}
|
|
12583
12892
|
let sessionContextFlag = "";
|
|
12584
12893
|
try {
|
|
12585
|
-
const ctxDir =
|
|
12586
|
-
|
|
12587
|
-
const ctxFile =
|
|
12894
|
+
const ctxDir = path29.join(os15.homedir(), ".exe-os", "session-cache");
|
|
12895
|
+
mkdirSync15(ctxDir, { recursive: true });
|
|
12896
|
+
const ctxFile = path29.join(ctxDir, `session-context-${sessionName}.md`);
|
|
12588
12897
|
const ctxContent = [
|
|
12589
12898
|
`## Session Context`,
|
|
12590
12899
|
`You are running in tmux session: ${sessionName}.`,
|
|
@@ -12670,7 +12979,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12670
12979
|
transport.pipeLog(sessionName, logFile);
|
|
12671
12980
|
try {
|
|
12672
12981
|
const mySession = getMySession();
|
|
12673
|
-
const dispatchInfo =
|
|
12982
|
+
const dispatchInfo = path29.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
12674
12983
|
writeFileSync15(dispatchInfo, JSON.stringify({
|
|
12675
12984
|
dispatchedBy: mySession,
|
|
12676
12985
|
rootExe: exeSession,
|
|
@@ -12684,7 +12993,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12684
12993
|
let booted = false;
|
|
12685
12994
|
for (let i = 0; i < 30; i++) {
|
|
12686
12995
|
try {
|
|
12687
|
-
|
|
12996
|
+
execSync9("sleep 0.5");
|
|
12688
12997
|
} catch {
|
|
12689
12998
|
}
|
|
12690
12999
|
try {
|
|
@@ -12745,15 +13054,15 @@ var init_tmux_routing = __esm({
|
|
|
12745
13054
|
init_intercom_queue();
|
|
12746
13055
|
init_plan_limits();
|
|
12747
13056
|
init_employees();
|
|
12748
|
-
SPAWN_LOCK_DIR =
|
|
12749
|
-
SESSION_CACHE =
|
|
13057
|
+
SPAWN_LOCK_DIR = path29.join(os15.homedir(), ".exe-os", "spawn-locks");
|
|
13058
|
+
SESSION_CACHE = path29.join(os15.homedir(), ".exe-os", "session-cache");
|
|
12750
13059
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
12751
13060
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
12752
13061
|
VERIFY_PANE_LINES = 200;
|
|
12753
13062
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
12754
13063
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
12755
|
-
INTERCOM_LOG2 =
|
|
12756
|
-
DEBOUNCE_FILE =
|
|
13064
|
+
INTERCOM_LOG2 = path29.join(os15.homedir(), ".exe-os", "intercom.log");
|
|
13065
|
+
DEBOUNCE_FILE = path29.join(SESSION_CACHE, "intercom-debounce.json");
|
|
12757
13066
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
12758
13067
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
12759
13068
|
}
|
|
@@ -13042,9 +13351,9 @@ __export(active_agent_exports, {
|
|
|
13042
13351
|
resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
|
|
13043
13352
|
writeActiveAgent: () => writeActiveAgent
|
|
13044
13353
|
});
|
|
13045
|
-
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16, mkdirSync as
|
|
13046
|
-
import { execSync as
|
|
13047
|
-
import
|
|
13354
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16, mkdirSync as mkdirSync16, unlinkSync as unlinkSync10, readdirSync as readdirSync8 } from "fs";
|
|
13355
|
+
import { execSync as execSync10 } from "child_process";
|
|
13356
|
+
import path30 from "path";
|
|
13048
13357
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
13049
13358
|
if (candidate === baseName) return true;
|
|
13050
13359
|
if (!candidate.startsWith(baseName)) return false;
|
|
@@ -13088,11 +13397,11 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
13088
13397
|
return null;
|
|
13089
13398
|
}
|
|
13090
13399
|
function getMarkerPath() {
|
|
13091
|
-
return
|
|
13400
|
+
return path30.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
13092
13401
|
}
|
|
13093
13402
|
function writeActiveAgent(agentId, agentRole) {
|
|
13094
13403
|
try {
|
|
13095
|
-
|
|
13404
|
+
mkdirSync16(CACHE_DIR, { recursive: true });
|
|
13096
13405
|
writeFileSync16(
|
|
13097
13406
|
getMarkerPath(),
|
|
13098
13407
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
@@ -13102,7 +13411,7 @@ function writeActiveAgent(agentId, agentRole) {
|
|
|
13102
13411
|
}
|
|
13103
13412
|
function clearActiveAgent() {
|
|
13104
13413
|
try {
|
|
13105
|
-
|
|
13414
|
+
unlinkSync10(getMarkerPath());
|
|
13106
13415
|
} catch {
|
|
13107
13416
|
}
|
|
13108
13417
|
}
|
|
@@ -13116,7 +13425,7 @@ function getActiveAgent() {
|
|
|
13116
13425
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
13117
13426
|
if (age > STALE_MS) {
|
|
13118
13427
|
try {
|
|
13119
|
-
|
|
13428
|
+
unlinkSync10(markerPath);
|
|
13120
13429
|
} catch {
|
|
13121
13430
|
}
|
|
13122
13431
|
} else {
|
|
@@ -13135,7 +13444,7 @@ function getActiveAgent() {
|
|
|
13135
13444
|
} catch {
|
|
13136
13445
|
}
|
|
13137
13446
|
try {
|
|
13138
|
-
const sessionName =
|
|
13447
|
+
const sessionName = execSync10(
|
|
13139
13448
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
13140
13449
|
{ encoding: "utf8", timeout: 2e3 }
|
|
13141
13450
|
).trim();
|
|
@@ -13150,21 +13459,21 @@ function getActiveAgent() {
|
|
|
13150
13459
|
}
|
|
13151
13460
|
function getAllActiveAgents() {
|
|
13152
13461
|
try {
|
|
13153
|
-
const files =
|
|
13462
|
+
const files = readdirSync8(CACHE_DIR);
|
|
13154
13463
|
const sessions = [];
|
|
13155
13464
|
for (const file of files) {
|
|
13156
13465
|
if (!file.startsWith("active-agent-") || !file.endsWith(".json")) continue;
|
|
13157
13466
|
const key = file.slice("active-agent-".length, -".json".length);
|
|
13158
13467
|
if (key === "undefined") continue;
|
|
13159
13468
|
try {
|
|
13160
|
-
const raw = readFileSync20(
|
|
13469
|
+
const raw = readFileSync20(path30.join(CACHE_DIR, file), "utf8");
|
|
13161
13470
|
const data = JSON.parse(raw);
|
|
13162
13471
|
if (!data.agentId) continue;
|
|
13163
13472
|
if (data.startedAt) {
|
|
13164
13473
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
13165
13474
|
if (age > STALE_MS) {
|
|
13166
13475
|
try {
|
|
13167
|
-
|
|
13476
|
+
unlinkSync10(path30.join(CACHE_DIR, file));
|
|
13168
13477
|
} catch {
|
|
13169
13478
|
}
|
|
13170
13479
|
continue;
|
|
@@ -13187,11 +13496,11 @@ function getAllActiveAgents() {
|
|
|
13187
13496
|
function cleanupSessionMarkers() {
|
|
13188
13497
|
const key = getSessionKey();
|
|
13189
13498
|
try {
|
|
13190
|
-
|
|
13499
|
+
unlinkSync10(path30.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
13191
13500
|
} catch {
|
|
13192
13501
|
}
|
|
13193
13502
|
try {
|
|
13194
|
-
|
|
13503
|
+
unlinkSync10(path30.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
13195
13504
|
} catch {
|
|
13196
13505
|
}
|
|
13197
13506
|
}
|
|
@@ -13202,7 +13511,7 @@ var init_active_agent = __esm({
|
|
|
13202
13511
|
init_config();
|
|
13203
13512
|
init_session_key();
|
|
13204
13513
|
init_employees();
|
|
13205
|
-
CACHE_DIR =
|
|
13514
|
+
CACHE_DIR = path30.join(EXE_AI_DIR, "session-cache");
|
|
13206
13515
|
STALE_MS = 24 * 60 * 60 * 1e3;
|
|
13207
13516
|
}
|
|
13208
13517
|
});
|
|
@@ -13830,14 +14139,14 @@ __export(exe_rename_exports, {
|
|
|
13830
14139
|
main: () => main2,
|
|
13831
14140
|
renameEmployee: () => renameEmployee
|
|
13832
14141
|
});
|
|
13833
|
-
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as renameSync4, unlinkSync as
|
|
13834
|
-
import { execSync as
|
|
13835
|
-
import
|
|
14142
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as renameSync4, unlinkSync as unlinkSync11, existsSync as existsSync25 } from "fs";
|
|
14143
|
+
import { execSync as execSync11 } from "child_process";
|
|
14144
|
+
import path31 from "path";
|
|
13836
14145
|
import { homedir as homedir4 } from "os";
|
|
13837
14146
|
async function renameEmployee(oldName, newName, opts = {}) {
|
|
13838
|
-
const rosterPath = opts.rosterPath ??
|
|
13839
|
-
const identityDir = opts.identityDir ??
|
|
13840
|
-
const agentsDir = opts.agentsDir ??
|
|
14147
|
+
const rosterPath = opts.rosterPath ?? path31.join(homedir4(), ".exe-os", "exe-employees.json");
|
|
14148
|
+
const identityDir = opts.identityDir ?? path31.join(homedir4(), ".exe-os", "identity");
|
|
14149
|
+
const agentsDir = opts.agentsDir ?? path31.join(homedir4(), ".claude", "agents");
|
|
13841
14150
|
const validation = validateEmployeeName(newName);
|
|
13842
14151
|
if (!validation.valid) {
|
|
13843
14152
|
return { success: false, error: validation.error };
|
|
@@ -13869,9 +14178,9 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
13869
14178
|
writeFileSync17(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
13870
14179
|
}
|
|
13871
14180
|
});
|
|
13872
|
-
const oldIdentityPath =
|
|
13873
|
-
const newIdentityPath =
|
|
13874
|
-
if (
|
|
14181
|
+
const oldIdentityPath = path31.join(identityDir, `${rosterOldName}.md`);
|
|
14182
|
+
const newIdentityPath = path31.join(identityDir, `${newName}.md`);
|
|
14183
|
+
if (existsSync25(oldIdentityPath)) {
|
|
13875
14184
|
const content = readFileSync21(oldIdentityPath, "utf-8");
|
|
13876
14185
|
const updatedContent = content.replace(
|
|
13877
14186
|
/^(agent_id:\s*)\S+/m,
|
|
@@ -13882,22 +14191,22 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
13882
14191
|
rollbackStack.push({
|
|
13883
14192
|
description: "restore identity file",
|
|
13884
14193
|
undo: () => {
|
|
13885
|
-
if (
|
|
14194
|
+
if (existsSync25(newIdentityPath)) {
|
|
13886
14195
|
writeFileSync17(newIdentityPath, content, "utf-8");
|
|
13887
14196
|
renameSync4(newIdentityPath, oldIdentityPath);
|
|
13888
14197
|
}
|
|
13889
14198
|
}
|
|
13890
14199
|
});
|
|
13891
14200
|
}
|
|
13892
|
-
const oldAgentPath =
|
|
13893
|
-
const newAgentPath =
|
|
13894
|
-
if (
|
|
14201
|
+
const oldAgentPath = path31.join(agentsDir, `${rosterOldName}.md`);
|
|
14202
|
+
const newAgentPath = path31.join(agentsDir, `${newName}.md`);
|
|
14203
|
+
if (existsSync25(oldAgentPath)) {
|
|
13895
14204
|
const agentContent = readFileSync21(oldAgentPath, "utf-8");
|
|
13896
14205
|
renameSync4(oldAgentPath, newAgentPath);
|
|
13897
14206
|
rollbackStack.push({
|
|
13898
14207
|
description: "restore agent file",
|
|
13899
14208
|
undo: () => {
|
|
13900
|
-
if (
|
|
14209
|
+
if (existsSync25(newAgentPath)) {
|
|
13901
14210
|
renameSync4(newAgentPath, oldAgentPath);
|
|
13902
14211
|
writeFileSync17(oldAgentPath, agentContent, "utf-8");
|
|
13903
14212
|
}
|
|
@@ -13968,7 +14277,7 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
13968
14277
|
}
|
|
13969
14278
|
function findExeBin2() {
|
|
13970
14279
|
try {
|
|
13971
|
-
return
|
|
14280
|
+
return execSync11(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
13972
14281
|
} catch {
|
|
13973
14282
|
return null;
|
|
13974
14283
|
}
|
|
@@ -13977,12 +14286,12 @@ function removeOldSymlinks(name) {
|
|
|
13977
14286
|
try {
|
|
13978
14287
|
const exeBinPath = findExeBin2();
|
|
13979
14288
|
if (!exeBinPath) return;
|
|
13980
|
-
const binDir =
|
|
14289
|
+
const binDir = path31.dirname(exeBinPath);
|
|
13981
14290
|
for (const suffix of ["", "-opencode"]) {
|
|
13982
|
-
const linkPath =
|
|
13983
|
-
if (
|
|
14291
|
+
const linkPath = path31.join(binDir, `${name}${suffix}`);
|
|
14292
|
+
if (existsSync25(linkPath)) {
|
|
13984
14293
|
try {
|
|
13985
|
-
|
|
14294
|
+
unlinkSync11(linkPath);
|
|
13986
14295
|
} catch {
|
|
13987
14296
|
}
|
|
13988
14297
|
}
|
|
@@ -14025,16 +14334,16 @@ var init_exe_rename = __esm({
|
|
|
14025
14334
|
});
|
|
14026
14335
|
|
|
14027
14336
|
// src/lib/model-downloader.ts
|
|
14028
|
-
import { createWriteStream, createReadStream as createReadStream2, existsSync as
|
|
14337
|
+
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync5 } from "fs";
|
|
14029
14338
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
14030
14339
|
import { createHash as createHash3 } from "crypto";
|
|
14031
|
-
import
|
|
14340
|
+
import path32 from "path";
|
|
14032
14341
|
async function downloadModel(opts) {
|
|
14033
14342
|
const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
|
|
14034
|
-
const destPath =
|
|
14343
|
+
const destPath = path32.join(destDir, LOCAL_FILENAME);
|
|
14035
14344
|
const tmpPath = destPath + ".tmp";
|
|
14036
14345
|
await mkdir6(destDir, { recursive: true });
|
|
14037
|
-
if (
|
|
14346
|
+
if (existsSync26(destPath)) {
|
|
14038
14347
|
const hash = await fileHash(destPath);
|
|
14039
14348
|
if (hash === EXPECTED_SHA256) {
|
|
14040
14349
|
return destPath;
|
|
@@ -14046,7 +14355,7 @@ async function downloadModel(opts) {
|
|
|
14046
14355
|
let downloaded = 0;
|
|
14047
14356
|
for (let attempt = 1; attempt <= MAX_RETRIES4; attempt++) {
|
|
14048
14357
|
try {
|
|
14049
|
-
if (
|
|
14358
|
+
if (existsSync26(tmpPath)) unlinkSync12(tmpPath);
|
|
14050
14359
|
const response = await fetchFn(GGUF_URL, {
|
|
14051
14360
|
redirect: "follow",
|
|
14052
14361
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
@@ -14078,7 +14387,7 @@ async function downloadModel(opts) {
|
|
|
14078
14387
|
}
|
|
14079
14388
|
const actualHash = hash.digest("hex");
|
|
14080
14389
|
if (actualHash !== EXPECTED_SHA256) {
|
|
14081
|
-
|
|
14390
|
+
unlinkSync12(tmpPath);
|
|
14082
14391
|
throw new Error(
|
|
14083
14392
|
`SHA256 mismatch: expected ${EXPECTED_SHA256}, got ${actualHash}`
|
|
14084
14393
|
);
|
|
@@ -14091,7 +14400,7 @@ async function downloadModel(opts) {
|
|
|
14091
14400
|
process.stderr.write(`
|
|
14092
14401
|
Download attempt ${attempt} failed, retrying...
|
|
14093
14402
|
`);
|
|
14094
|
-
if (
|
|
14403
|
+
if (existsSync26(tmpPath)) unlinkSync12(tmpPath);
|
|
14095
14404
|
}
|
|
14096
14405
|
}
|
|
14097
14406
|
}
|
|
@@ -14664,28 +14973,28 @@ __export(session_wrappers_exports, {
|
|
|
14664
14973
|
generateSessionWrappers: () => generateSessionWrappers
|
|
14665
14974
|
});
|
|
14666
14975
|
import {
|
|
14667
|
-
existsSync as
|
|
14976
|
+
existsSync as existsSync27,
|
|
14668
14977
|
readFileSync as readFileSync22,
|
|
14669
14978
|
writeFileSync as writeFileSync18,
|
|
14670
|
-
mkdirSync as
|
|
14979
|
+
mkdirSync as mkdirSync17,
|
|
14671
14980
|
chmodSync as chmodSync2,
|
|
14672
|
-
readdirSync as
|
|
14673
|
-
unlinkSync as
|
|
14981
|
+
readdirSync as readdirSync9,
|
|
14982
|
+
unlinkSync as unlinkSync13
|
|
14674
14983
|
} from "fs";
|
|
14675
|
-
import
|
|
14984
|
+
import path33 from "path";
|
|
14676
14985
|
import { homedir as homedir5 } from "os";
|
|
14677
14986
|
function generateSessionWrappers(packageRoot, homeDir) {
|
|
14678
14987
|
const home = homeDir ?? homedir5();
|
|
14679
|
-
const binDir =
|
|
14680
|
-
const rosterPath =
|
|
14681
|
-
|
|
14682
|
-
const exeStartDst =
|
|
14988
|
+
const binDir = path33.join(home, ".exe-os", "bin");
|
|
14989
|
+
const rosterPath = path33.join(home, ".exe-os", "exe-employees.json");
|
|
14990
|
+
mkdirSync17(binDir, { recursive: true });
|
|
14991
|
+
const exeStartDst = path33.join(binDir, "exe-start");
|
|
14683
14992
|
const candidates = [
|
|
14684
|
-
|
|
14685
|
-
|
|
14993
|
+
path33.join(packageRoot, "dist", "bin", "exe-start.sh"),
|
|
14994
|
+
path33.join(packageRoot, "src", "bin", "exe-start.sh")
|
|
14686
14995
|
];
|
|
14687
14996
|
for (const src of candidates) {
|
|
14688
|
-
if (
|
|
14997
|
+
if (existsSync27(src)) {
|
|
14689
14998
|
writeFileSync18(exeStartDst, readFileSync22(src));
|
|
14690
14999
|
chmodSync2(exeStartDst, 493);
|
|
14691
15000
|
break;
|
|
@@ -14701,13 +15010,13 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
14701
15010
|
return { created: 0, pathConfigured: false };
|
|
14702
15011
|
}
|
|
14703
15012
|
try {
|
|
14704
|
-
for (const f of
|
|
15013
|
+
for (const f of readdirSync9(binDir)) {
|
|
14705
15014
|
if (f === "exe-start") continue;
|
|
14706
|
-
const fPath =
|
|
15015
|
+
const fPath = path33.join(binDir, f);
|
|
14707
15016
|
try {
|
|
14708
15017
|
const content = readFileSync22(fPath, "utf8");
|
|
14709
15018
|
if (content.includes("exe-start")) {
|
|
14710
|
-
|
|
15019
|
+
unlinkSync13(fPath);
|
|
14711
15020
|
}
|
|
14712
15021
|
} catch {
|
|
14713
15022
|
}
|
|
@@ -14720,30 +15029,30 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
14720
15029
|
`;
|
|
14721
15030
|
for (const emp of employees) {
|
|
14722
15031
|
for (let n = 1; n <= MAX_N; n++) {
|
|
14723
|
-
const wrapperPath =
|
|
15032
|
+
const wrapperPath = path33.join(binDir, `${emp.name}${n}`);
|
|
14724
15033
|
writeFileSync18(wrapperPath, wrapperContent);
|
|
14725
15034
|
chmodSync2(wrapperPath, 493);
|
|
14726
15035
|
created++;
|
|
14727
|
-
const codexPath =
|
|
15036
|
+
const codexPath = path33.join(binDir, `${emp.name}${n}-codex`);
|
|
14728
15037
|
writeFileSync18(codexPath, wrapperContent);
|
|
14729
15038
|
chmodSync2(codexPath, 493);
|
|
14730
15039
|
created++;
|
|
14731
15040
|
}
|
|
14732
15041
|
}
|
|
14733
15042
|
const codexLauncherCandidates = [
|
|
14734
|
-
|
|
14735
|
-
|
|
15043
|
+
path33.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
|
|
15044
|
+
path33.join(packageRoot, "src", "bin", "exe-start-codex.ts")
|
|
14736
15045
|
];
|
|
14737
15046
|
let codexLauncher = null;
|
|
14738
15047
|
for (const c of codexLauncherCandidates) {
|
|
14739
|
-
if (
|
|
15048
|
+
if (existsSync27(c)) {
|
|
14740
15049
|
codexLauncher = c;
|
|
14741
15050
|
break;
|
|
14742
15051
|
}
|
|
14743
15052
|
}
|
|
14744
15053
|
if (codexLauncher) {
|
|
14745
15054
|
for (const emp of employees) {
|
|
14746
|
-
const wrapperPath =
|
|
15055
|
+
const wrapperPath = path33.join(binDir, `${emp.name}-codex`);
|
|
14747
15056
|
const content = `#!/bin/bash
|
|
14748
15057
|
exec node "${codexLauncher}" --agent ${emp.name} "$@"
|
|
14749
15058
|
`;
|
|
@@ -14766,12 +15075,12 @@ export PATH="${binDir}:$PATH"
|
|
|
14766
15075
|
const shell = process.env.SHELL ?? "/bin/bash";
|
|
14767
15076
|
const profilePaths = [];
|
|
14768
15077
|
if (shell.includes("zsh")) {
|
|
14769
|
-
profilePaths.push(
|
|
15078
|
+
profilePaths.push(path33.join(home, ".zshrc"));
|
|
14770
15079
|
} else if (shell.includes("bash")) {
|
|
14771
|
-
profilePaths.push(
|
|
14772
|
-
profilePaths.push(
|
|
15080
|
+
profilePaths.push(path33.join(home, ".bashrc"));
|
|
15081
|
+
profilePaths.push(path33.join(home, ".bash_profile"));
|
|
14773
15082
|
} else {
|
|
14774
|
-
profilePaths.push(
|
|
15083
|
+
profilePaths.push(path33.join(home, ".profile"));
|
|
14775
15084
|
}
|
|
14776
15085
|
for (const profilePath of profilePaths) {
|
|
14777
15086
|
try {
|
|
@@ -14806,23 +15115,23 @@ __export(setup_wizard_exports, {
|
|
|
14806
15115
|
validateModel: () => validateModel
|
|
14807
15116
|
});
|
|
14808
15117
|
import crypto12 from "crypto";
|
|
14809
|
-
import { existsSync as
|
|
15118
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync18, readFileSync as readFileSync23, writeFileSync as writeFileSync19, unlinkSync as unlinkSync14 } from "fs";
|
|
14810
15119
|
import os16 from "os";
|
|
14811
|
-
import
|
|
15120
|
+
import path34 from "path";
|
|
14812
15121
|
import { createInterface as createInterface3 } from "readline";
|
|
14813
15122
|
function findPackageRoot2() {
|
|
14814
|
-
let dir =
|
|
14815
|
-
const root =
|
|
15123
|
+
let dir = path34.dirname(new URL(import.meta.url).pathname);
|
|
15124
|
+
const root = path34.parse(dir).root;
|
|
14816
15125
|
while (dir !== root) {
|
|
14817
|
-
const pkgPath =
|
|
14818
|
-
if (
|
|
15126
|
+
const pkgPath = path34.join(dir, "package.json");
|
|
15127
|
+
if (existsSync28(pkgPath)) {
|
|
14819
15128
|
try {
|
|
14820
15129
|
const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
|
|
14821
15130
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
14822
15131
|
} catch {
|
|
14823
15132
|
}
|
|
14824
15133
|
}
|
|
14825
|
-
dir =
|
|
15134
|
+
dir = path34.dirname(dir);
|
|
14826
15135
|
}
|
|
14827
15136
|
return null;
|
|
14828
15137
|
}
|
|
@@ -14834,12 +15143,12 @@ function loadSetupState() {
|
|
|
14834
15143
|
}
|
|
14835
15144
|
}
|
|
14836
15145
|
function saveSetupState(state) {
|
|
14837
|
-
|
|
15146
|
+
mkdirSync18(path34.dirname(SETUP_STATE_PATH), { recursive: true });
|
|
14838
15147
|
writeFileSync19(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
|
|
14839
15148
|
}
|
|
14840
15149
|
function clearSetupState() {
|
|
14841
15150
|
try {
|
|
14842
|
-
|
|
15151
|
+
unlinkSync14(SETUP_STATE_PATH);
|
|
14843
15152
|
} catch {
|
|
14844
15153
|
}
|
|
14845
15154
|
}
|
|
@@ -14856,8 +15165,8 @@ function ask2(rl, prompt) {
|
|
|
14856
15165
|
function getAvailableMemoryGB2() {
|
|
14857
15166
|
if (process.platform === "darwin") {
|
|
14858
15167
|
try {
|
|
14859
|
-
const { execSync:
|
|
14860
|
-
const vmstat =
|
|
15168
|
+
const { execSync: execSync16 } = __require("child_process");
|
|
15169
|
+
const vmstat = execSync16("vm_stat", { encoding: "utf8" });
|
|
14861
15170
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
14862
15171
|
const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 16384;
|
|
14863
15172
|
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
@@ -14885,10 +15194,10 @@ async function validateModel(log) {
|
|
|
14885
15194
|
if (totalGB <= 8 || isLowMemory()) {
|
|
14886
15195
|
log(`System memory: ${totalGB.toFixed(0)}GB total, ${freeGB.toFixed(1)}GB free`);
|
|
14887
15196
|
log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
|
|
14888
|
-
const modelPath =
|
|
14889
|
-
if (
|
|
14890
|
-
const { statSync:
|
|
14891
|
-
const size =
|
|
15197
|
+
const modelPath = path34.join(MODELS_DIR, LOCAL_FILENAME);
|
|
15198
|
+
if (existsSync28(modelPath)) {
|
|
15199
|
+
const { statSync: statSync3 } = await import("fs");
|
|
15200
|
+
const size = statSync3(modelPath).size;
|
|
14892
15201
|
if (size > 300 * 1e6) {
|
|
14893
15202
|
log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
|
|
14894
15203
|
return;
|
|
@@ -14977,7 +15286,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
14977
15286
|
if (state.completedSteps.length > 0) {
|
|
14978
15287
|
log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
|
|
14979
15288
|
}
|
|
14980
|
-
if (
|
|
15289
|
+
if (existsSync28(LEGACY_LANCE_PATH)) {
|
|
14981
15290
|
log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
|
|
14982
15291
|
log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
|
|
14983
15292
|
log(" The old directory will not be modified or deleted.");
|
|
@@ -14992,6 +15301,23 @@ async function runSetupWizard(opts = {}) {
|
|
|
14992
15301
|
const key = crypto12.randomBytes(32);
|
|
14993
15302
|
await setMasterKey(key);
|
|
14994
15303
|
log("Encryption key generated and stored securely.");
|
|
15304
|
+
log("");
|
|
15305
|
+
const { exportMnemonic: exportMnemonic2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));
|
|
15306
|
+
const mnemonic = await exportMnemonic2(key);
|
|
15307
|
+
log("=============================================================");
|
|
15308
|
+
log(" YOUR 24-WORD RECOVERY PHRASE");
|
|
15309
|
+
log("=============================================================");
|
|
15310
|
+
log("");
|
|
15311
|
+
log(" " + mnemonic);
|
|
15312
|
+
log("");
|
|
15313
|
+
log(" SAVE THIS NOW. Write it down or store it in your password");
|
|
15314
|
+
log(" manager. This phrase is the ONLY way to decrypt your memories");
|
|
15315
|
+
log(" if you lose this computer. We cannot recover it for you.");
|
|
15316
|
+
log("");
|
|
15317
|
+
log(" Like a Bitcoin wallet \u2014 lose the phrase, lose everything.");
|
|
15318
|
+
log("=============================================================");
|
|
15319
|
+
log("");
|
|
15320
|
+
await ask2(rl, "Press Enter after you've saved your recovery phrase...");
|
|
14995
15321
|
}
|
|
14996
15322
|
state.completedSteps.push(1);
|
|
14997
15323
|
saveSetupState(state);
|
|
@@ -15141,7 +15467,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15141
15467
|
await saveConfig(config);
|
|
15142
15468
|
log("");
|
|
15143
15469
|
try {
|
|
15144
|
-
const claudeJsonPath =
|
|
15470
|
+
const claudeJsonPath = path34.join(os16.homedir(), ".claude.json");
|
|
15145
15471
|
let claudeJson = {};
|
|
15146
15472
|
try {
|
|
15147
15473
|
claudeJson = JSON.parse(readFileSync23(claudeJsonPath, "utf8"));
|
|
@@ -15167,7 +15493,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15167
15493
|
const prefs = { ...existingPrefs };
|
|
15168
15494
|
log("=== Config Defaults ===");
|
|
15169
15495
|
log("");
|
|
15170
|
-
const ghosttyDetected =
|
|
15496
|
+
const ghosttyDetected = existsSync28(path34.join(os16.homedir(), ".config", "ghostty")) || existsSync28(path34.join(os16.homedir(), "Library", "Application Support", "com.mitchellh.ghostty"));
|
|
15171
15497
|
if (ghosttyDetected) {
|
|
15172
15498
|
const ghosttyAnswer = await ask2(rl, "Detected Ghostty terminal. Use exe-os Ghostty defaults? (Y/n) ");
|
|
15173
15499
|
prefs.ghostty = ghosttyAnswer.toLowerCase() !== "n";
|
|
@@ -15214,7 +15540,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15214
15540
|
let missingIdentities = [];
|
|
15215
15541
|
for (const emp of roster) {
|
|
15216
15542
|
const idPath = identityPath2(emp.name);
|
|
15217
|
-
if (!
|
|
15543
|
+
if (!existsSync28(idPath)) {
|
|
15218
15544
|
missingIdentities.push(emp.name);
|
|
15219
15545
|
}
|
|
15220
15546
|
}
|
|
@@ -15246,7 +15572,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15246
15572
|
}
|
|
15247
15573
|
missingIdentities = [];
|
|
15248
15574
|
for (const emp of roster) {
|
|
15249
|
-
if (!
|
|
15575
|
+
if (!existsSync28(identityPath2(emp.name))) {
|
|
15250
15576
|
missingIdentities.push(emp.name);
|
|
15251
15577
|
}
|
|
15252
15578
|
}
|
|
@@ -15311,7 +15637,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15311
15637
|
const cooIdentityContent = getIdentityTemplate("coo");
|
|
15312
15638
|
if (cooIdentityContent) {
|
|
15313
15639
|
const cooIdPath = identityPath2(cooName);
|
|
15314
|
-
|
|
15640
|
+
mkdirSync18(path34.dirname(cooIdPath), { recursive: true });
|
|
15315
15641
|
const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
|
|
15316
15642
|
writeFileSync19(cooIdPath, replaced, "utf-8");
|
|
15317
15643
|
}
|
|
@@ -15407,7 +15733,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15407
15733
|
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
15408
15734
|
if (ctoIdentityContent) {
|
|
15409
15735
|
const ctoIdPath = identityPath2(ctoName);
|
|
15410
|
-
|
|
15736
|
+
mkdirSync18(path34.dirname(ctoIdPath), { recursive: true });
|
|
15411
15737
|
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
15412
15738
|
writeFileSync19(ctoIdPath, replaced, "utf-8");
|
|
15413
15739
|
}
|
|
@@ -15430,7 +15756,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15430
15756
|
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
15431
15757
|
if (cmoIdentityContent) {
|
|
15432
15758
|
const cmoIdPath = identityPath2(cmoName);
|
|
15433
|
-
|
|
15759
|
+
mkdirSync18(path34.dirname(cmoIdPath), { recursive: true });
|
|
15434
15760
|
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
15435
15761
|
writeFileSync19(cmoIdPath, replaced, "utf-8");
|
|
15436
15762
|
}
|
|
@@ -15454,7 +15780,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15454
15780
|
log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
|
|
15455
15781
|
}
|
|
15456
15782
|
if (wrapResult.pathConfigured) {
|
|
15457
|
-
const binDir =
|
|
15783
|
+
const binDir = path34.join(os16.homedir(), ".exe-os", "bin");
|
|
15458
15784
|
process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
|
|
15459
15785
|
pathJustConfigured = true;
|
|
15460
15786
|
}
|
|
@@ -15497,7 +15823,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
15497
15823
|
const pkgRoot2 = findPackageRoot2();
|
|
15498
15824
|
if (pkgRoot2) {
|
|
15499
15825
|
try {
|
|
15500
|
-
version = JSON.parse(readFileSync23(
|
|
15826
|
+
version = JSON.parse(readFileSync23(path34.join(pkgRoot2, "package.json"), "utf-8")).version;
|
|
15501
15827
|
} catch {
|
|
15502
15828
|
}
|
|
15503
15829
|
}
|
|
@@ -15531,32 +15857,32 @@ var init_setup_wizard = __esm({
|
|
|
15531
15857
|
init_config();
|
|
15532
15858
|
init_keychain();
|
|
15533
15859
|
init_model_downloader();
|
|
15534
|
-
SETUP_STATE_PATH =
|
|
15860
|
+
SETUP_STATE_PATH = path34.join(os16.homedir(), ".exe-os", "setup-state.json");
|
|
15535
15861
|
}
|
|
15536
15862
|
});
|
|
15537
15863
|
|
|
15538
15864
|
// src/lib/update-backup.ts
|
|
15539
15865
|
import { copyFile, readFile as readFile6, readdir as readdir3, writeFile as writeFile7, rm, mkdir as mkdir7, cp } from "fs/promises";
|
|
15540
|
-
import { existsSync as
|
|
15541
|
-
import
|
|
15866
|
+
import { existsSync as existsSync29 } from "fs";
|
|
15867
|
+
import path35 from "path";
|
|
15542
15868
|
import os17 from "os";
|
|
15543
15869
|
function resolveDataDir2() {
|
|
15544
15870
|
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
15545
15871
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
15546
|
-
return
|
|
15872
|
+
return path35.join(os17.homedir(), ".exe-os");
|
|
15547
15873
|
}
|
|
15548
15874
|
async function createUpdateBackup(currentVersion, dataDir) {
|
|
15549
15875
|
const dir = dataDir ?? resolveDataDir2();
|
|
15550
|
-
const backupDir =
|
|
15551
|
-
if (
|
|
15876
|
+
const backupDir = path35.join(dir, BACKUP_DIR_NAME);
|
|
15877
|
+
if (existsSync29(backupDir)) {
|
|
15552
15878
|
await rm(backupDir, { recursive: true, force: true });
|
|
15553
15879
|
}
|
|
15554
15880
|
await mkdir7(backupDir, { recursive: true });
|
|
15555
15881
|
const backedUpFiles = [];
|
|
15556
15882
|
for (const target of BACKUP_TARGETS) {
|
|
15557
|
-
const src =
|
|
15558
|
-
if (!
|
|
15559
|
-
const dest =
|
|
15883
|
+
const src = path35.join(dir, target.name);
|
|
15884
|
+
if (!existsSync29(src)) continue;
|
|
15885
|
+
const dest = path35.join(backupDir, target.name);
|
|
15560
15886
|
if (target.type === "file") {
|
|
15561
15887
|
await copyFile(src, dest);
|
|
15562
15888
|
} else {
|
|
@@ -15567,8 +15893,8 @@ async function createUpdateBackup(currentVersion, dataDir) {
|
|
|
15567
15893
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
15568
15894
|
for (const entry of entries) {
|
|
15569
15895
|
if (entry.isFile() && entry.name.endsWith(".db") && entry.name !== BACKUP_DIR_NAME) {
|
|
15570
|
-
const src =
|
|
15571
|
-
const dest =
|
|
15896
|
+
const src = path35.join(dir, entry.name);
|
|
15897
|
+
const dest = path35.join(backupDir, entry.name);
|
|
15572
15898
|
await copyFile(src, dest);
|
|
15573
15899
|
backedUpFiles.push(entry.name);
|
|
15574
15900
|
}
|
|
@@ -15579,16 +15905,16 @@ async function createUpdateBackup(currentVersion, dataDir) {
|
|
|
15579
15905
|
files: backedUpFiles
|
|
15580
15906
|
};
|
|
15581
15907
|
await writeFile7(
|
|
15582
|
-
|
|
15908
|
+
path35.join(backupDir, "manifest.json"),
|
|
15583
15909
|
JSON.stringify(manifest, null, 2) + "\n"
|
|
15584
15910
|
);
|
|
15585
15911
|
return manifest;
|
|
15586
15912
|
}
|
|
15587
15913
|
async function restoreFromBackup(dataDir) {
|
|
15588
15914
|
const dir = dataDir ?? resolveDataDir2();
|
|
15589
|
-
const backupDir =
|
|
15590
|
-
const manifestPath =
|
|
15591
|
-
if (!
|
|
15915
|
+
const backupDir = path35.join(dir, BACKUP_DIR_NAME);
|
|
15916
|
+
const manifestPath = path35.join(backupDir, "manifest.json");
|
|
15917
|
+
if (!existsSync29(manifestPath)) {
|
|
15592
15918
|
throw new Error(
|
|
15593
15919
|
`No backup found at ${backupDir}. Nothing to restore.`
|
|
15594
15920
|
);
|
|
@@ -15597,9 +15923,9 @@ async function restoreFromBackup(dataDir) {
|
|
|
15597
15923
|
await readFile6(manifestPath, "utf-8")
|
|
15598
15924
|
);
|
|
15599
15925
|
for (const fileName of manifest.files) {
|
|
15600
|
-
const src =
|
|
15601
|
-
const dest =
|
|
15602
|
-
if (!
|
|
15926
|
+
const src = path35.join(backupDir, fileName);
|
|
15927
|
+
const dest = path35.join(dir, fileName);
|
|
15928
|
+
if (!existsSync29(src)) continue;
|
|
15603
15929
|
const stat2 = await import("fs/promises").then((m) => m.stat(src));
|
|
15604
15930
|
if (stat2.isDirectory()) {
|
|
15605
15931
|
await cp(src, dest, { recursive: true, force: true });
|
|
@@ -15611,8 +15937,8 @@ async function restoreFromBackup(dataDir) {
|
|
|
15611
15937
|
}
|
|
15612
15938
|
async function deleteBackup(dataDir) {
|
|
15613
15939
|
const dir = dataDir ?? resolveDataDir2();
|
|
15614
|
-
const backupDir =
|
|
15615
|
-
if (
|
|
15940
|
+
const backupDir = path35.join(dir, BACKUP_DIR_NAME);
|
|
15941
|
+
if (existsSync29(backupDir)) {
|
|
15616
15942
|
await rm(backupDir, { recursive: true, force: true });
|
|
15617
15943
|
}
|
|
15618
15944
|
}
|
|
@@ -15632,17 +15958,17 @@ var init_update_backup = __esm({
|
|
|
15632
15958
|
});
|
|
15633
15959
|
|
|
15634
15960
|
// src/lib/update-check.ts
|
|
15635
|
-
import { execSync as
|
|
15961
|
+
import { execSync as execSync12 } from "child_process";
|
|
15636
15962
|
import { readFileSync as readFileSync24 } from "fs";
|
|
15637
|
-
import
|
|
15963
|
+
import path36 from "path";
|
|
15638
15964
|
function getLocalVersion(packageRoot) {
|
|
15639
|
-
const pkgPath =
|
|
15965
|
+
const pkgPath = path36.join(packageRoot, "package.json");
|
|
15640
15966
|
const pkg = JSON.parse(readFileSync24(pkgPath, "utf-8"));
|
|
15641
15967
|
return pkg.version;
|
|
15642
15968
|
}
|
|
15643
15969
|
function getRemoteVersion() {
|
|
15644
15970
|
try {
|
|
15645
|
-
const output =
|
|
15971
|
+
const output = execSync12("npm view @askexenow/exe-os version", {
|
|
15646
15972
|
encoding: "utf-8",
|
|
15647
15973
|
timeout: 15e3,
|
|
15648
15974
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -15681,7 +16007,7 @@ __export(update_exports, {
|
|
|
15681
16007
|
getRemoteVersion: () => getRemoteVersion,
|
|
15682
16008
|
runUpdate: () => runUpdate
|
|
15683
16009
|
});
|
|
15684
|
-
import { execSync as
|
|
16010
|
+
import { execSync as execSync13 } from "child_process";
|
|
15685
16011
|
import { createInterface as createInterface4 } from "readline";
|
|
15686
16012
|
async function runRestore() {
|
|
15687
16013
|
console.log("\n\u{1F504} Restoring from update backup...");
|
|
@@ -15692,7 +16018,7 @@ async function runRestore() {
|
|
|
15692
16018
|
console.log(`
|
|
15693
16019
|
\u{1F4E5} Reinstalling @askexenow/exe-os@${manifest.version}...`);
|
|
15694
16020
|
try {
|
|
15695
|
-
|
|
16021
|
+
execSync13(`npm install -g @askexenow/exe-os@${manifest.version}`, {
|
|
15696
16022
|
stdio: ["pipe", "pipe", "inherit"],
|
|
15697
16023
|
timeout: 3e5
|
|
15698
16024
|
});
|
|
@@ -15769,7 +16095,7 @@ async function runUpdate(cliArgs) {
|
|
|
15769
16095
|
}
|
|
15770
16096
|
console.log("\u{1F9F9} Clearing npm cache...");
|
|
15771
16097
|
try {
|
|
15772
|
-
|
|
16098
|
+
execSync13("npm cache clean --force", { stdio: "pipe" });
|
|
15773
16099
|
console.log(" Done");
|
|
15774
16100
|
} catch {
|
|
15775
16101
|
console.log(" Skipped (non-critical)");
|
|
@@ -15777,7 +16103,7 @@ async function runUpdate(cliArgs) {
|
|
|
15777
16103
|
console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
|
|
15778
16104
|
console.log(" This may take a minute...\n");
|
|
15779
16105
|
try {
|
|
15780
|
-
|
|
16106
|
+
execSync13("npm install -g @askexenow/exe-os@latest", {
|
|
15781
16107
|
stdio: ["pipe", "pipe", "inherit"],
|
|
15782
16108
|
timeout: 3e5
|
|
15783
16109
|
});
|
|
@@ -15795,7 +16121,7 @@ async function runUpdate(cliArgs) {
|
|
|
15795
16121
|
newVersion = getLocalVersion(packageRoot);
|
|
15796
16122
|
} catch {
|
|
15797
16123
|
try {
|
|
15798
|
-
const out =
|
|
16124
|
+
const out = execSync13("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
|
|
15799
16125
|
const match = out.match(/@askexenow\/exe-os@(\S+)/);
|
|
15800
16126
|
newVersion = match?.[1] ?? "unknown";
|
|
15801
16127
|
} catch {
|
|
@@ -20220,8 +20546,8 @@ var init_ErrorOverview = __esm({
|
|
|
20220
20546
|
"use strict";
|
|
20221
20547
|
init_Box();
|
|
20222
20548
|
init_Text();
|
|
20223
|
-
cleanupPath = (
|
|
20224
|
-
return
|
|
20549
|
+
cleanupPath = (path48) => {
|
|
20550
|
+
return path48?.replace(`file://${cwd()}/`, "");
|
|
20225
20551
|
};
|
|
20226
20552
|
stackUtils = new StackUtils({
|
|
20227
20553
|
cwd: cwd(),
|
|
@@ -22325,13 +22651,13 @@ __export(tmux_status_exports, {
|
|
|
22325
22651
|
parseActivity: () => parseActivity,
|
|
22326
22652
|
parseContextPercentage: () => parseContextPercentage
|
|
22327
22653
|
});
|
|
22328
|
-
import { execSync as
|
|
22654
|
+
import { execSync as execSync14 } from "child_process";
|
|
22329
22655
|
function inTmux() {
|
|
22330
22656
|
if (process.env.TMUX || process.env.TMUX_PANE) return true;
|
|
22331
22657
|
const term = process.env.TERM ?? "";
|
|
22332
22658
|
if (term.startsWith("tmux") || term.startsWith("screen")) return true;
|
|
22333
22659
|
try {
|
|
22334
|
-
|
|
22660
|
+
execSync14("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
22335
22661
|
encoding: "utf8",
|
|
22336
22662
|
timeout: 2e3
|
|
22337
22663
|
});
|
|
@@ -22341,12 +22667,12 @@ function inTmux() {
|
|
|
22341
22667
|
try {
|
|
22342
22668
|
let pid = process.ppid;
|
|
22343
22669
|
for (let depth = 0; depth < 8 && pid > 1; depth++) {
|
|
22344
|
-
const comm =
|
|
22670
|
+
const comm = execSync14(`ps -p ${pid} -o comm= 2>/dev/null`, {
|
|
22345
22671
|
encoding: "utf8",
|
|
22346
22672
|
timeout: 1e3
|
|
22347
22673
|
}).trim();
|
|
22348
22674
|
if (/tmux/.test(comm)) return true;
|
|
22349
|
-
const ppid =
|
|
22675
|
+
const ppid = execSync14(`ps -p ${pid} -o ppid= 2>/dev/null`, {
|
|
22350
22676
|
encoding: "utf8",
|
|
22351
22677
|
timeout: 1e3
|
|
22352
22678
|
}).trim();
|
|
@@ -22359,7 +22685,7 @@ function inTmux() {
|
|
|
22359
22685
|
}
|
|
22360
22686
|
function listTmuxSessions() {
|
|
22361
22687
|
try {
|
|
22362
|
-
const out =
|
|
22688
|
+
const out = execSync14("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
22363
22689
|
encoding: "utf8",
|
|
22364
22690
|
timeout: 3e3
|
|
22365
22691
|
});
|
|
@@ -22370,7 +22696,7 @@ function listTmuxSessions() {
|
|
|
22370
22696
|
}
|
|
22371
22697
|
function capturePaneLines(windowName, lines = 10) {
|
|
22372
22698
|
try {
|
|
22373
|
-
const out =
|
|
22699
|
+
const out = execSync14(
|
|
22374
22700
|
`tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
|
|
22375
22701
|
{ encoding: "utf8", timeout: 3e3 }
|
|
22376
22702
|
);
|
|
@@ -22381,7 +22707,7 @@ function capturePaneLines(windowName, lines = 10) {
|
|
|
22381
22707
|
}
|
|
22382
22708
|
function getPaneCwd(windowName) {
|
|
22383
22709
|
try {
|
|
22384
|
-
const out =
|
|
22710
|
+
const out = execSync14(
|
|
22385
22711
|
`tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
|
|
22386
22712
|
{ encoding: "utf8", timeout: 3e3 }
|
|
22387
22713
|
);
|
|
@@ -22392,7 +22718,7 @@ function getPaneCwd(windowName) {
|
|
|
22392
22718
|
}
|
|
22393
22719
|
function projectFromPath(dir) {
|
|
22394
22720
|
try {
|
|
22395
|
-
const root =
|
|
22721
|
+
const root = execSync14("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
|
|
22396
22722
|
encoding: "utf8",
|
|
22397
22723
|
timeout: 3e3
|
|
22398
22724
|
}).trim();
|
|
@@ -22461,7 +22787,7 @@ function getEmployeeStatuses(employeeNames) {
|
|
|
22461
22787
|
}
|
|
22462
22788
|
let paneAlive = true;
|
|
22463
22789
|
try {
|
|
22464
|
-
const paneStatus =
|
|
22790
|
+
const paneStatus = execSync14(
|
|
22465
22791
|
`tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
|
|
22466
22792
|
{ encoding: "utf8", timeout: 3e3 }
|
|
22467
22793
|
).trim();
|
|
@@ -22629,11 +22955,11 @@ function Footer() {
|
|
|
22629
22955
|
} catch {
|
|
22630
22956
|
}
|
|
22631
22957
|
try {
|
|
22632
|
-
const { existsSync:
|
|
22958
|
+
const { existsSync: existsSync34 } = await import("fs");
|
|
22633
22959
|
const { join } = await import("path");
|
|
22634
22960
|
const home = process.env.HOME ?? "";
|
|
22635
22961
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
22636
|
-
setDaemon(
|
|
22962
|
+
setDaemon(existsSync34(pidPath) ? "running" : "stopped");
|
|
22637
22963
|
} catch {
|
|
22638
22964
|
setDaemon("unknown");
|
|
22639
22965
|
}
|
|
@@ -22651,8 +22977,8 @@ function Footer() {
|
|
|
22651
22977
|
setSessions(allSessions.length);
|
|
22652
22978
|
if (!currentSession) {
|
|
22653
22979
|
try {
|
|
22654
|
-
const { execSync:
|
|
22655
|
-
const name =
|
|
22980
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
22981
|
+
const name = execSync16("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
22656
22982
|
encoding: "utf8",
|
|
22657
22983
|
timeout: 2e3
|
|
22658
22984
|
}).trim();
|
|
@@ -24684,10 +25010,10 @@ var init_hooks = __esm({
|
|
|
24684
25010
|
});
|
|
24685
25011
|
|
|
24686
25012
|
// src/runtime/safety-checks.ts
|
|
24687
|
-
import
|
|
25013
|
+
import path37 from "path";
|
|
24688
25014
|
import os18 from "os";
|
|
24689
25015
|
function checkPathSafety(filePath) {
|
|
24690
|
-
const resolved =
|
|
25016
|
+
const resolved = path37.resolve(filePath);
|
|
24691
25017
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
24692
25018
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
24693
25019
|
if (matches) {
|
|
@@ -24697,7 +25023,7 @@ function checkPathSafety(filePath) {
|
|
|
24697
25023
|
return { safe: true, bypassImmune: true };
|
|
24698
25024
|
}
|
|
24699
25025
|
function checkReadPathSafety(filePath) {
|
|
24700
|
-
const resolved =
|
|
25026
|
+
const resolved = path37.resolve(filePath);
|
|
24701
25027
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
24702
25028
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
24703
25029
|
);
|
|
@@ -24723,11 +25049,11 @@ var init_safety_checks = __esm({
|
|
|
24723
25049
|
reason: "Git config can set hooks and command execution"
|
|
24724
25050
|
},
|
|
24725
25051
|
{
|
|
24726
|
-
pattern: (p) => p.startsWith(
|
|
25052
|
+
pattern: (p) => p.startsWith(path37.join(HOME, ".claude")),
|
|
24727
25053
|
reason: "Claude configuration files are protected"
|
|
24728
25054
|
},
|
|
24729
25055
|
{
|
|
24730
|
-
pattern: (p) => p.startsWith(
|
|
25056
|
+
pattern: (p) => p.startsWith(path37.join(HOME, ".exe-os")),
|
|
24731
25057
|
reason: "exe-os configuration files are protected"
|
|
24732
25058
|
},
|
|
24733
25059
|
{
|
|
@@ -24744,7 +25070,7 @@ var init_safety_checks = __esm({
|
|
|
24744
25070
|
},
|
|
24745
25071
|
{
|
|
24746
25072
|
pattern: (p) => {
|
|
24747
|
-
const name =
|
|
25073
|
+
const name = path37.basename(p);
|
|
24748
25074
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
24749
25075
|
},
|
|
24750
25076
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -24771,7 +25097,7 @@ __export(file_read_exports, {
|
|
|
24771
25097
|
FileReadTool: () => FileReadTool
|
|
24772
25098
|
});
|
|
24773
25099
|
import fs3 from "fs/promises";
|
|
24774
|
-
import
|
|
25100
|
+
import path38 from "path";
|
|
24775
25101
|
import { z } from "zod";
|
|
24776
25102
|
function isBinary(buf) {
|
|
24777
25103
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -24807,7 +25133,7 @@ var init_file_read = __esm({
|
|
|
24807
25133
|
return { behavior: "allow" };
|
|
24808
25134
|
},
|
|
24809
25135
|
async call(input, context) {
|
|
24810
|
-
const filePath =
|
|
25136
|
+
const filePath = path38.isAbsolute(input.file_path) ? input.file_path : path38.resolve(context.cwd, input.file_path);
|
|
24811
25137
|
let stat2;
|
|
24812
25138
|
try {
|
|
24813
25139
|
stat2 = await fs3.stat(filePath);
|
|
@@ -24847,7 +25173,7 @@ __export(glob_exports, {
|
|
|
24847
25173
|
GlobTool: () => GlobTool
|
|
24848
25174
|
});
|
|
24849
25175
|
import fs4 from "fs/promises";
|
|
24850
|
-
import
|
|
25176
|
+
import path39 from "path";
|
|
24851
25177
|
import { z as z2 } from "zod";
|
|
24852
25178
|
async function walkDir(dir, maxDepth = 10) {
|
|
24853
25179
|
const results = [];
|
|
@@ -24863,7 +25189,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
24863
25189
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
24864
25190
|
continue;
|
|
24865
25191
|
}
|
|
24866
|
-
const fullPath =
|
|
25192
|
+
const fullPath = path39.join(current, entry.name);
|
|
24867
25193
|
if (entry.isDirectory()) {
|
|
24868
25194
|
await walk(fullPath, depth + 1);
|
|
24869
25195
|
} else {
|
|
@@ -24897,11 +25223,11 @@ var init_glob = __esm({
|
|
|
24897
25223
|
inputSchema: inputSchema2,
|
|
24898
25224
|
isReadOnly: true,
|
|
24899
25225
|
async call(input, context) {
|
|
24900
|
-
const baseDir = input.path ?
|
|
25226
|
+
const baseDir = input.path ? path39.isAbsolute(input.path) ? input.path : path39.resolve(context.cwd, input.path) : context.cwd;
|
|
24901
25227
|
try {
|
|
24902
25228
|
const entries = await walkDir(baseDir);
|
|
24903
25229
|
const matched = entries.filter(
|
|
24904
|
-
(e) => simpleGlobMatch(
|
|
25230
|
+
(e) => simpleGlobMatch(path39.relative(baseDir, e.path), input.pattern)
|
|
24905
25231
|
);
|
|
24906
25232
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
24907
25233
|
if (matched.length === 0) {
|
|
@@ -24927,7 +25253,7 @@ __export(grep_exports, {
|
|
|
24927
25253
|
});
|
|
24928
25254
|
import { spawn as spawn2 } from "child_process";
|
|
24929
25255
|
import fs5 from "fs/promises";
|
|
24930
|
-
import
|
|
25256
|
+
import path40 from "path";
|
|
24931
25257
|
import { z as z3 } from "zod";
|
|
24932
25258
|
function runRipgrep(input, searchPath, context) {
|
|
24933
25259
|
return new Promise((resolve, reject) => {
|
|
@@ -24981,7 +25307,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
24981
25307
|
}
|
|
24982
25308
|
for (const entry of entries) {
|
|
24983
25309
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
24984
|
-
const fullPath =
|
|
25310
|
+
const fullPath = path40.join(dir, entry.name);
|
|
24985
25311
|
if (entry.isDirectory()) {
|
|
24986
25312
|
await walk(fullPath);
|
|
24987
25313
|
} else {
|
|
@@ -25027,7 +25353,7 @@ var init_grep = __esm({
|
|
|
25027
25353
|
inputSchema: inputSchema3,
|
|
25028
25354
|
isReadOnly: true,
|
|
25029
25355
|
async call(input, context) {
|
|
25030
|
-
const searchPath = input.path ?
|
|
25356
|
+
const searchPath = input.path ? path40.isAbsolute(input.path) ? input.path : path40.resolve(context.cwd, input.path) : context.cwd;
|
|
25031
25357
|
try {
|
|
25032
25358
|
const result = await runRipgrep(input, searchPath, context);
|
|
25033
25359
|
return result;
|
|
@@ -25052,7 +25378,7 @@ __export(file_write_exports, {
|
|
|
25052
25378
|
FileWriteTool: () => FileWriteTool
|
|
25053
25379
|
});
|
|
25054
25380
|
import fs6 from "fs/promises";
|
|
25055
|
-
import
|
|
25381
|
+
import path41 from "path";
|
|
25056
25382
|
import { z as z4 } from "zod";
|
|
25057
25383
|
var inputSchema4, FileWriteTool;
|
|
25058
25384
|
var init_file_write = __esm({
|
|
@@ -25080,8 +25406,8 @@ var init_file_write = __esm({
|
|
|
25080
25406
|
return { behavior: "allow" };
|
|
25081
25407
|
},
|
|
25082
25408
|
async call(input, context) {
|
|
25083
|
-
const filePath =
|
|
25084
|
-
const dir =
|
|
25409
|
+
const filePath = path41.isAbsolute(input.file_path) ? input.file_path : path41.resolve(context.cwd, input.file_path);
|
|
25410
|
+
const dir = path41.dirname(filePath);
|
|
25085
25411
|
await fs6.mkdir(dir, { recursive: true });
|
|
25086
25412
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
25087
25413
|
return {
|
|
@@ -25099,7 +25425,7 @@ __export(file_edit_exports, {
|
|
|
25099
25425
|
FileEditTool: () => FileEditTool
|
|
25100
25426
|
});
|
|
25101
25427
|
import fs7 from "fs/promises";
|
|
25102
|
-
import
|
|
25428
|
+
import path42 from "path";
|
|
25103
25429
|
import { z as z5 } from "zod";
|
|
25104
25430
|
function countOccurrences(haystack, needle) {
|
|
25105
25431
|
let count = 0;
|
|
@@ -25140,7 +25466,7 @@ var init_file_edit = __esm({
|
|
|
25140
25466
|
return { behavior: "allow" };
|
|
25141
25467
|
},
|
|
25142
25468
|
async call(input, context) {
|
|
25143
|
-
const filePath =
|
|
25469
|
+
const filePath = path42.isAbsolute(input.file_path) ? input.file_path : path42.resolve(context.cwd, input.file_path);
|
|
25144
25470
|
let content;
|
|
25145
25471
|
try {
|
|
25146
25472
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -25382,7 +25708,7 @@ var init_bash = __esm({
|
|
|
25382
25708
|
// src/tui/views/CommandCenter.tsx
|
|
25383
25709
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
25384
25710
|
import TextInput from "ink-text-input";
|
|
25385
|
-
import
|
|
25711
|
+
import path43 from "path";
|
|
25386
25712
|
import { homedir as homedir6 } from "os";
|
|
25387
25713
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
25388
25714
|
function CommandCenterView({
|
|
@@ -25417,13 +25743,13 @@ function CommandCenterView({
|
|
|
25417
25743
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
25418
25744
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
25419
25745
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
25420
|
-
const { readFileSync: readFileSync28, existsSync:
|
|
25746
|
+
const { readFileSync: readFileSync28, existsSync: existsSync34 } = await import("fs");
|
|
25421
25747
|
const { join } = await import("path");
|
|
25422
25748
|
const { homedir: homedir8 } = await import("os");
|
|
25423
25749
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
25424
25750
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
25425
25751
|
let providerConfigs = {};
|
|
25426
|
-
if (
|
|
25752
|
+
if (existsSync34(configPath)) {
|
|
25427
25753
|
try {
|
|
25428
25754
|
const raw = JSON.parse(readFileSync28(configPath, "utf8"));
|
|
25429
25755
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
@@ -25631,7 +25957,7 @@ function CommandCenterView({
|
|
|
25631
25957
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
25632
25958
|
projectName: p.projectName,
|
|
25633
25959
|
exeSession: p.exeSession,
|
|
25634
|
-
projectDir:
|
|
25960
|
+
projectDir: path43.join(homedir6(), p.projectName),
|
|
25635
25961
|
employeeCount: p.employees.length,
|
|
25636
25962
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
25637
25963
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -25669,7 +25995,7 @@ function CommandCenterView({
|
|
|
25669
25995
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
25670
25996
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
25671
25997
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
25672
|
-
const { existsSync:
|
|
25998
|
+
const { existsSync: existsSync34 } = await import("fs");
|
|
25673
25999
|
const { join } = await import("path");
|
|
25674
26000
|
const client = getClient2();
|
|
25675
26001
|
if (!client) {
|
|
@@ -25740,7 +26066,7 @@ function CommandCenterView({
|
|
|
25740
26066
|
}
|
|
25741
26067
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
25742
26068
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
25743
|
-
const hasGit = projectDir ?
|
|
26069
|
+
const hasGit = projectDir ? existsSync34(join(projectDir, ".git")) : false;
|
|
25744
26070
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
25745
26071
|
projectList.push({
|
|
25746
26072
|
projectName: name,
|
|
@@ -25765,7 +26091,7 @@ function CommandCenterView({
|
|
|
25765
26091
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
25766
26092
|
try {
|
|
25767
26093
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
25768
|
-
setHealth((h) => ({ ...h, daemon:
|
|
26094
|
+
setHealth((h) => ({ ...h, daemon: existsSync34(pidPath) ? "running" : "stopped" }));
|
|
25769
26095
|
} catch {
|
|
25770
26096
|
}
|
|
25771
26097
|
const activityResult = await client.execute(
|
|
@@ -26006,8 +26332,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
26006
26332
|
}
|
|
26007
26333
|
const capture = () => {
|
|
26008
26334
|
try {
|
|
26009
|
-
const { execSync:
|
|
26010
|
-
const output =
|
|
26335
|
+
const { execSync: execSync16 } = __require("child_process");
|
|
26336
|
+
const output = execSync16(
|
|
26011
26337
|
`tmux capture-pane -t ${JSON.stringify(sessionName)} -p -e 2>/dev/null | tail -${CAPTURE_LINES}`,
|
|
26012
26338
|
{ encoding: "utf8", timeout: 3e3 }
|
|
26013
26339
|
);
|
|
@@ -26031,8 +26357,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
26031
26357
|
if (key.return) {
|
|
26032
26358
|
if (!demo && inputBuffer.trim()) {
|
|
26033
26359
|
try {
|
|
26034
|
-
const { execSync:
|
|
26035
|
-
|
|
26360
|
+
const { execSync: execSync16 } = __require("child_process");
|
|
26361
|
+
execSync16(
|
|
26036
26362
|
`tmux send-keys -t ${JSON.stringify(sessionName)} ${JSON.stringify(inputBuffer)} Enter`,
|
|
26037
26363
|
{ timeout: 2e3 }
|
|
26038
26364
|
);
|
|
@@ -26040,8 +26366,8 @@ function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDeta
|
|
|
26040
26366
|
}
|
|
26041
26367
|
} else if (!demo) {
|
|
26042
26368
|
try {
|
|
26043
|
-
const { execSync:
|
|
26044
|
-
|
|
26369
|
+
const { execSync: execSync16 } = __require("child_process");
|
|
26370
|
+
execSync16(`tmux send-keys -t ${JSON.stringify(sessionName)} Enter`, { timeout: 2e3 });
|
|
26045
26371
|
} catch {
|
|
26046
26372
|
}
|
|
26047
26373
|
}
|
|
@@ -26635,7 +26961,7 @@ var init_useOrchestrator = __esm({
|
|
|
26635
26961
|
|
|
26636
26962
|
// src/tui/views/Sessions.tsx
|
|
26637
26963
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
26638
|
-
import
|
|
26964
|
+
import path44 from "path";
|
|
26639
26965
|
import { homedir as homedir7 } from "os";
|
|
26640
26966
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
26641
26967
|
function isCoordinatorEntry(entry) {
|
|
@@ -26673,7 +26999,7 @@ function SessionsView({
|
|
|
26673
26999
|
if (demo) {
|
|
26674
27000
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
26675
27001
|
...p,
|
|
26676
|
-
projectDir:
|
|
27002
|
+
projectDir: path44.join(homedir7(), p.projectName),
|
|
26677
27003
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
26678
27004
|
})));
|
|
26679
27005
|
return;
|
|
@@ -26728,12 +27054,12 @@ function SessionsView({
|
|
|
26728
27054
|
return;
|
|
26729
27055
|
}
|
|
26730
27056
|
} else {
|
|
26731
|
-
const { execSync:
|
|
27057
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
26732
27058
|
const dir = projectDir || process.cwd();
|
|
26733
|
-
|
|
26734
|
-
|
|
27059
|
+
execSync16(`tmux new-session -d -s ${JSON.stringify(entry.sessionName)} -c ${JSON.stringify(dir)}`, { timeout: 5e3 });
|
|
27060
|
+
execSync16(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "claude --dangerously-skip-permissions" Enter`, { timeout: 3e3 });
|
|
26735
27061
|
await new Promise((r) => setTimeout(r, 3e3));
|
|
26736
|
-
|
|
27062
|
+
execSync16(`tmux send-keys -t ${JSON.stringify(entry.sessionName)} "/exe" Enter`, { timeout: 3e3 });
|
|
26737
27063
|
}
|
|
26738
27064
|
const updated = { ...entry, status: "active", activity: "Starting...", attached: false };
|
|
26739
27065
|
setViewingEmployee(updated);
|
|
@@ -26836,7 +27162,7 @@ function SessionsView({
|
|
|
26836
27162
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2, capturePaneLines: capturePaneLines2, parseActivity: parseActivity2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
26837
27163
|
const { getCoordinatorName: getCoordinatorName2, isCoordinatorRole: isCoordinatorRole2, loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
26838
27164
|
const { isExeSession: isExeSession2 } = await Promise.resolve().then(() => (init_tmux_routing(), tmux_routing_exports));
|
|
26839
|
-
const { execSync:
|
|
27165
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
26840
27166
|
if (!inTmux2()) {
|
|
26841
27167
|
setTmuxAvailable(false);
|
|
26842
27168
|
setProjects([]);
|
|
@@ -26845,7 +27171,7 @@ function SessionsView({
|
|
|
26845
27171
|
setTmuxAvailable(true);
|
|
26846
27172
|
const attachedMap = /* @__PURE__ */ new Map();
|
|
26847
27173
|
try {
|
|
26848
|
-
const out =
|
|
27174
|
+
const out = execSync16("tmux list-sessions -F '#{session_name}:#{session_attached}' 2>/dev/null", {
|
|
26849
27175
|
encoding: "utf8",
|
|
26850
27176
|
timeout: 3e3
|
|
26851
27177
|
});
|
|
@@ -27881,18 +28207,18 @@ function upsertConversation(conversations, platform, senderId, message) {
|
|
|
27881
28207
|
async function loadGatewayConfig() {
|
|
27882
28208
|
const state = { running: false, port: 3100, adapters: [], agents: [], gatewayUrl: "" };
|
|
27883
28209
|
try {
|
|
27884
|
-
const { execSync:
|
|
27885
|
-
const ps =
|
|
28210
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
28211
|
+
const ps = execSync16("pgrep -f exe-gateway 2>/dev/null", { encoding: "utf8", timeout: 3e3 });
|
|
27886
28212
|
state.running = ps.trim().length > 0;
|
|
27887
28213
|
} catch {
|
|
27888
28214
|
state.running = false;
|
|
27889
28215
|
}
|
|
27890
28216
|
try {
|
|
27891
|
-
const { existsSync:
|
|
28217
|
+
const { existsSync: existsSync34, readFileSync: readFileSync28 } = await import("fs");
|
|
27892
28218
|
const { join } = await import("path");
|
|
27893
28219
|
const home = process.env.HOME ?? "";
|
|
27894
28220
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
27895
|
-
if (
|
|
28221
|
+
if (existsSync34(configPath)) {
|
|
27896
28222
|
const raw = JSON.parse(readFileSync28(configPath, "utf8"));
|
|
27897
28223
|
state.port = raw.port ?? 3100;
|
|
27898
28224
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
@@ -28359,10 +28685,10 @@ var init_Gateway = __esm({
|
|
|
28359
28685
|
});
|
|
28360
28686
|
|
|
28361
28687
|
// src/tui/utils/agent-status.ts
|
|
28362
|
-
import { execSync as
|
|
28688
|
+
import { execSync as execSync15 } from "child_process";
|
|
28363
28689
|
function getAgentStatus(agentId) {
|
|
28364
28690
|
try {
|
|
28365
|
-
const sessions =
|
|
28691
|
+
const sessions = execSync15("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
28366
28692
|
encoding: "utf8",
|
|
28367
28693
|
timeout: 2e3
|
|
28368
28694
|
}).trim().split("\n");
|
|
@@ -28373,7 +28699,7 @@ function getAgentStatus(agentId) {
|
|
|
28373
28699
|
return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
|
|
28374
28700
|
});
|
|
28375
28701
|
if (!agentSession) return { label: "offline", color: "gray" };
|
|
28376
|
-
const pane =
|
|
28702
|
+
const pane = execSync15(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
|
|
28377
28703
|
encoding: "utf8",
|
|
28378
28704
|
timeout: 2e3
|
|
28379
28705
|
});
|
|
@@ -28491,11 +28817,11 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
28491
28817
|
setMembers(teamData);
|
|
28492
28818
|
setDbError(null);
|
|
28493
28819
|
try {
|
|
28494
|
-
const { existsSync:
|
|
28820
|
+
const { existsSync: existsSync34, readFileSync: readFileSync28 } = await import("fs");
|
|
28495
28821
|
const { join } = await import("path");
|
|
28496
28822
|
const home = process.env.HOME ?? "";
|
|
28497
28823
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
28498
|
-
if (
|
|
28824
|
+
if (existsSync34(gatewayConfig)) {
|
|
28499
28825
|
const raw = JSON.parse(readFileSync28(gatewayConfig, "utf8"));
|
|
28500
28826
|
if (raw.agents && raw.agents.length > 0) {
|
|
28501
28827
|
setExternals(raw.agents.map((a) => ({
|
|
@@ -28676,8 +29002,8 @@ __export(wiki_client_exports, {
|
|
|
28676
29002
|
listDocuments: () => listDocuments,
|
|
28677
29003
|
listWorkspaces: () => listWorkspaces
|
|
28678
29004
|
});
|
|
28679
|
-
async function wikiFetch(config,
|
|
28680
|
-
const url = `${config.baseUrl}/api/v1${
|
|
29005
|
+
async function wikiFetch(config, path48, method = "GET", body) {
|
|
29006
|
+
const url = `${config.baseUrl}/api/v1${path48}`;
|
|
28681
29007
|
const headers = {
|
|
28682
29008
|
Authorization: `Bearer ${config.apiKey}`,
|
|
28683
29009
|
"Content-Type": "application/json"
|
|
@@ -28710,7 +29036,7 @@ async function wikiFetch(config, path47, method = "GET", body) {
|
|
|
28710
29036
|
}
|
|
28711
29037
|
}
|
|
28712
29038
|
if (!response.ok) {
|
|
28713
|
-
throw new Error(`Wiki API ${method} ${
|
|
29039
|
+
throw new Error(`Wiki API ${method} ${path48}: ${response.status} ${response.statusText}`);
|
|
28714
29040
|
}
|
|
28715
29041
|
return response.json();
|
|
28716
29042
|
} finally {
|
|
@@ -29296,20 +29622,20 @@ function SettingsView({ onBack }) {
|
|
|
29296
29622
|
};
|
|
29297
29623
|
});
|
|
29298
29624
|
try {
|
|
29299
|
-
const { execSync:
|
|
29300
|
-
|
|
29625
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
29626
|
+
execSync16("curl -s --max-time 1 http://localhost:11434/api/tags", { timeout: 2e3 });
|
|
29301
29627
|
providerList.push({ name: "Ollama", configured: true, detail: "localhost:11434" });
|
|
29302
29628
|
} catch {
|
|
29303
29629
|
providerList.push({ name: "Ollama", configured: false, detail: "not running" });
|
|
29304
29630
|
}
|
|
29305
29631
|
setProviders(providerList);
|
|
29306
29632
|
try {
|
|
29307
|
-
const { existsSync:
|
|
29633
|
+
const { existsSync: existsSync34 } = await import("fs");
|
|
29308
29634
|
const { join } = await import("path");
|
|
29309
29635
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
29310
29636
|
const cfg = await loadConfig2();
|
|
29311
29637
|
const home = process.env.HOME ?? "";
|
|
29312
|
-
const hasKey =
|
|
29638
|
+
const hasKey = existsSync34(join(home, ".exe-os", "master.key"));
|
|
29313
29639
|
if (cfg.cloud) {
|
|
29314
29640
|
setCloud({
|
|
29315
29641
|
configured: true,
|
|
@@ -29322,7 +29648,7 @@ function SettingsView({ onBack }) {
|
|
|
29322
29648
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
29323
29649
|
let daemon = "unknown";
|
|
29324
29650
|
try {
|
|
29325
|
-
daemon =
|
|
29651
|
+
daemon = existsSync34(pidPath) ? "running" : "stopped";
|
|
29326
29652
|
} catch {
|
|
29327
29653
|
}
|
|
29328
29654
|
let version = "unknown";
|
|
@@ -30138,15 +30464,15 @@ __export(installer_exports2, {
|
|
|
30138
30464
|
verifyOpenCodeHooks: () => verifyOpenCodeHooks
|
|
30139
30465
|
});
|
|
30140
30466
|
import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
30141
|
-
import { existsSync as
|
|
30142
|
-
import
|
|
30467
|
+
import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
|
|
30468
|
+
import path45 from "path";
|
|
30143
30469
|
import os19 from "os";
|
|
30144
30470
|
async function registerOpenCodeMcp(packageRoot, homeDir = os19.homedir()) {
|
|
30145
|
-
const configDir =
|
|
30146
|
-
const configPath =
|
|
30471
|
+
const configDir = path45.join(homeDir, ".config", "opencode");
|
|
30472
|
+
const configPath = path45.join(configDir, "opencode.json");
|
|
30147
30473
|
await mkdir8(configDir, { recursive: true });
|
|
30148
30474
|
let config = {};
|
|
30149
|
-
if (
|
|
30475
|
+
if (existsSync31(configPath)) {
|
|
30150
30476
|
try {
|
|
30151
30477
|
config = JSON.parse(await readFile7(configPath, "utf-8"));
|
|
30152
30478
|
} catch {
|
|
@@ -30158,7 +30484,7 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os19.homedir()) {
|
|
|
30158
30484
|
}
|
|
30159
30485
|
const newEntry = {
|
|
30160
30486
|
type: "local",
|
|
30161
|
-
command: ["node",
|
|
30487
|
+
command: ["node", path45.join(packageRoot, "dist", "mcp", "server.js")],
|
|
30162
30488
|
enabled: true
|
|
30163
30489
|
};
|
|
30164
30490
|
const current = config.mcp["exe-os"];
|
|
@@ -30173,14 +30499,14 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os19.homedir()) {
|
|
|
30173
30499
|
return true;
|
|
30174
30500
|
}
|
|
30175
30501
|
async function installOpenCodePlugin(packageRoot, homeDir = os19.homedir()) {
|
|
30176
|
-
const pluginDir =
|
|
30177
|
-
const pluginPath =
|
|
30502
|
+
const pluginDir = path45.join(homeDir, ".config", "opencode", "plugins");
|
|
30503
|
+
const pluginPath = path45.join(pluginDir, "exe-os.mjs");
|
|
30178
30504
|
await mkdir8(pluginDir, { recursive: true });
|
|
30179
30505
|
const pluginContent = PLUGIN_TEMPLATE.replace(
|
|
30180
30506
|
/__PACKAGE_ROOT__/g,
|
|
30181
30507
|
packageRoot.replace(/\\/g, "\\\\")
|
|
30182
30508
|
);
|
|
30183
|
-
if (
|
|
30509
|
+
if (existsSync31(pluginPath)) {
|
|
30184
30510
|
const existing = await readFile7(pluginPath, "utf-8");
|
|
30185
30511
|
if (existing === pluginContent) {
|
|
30186
30512
|
return false;
|
|
@@ -30190,16 +30516,16 @@ async function installOpenCodePlugin(packageRoot, homeDir = os19.homedir()) {
|
|
|
30190
30516
|
return true;
|
|
30191
30517
|
}
|
|
30192
30518
|
function verifyOpenCodeHooks(homeDir = os19.homedir()) {
|
|
30193
|
-
const configPath =
|
|
30194
|
-
const pluginPath =
|
|
30195
|
-
if (!
|
|
30519
|
+
const configPath = path45.join(homeDir, ".config", "opencode", "opencode.json");
|
|
30520
|
+
const pluginPath = path45.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
|
|
30521
|
+
if (!existsSync31(configPath)) return false;
|
|
30196
30522
|
try {
|
|
30197
30523
|
const config = JSON.parse(readFileSync26(configPath, "utf-8"));
|
|
30198
30524
|
if (!config.mcp?.["exe-os"]?.enabled) return false;
|
|
30199
30525
|
} catch {
|
|
30200
30526
|
return false;
|
|
30201
30527
|
}
|
|
30202
|
-
if (!
|
|
30528
|
+
if (!existsSync31(pluginPath)) return false;
|
|
30203
30529
|
return true;
|
|
30204
30530
|
}
|
|
30205
30531
|
async function runOpenCodeInstaller(homeDir) {
|
|
@@ -30234,19 +30560,19 @@ __export(installer_exports3, {
|
|
|
30234
30560
|
verifyCodexHooks: () => verifyCodexHooks
|
|
30235
30561
|
});
|
|
30236
30562
|
import { readFile as readFile8, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
|
|
30237
|
-
import { existsSync as
|
|
30238
|
-
import
|
|
30563
|
+
import { existsSync as existsSync32 } from "fs";
|
|
30564
|
+
import path46 from "path";
|
|
30239
30565
|
import os20 from "os";
|
|
30240
30566
|
async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
30241
|
-
const codexDir =
|
|
30242
|
-
const hooksPath =
|
|
30243
|
-
const logsDir =
|
|
30244
|
-
const hookLogPath =
|
|
30567
|
+
const codexDir = path46.join(homeDir, ".codex");
|
|
30568
|
+
const hooksPath = path46.join(codexDir, "hooks.json");
|
|
30569
|
+
const logsDir = path46.join(homeDir, ".exe-os", "logs");
|
|
30570
|
+
const hookLogPath = path46.join(logsDir, "hooks.log");
|
|
30245
30571
|
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
30246
30572
|
await mkdir9(codexDir, { recursive: true });
|
|
30247
30573
|
await mkdir9(logsDir, { recursive: true });
|
|
30248
30574
|
let hooksJson = {};
|
|
30249
|
-
if (
|
|
30575
|
+
if (existsSync32(hooksPath)) {
|
|
30250
30576
|
try {
|
|
30251
30577
|
hooksJson = JSON.parse(await readFile8(hooksPath, "utf-8"));
|
|
30252
30578
|
} catch {
|
|
@@ -30263,7 +30589,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30263
30589
|
hooks: [
|
|
30264
30590
|
{
|
|
30265
30591
|
type: "command",
|
|
30266
|
-
command: `node "${
|
|
30592
|
+
command: `node "${path46.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
30267
30593
|
timeout: 30
|
|
30268
30594
|
}
|
|
30269
30595
|
]
|
|
@@ -30279,7 +30605,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30279
30605
|
// Combined hook: runs ingest + error-recall in one Node process.
|
|
30280
30606
|
// Eliminates a cold-start cycle per tool call (~3-6s savings on Codex).
|
|
30281
30607
|
type: "command",
|
|
30282
|
-
command: `node "${
|
|
30608
|
+
command: `node "${path46.join(packageRoot, "dist", "hooks", "post-tool-combined.js")}"${logSuffix}`
|
|
30283
30609
|
}
|
|
30284
30610
|
]
|
|
30285
30611
|
},
|
|
@@ -30293,7 +30619,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30293
30619
|
// Single hook: prompt-submit handles memory retrieval + entity boost.
|
|
30294
30620
|
// exe-heartbeat-hook is CC-specific (intercom) — omitted on Codex.
|
|
30295
30621
|
type: "command",
|
|
30296
|
-
command: `node "${
|
|
30622
|
+
command: `node "${path46.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
30297
30623
|
}
|
|
30298
30624
|
]
|
|
30299
30625
|
},
|
|
@@ -30305,7 +30631,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30305
30631
|
hooks: [
|
|
30306
30632
|
{
|
|
30307
30633
|
type: "command",
|
|
30308
|
-
command: `node "${
|
|
30634
|
+
command: `node "${path46.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
30309
30635
|
}
|
|
30310
30636
|
]
|
|
30311
30637
|
},
|
|
@@ -30318,7 +30644,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30318
30644
|
hooks: [
|
|
30319
30645
|
{
|
|
30320
30646
|
type: "command",
|
|
30321
|
-
command: `node "${
|
|
30647
|
+
command: `node "${path46.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
30322
30648
|
}
|
|
30323
30649
|
]
|
|
30324
30650
|
},
|
|
@@ -30350,8 +30676,8 @@ async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
|
30350
30676
|
return { added, skipped };
|
|
30351
30677
|
}
|
|
30352
30678
|
function verifyCodexHooks(homeDir = os20.homedir()) {
|
|
30353
|
-
const hooksPath =
|
|
30354
|
-
if (!
|
|
30679
|
+
const hooksPath = path46.join(homeDir, ".codex", "hooks.json");
|
|
30680
|
+
if (!existsSync32(hooksPath)) return false;
|
|
30355
30681
|
try {
|
|
30356
30682
|
const hooksJson = JSON.parse(
|
|
30357
30683
|
__require("fs").readFileSync(hooksPath, "utf-8")
|
|
@@ -30374,11 +30700,11 @@ function verifyCodexHooks(homeDir = os20.homedir()) {
|
|
|
30374
30700
|
async function installCodexStatusLine(homeDir = os20.homedir()) {
|
|
30375
30701
|
const prefs = loadPreferences(homeDir);
|
|
30376
30702
|
if (prefs.codexStatusLine === false) return "opted-out";
|
|
30377
|
-
const codexDir =
|
|
30378
|
-
const configPath =
|
|
30703
|
+
const codexDir = path46.join(homeDir, ".codex");
|
|
30704
|
+
const configPath = path46.join(codexDir, "config.toml");
|
|
30379
30705
|
await mkdir9(codexDir, { recursive: true });
|
|
30380
30706
|
let content = "";
|
|
30381
|
-
if (
|
|
30707
|
+
if (existsSync32(configPath)) {
|
|
30382
30708
|
content = await readFile8(configPath, "utf-8");
|
|
30383
30709
|
if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
|
|
30384
30710
|
return "already-configured";
|
|
@@ -30436,12 +30762,12 @@ ${desired}
|
|
|
30436
30762
|
return { content: next, changed };
|
|
30437
30763
|
}
|
|
30438
30764
|
async function registerCodexMcpServer(packageRoot, homeDir = os20.homedir()) {
|
|
30439
|
-
const codexDir =
|
|
30440
|
-
const configPath =
|
|
30441
|
-
const serverJsPath =
|
|
30765
|
+
const codexDir = path46.join(homeDir, ".codex");
|
|
30766
|
+
const configPath = path46.join(codexDir, "config.toml");
|
|
30767
|
+
const serverJsPath = path46.join(packageRoot, "dist", "mcp", "server.js");
|
|
30442
30768
|
await mkdir9(codexDir, { recursive: true });
|
|
30443
30769
|
let content = "";
|
|
30444
|
-
if (
|
|
30770
|
+
if (existsSync32(configPath)) {
|
|
30445
30771
|
content = await readFile8(configPath, "utf-8");
|
|
30446
30772
|
}
|
|
30447
30773
|
const sectionHeader = "[mcp_servers.exe-os]";
|
|
@@ -30466,10 +30792,10 @@ async function registerCodexMcpServer(packageRoot, homeDir = os20.homedir()) {
|
|
|
30466
30792
|
return "registered";
|
|
30467
30793
|
}
|
|
30468
30794
|
async function ensureCodexHooksFeature(homeDir = os20.homedir()) {
|
|
30469
|
-
const configPath =
|
|
30470
|
-
await mkdir9(
|
|
30795
|
+
const configPath = path46.join(homeDir, ".codex", "config.toml");
|
|
30796
|
+
await mkdir9(path46.join(homeDir, ".codex"), { recursive: true });
|
|
30471
30797
|
let content = "";
|
|
30472
|
-
if (
|
|
30798
|
+
if (existsSync32(configPath)) {
|
|
30473
30799
|
content = await readFile8(configPath, "utf-8");
|
|
30474
30800
|
}
|
|
30475
30801
|
if (/\[features\][\s\S]*?codex_hooks\s*=\s*true/.test(content)) {
|
|
@@ -30537,13 +30863,13 @@ var init_installer3 = __esm({
|
|
|
30537
30863
|
});
|
|
30538
30864
|
|
|
30539
30865
|
// src/bin/cli.ts
|
|
30540
|
-
import { existsSync as
|
|
30541
|
-
import
|
|
30866
|
+
import { existsSync as existsSync33, readFileSync as readFileSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync10, rmSync } from "fs";
|
|
30867
|
+
import path47 from "path";
|
|
30542
30868
|
import os21 from "os";
|
|
30543
30869
|
var args = process.argv.slice(2);
|
|
30544
30870
|
if (args.includes("--version") || args.includes("-v")) {
|
|
30545
30871
|
try {
|
|
30546
|
-
const pkgPath =
|
|
30872
|
+
const pkgPath = path47.join(path47.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
|
|
30547
30873
|
const pkg = JSON.parse(readFileSync27(pkgPath, "utf8"));
|
|
30548
30874
|
console.log(pkg.version);
|
|
30549
30875
|
} catch {
|
|
@@ -30708,9 +31034,9 @@ ID: ${result.id}`);
|
|
|
30708
31034
|
});
|
|
30709
31035
|
await init_App2().then(() => App_exports);
|
|
30710
31036
|
} else {
|
|
30711
|
-
const claudeDir =
|
|
30712
|
-
const settingsPath =
|
|
30713
|
-
const hasClaudeCode =
|
|
31037
|
+
const claudeDir = path47.join(os21.homedir(), ".claude");
|
|
31038
|
+
const settingsPath = path47.join(claudeDir, "settings.json");
|
|
31039
|
+
const hasClaudeCode = existsSync33(settingsPath) && (() => {
|
|
30714
31040
|
try {
|
|
30715
31041
|
const raw = readFileSync27(settingsPath, "utf8");
|
|
30716
31042
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
@@ -30722,8 +31048,8 @@ ID: ${result.id}`);
|
|
|
30722
31048
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
30723
31049
|
let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
30724
31050
|
try {
|
|
30725
|
-
const rosterPath =
|
|
30726
|
-
if (
|
|
31051
|
+
const rosterPath = path47.join(os21.homedir(), ".exe-os", "exe-employees.json");
|
|
31052
|
+
if (existsSync33(rosterPath)) {
|
|
30727
31053
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
30728
31054
|
const coo = roster.find((e) => e.role === "COO");
|
|
30729
31055
|
if (coo) cooName = coo.name;
|
|
@@ -30788,11 +31114,11 @@ async function runCodexInstall() {
|
|
|
30788
31114
|
}
|
|
30789
31115
|
}
|
|
30790
31116
|
async function runClaudeCheck() {
|
|
30791
|
-
const claudeDir =
|
|
30792
|
-
const settingsPath =
|
|
30793
|
-
const claudeJsonPath =
|
|
31117
|
+
const claudeDir = path47.join(os21.homedir(), ".claude");
|
|
31118
|
+
const settingsPath = path47.join(claudeDir, "settings.json");
|
|
31119
|
+
const claudeJsonPath = path47.join(os21.homedir(), ".claude.json");
|
|
30794
31120
|
let ok = true;
|
|
30795
|
-
if (
|
|
31121
|
+
if (existsSync33(settingsPath)) {
|
|
30796
31122
|
let settings;
|
|
30797
31123
|
try {
|
|
30798
31124
|
settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
|
|
@@ -30821,7 +31147,7 @@ async function runClaudeCheck() {
|
|
|
30821
31147
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
30822
31148
|
ok = false;
|
|
30823
31149
|
}
|
|
30824
|
-
if (
|
|
31150
|
+
if (existsSync33(claudeJsonPath)) {
|
|
30825
31151
|
let claudeJson;
|
|
30826
31152
|
try {
|
|
30827
31153
|
claudeJson = JSON.parse(readFileSync27(claudeJsonPath, "utf8"));
|
|
@@ -30843,8 +31169,8 @@ async function runClaudeCheck() {
|
|
|
30843
31169
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
30844
31170
|
ok = false;
|
|
30845
31171
|
}
|
|
30846
|
-
const skillsDir =
|
|
30847
|
-
if (
|
|
31172
|
+
const skillsDir = path47.join(claudeDir, "skills");
|
|
31173
|
+
if (existsSync33(skillsDir)) {
|
|
30848
31174
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
30849
31175
|
} else {
|
|
30850
31176
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -30861,14 +31187,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30861
31187
|
const dryRun = flags.includes("--dry-run");
|
|
30862
31188
|
const purge = flags.includes("--purge");
|
|
30863
31189
|
const homeDir = os21.homedir();
|
|
30864
|
-
const claudeDir =
|
|
30865
|
-
const settingsPath =
|
|
30866
|
-
const claudeJsonPath =
|
|
30867
|
-
const exeOsDir =
|
|
31190
|
+
const claudeDir = path47.join(homeDir, ".claude");
|
|
31191
|
+
const settingsPath = path47.join(claudeDir, "settings.json");
|
|
31192
|
+
const claudeJsonPath = path47.join(homeDir, ".claude.json");
|
|
31193
|
+
const exeOsDir = path47.join(homeDir, ".exe-os");
|
|
30868
31194
|
let removed = 0;
|
|
30869
31195
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
30870
31196
|
let settings = {};
|
|
30871
|
-
if (
|
|
31197
|
+
if (existsSync33(settingsPath)) {
|
|
30872
31198
|
try {
|
|
30873
31199
|
settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
|
|
30874
31200
|
} catch {
|
|
@@ -30915,7 +31241,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30915
31241
|
removed++;
|
|
30916
31242
|
}
|
|
30917
31243
|
}
|
|
30918
|
-
if (
|
|
31244
|
+
if (existsSync33(claudeJsonPath)) {
|
|
30919
31245
|
const raw = readFileSync27(claudeJsonPath, "utf8");
|
|
30920
31246
|
if (raw.length > 1e6) {
|
|
30921
31247
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
@@ -30945,14 +31271,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30945
31271
|
}
|
|
30946
31272
|
}
|
|
30947
31273
|
}
|
|
30948
|
-
const skillsDir =
|
|
30949
|
-
if (
|
|
31274
|
+
const skillsDir = path47.join(claudeDir, "skills");
|
|
31275
|
+
if (existsSync33(skillsDir)) {
|
|
30950
31276
|
let skillCount = 0;
|
|
30951
31277
|
try {
|
|
30952
|
-
const entries =
|
|
31278
|
+
const entries = readdirSync10(skillsDir);
|
|
30953
31279
|
for (const entry of entries) {
|
|
30954
31280
|
if (entry.startsWith("exe")) {
|
|
30955
|
-
const fullPath =
|
|
31281
|
+
const fullPath = path47.join(skillsDir, entry);
|
|
30956
31282
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
30957
31283
|
skillCount++;
|
|
30958
31284
|
}
|
|
@@ -30964,8 +31290,8 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30964
31290
|
removed++;
|
|
30965
31291
|
}
|
|
30966
31292
|
}
|
|
30967
|
-
const claudeMdPath =
|
|
30968
|
-
if (
|
|
31293
|
+
const claudeMdPath = path47.join(claudeDir, "CLAUDE.md");
|
|
31294
|
+
if (existsSync33(claudeMdPath)) {
|
|
30969
31295
|
const content = readFileSync27(claudeMdPath, "utf8");
|
|
30970
31296
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
30971
31297
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
@@ -30978,14 +31304,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30978
31304
|
removed++;
|
|
30979
31305
|
}
|
|
30980
31306
|
}
|
|
30981
|
-
const agentsDir =
|
|
30982
|
-
if (
|
|
31307
|
+
const agentsDir = path47.join(claudeDir, "agents");
|
|
31308
|
+
if (existsSync33(agentsDir)) {
|
|
30983
31309
|
let agentCount = 0;
|
|
30984
31310
|
try {
|
|
30985
|
-
const entries =
|
|
31311
|
+
const entries = readdirSync10(agentsDir).filter((f) => f.endsWith(".md"));
|
|
30986
31312
|
let knownNames = /* @__PURE__ */ new Set();
|
|
30987
|
-
const rosterPath =
|
|
30988
|
-
if (
|
|
31313
|
+
const rosterPath = path47.join(exeOsDir, "exe-employees.json");
|
|
31314
|
+
if (existsSync33(rosterPath)) {
|
|
30989
31315
|
try {
|
|
30990
31316
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
30991
31317
|
knownNames = new Set(roster.map((e) => e.name));
|
|
@@ -30995,7 +31321,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30995
31321
|
for (const entry of entries) {
|
|
30996
31322
|
const name = entry.replace(/\.md$/, "");
|
|
30997
31323
|
if (knownNames.has(name)) {
|
|
30998
|
-
if (!dryRun) rmSync(
|
|
31324
|
+
if (!dryRun) rmSync(path47.join(agentsDir, entry), { force: true });
|
|
30999
31325
|
agentCount++;
|
|
31000
31326
|
}
|
|
31001
31327
|
}
|
|
@@ -31006,14 +31332,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
31006
31332
|
removed++;
|
|
31007
31333
|
}
|
|
31008
31334
|
}
|
|
31009
|
-
const projectsDir =
|
|
31010
|
-
if (
|
|
31335
|
+
const projectsDir = path47.join(claudeDir, "projects");
|
|
31336
|
+
if (existsSync33(projectsDir)) {
|
|
31011
31337
|
let projectCount = 0;
|
|
31012
31338
|
try {
|
|
31013
|
-
const projects =
|
|
31339
|
+
const projects = readdirSync10(projectsDir);
|
|
31014
31340
|
for (const proj of projects) {
|
|
31015
|
-
const projSettings =
|
|
31016
|
-
if (!
|
|
31341
|
+
const projSettings = path47.join(projectsDir, proj, "settings.json");
|
|
31342
|
+
if (!existsSync33(projSettings)) continue;
|
|
31017
31343
|
try {
|
|
31018
31344
|
const pSettings = JSON.parse(readFileSync27(projSettings, "utf8"));
|
|
31019
31345
|
let changed = false;
|
|
@@ -31039,28 +31365,28 @@ async function runClaudeUninstall(flags = []) {
|
|
|
31039
31365
|
}
|
|
31040
31366
|
}
|
|
31041
31367
|
try {
|
|
31042
|
-
const { execSync:
|
|
31368
|
+
const { execSync: execSync16 } = await import("child_process");
|
|
31043
31369
|
const findExeBin3 = () => {
|
|
31044
31370
|
try {
|
|
31045
|
-
return
|
|
31371
|
+
return execSync16(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
31046
31372
|
} catch {
|
|
31047
31373
|
return null;
|
|
31048
31374
|
}
|
|
31049
31375
|
};
|
|
31050
31376
|
const exeBinPath = findExeBin3();
|
|
31051
31377
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
31052
|
-
const binDir =
|
|
31378
|
+
const binDir = path47.dirname(exeBinPath);
|
|
31053
31379
|
let symlinkCount = 0;
|
|
31054
|
-
const rosterPath =
|
|
31055
|
-
if (
|
|
31380
|
+
const rosterPath = path47.join(exeOsDir, "exe-employees.json");
|
|
31381
|
+
if (existsSync33(rosterPath)) {
|
|
31056
31382
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
31057
31383
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
31058
31384
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
31059
31385
|
for (const emp of roster) {
|
|
31060
31386
|
if (emp.name === coordinatorName) continue;
|
|
31061
31387
|
for (const suffix of ["", "-opencode"]) {
|
|
31062
|
-
const linkPath =
|
|
31063
|
-
if (
|
|
31388
|
+
const linkPath = path47.join(binDir, `${emp.name}${suffix}`);
|
|
31389
|
+
if (existsSync33(linkPath)) {
|
|
31064
31390
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
31065
31391
|
symlinkCount++;
|
|
31066
31392
|
}
|
|
@@ -31073,7 +31399,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
31073
31399
|
}
|
|
31074
31400
|
} catch {
|
|
31075
31401
|
}
|
|
31076
|
-
if (purge &&
|
|
31402
|
+
if (purge && existsSync33(exeOsDir)) {
|
|
31077
31403
|
if (!dryRun) {
|
|
31078
31404
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
31079
31405
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -31098,7 +31424,7 @@ async function checkForUpdateOnBoot() {
|
|
|
31098
31424
|
const config = await loadConfig2();
|
|
31099
31425
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
31100
31426
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
31101
|
-
const packageRoot =
|
|
31427
|
+
const packageRoot = path47.resolve(
|
|
31102
31428
|
new URL("../..", import.meta.url).pathname
|
|
31103
31429
|
);
|
|
31104
31430
|
const result = checkForUpdate2(packageRoot);
|
|
@@ -31158,7 +31484,7 @@ async function runActivate(key) {
|
|
|
31158
31484
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
31159
31485
|
if (idTemplate) {
|
|
31160
31486
|
const idPath = identityPath2(name);
|
|
31161
|
-
const dir =
|
|
31487
|
+
const dir = path47.dirname(idPath);
|
|
31162
31488
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
31163
31489
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
31164
31490
|
}
|