@askexenow/exe-os 0.8.65 → 0.8.69
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/cleanup-stale-review-tasks.js +8 -7
- package/dist/bin/cli.js +204 -120
- package/dist/bin/exe-assign.js +11 -10
- package/dist/bin/exe-boot.js +83 -78
- package/dist/bin/exe-call.js +33 -1
- package/dist/bin/exe-cloud.js +3 -2
- package/dist/bin/exe-dispatch.js +31 -30
- package/dist/bin/exe-gateway.js +33 -32
- package/dist/bin/exe-heartbeat.js +21 -20
- package/dist/bin/exe-launch-agent.js +84 -19
- package/dist/bin/exe-link.js +16 -11
- package/dist/bin/exe-new-employee.js +20 -19
- package/dist/bin/exe-pending-messages.js +7 -6
- package/dist/bin/exe-pending-reviews.js +16 -15
- package/dist/bin/exe-rename.js +12 -11
- package/dist/bin/exe-review.js +4 -3
- package/dist/bin/exe-session-cleanup.js +20 -19
- package/dist/bin/exe-settings.js +3 -2
- package/dist/bin/exe-status.js +16 -15
- package/dist/bin/exe-team.js +4 -3
- package/dist/bin/git-sweep.js +31 -30
- package/dist/bin/install.js +284 -113
- package/dist/bin/scan-tasks.js +33 -32
- package/dist/bin/setup.js +114 -30
- package/dist/gateway/index.js +32 -31
- package/dist/hooks/bug-report-worker.js +58 -26
- package/dist/hooks/commit-complete.js +31 -30
- package/dist/hooks/ingest-worker.js +58 -57
- package/dist/hooks/post-compact.js +10 -9
- package/dist/hooks/pre-compact.js +31 -30
- package/dist/hooks/pre-tool-use.js +46 -14
- package/dist/hooks/prompt-ingest-worker.js +15 -14
- package/dist/hooks/prompt-submit.js +15 -14
- package/dist/hooks/response-ingest-worker.js +8 -7
- package/dist/hooks/session-end.js +14 -13
- package/dist/hooks/session-start.js +10 -9
- package/dist/hooks/stop.js +10 -9
- package/dist/hooks/subagent-stop.js +10 -9
- package/dist/hooks/summary-worker.js +41 -36
- package/dist/index.js +43 -42
- package/dist/lib/cloud-sync.js +16 -11
- package/dist/lib/employees.js +33 -1
- package/dist/lib/exe-daemon.js +56 -55
- package/dist/lib/messaging.js +9 -8
- package/dist/lib/tasks.js +27 -26
- package/dist/lib/tmux-routing.js +29 -28
- package/dist/mcp/server.js +94 -62
- package/dist/mcp/tools/create-task.js +60 -28
- package/dist/mcp/tools/list-tasks.js +10 -9
- package/dist/mcp/tools/send-message.js +11 -10
- package/dist/mcp/tools/update-task.js +21 -20
- package/dist/runtime/index.js +31 -30
- package/dist/tui/App.js +67 -35
- package/package.json +1 -1
|
@@ -1614,9 +1614,10 @@ ${p.content}`).join("\n\n");
|
|
|
1614
1614
|
|
|
1615
1615
|
// src/lib/employees.ts
|
|
1616
1616
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1617
|
-
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
|
|
1617
|
+
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
1618
1618
|
import { execSync } from "child_process";
|
|
1619
1619
|
import path4 from "path";
|
|
1620
|
+
import os3 from "os";
|
|
1620
1621
|
var EMPLOYEES_PATH;
|
|
1621
1622
|
var init_employees = __esm({
|
|
1622
1623
|
"src/lib/employees.ts"() {
|
|
@@ -1629,11 +1630,11 @@ var init_employees = __esm({
|
|
|
1629
1630
|
// src/lib/notifications.ts
|
|
1630
1631
|
import crypto from "crypto";
|
|
1631
1632
|
import path5 from "path";
|
|
1632
|
-
import
|
|
1633
|
+
import os4 from "os";
|
|
1633
1634
|
import {
|
|
1634
1635
|
readFileSync as readFileSync3,
|
|
1635
1636
|
readdirSync as readdirSync2,
|
|
1636
|
-
unlinkSync,
|
|
1637
|
+
unlinkSync as unlinkSync2,
|
|
1637
1638
|
existsSync as existsSync5,
|
|
1638
1639
|
rmdirSync
|
|
1639
1640
|
} from "fs";
|
|
@@ -1646,12 +1647,12 @@ var init_notifications = __esm({
|
|
|
1646
1647
|
|
|
1647
1648
|
// src/lib/session-registry.ts
|
|
1648
1649
|
import path6 from "path";
|
|
1649
|
-
import
|
|
1650
|
+
import os5 from "os";
|
|
1650
1651
|
var REGISTRY_PATH;
|
|
1651
1652
|
var init_session_registry = __esm({
|
|
1652
1653
|
"src/lib/session-registry.ts"() {
|
|
1653
1654
|
"use strict";
|
|
1654
|
-
REGISTRY_PATH = path6.join(
|
|
1655
|
+
REGISTRY_PATH = path6.join(os5.homedir(), ".exe-os", "session-registry.json");
|
|
1655
1656
|
}
|
|
1656
1657
|
});
|
|
1657
1658
|
|
|
@@ -1827,21 +1828,21 @@ var init_provider_table = __esm({
|
|
|
1827
1828
|
});
|
|
1828
1829
|
|
|
1829
1830
|
// src/lib/intercom-queue.ts
|
|
1830
|
-
import { readFileSync as readFileSync4, writeFileSync, renameSync as
|
|
1831
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
|
|
1831
1832
|
import path7 from "path";
|
|
1832
|
-
import
|
|
1833
|
+
import os6 from "os";
|
|
1833
1834
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
1834
1835
|
var init_intercom_queue = __esm({
|
|
1835
1836
|
"src/lib/intercom-queue.ts"() {
|
|
1836
1837
|
"use strict";
|
|
1837
|
-
QUEUE_PATH = path7.join(
|
|
1838
|
+
QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
1838
1839
|
TTL_MS = 60 * 60 * 1e3;
|
|
1839
|
-
INTERCOM_LOG = path7.join(
|
|
1840
|
+
INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
1840
1841
|
}
|
|
1841
1842
|
});
|
|
1842
1843
|
|
|
1843
1844
|
// src/lib/license.ts
|
|
1844
|
-
import { readFileSync as readFileSync5, writeFileSync as
|
|
1845
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
|
|
1845
1846
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1846
1847
|
import path8 from "path";
|
|
1847
1848
|
import { jwtVerify, importSPKI } from "jose";
|
|
@@ -1872,9 +1873,9 @@ var init_plan_limits = __esm({
|
|
|
1872
1873
|
});
|
|
1873
1874
|
|
|
1874
1875
|
// src/lib/tmux-routing.ts
|
|
1875
|
-
import { readFileSync as readFileSync7, writeFileSync as
|
|
1876
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync9, appendFileSync } from "fs";
|
|
1876
1877
|
import path10 from "path";
|
|
1877
|
-
import
|
|
1878
|
+
import os7 from "os";
|
|
1878
1879
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1879
1880
|
function getMySession() {
|
|
1880
1881
|
return getTransport().getMySession();
|
|
@@ -1916,9 +1917,9 @@ var init_tmux_routing = __esm({
|
|
|
1916
1917
|
init_provider_table();
|
|
1917
1918
|
init_intercom_queue();
|
|
1918
1919
|
init_plan_limits();
|
|
1919
|
-
SPAWN_LOCK_DIR = path10.join(
|
|
1920
|
-
SESSION_CACHE = path10.join(
|
|
1921
|
-
INTERCOM_LOG2 = path10.join(
|
|
1920
|
+
SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
|
|
1921
|
+
SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
|
|
1922
|
+
INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
1922
1923
|
DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1923
1924
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1924
1925
|
}
|
|
@@ -1926,7 +1927,7 @@ var init_tmux_routing = __esm({
|
|
|
1926
1927
|
|
|
1927
1928
|
// src/lib/tasks-review.ts
|
|
1928
1929
|
import path11 from "path";
|
|
1929
|
-
import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as
|
|
1930
|
+
import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
1930
1931
|
async function listPendingReviews(limit, sessionScope) {
|
|
1931
1932
|
const client = getClient();
|
|
1932
1933
|
if (sessionScope) {
|
|
@@ -1986,8 +1987,8 @@ var init_task_scope = __esm({
|
|
|
1986
1987
|
|
|
1987
1988
|
// src/bin/exe-heartbeat.ts
|
|
1988
1989
|
import { createHash } from "crypto";
|
|
1989
|
-
import { readFileSync as readFileSync8, writeFileSync as
|
|
1990
|
-
import
|
|
1990
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
|
|
1991
|
+
import os8 from "os";
|
|
1991
1992
|
import path12 from "path";
|
|
1992
1993
|
|
|
1993
1994
|
// src/lib/store.ts
|
|
@@ -2148,7 +2149,7 @@ var MESSAGE_PREVIEW_CHARS = 80;
|
|
|
2148
2149
|
var MARKER_FILENAME = "exe-heartbeat-marker.json";
|
|
2149
2150
|
var SESSION_CACHE_SUBDIR = "session-cache";
|
|
2150
2151
|
function resolveExeOsDir() {
|
|
2151
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(
|
|
2152
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(os8.homedir(), ".exe-os");
|
|
2152
2153
|
}
|
|
2153
2154
|
function getMarkerDir() {
|
|
2154
2155
|
return path12.join(resolveExeOsDir(), SESSION_CACHE_SUBDIR);
|
|
@@ -2172,7 +2173,7 @@ function readMarker() {
|
|
|
2172
2173
|
function writeMarker(marker) {
|
|
2173
2174
|
try {
|
|
2174
2175
|
mkdirSync5(getMarkerDir(), { recursive: true });
|
|
2175
|
-
|
|
2176
|
+
writeFileSync5(getMarkerPath(), JSON.stringify(marker));
|
|
2176
2177
|
} catch {
|
|
2177
2178
|
}
|
|
2178
2179
|
}
|
|
@@ -2170,14 +2170,16 @@ __export(employees_exports, {
|
|
|
2170
2170
|
isMultiInstance: () => isMultiInstance,
|
|
2171
2171
|
loadEmployees: () => loadEmployees,
|
|
2172
2172
|
loadEmployeesSync: () => loadEmployeesSync,
|
|
2173
|
+
normalizeRosterCase: () => normalizeRosterCase,
|
|
2173
2174
|
registerBinSymlinks: () => registerBinSymlinks,
|
|
2174
2175
|
saveEmployees: () => saveEmployees,
|
|
2175
2176
|
validateEmployeeName: () => validateEmployeeName
|
|
2176
2177
|
});
|
|
2177
2178
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
2178
|
-
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
|
|
2179
|
+
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2179
2180
|
import { execSync as execSync2 } from "child_process";
|
|
2180
2181
|
import path5 from "path";
|
|
2182
|
+
import os4 from "os";
|
|
2181
2183
|
function validateEmployeeName(name) {
|
|
2182
2184
|
if (!name) {
|
|
2183
2185
|
return { valid: false, error: "Name is required" };
|
|
@@ -2245,6 +2247,36 @@ function addEmployee(employees, employee) {
|
|
|
2245
2247
|
}
|
|
2246
2248
|
return [...employees, normalized];
|
|
2247
2249
|
}
|
|
2250
|
+
async function normalizeRosterCase(rosterPath) {
|
|
2251
|
+
const employees = await loadEmployees(rosterPath);
|
|
2252
|
+
let changed = false;
|
|
2253
|
+
for (const emp of employees) {
|
|
2254
|
+
if (emp.name !== emp.name.toLowerCase()) {
|
|
2255
|
+
const oldName = emp.name;
|
|
2256
|
+
emp.name = emp.name.toLowerCase();
|
|
2257
|
+
changed = true;
|
|
2258
|
+
try {
|
|
2259
|
+
const identityDir = path5.join(os4.homedir(), ".exe-os", "identity");
|
|
2260
|
+
const oldPath = path5.join(identityDir, `${oldName}.md`);
|
|
2261
|
+
const newPath = path5.join(identityDir, `${emp.name}.md`);
|
|
2262
|
+
if (existsSync5(oldPath) && !existsSync5(newPath)) {
|
|
2263
|
+
renameSync2(oldPath, newPath);
|
|
2264
|
+
} else if (existsSync5(oldPath) && oldPath !== newPath) {
|
|
2265
|
+
const content = readFileSync2(oldPath, "utf-8");
|
|
2266
|
+
writeFileSync2(newPath, content, "utf-8");
|
|
2267
|
+
if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
|
|
2268
|
+
unlinkSync2(oldPath);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
} catch {
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
if (changed) {
|
|
2276
|
+
await saveEmployees(employees, rosterPath);
|
|
2277
|
+
}
|
|
2278
|
+
return changed;
|
|
2279
|
+
}
|
|
2248
2280
|
function findExeBin() {
|
|
2249
2281
|
try {
|
|
2250
2282
|
return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
@@ -2347,7 +2379,7 @@ __export(active_agent_exports, {
|
|
|
2347
2379
|
getAllActiveAgents: () => getAllActiveAgents,
|
|
2348
2380
|
writeActiveAgent: () => writeActiveAgent
|
|
2349
2381
|
});
|
|
2350
|
-
import { readFileSync as readFileSync3, writeFileSync as
|
|
2382
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3, readdirSync as readdirSync3 } from "fs";
|
|
2351
2383
|
import { execSync as execSync4 } from "child_process";
|
|
2352
2384
|
import path6 from "path";
|
|
2353
2385
|
function getMarkerPath() {
|
|
@@ -2356,7 +2388,7 @@ function getMarkerPath() {
|
|
|
2356
2388
|
function writeActiveAgent(agentId, agentRole) {
|
|
2357
2389
|
try {
|
|
2358
2390
|
mkdirSync3(CACHE_DIR, { recursive: true });
|
|
2359
|
-
|
|
2391
|
+
writeFileSync3(
|
|
2360
2392
|
getMarkerPath(),
|
|
2361
2393
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
2362
2394
|
);
|
|
@@ -2365,7 +2397,7 @@ function writeActiveAgent(agentId, agentRole) {
|
|
|
2365
2397
|
}
|
|
2366
2398
|
function clearActiveAgent() {
|
|
2367
2399
|
try {
|
|
2368
|
-
|
|
2400
|
+
unlinkSync3(getMarkerPath());
|
|
2369
2401
|
} catch {
|
|
2370
2402
|
}
|
|
2371
2403
|
}
|
|
@@ -2379,7 +2411,7 @@ function getActiveAgent() {
|
|
|
2379
2411
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
2380
2412
|
if (age > STALE_MS) {
|
|
2381
2413
|
try {
|
|
2382
|
-
|
|
2414
|
+
unlinkSync3(markerPath);
|
|
2383
2415
|
} catch {
|
|
2384
2416
|
}
|
|
2385
2417
|
} else {
|
|
@@ -2432,7 +2464,7 @@ function getAllActiveAgents() {
|
|
|
2432
2464
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
2433
2465
|
if (age > STALE_MS) {
|
|
2434
2466
|
try {
|
|
2435
|
-
|
|
2467
|
+
unlinkSync3(path6.join(CACHE_DIR, file));
|
|
2436
2468
|
} catch {
|
|
2437
2469
|
}
|
|
2438
2470
|
continue;
|
|
@@ -2455,11 +2487,11 @@ function getAllActiveAgents() {
|
|
|
2455
2487
|
function cleanupSessionMarkers() {
|
|
2456
2488
|
const key = getSessionKey();
|
|
2457
2489
|
try {
|
|
2458
|
-
|
|
2490
|
+
unlinkSync3(path6.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
2459
2491
|
} catch {
|
|
2460
2492
|
}
|
|
2461
2493
|
try {
|
|
2462
|
-
|
|
2494
|
+
unlinkSync3(path6.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
2463
2495
|
} catch {
|
|
2464
2496
|
}
|
|
2465
2497
|
}
|
|
@@ -2475,9 +2507,9 @@ var init_active_agent = __esm({
|
|
|
2475
2507
|
});
|
|
2476
2508
|
|
|
2477
2509
|
// src/bin/exe-launch-agent.ts
|
|
2478
|
-
import
|
|
2510
|
+
import os5 from "os";
|
|
2479
2511
|
import path7 from "path";
|
|
2480
|
-
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as
|
|
2512
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync4 } from "fs";
|
|
2481
2513
|
import { spawnSync } from "child_process";
|
|
2482
2514
|
|
|
2483
2515
|
// src/lib/store.ts
|
|
@@ -2972,7 +3004,7 @@ function parseBasename(basename) {
|
|
|
2972
3004
|
function resolveAgent(argv) {
|
|
2973
3005
|
const invokedAs = path7.basename(argv[1] ?? "");
|
|
2974
3006
|
if (invokedAs && invokedAs !== "exe-launch-agent" && !invokedAs.endsWith(".js")) {
|
|
2975
|
-
const { agent: agent2, provider } = parseBasename(invokedAs);
|
|
3007
|
+
const { agent: agent2, provider } = parseBasename(invokedAs.toLowerCase());
|
|
2976
3008
|
return { agent: agent2, provider, passthrough: argv.slice(2) };
|
|
2977
3009
|
}
|
|
2978
3010
|
const rest = argv.slice(2);
|
|
@@ -2982,7 +3014,7 @@ function resolveAgent(argv) {
|
|
|
2982
3014
|
"exe-launch-agent: missing --agent <name>. Invoke via the per-agent symlink (exe/yoshi/tom/mari/sasha) or pass --agent explicitly."
|
|
2983
3015
|
);
|
|
2984
3016
|
}
|
|
2985
|
-
const agent = rest[agentIdx + 1];
|
|
3017
|
+
const agent = rest[agentIdx + 1].toLowerCase();
|
|
2986
3018
|
const passthrough = [...rest.slice(0, agentIdx), ...rest.slice(agentIdx + 2)];
|
|
2987
3019
|
return { agent, provider: DEFAULT_PROVIDER, passthrough };
|
|
2988
3020
|
}
|
|
@@ -2997,10 +3029,19 @@ async function isKnownAgent(agent) {
|
|
|
2997
3029
|
}
|
|
2998
3030
|
}
|
|
2999
3031
|
function identityPathFor(agent) {
|
|
3000
|
-
|
|
3032
|
+
const dir = path7.join(os5.homedir(), ".exe-os", "identity");
|
|
3033
|
+
const exactPath = path7.join(dir, `${agent}.md`);
|
|
3034
|
+
if (existsSync6(exactPath)) return exactPath;
|
|
3035
|
+
try {
|
|
3036
|
+
const files = readdirSync4(dir);
|
|
3037
|
+
const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
|
|
3038
|
+
if (match) return path7.join(dir, match);
|
|
3039
|
+
} catch {
|
|
3040
|
+
}
|
|
3041
|
+
return exactPath;
|
|
3001
3042
|
}
|
|
3002
3043
|
function leanMcpConfigFor(agent) {
|
|
3003
|
-
const p = path7.join(
|
|
3044
|
+
const p = path7.join(os5.homedir(), ".exe-os", "mcp-configs", `${agent}-lean.json`);
|
|
3004
3045
|
return existsSync6(p) ? p : null;
|
|
3005
3046
|
}
|
|
3006
3047
|
var _ccHelpOutput = null;
|
|
@@ -3024,8 +3065,32 @@ function _resetCcHelpCache() {
|
|
|
3024
3065
|
function buildLaunchPlan(agent, behaviorsPath, passthrough, _hasAgentFlag, _provider) {
|
|
3025
3066
|
const args = ["--dangerously-skip-permissions"];
|
|
3026
3067
|
const idPath = identityPathFor(agent);
|
|
3027
|
-
const ccAgentPath = path7.join(
|
|
3028
|
-
|
|
3068
|
+
const ccAgentPath = path7.join(os5.homedir(), ".claude", "agents", `${agent}.md`);
|
|
3069
|
+
let effectiveCcPath = null;
|
|
3070
|
+
if (existsSync6(ccAgentPath)) {
|
|
3071
|
+
effectiveCcPath = ccAgentPath;
|
|
3072
|
+
} else {
|
|
3073
|
+
try {
|
|
3074
|
+
const ccAgentDir = path7.join(os5.homedir(), ".claude", "agents");
|
|
3075
|
+
const ccFiles = readdirSync4(ccAgentDir);
|
|
3076
|
+
const ccMatch = ccFiles.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
|
|
3077
|
+
if (ccMatch) effectiveCcPath = path7.join(ccAgentDir, ccMatch);
|
|
3078
|
+
} catch {
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
const effectiveIdPath = existsSync6(idPath) ? idPath : effectiveCcPath;
|
|
3082
|
+
if (!effectiveIdPath) {
|
|
3083
|
+
process.stderr.write(
|
|
3084
|
+
`
|
|
3085
|
+
\u26A0\uFE0F No identity file found for agent "${agent}".
|
|
3086
|
+
Checked: ${idPath}
|
|
3087
|
+
Checked: ${ccAgentPath}
|
|
3088
|
+
Claude will boot without agent identity.
|
|
3089
|
+
Fix: run exe-os setup (option 2) to sync from cloud, or copy the identity file manually.
|
|
3090
|
+
|
|
3091
|
+
`
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3029
3094
|
if (effectiveIdPath) {
|
|
3030
3095
|
if (ccSupportsFlag("--system-prompt")) {
|
|
3031
3096
|
try {
|
|
@@ -3156,7 +3221,7 @@ async function main() {
|
|
|
3156
3221
|
_resetCcAgentSupportCache();
|
|
3157
3222
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
3158
3223
|
if (hasAgentFlag) {
|
|
3159
|
-
const ccAgentDir = path7.join(
|
|
3224
|
+
const ccAgentDir = path7.join(os5.homedir(), ".claude", "agents");
|
|
3160
3225
|
const ccAgentFile = path7.join(ccAgentDir, `${agent}.md`);
|
|
3161
3226
|
if (!existsSync6(ccAgentFile)) {
|
|
3162
3227
|
const exeIdentity = identityPathFor(agent);
|
|
@@ -3177,7 +3242,7 @@ async function main() {
|
|
|
3177
3242
|
mkdirSync4(ccAgentDir, { recursive: true });
|
|
3178
3243
|
let content = readFileSync4(sourceFile, "utf-8");
|
|
3179
3244
|
content = content.replace(/\$\{agent_id\}/g, agent);
|
|
3180
|
-
|
|
3245
|
+
writeFileSync4(ccAgentFile, content, "utf-8");
|
|
3181
3246
|
process.stderr.write(
|
|
3182
3247
|
`[exe-launch-agent] auto-provisioned ${ccAgentFile} from ${sourceFile}
|
|
3183
3248
|
`
|
|
@@ -3192,7 +3257,7 @@ async function main() {
|
|
|
3192
3257
|
const empRole = (() => {
|
|
3193
3258
|
try {
|
|
3194
3259
|
const emps = __require("fs").readFileSync(
|
|
3195
|
-
path7.join(
|
|
3260
|
+
path7.join(os5.homedir(), ".exe-os", "exe-employees.json"),
|
|
3196
3261
|
"utf-8"
|
|
3197
3262
|
);
|
|
3198
3263
|
const found = JSON.parse(emps).find(
|
package/dist/bin/exe-link.js
CHANGED
|
@@ -399,9 +399,10 @@ var init_license = __esm({
|
|
|
399
399
|
|
|
400
400
|
// src/lib/employees.ts
|
|
401
401
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
402
|
-
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3 } from "fs";
|
|
402
|
+
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
403
403
|
import { execSync } from "child_process";
|
|
404
404
|
import path4 from "path";
|
|
405
|
+
import os3 from "os";
|
|
405
406
|
async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
406
407
|
if (!existsSync4(employeesPath)) {
|
|
407
408
|
return [];
|
|
@@ -494,7 +495,7 @@ __export(cloud_sync_exports, {
|
|
|
494
495
|
mergeRosterFromRemote: () => mergeRosterFromRemote,
|
|
495
496
|
recordRosterDeletion: () => recordRosterDeletion
|
|
496
497
|
});
|
|
497
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
498
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, readdirSync, mkdirSync as mkdirSync2, appendFileSync, unlinkSync as unlinkSync2, openSync, closeSync } from "fs";
|
|
498
499
|
import crypto2 from "crypto";
|
|
499
500
|
import path5 from "path";
|
|
500
501
|
import { homedir } from "os";
|
|
@@ -513,7 +514,7 @@ async function withRosterLock(fn) {
|
|
|
513
514
|
try {
|
|
514
515
|
const fd = openSync(ROSTER_LOCK_PATH, "wx");
|
|
515
516
|
closeSync(fd);
|
|
516
|
-
|
|
517
|
+
writeFileSync3(ROSTER_LOCK_PATH, String(Date.now()));
|
|
517
518
|
} catch (err) {
|
|
518
519
|
if (err.code === "EEXIST") {
|
|
519
520
|
try {
|
|
@@ -521,10 +522,10 @@ async function withRosterLock(fn) {
|
|
|
521
522
|
if (Date.now() - ts < LOCK_STALE_MS) {
|
|
522
523
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
523
524
|
}
|
|
524
|
-
|
|
525
|
+
unlinkSync2(ROSTER_LOCK_PATH);
|
|
525
526
|
const fd = openSync(ROSTER_LOCK_PATH, "wx");
|
|
526
527
|
closeSync(fd);
|
|
527
|
-
|
|
528
|
+
writeFileSync3(ROSTER_LOCK_PATH, String(Date.now()));
|
|
528
529
|
} catch (retryErr) {
|
|
529
530
|
if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
|
|
530
531
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
@@ -537,7 +538,7 @@ async function withRosterLock(fn) {
|
|
|
537
538
|
return await fn();
|
|
538
539
|
} finally {
|
|
539
540
|
try {
|
|
540
|
-
|
|
541
|
+
unlinkSync2(ROSTER_LOCK_PATH);
|
|
541
542
|
} catch {
|
|
542
543
|
}
|
|
543
544
|
}
|
|
@@ -837,13 +838,13 @@ function recordRosterDeletion(name) {
|
|
|
837
838
|
} catch {
|
|
838
839
|
}
|
|
839
840
|
if (!deletions.includes(name)) deletions.push(name);
|
|
840
|
-
|
|
841
|
+
writeFileSync3(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
|
|
841
842
|
}
|
|
842
843
|
function consumeRosterDeletions() {
|
|
843
844
|
try {
|
|
844
845
|
if (!existsSync5(ROSTER_DELETIONS_PATH)) return [];
|
|
845
846
|
const deletions = JSON.parse(readFileSync4(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
846
|
-
|
|
847
|
+
writeFileSync3(ROSTER_DELETIONS_PATH, "[]");
|
|
847
848
|
return deletions;
|
|
848
849
|
} catch {
|
|
849
850
|
return [];
|
|
@@ -959,7 +960,7 @@ function mergeConfig(remoteConfig, configPath) {
|
|
|
959
960
|
const merged = { ...remoteConfig, ...local };
|
|
960
961
|
const dir = path5.dirname(cfgPath);
|
|
961
962
|
if (!existsSync5(dir)) mkdirSync2(dir, { recursive: true });
|
|
962
|
-
|
|
963
|
+
writeFileSync3(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
963
964
|
}
|
|
964
965
|
async function mergeRosterFromRemote(remote, paths) {
|
|
965
966
|
return withRosterLock(async () => {
|
|
@@ -979,7 +980,11 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
979
980
|
} catch {
|
|
980
981
|
}
|
|
981
982
|
}
|
|
982
|
-
const
|
|
983
|
+
const lookupKey = `${remoteEmp.name}.md`;
|
|
984
|
+
const matchedKey = Object.keys(remote.identities).find(
|
|
985
|
+
(k) => k.toLowerCase() === lookupKey.toLowerCase()
|
|
986
|
+
) ?? lookupKey;
|
|
987
|
+
const remoteIdentity = remote.identities[matchedKey];
|
|
983
988
|
if (remoteIdentity) {
|
|
984
989
|
if (!existsSync5(identityDir)) mkdirSync2(identityDir, { recursive: true });
|
|
985
990
|
const idPath = path5.join(identityDir, `${remoteEmp.name}.md`);
|
|
@@ -989,7 +994,7 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
989
994
|
} catch {
|
|
990
995
|
}
|
|
991
996
|
if (localIdentity !== remoteIdentity) {
|
|
992
|
-
|
|
997
|
+
writeFileSync3(idPath, remoteIdentity, "utf-8");
|
|
993
998
|
identitiesUpdated++;
|
|
994
999
|
}
|
|
995
1000
|
}
|
|
@@ -114,9 +114,10 @@ var init_config = __esm({
|
|
|
114
114
|
|
|
115
115
|
// src/lib/employees.ts
|
|
116
116
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
117
|
-
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3 } from "fs";
|
|
117
|
+
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
118
118
|
import { execSync } from "child_process";
|
|
119
119
|
import path3 from "path";
|
|
120
|
+
import os2 from "os";
|
|
120
121
|
function validateEmployeeName(name) {
|
|
121
122
|
if (!name) {
|
|
122
123
|
return { valid: false, error: "Name is required" };
|
|
@@ -766,7 +767,7 @@ __export(identity_exports, {
|
|
|
766
767
|
listIdentities: () => listIdentities,
|
|
767
768
|
updateIdentity: () => updateIdentity
|
|
768
769
|
});
|
|
769
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as
|
|
770
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
770
771
|
import { readdirSync as readdirSync2 } from "fs";
|
|
771
772
|
import path6 from "path";
|
|
772
773
|
import { createHash } from "crypto";
|
|
@@ -832,7 +833,7 @@ async function updateIdentity(agentId, content, updatedBy) {
|
|
|
832
833
|
ensureDir();
|
|
833
834
|
const filePath = identityPath(agentId);
|
|
834
835
|
const hash = contentHash(content);
|
|
835
|
-
|
|
836
|
+
writeFileSync4(filePath, content, "utf-8");
|
|
836
837
|
try {
|
|
837
838
|
const client = getClient();
|
|
838
839
|
await client.execute({
|
|
@@ -893,7 +894,7 @@ var init_identity = __esm({
|
|
|
893
894
|
});
|
|
894
895
|
|
|
895
896
|
// src/lib/agent-symlinks.ts
|
|
896
|
-
import
|
|
897
|
+
import os3 from "os";
|
|
897
898
|
import path7 from "path";
|
|
898
899
|
import {
|
|
899
900
|
existsSync as existsSync7,
|
|
@@ -911,7 +912,7 @@ function identitySourcePath(homeDir, agentId) {
|
|
|
911
912
|
function claudeAgentLinkPath(homeDir, agentId) {
|
|
912
913
|
return path7.join(claudeAgentsDir(homeDir), `${agentId}.md`);
|
|
913
914
|
}
|
|
914
|
-
function ensureAgentSymlink(agentId, homeDir =
|
|
915
|
+
function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
|
|
915
916
|
const target = identitySourcePath(homeDir, agentId);
|
|
916
917
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
917
918
|
mkdirSync4(claudeAgentsDir(homeDir), { recursive: true });
|
|
@@ -949,7 +950,7 @@ function ensureAgentSymlink(agentId, homeDir = os2.homedir()) {
|
|
|
949
950
|
}
|
|
950
951
|
return { agentId, action: "created", target, link };
|
|
951
952
|
}
|
|
952
|
-
async function ensureAllAgentSymlinks(homeDir =
|
|
953
|
+
async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
|
|
953
954
|
const employees = await loadEmployees();
|
|
954
955
|
return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
|
|
955
956
|
}
|
|
@@ -994,9 +995,9 @@ __export(installer_exports, {
|
|
|
994
995
|
setupTmux: () => setupTmux
|
|
995
996
|
});
|
|
996
997
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
997
|
-
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as
|
|
998
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5, copyFileSync, mkdirSync as mkdirSync5 } from "fs";
|
|
998
999
|
import path8 from "path";
|
|
999
|
-
import
|
|
1000
|
+
import os4 from "os";
|
|
1000
1001
|
import { execSync as execSync2 } from "child_process";
|
|
1001
1002
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1002
1003
|
function resolvePackageRoot() {
|
|
@@ -1016,7 +1017,7 @@ function resolvePackageRoot() {
|
|
|
1016
1017
|
}
|
|
1017
1018
|
return path8.resolve(path8.dirname(thisFile), "..", "..", "..");
|
|
1018
1019
|
}
|
|
1019
|
-
async function copySlashCommands(packageRoot, homeDir =
|
|
1020
|
+
async function copySlashCommands(packageRoot, homeDir = os4.homedir()) {
|
|
1020
1021
|
let copied = 0;
|
|
1021
1022
|
let skipped = 0;
|
|
1022
1023
|
const skillsBase = path8.join(homeDir, ".claude", "skills");
|
|
@@ -1069,7 +1070,7 @@ name: ${skillName}
|
|
|
1069
1070
|
await writeFile3(destPath, content);
|
|
1070
1071
|
return true;
|
|
1071
1072
|
}
|
|
1072
|
-
async function registerMcpServer(packageRoot, homeDir =
|
|
1073
|
+
async function registerMcpServer(packageRoot, homeDir = os4.homedir()) {
|
|
1073
1074
|
const claudeJsonPath = path8.join(homeDir, ".claude.json");
|
|
1074
1075
|
let claudeJson = {};
|
|
1075
1076
|
if (existsSync8(claudeJsonPath)) {
|
|
@@ -1101,7 +1102,7 @@ async function registerMcpServer(packageRoot, homeDir = os3.homedir()) {
|
|
|
1101
1102
|
await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
1102
1103
|
return true;
|
|
1103
1104
|
}
|
|
1104
|
-
async function mergeHooks(packageRoot, homeDir =
|
|
1105
|
+
async function mergeHooks(packageRoot, homeDir = os4.homedir()) {
|
|
1105
1106
|
const settingsPath = path8.join(homeDir, ".claude", "settings.json");
|
|
1106
1107
|
let settings = {};
|
|
1107
1108
|
if (existsSync8(settingsPath)) {
|
|
@@ -1416,7 +1417,7 @@ async function runInstaller(homeDir) {
|
|
|
1416
1417
|
`Hooks: ${hookResult.added} added, ${hookResult.skipped} unchanged
|
|
1417
1418
|
`
|
|
1418
1419
|
);
|
|
1419
|
-
const resolvedHome = homeDir ??
|
|
1420
|
+
const resolvedHome = homeDir ?? os4.homedir();
|
|
1420
1421
|
const exeWorkspace = path8.join(resolvedHome, "exe");
|
|
1421
1422
|
if (!existsSync8(exeWorkspace)) {
|
|
1422
1423
|
try {
|
|
@@ -1445,7 +1446,7 @@ exe-os installed successfully.
|
|
|
1445
1446
|
`);
|
|
1446
1447
|
}
|
|
1447
1448
|
function setupTmux(home) {
|
|
1448
|
-
const homeDir = home ??
|
|
1449
|
+
const homeDir = home ?? os4.homedir();
|
|
1449
1450
|
const exeDir = path8.join(homeDir, ".exe-os");
|
|
1450
1451
|
const exeTmuxConf = path8.join(exeDir, "tmux.conf");
|
|
1451
1452
|
const userTmuxConf = path8.join(homeDir, ".tmux.conf");
|
|
@@ -1468,11 +1469,11 @@ function setupTmux(home) {
|
|
|
1468
1469
|
process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
|
|
1469
1470
|
`);
|
|
1470
1471
|
}
|
|
1471
|
-
|
|
1472
|
+
writeFileSync5(userTmuxConf, `${sourceLine}
|
|
1472
1473
|
${existing}`);
|
|
1473
1474
|
}
|
|
1474
1475
|
} else {
|
|
1475
|
-
|
|
1476
|
+
writeFileSync5(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
|
|
1476
1477
|
${sourceLine}
|
|
1477
1478
|
`);
|
|
1478
1479
|
}
|
|
@@ -2086,7 +2087,7 @@ import path5 from "path";
|
|
|
2086
2087
|
|
|
2087
2088
|
// src/lib/license.ts
|
|
2088
2089
|
init_config();
|
|
2089
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
2090
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
2090
2091
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2091
2092
|
import path4 from "path";
|
|
2092
2093
|
import { jwtVerify, importSPKI } from "jose";
|
|
@@ -2142,7 +2143,7 @@ function loadDeviceId() {
|
|
|
2142
2143
|
}
|
|
2143
2144
|
const id = randomUUID2();
|
|
2144
2145
|
mkdirSync2(EXE_AI_DIR, { recursive: true });
|
|
2145
|
-
|
|
2146
|
+
writeFileSync3(DEVICE_ID_PATH, id, "utf8");
|
|
2146
2147
|
return id;
|
|
2147
2148
|
}
|
|
2148
2149
|
function loadLicense() {
|
|
@@ -2155,7 +2156,7 @@ function loadLicense() {
|
|
|
2155
2156
|
}
|
|
2156
2157
|
function saveLicense(apiKey) {
|
|
2157
2158
|
mkdirSync2(EXE_AI_DIR, { recursive: true });
|
|
2158
|
-
|
|
2159
|
+
writeFileSync3(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
|
|
2159
2160
|
}
|
|
2160
2161
|
async function verifyLicenseJwt(token) {
|
|
2161
2162
|
try {
|
|
@@ -2226,7 +2227,7 @@ function getRawCachedPlan() {
|
|
|
2226
2227
|
}
|
|
2227
2228
|
function cacheResponse(token) {
|
|
2228
2229
|
try {
|
|
2229
|
-
|
|
2230
|
+
writeFileSync3(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
2230
2231
|
} catch {
|
|
2231
2232
|
}
|
|
2232
2233
|
}
|
|
@@ -1652,9 +1652,10 @@ var init_intercom_queue = __esm({
|
|
|
1652
1652
|
|
|
1653
1653
|
// src/lib/employees.ts
|
|
1654
1654
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1655
|
-
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync3 } from "fs";
|
|
1655
|
+
import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1656
1656
|
import { execSync as execSync3 } from "child_process";
|
|
1657
1657
|
import path6 from "path";
|
|
1658
|
+
import os5 from "os";
|
|
1658
1659
|
var EMPLOYEES_PATH;
|
|
1659
1660
|
var init_employees = __esm({
|
|
1660
1661
|
"src/lib/employees.ts"() {
|
|
@@ -1665,7 +1666,7 @@ var init_employees = __esm({
|
|
|
1665
1666
|
});
|
|
1666
1667
|
|
|
1667
1668
|
// src/lib/license.ts
|
|
1668
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
1669
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
1669
1670
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1670
1671
|
import path7 from "path";
|
|
1671
1672
|
import { jwtVerify, importSPKI } from "jose";
|
|
@@ -1697,7 +1698,7 @@ var init_plan_limits = __esm({
|
|
|
1697
1698
|
|
|
1698
1699
|
// src/lib/tmux-routing.ts
|
|
1699
1700
|
import path9 from "path";
|
|
1700
|
-
import
|
|
1701
|
+
import os6 from "os";
|
|
1701
1702
|
import { fileURLToPath } from "url";
|
|
1702
1703
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1703
1704
|
var init_tmux_routing = __esm({
|
|
@@ -1711,9 +1712,9 @@ var init_tmux_routing = __esm({
|
|
|
1711
1712
|
init_provider_table();
|
|
1712
1713
|
init_intercom_queue();
|
|
1713
1714
|
init_plan_limits();
|
|
1714
|
-
SPAWN_LOCK_DIR = path9.join(
|
|
1715
|
-
SESSION_CACHE = path9.join(
|
|
1716
|
-
INTERCOM_LOG2 = path9.join(
|
|
1715
|
+
SPAWN_LOCK_DIR = path9.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
1716
|
+
SESSION_CACHE = path9.join(os6.homedir(), ".exe-os", "session-cache");
|
|
1717
|
+
INTERCOM_LOG2 = path9.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
1717
1718
|
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1718
1719
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1719
1720
|
}
|