@askexenow/exe-os 0.8.49 → 0.8.51
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/cli.js +310 -210
- package/dist/bin/exe-boot.js +11 -1
- package/dist/bin/exe-gateway.js +11 -1
- package/dist/bin/exe-heartbeat.js +11 -1
- package/dist/bin/exe-pending-reviews.js +13 -2
- package/dist/bin/exe-session-cleanup.js +11 -1
- package/dist/bin/git-sweep.js +11 -1
- package/dist/bin/scan-tasks.js +11 -1
- package/dist/bin/update.js +80 -22
- package/dist/gateway/index.js +11 -1
- package/dist/hooks/bug-report-worker.js +11 -1
- package/dist/hooks/commit-complete.js +11 -1
- package/dist/hooks/ingest-worker.js +11 -1
- package/dist/hooks/pre-compact.js +11 -1
- package/dist/hooks/prompt-submit.js +11 -1
- package/dist/index.js +11 -1
- package/dist/lib/exe-daemon.js +11 -1
- package/dist/lib/tasks.js +11 -1
- package/dist/lib/tmux-routing.js +11 -1
- package/dist/mcp/server.js +43 -1
- package/dist/mcp/tools/create-task.js +11 -1
- package/dist/mcp/tools/list-tasks.js +11 -1
- package/dist/runtime/index.js +11 -1
- package/dist/tui/App.js +42 -3
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -6096,6 +6096,159 @@ var init_setup_wizard = __esm({
|
|
|
6096
6096
|
}
|
|
6097
6097
|
});
|
|
6098
6098
|
|
|
6099
|
+
// src/lib/update-check.ts
|
|
6100
|
+
import { execSync as execSync3 } from "child_process";
|
|
6101
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
6102
|
+
import path14 from "path";
|
|
6103
|
+
function getLocalVersion(packageRoot) {
|
|
6104
|
+
const pkgPath = path14.join(packageRoot, "package.json");
|
|
6105
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
6106
|
+
return pkg.version;
|
|
6107
|
+
}
|
|
6108
|
+
function getRemoteVersion() {
|
|
6109
|
+
try {
|
|
6110
|
+
const output = execSync3("npm view @askexenow/exe-os version", {
|
|
6111
|
+
encoding: "utf-8",
|
|
6112
|
+
timeout: 15e3,
|
|
6113
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6114
|
+
});
|
|
6115
|
+
return output.trim();
|
|
6116
|
+
} catch {
|
|
6117
|
+
return null;
|
|
6118
|
+
}
|
|
6119
|
+
}
|
|
6120
|
+
function checkForUpdate(packageRoot) {
|
|
6121
|
+
const localVersion = getLocalVersion(packageRoot);
|
|
6122
|
+
const remoteVersion = getRemoteVersion();
|
|
6123
|
+
if (!remoteVersion) {
|
|
6124
|
+
return {
|
|
6125
|
+
updateAvailable: false,
|
|
6126
|
+
localVersion,
|
|
6127
|
+
error: "Could not reach npm registry or package not published yet"
|
|
6128
|
+
};
|
|
6129
|
+
}
|
|
6130
|
+
if (remoteVersion === localVersion) {
|
|
6131
|
+
return { updateAvailable: false, localVersion, remoteVersion };
|
|
6132
|
+
}
|
|
6133
|
+
return { updateAvailable: true, localVersion, remoteVersion };
|
|
6134
|
+
}
|
|
6135
|
+
var init_update_check = __esm({
|
|
6136
|
+
"src/lib/update-check.ts"() {
|
|
6137
|
+
"use strict";
|
|
6138
|
+
}
|
|
6139
|
+
});
|
|
6140
|
+
|
|
6141
|
+
// src/bin/update.ts
|
|
6142
|
+
var update_exports = {};
|
|
6143
|
+
__export(update_exports, {
|
|
6144
|
+
checkForUpdate: () => checkForUpdate,
|
|
6145
|
+
getLocalVersion: () => getLocalVersion,
|
|
6146
|
+
getRemoteVersion: () => getRemoteVersion,
|
|
6147
|
+
runUpdate: () => runUpdate
|
|
6148
|
+
});
|
|
6149
|
+
import { execSync as execSync4 } from "child_process";
|
|
6150
|
+
import { createInterface as createInterface3 } from "readline";
|
|
6151
|
+
async function runUpdate(cliArgs) {
|
|
6152
|
+
const args2 = cliArgs ?? process.argv.slice(2);
|
|
6153
|
+
const autoMode = args2.includes("--auto") || args2.includes("-y");
|
|
6154
|
+
const checkOnly = args2.includes("--check");
|
|
6155
|
+
const packageRoot = new URL("../..", import.meta.url).pathname;
|
|
6156
|
+
const result = checkForUpdate(packageRoot);
|
|
6157
|
+
if (result.error) {
|
|
6158
|
+
console.error(`\u26A0\uFE0F ${result.error}`);
|
|
6159
|
+
process.exit(0);
|
|
6160
|
+
}
|
|
6161
|
+
if (checkOnly) {
|
|
6162
|
+
if (result.updateAvailable) {
|
|
6163
|
+
console.log(`Update available: v${result.localVersion} \u2192 v${result.remoteVersion}`);
|
|
6164
|
+
} else {
|
|
6165
|
+
console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
|
|
6166
|
+
}
|
|
6167
|
+
process.exit(0);
|
|
6168
|
+
}
|
|
6169
|
+
if (!result.updateAvailable) {
|
|
6170
|
+
console.log(`\u2705 exe-os is up to date (v${result.localVersion})`);
|
|
6171
|
+
process.exit(0);
|
|
6172
|
+
}
|
|
6173
|
+
console.log(`
|
|
6174
|
+
\u{1F4E6} Update available: v${result.localVersion} \u2192 v${result.remoteVersion}
|
|
6175
|
+
`);
|
|
6176
|
+
let proceed = autoMode;
|
|
6177
|
+
if (!proceed) {
|
|
6178
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
6179
|
+
const answer = await new Promise((resolve) => {
|
|
6180
|
+
rl.question("Install update? (Y/n) ", resolve);
|
|
6181
|
+
});
|
|
6182
|
+
rl.close();
|
|
6183
|
+
proceed = answer.toLowerCase() !== "n";
|
|
6184
|
+
}
|
|
6185
|
+
if (!proceed) {
|
|
6186
|
+
console.log("Update skipped.");
|
|
6187
|
+
process.exit(0);
|
|
6188
|
+
}
|
|
6189
|
+
console.log("\n\u{1F9F9} Clearing npm cache...");
|
|
6190
|
+
try {
|
|
6191
|
+
execSync4("npm cache clean --force", { stdio: "pipe" });
|
|
6192
|
+
console.log(" Done");
|
|
6193
|
+
} catch {
|
|
6194
|
+
console.log(" Skipped (non-critical)");
|
|
6195
|
+
}
|
|
6196
|
+
console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
|
|
6197
|
+
try {
|
|
6198
|
+
execSync4("npm install -g @askexenow/exe-os@latest", {
|
|
6199
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
6200
|
+
timeout: 12e4
|
|
6201
|
+
});
|
|
6202
|
+
} catch (err) {
|
|
6203
|
+
console.error("\n\u274C Update failed.");
|
|
6204
|
+
console.error(" Try manually: npm install -g @askexenow/exe-os@latest");
|
|
6205
|
+
if (err instanceof Error && err.message) {
|
|
6206
|
+
console.error(` Error: ${err.message.split("\n")[0]}`);
|
|
6207
|
+
}
|
|
6208
|
+
process.exit(1);
|
|
6209
|
+
}
|
|
6210
|
+
let newVersion;
|
|
6211
|
+
try {
|
|
6212
|
+
newVersion = getLocalVersion(packageRoot);
|
|
6213
|
+
} catch {
|
|
6214
|
+
try {
|
|
6215
|
+
const out = execSync4("npm list -g @askexenow/exe-os --depth=0 2>/dev/null", { encoding: "utf8" });
|
|
6216
|
+
const match = out.match(/@askexenow\/exe-os@(\S+)/);
|
|
6217
|
+
newVersion = match?.[1] ?? "unknown";
|
|
6218
|
+
} catch {
|
|
6219
|
+
newVersion = "unknown";
|
|
6220
|
+
}
|
|
6221
|
+
}
|
|
6222
|
+
const remoteVersion = result.remoteVersion;
|
|
6223
|
+
if (newVersion === remoteVersion) {
|
|
6224
|
+
console.log(`
|
|
6225
|
+
\u2705 Updated to v${newVersion}`);
|
|
6226
|
+
} else if (newVersion !== result.localVersion) {
|
|
6227
|
+
console.log(`
|
|
6228
|
+
\u2705 Updated to v${newVersion} (latest: v${remoteVersion})`);
|
|
6229
|
+
} else {
|
|
6230
|
+
console.log(`
|
|
6231
|
+
\u26A0\uFE0F Version unchanged (v${newVersion}). npm cache may be stale.`);
|
|
6232
|
+
console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
|
|
6233
|
+
}
|
|
6234
|
+
console.log(" Hooks re-wired, daemon restarted automatically.");
|
|
6235
|
+
console.log("\n\u{1F680} Ready. Start your COO session to use the new version.\n");
|
|
6236
|
+
}
|
|
6237
|
+
var init_update = __esm({
|
|
6238
|
+
"src/bin/update.ts"() {
|
|
6239
|
+
"use strict";
|
|
6240
|
+
init_is_main();
|
|
6241
|
+
init_update_check();
|
|
6242
|
+
init_update_check();
|
|
6243
|
+
if (isMainModule(import.meta.url)) {
|
|
6244
|
+
runUpdate().catch((err) => {
|
|
6245
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
6246
|
+
process.exit(1);
|
|
6247
|
+
});
|
|
6248
|
+
}
|
|
6249
|
+
}
|
|
6250
|
+
});
|
|
6251
|
+
|
|
6099
6252
|
// node_modules/es-toolkit/dist/function/debounce.mjs
|
|
6100
6253
|
function debounce(func, debounceMs, { signal, edges } = {}) {
|
|
6101
6254
|
let pendingThis = void 0;
|
|
@@ -12558,13 +12711,13 @@ __export(tmux_status_exports, {
|
|
|
12558
12711
|
parseActivity: () => parseActivity,
|
|
12559
12712
|
parseContextPercentage: () => parseContextPercentage
|
|
12560
12713
|
});
|
|
12561
|
-
import { execSync as
|
|
12714
|
+
import { execSync as execSync5 } from "child_process";
|
|
12562
12715
|
function inTmux() {
|
|
12563
12716
|
if (process.env.TMUX || process.env.TMUX_PANE) return true;
|
|
12564
12717
|
const term = process.env.TERM ?? "";
|
|
12565
12718
|
if (term.startsWith("tmux") || term.startsWith("screen")) return true;
|
|
12566
12719
|
try {
|
|
12567
|
-
|
|
12720
|
+
execSync5("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
12568
12721
|
encoding: "utf8",
|
|
12569
12722
|
timeout: 2e3
|
|
12570
12723
|
});
|
|
@@ -12574,12 +12727,12 @@ function inTmux() {
|
|
|
12574
12727
|
try {
|
|
12575
12728
|
let pid = process.ppid;
|
|
12576
12729
|
for (let depth = 0; depth < 8 && pid > 1; depth++) {
|
|
12577
|
-
const comm =
|
|
12730
|
+
const comm = execSync5(`ps -p ${pid} -o comm= 2>/dev/null`, {
|
|
12578
12731
|
encoding: "utf8",
|
|
12579
12732
|
timeout: 1e3
|
|
12580
12733
|
}).trim();
|
|
12581
12734
|
if (/tmux/.test(comm)) return true;
|
|
12582
|
-
const ppid =
|
|
12735
|
+
const ppid = execSync5(`ps -p ${pid} -o ppid= 2>/dev/null`, {
|
|
12583
12736
|
encoding: "utf8",
|
|
12584
12737
|
timeout: 1e3
|
|
12585
12738
|
}).trim();
|
|
@@ -12592,7 +12745,7 @@ function inTmux() {
|
|
|
12592
12745
|
}
|
|
12593
12746
|
function listTmuxSessions() {
|
|
12594
12747
|
try {
|
|
12595
|
-
const out =
|
|
12748
|
+
const out = execSync5("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
12596
12749
|
encoding: "utf8",
|
|
12597
12750
|
timeout: 3e3
|
|
12598
12751
|
});
|
|
@@ -12603,7 +12756,7 @@ function listTmuxSessions() {
|
|
|
12603
12756
|
}
|
|
12604
12757
|
function capturePaneLines(windowName, lines = 10) {
|
|
12605
12758
|
try {
|
|
12606
|
-
const out =
|
|
12759
|
+
const out = execSync5(
|
|
12607
12760
|
`tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
|
|
12608
12761
|
{ encoding: "utf8", timeout: 3e3 }
|
|
12609
12762
|
);
|
|
@@ -12614,7 +12767,7 @@ function capturePaneLines(windowName, lines = 10) {
|
|
|
12614
12767
|
}
|
|
12615
12768
|
function getPaneCwd(windowName) {
|
|
12616
12769
|
try {
|
|
12617
|
-
const out =
|
|
12770
|
+
const out = execSync5(
|
|
12618
12771
|
`tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
|
|
12619
12772
|
{ encoding: "utf8", timeout: 3e3 }
|
|
12620
12773
|
);
|
|
@@ -12625,7 +12778,7 @@ function getPaneCwd(windowName) {
|
|
|
12625
12778
|
}
|
|
12626
12779
|
function projectFromPath(dir) {
|
|
12627
12780
|
try {
|
|
12628
|
-
const root =
|
|
12781
|
+
const root = execSync5("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
|
|
12629
12782
|
encoding: "utf8",
|
|
12630
12783
|
timeout: 3e3
|
|
12631
12784
|
}).trim();
|
|
@@ -12694,7 +12847,7 @@ function getEmployeeStatuses(employeeNames) {
|
|
|
12694
12847
|
}
|
|
12695
12848
|
let paneAlive = true;
|
|
12696
12849
|
try {
|
|
12697
|
-
const paneStatus =
|
|
12850
|
+
const paneStatus = execSync5(
|
|
12698
12851
|
`tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
|
|
12699
12852
|
{ encoding: "utf8", timeout: 3e3 }
|
|
12700
12853
|
).trim();
|
|
@@ -14894,10 +15047,10 @@ var init_hooks = __esm({
|
|
|
14894
15047
|
});
|
|
14895
15048
|
|
|
14896
15049
|
// src/runtime/safety-checks.ts
|
|
14897
|
-
import
|
|
15050
|
+
import path15 from "path";
|
|
14898
15051
|
import os6 from "os";
|
|
14899
15052
|
function checkPathSafety(filePath) {
|
|
14900
|
-
const resolved =
|
|
15053
|
+
const resolved = path15.resolve(filePath);
|
|
14901
15054
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
14902
15055
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
14903
15056
|
if (matches) {
|
|
@@ -14907,7 +15060,7 @@ function checkPathSafety(filePath) {
|
|
|
14907
15060
|
return { safe: true, bypassImmune: true };
|
|
14908
15061
|
}
|
|
14909
15062
|
function checkReadPathSafety(filePath) {
|
|
14910
|
-
const resolved =
|
|
15063
|
+
const resolved = path15.resolve(filePath);
|
|
14911
15064
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
14912
15065
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
14913
15066
|
);
|
|
@@ -14933,11 +15086,11 @@ var init_safety_checks = __esm({
|
|
|
14933
15086
|
reason: "Git config can set hooks and command execution"
|
|
14934
15087
|
},
|
|
14935
15088
|
{
|
|
14936
|
-
pattern: (p) => p.startsWith(
|
|
15089
|
+
pattern: (p) => p.startsWith(path15.join(HOME, ".claude")),
|
|
14937
15090
|
reason: "Claude configuration files are protected"
|
|
14938
15091
|
},
|
|
14939
15092
|
{
|
|
14940
|
-
pattern: (p) => p.startsWith(
|
|
15093
|
+
pattern: (p) => p.startsWith(path15.join(HOME, ".exe-os")),
|
|
14941
15094
|
reason: "exe-os configuration files are protected"
|
|
14942
15095
|
},
|
|
14943
15096
|
{
|
|
@@ -14954,7 +15107,7 @@ var init_safety_checks = __esm({
|
|
|
14954
15107
|
},
|
|
14955
15108
|
{
|
|
14956
15109
|
pattern: (p) => {
|
|
14957
|
-
const name =
|
|
15110
|
+
const name = path15.basename(p);
|
|
14958
15111
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
14959
15112
|
},
|
|
14960
15113
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -14981,7 +15134,7 @@ __export(file_read_exports, {
|
|
|
14981
15134
|
FileReadTool: () => FileReadTool
|
|
14982
15135
|
});
|
|
14983
15136
|
import fs3 from "fs/promises";
|
|
14984
|
-
import
|
|
15137
|
+
import path16 from "path";
|
|
14985
15138
|
import { z } from "zod";
|
|
14986
15139
|
function isBinary(buf) {
|
|
14987
15140
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -15017,7 +15170,7 @@ var init_file_read = __esm({
|
|
|
15017
15170
|
return { behavior: "allow" };
|
|
15018
15171
|
},
|
|
15019
15172
|
async call(input, context) {
|
|
15020
|
-
const filePath =
|
|
15173
|
+
const filePath = path16.isAbsolute(input.file_path) ? input.file_path : path16.resolve(context.cwd, input.file_path);
|
|
15021
15174
|
let stat2;
|
|
15022
15175
|
try {
|
|
15023
15176
|
stat2 = await fs3.stat(filePath);
|
|
@@ -15057,7 +15210,7 @@ __export(glob_exports, {
|
|
|
15057
15210
|
GlobTool: () => GlobTool
|
|
15058
15211
|
});
|
|
15059
15212
|
import fs4 from "fs/promises";
|
|
15060
|
-
import
|
|
15213
|
+
import path17 from "path";
|
|
15061
15214
|
import { z as z2 } from "zod";
|
|
15062
15215
|
async function walkDir(dir, maxDepth = 10) {
|
|
15063
15216
|
const results = [];
|
|
@@ -15073,7 +15226,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
15073
15226
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
15074
15227
|
continue;
|
|
15075
15228
|
}
|
|
15076
|
-
const fullPath =
|
|
15229
|
+
const fullPath = path17.join(current, entry.name);
|
|
15077
15230
|
if (entry.isDirectory()) {
|
|
15078
15231
|
await walk(fullPath, depth + 1);
|
|
15079
15232
|
} else {
|
|
@@ -15107,11 +15260,11 @@ var init_glob = __esm({
|
|
|
15107
15260
|
inputSchema: inputSchema2,
|
|
15108
15261
|
isReadOnly: true,
|
|
15109
15262
|
async call(input, context) {
|
|
15110
|
-
const baseDir = input.path ?
|
|
15263
|
+
const baseDir = input.path ? path17.isAbsolute(input.path) ? input.path : path17.resolve(context.cwd, input.path) : context.cwd;
|
|
15111
15264
|
try {
|
|
15112
15265
|
const entries = await walkDir(baseDir);
|
|
15113
15266
|
const matched = entries.filter(
|
|
15114
|
-
(e) => simpleGlobMatch(
|
|
15267
|
+
(e) => simpleGlobMatch(path17.relative(baseDir, e.path), input.pattern)
|
|
15115
15268
|
);
|
|
15116
15269
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
15117
15270
|
if (matched.length === 0) {
|
|
@@ -15137,7 +15290,7 @@ __export(grep_exports, {
|
|
|
15137
15290
|
});
|
|
15138
15291
|
import { spawn as spawn2 } from "child_process";
|
|
15139
15292
|
import fs5 from "fs/promises";
|
|
15140
|
-
import
|
|
15293
|
+
import path18 from "path";
|
|
15141
15294
|
import { z as z3 } from "zod";
|
|
15142
15295
|
function runRipgrep(input, searchPath, context) {
|
|
15143
15296
|
return new Promise((resolve, reject) => {
|
|
@@ -15191,7 +15344,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
15191
15344
|
}
|
|
15192
15345
|
for (const entry of entries) {
|
|
15193
15346
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
15194
|
-
const fullPath =
|
|
15347
|
+
const fullPath = path18.join(dir, entry.name);
|
|
15195
15348
|
if (entry.isDirectory()) {
|
|
15196
15349
|
await walk(fullPath);
|
|
15197
15350
|
} else {
|
|
@@ -15237,7 +15390,7 @@ var init_grep = __esm({
|
|
|
15237
15390
|
inputSchema: inputSchema3,
|
|
15238
15391
|
isReadOnly: true,
|
|
15239
15392
|
async call(input, context) {
|
|
15240
|
-
const searchPath = input.path ?
|
|
15393
|
+
const searchPath = input.path ? path18.isAbsolute(input.path) ? input.path : path18.resolve(context.cwd, input.path) : context.cwd;
|
|
15241
15394
|
try {
|
|
15242
15395
|
const result = await runRipgrep(input, searchPath, context);
|
|
15243
15396
|
return result;
|
|
@@ -15262,7 +15415,7 @@ __export(file_write_exports, {
|
|
|
15262
15415
|
FileWriteTool: () => FileWriteTool
|
|
15263
15416
|
});
|
|
15264
15417
|
import fs6 from "fs/promises";
|
|
15265
|
-
import
|
|
15418
|
+
import path19 from "path";
|
|
15266
15419
|
import { z as z4 } from "zod";
|
|
15267
15420
|
var inputSchema4, FileWriteTool;
|
|
15268
15421
|
var init_file_write = __esm({
|
|
@@ -15290,8 +15443,8 @@ var init_file_write = __esm({
|
|
|
15290
15443
|
return { behavior: "allow" };
|
|
15291
15444
|
},
|
|
15292
15445
|
async call(input, context) {
|
|
15293
|
-
const filePath =
|
|
15294
|
-
const dir =
|
|
15446
|
+
const filePath = path19.isAbsolute(input.file_path) ? input.file_path : path19.resolve(context.cwd, input.file_path);
|
|
15447
|
+
const dir = path19.dirname(filePath);
|
|
15295
15448
|
await fs6.mkdir(dir, { recursive: true });
|
|
15296
15449
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
15297
15450
|
return {
|
|
@@ -15309,7 +15462,7 @@ __export(file_edit_exports, {
|
|
|
15309
15462
|
FileEditTool: () => FileEditTool
|
|
15310
15463
|
});
|
|
15311
15464
|
import fs7 from "fs/promises";
|
|
15312
|
-
import
|
|
15465
|
+
import path20 from "path";
|
|
15313
15466
|
import { z as z5 } from "zod";
|
|
15314
15467
|
function countOccurrences(haystack, needle) {
|
|
15315
15468
|
let count = 0;
|
|
@@ -15350,7 +15503,7 @@ var init_file_edit = __esm({
|
|
|
15350
15503
|
return { behavior: "allow" };
|
|
15351
15504
|
},
|
|
15352
15505
|
async call(input, context) {
|
|
15353
|
-
const filePath =
|
|
15506
|
+
const filePath = path20.isAbsolute(input.file_path) ? input.file_path : path20.resolve(context.cwd, input.file_path);
|
|
15354
15507
|
let content;
|
|
15355
15508
|
try {
|
|
15356
15509
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -15596,12 +15749,12 @@ __export(session_registry_exports, {
|
|
|
15596
15749
|
pruneStaleSessions: () => pruneStaleSessions,
|
|
15597
15750
|
registerSession: () => registerSession
|
|
15598
15751
|
});
|
|
15599
|
-
import { readFileSync as
|
|
15600
|
-
import { execSync as
|
|
15601
|
-
import
|
|
15752
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync14 } from "fs";
|
|
15753
|
+
import { execSync as execSync6 } from "child_process";
|
|
15754
|
+
import path21 from "path";
|
|
15602
15755
|
import os7 from "os";
|
|
15603
15756
|
function registerSession(entry) {
|
|
15604
|
-
const dir =
|
|
15757
|
+
const dir = path21.dirname(REGISTRY_PATH);
|
|
15605
15758
|
if (!existsSync14(dir)) {
|
|
15606
15759
|
mkdirSync6(dir, { recursive: true });
|
|
15607
15760
|
}
|
|
@@ -15616,7 +15769,7 @@ function registerSession(entry) {
|
|
|
15616
15769
|
}
|
|
15617
15770
|
function listSessions() {
|
|
15618
15771
|
try {
|
|
15619
|
-
const raw =
|
|
15772
|
+
const raw = readFileSync11(REGISTRY_PATH, "utf8");
|
|
15620
15773
|
return JSON.parse(raw);
|
|
15621
15774
|
} catch {
|
|
15622
15775
|
return [];
|
|
@@ -15627,7 +15780,7 @@ function pruneStaleSessions() {
|
|
|
15627
15780
|
if (sessions.length === 0) return 0;
|
|
15628
15781
|
let liveSessions = [];
|
|
15629
15782
|
try {
|
|
15630
|
-
liveSessions =
|
|
15783
|
+
liveSessions = execSync6("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
15631
15784
|
encoding: "utf8"
|
|
15632
15785
|
}).trim().split("\n").filter(Boolean);
|
|
15633
15786
|
} catch {
|
|
@@ -15645,14 +15798,14 @@ var REGISTRY_PATH;
|
|
|
15645
15798
|
var init_session_registry = __esm({
|
|
15646
15799
|
"src/lib/session-registry.ts"() {
|
|
15647
15800
|
"use strict";
|
|
15648
|
-
REGISTRY_PATH =
|
|
15801
|
+
REGISTRY_PATH = path21.join(os7.homedir(), ".exe-os", "session-registry.json");
|
|
15649
15802
|
}
|
|
15650
15803
|
});
|
|
15651
15804
|
|
|
15652
15805
|
// src/tui/views/CommandCenter.tsx
|
|
15653
15806
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
15654
15807
|
import TextInput from "ink-text-input";
|
|
15655
|
-
import
|
|
15808
|
+
import path22 from "path";
|
|
15656
15809
|
import { homedir as homedir3 } from "os";
|
|
15657
15810
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
15658
15811
|
function CommandCenterView({
|
|
@@ -15893,7 +16046,7 @@ function CommandCenterView({
|
|
|
15893
16046
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
15894
16047
|
projectName: p.projectName,
|
|
15895
16048
|
exeSession: p.exeSession,
|
|
15896
|
-
projectDir:
|
|
16049
|
+
projectDir: path22.join(homedir3(), p.projectName),
|
|
15897
16050
|
employeeCount: p.employees.length,
|
|
15898
16051
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
15899
16052
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -16463,13 +16616,13 @@ var init_task_router = __esm({
|
|
|
16463
16616
|
});
|
|
16464
16617
|
|
|
16465
16618
|
// src/lib/session-key.ts
|
|
16466
|
-
import { execSync as
|
|
16619
|
+
import { execSync as execSync7 } from "child_process";
|
|
16467
16620
|
function getSessionKey() {
|
|
16468
16621
|
if (_cached) return _cached;
|
|
16469
16622
|
let pid = process.ppid;
|
|
16470
16623
|
for (let i = 0; i < 10; i++) {
|
|
16471
16624
|
try {
|
|
16472
|
-
const info =
|
|
16625
|
+
const info = execSync7(`ps -p ${pid} -o ppid=,comm=`, {
|
|
16473
16626
|
encoding: "utf8",
|
|
16474
16627
|
timeout: 2e3
|
|
16475
16628
|
}).trim();
|
|
@@ -16613,14 +16766,14 @@ var init_transport = __esm({
|
|
|
16613
16766
|
});
|
|
16614
16767
|
|
|
16615
16768
|
// src/lib/cc-agent-support.ts
|
|
16616
|
-
import { execSync as
|
|
16769
|
+
import { execSync as execSync8 } from "child_process";
|
|
16617
16770
|
function _resetCcAgentSupportCache() {
|
|
16618
16771
|
_cachedSupport = null;
|
|
16619
16772
|
}
|
|
16620
16773
|
function claudeSupportsAgentFlag() {
|
|
16621
16774
|
if (_cachedSupport !== null) return _cachedSupport;
|
|
16622
16775
|
try {
|
|
16623
|
-
const helpOutput =
|
|
16776
|
+
const helpOutput = execSync8("claude --help 2>&1", {
|
|
16624
16777
|
encoding: "utf-8",
|
|
16625
16778
|
timeout: 5e3
|
|
16626
16779
|
});
|
|
@@ -16663,17 +16816,17 @@ var init_provider_table = __esm({
|
|
|
16663
16816
|
});
|
|
16664
16817
|
|
|
16665
16818
|
// src/lib/intercom-queue.ts
|
|
16666
|
-
import { readFileSync as
|
|
16667
|
-
import
|
|
16819
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, renameSync as renameSync4, existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
|
|
16820
|
+
import path23 from "path";
|
|
16668
16821
|
import os8 from "os";
|
|
16669
16822
|
function ensureDir2() {
|
|
16670
|
-
const dir =
|
|
16823
|
+
const dir = path23.dirname(QUEUE_PATH);
|
|
16671
16824
|
if (!existsSync15(dir)) mkdirSync7(dir, { recursive: true });
|
|
16672
16825
|
}
|
|
16673
16826
|
function readQueue() {
|
|
16674
16827
|
try {
|
|
16675
16828
|
if (!existsSync15(QUEUE_PATH)) return [];
|
|
16676
|
-
return JSON.parse(
|
|
16829
|
+
return JSON.parse(readFileSync12(QUEUE_PATH, "utf8"));
|
|
16677
16830
|
} catch {
|
|
16678
16831
|
return [];
|
|
16679
16832
|
}
|
|
@@ -16705,19 +16858,19 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
16705
16858
|
var init_intercom_queue = __esm({
|
|
16706
16859
|
"src/lib/intercom-queue.ts"() {
|
|
16707
16860
|
"use strict";
|
|
16708
|
-
QUEUE_PATH =
|
|
16861
|
+
QUEUE_PATH = path23.join(os8.homedir(), ".exe-os", "intercom-queue.json");
|
|
16709
16862
|
TTL_MS = 60 * 60 * 1e3;
|
|
16710
|
-
INTERCOM_LOG =
|
|
16863
|
+
INTERCOM_LOG = path23.join(os8.homedir(), ".exe-os", "intercom.log");
|
|
16711
16864
|
}
|
|
16712
16865
|
});
|
|
16713
16866
|
|
|
16714
16867
|
// src/lib/plan-limits.ts
|
|
16715
|
-
import { readFileSync as
|
|
16716
|
-
import
|
|
16868
|
+
import { readFileSync as readFileSync13, existsSync as existsSync16 } from "fs";
|
|
16869
|
+
import path24 from "path";
|
|
16717
16870
|
function getLicenseSync() {
|
|
16718
16871
|
try {
|
|
16719
16872
|
if (!existsSync16(CACHE_PATH2)) return freeLicense();
|
|
16720
|
-
const raw = JSON.parse(
|
|
16873
|
+
const raw = JSON.parse(readFileSync13(CACHE_PATH2, "utf8"));
|
|
16721
16874
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
16722
16875
|
const parts = raw.token.split(".");
|
|
16723
16876
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -16756,7 +16909,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
16756
16909
|
let count = 0;
|
|
16757
16910
|
try {
|
|
16758
16911
|
if (existsSync16(filePath)) {
|
|
16759
|
-
const raw =
|
|
16912
|
+
const raw = readFileSync13(filePath, "utf8");
|
|
16760
16913
|
const employees = JSON.parse(raw);
|
|
16761
16914
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
16762
16915
|
}
|
|
@@ -16785,16 +16938,16 @@ var init_plan_limits = __esm({
|
|
|
16785
16938
|
this.name = "PlanLimitError";
|
|
16786
16939
|
}
|
|
16787
16940
|
};
|
|
16788
|
-
CACHE_PATH2 =
|
|
16941
|
+
CACHE_PATH2 = path24.join(EXE_AI_DIR, "license-cache.json");
|
|
16789
16942
|
}
|
|
16790
16943
|
});
|
|
16791
16944
|
|
|
16792
16945
|
// src/lib/notifications.ts
|
|
16793
16946
|
import crypto4 from "crypto";
|
|
16794
|
-
import
|
|
16947
|
+
import path25 from "path";
|
|
16795
16948
|
import os9 from "os";
|
|
16796
16949
|
import {
|
|
16797
|
-
readFileSync as
|
|
16950
|
+
readFileSync as readFileSync14,
|
|
16798
16951
|
readdirSync as readdirSync3,
|
|
16799
16952
|
unlinkSync as unlinkSync5,
|
|
16800
16953
|
existsSync as existsSync17,
|
|
@@ -16877,10 +17030,10 @@ var init_session_kill_telemetry = __esm({
|
|
|
16877
17030
|
|
|
16878
17031
|
// src/lib/tasks-crud.ts
|
|
16879
17032
|
import crypto6 from "crypto";
|
|
16880
|
-
import
|
|
16881
|
-
import { execSync as
|
|
17033
|
+
import path26 from "path";
|
|
17034
|
+
import { execSync as execSync9 } from "child_process";
|
|
16882
17035
|
import { mkdir as mkdir6, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
16883
|
-
import { existsSync as existsSync18, readFileSync as
|
|
17036
|
+
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "fs";
|
|
16884
17037
|
async function writeCheckpoint(input) {
|
|
16885
17038
|
const client = getClient();
|
|
16886
17039
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -17010,8 +17163,8 @@ async function createTaskCore(input) {
|
|
|
17010
17163
|
}
|
|
17011
17164
|
if (input.baseDir) {
|
|
17012
17165
|
try {
|
|
17013
|
-
await mkdir6(
|
|
17014
|
-
await mkdir6(
|
|
17166
|
+
await mkdir6(path26.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
17167
|
+
await mkdir6(path26.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
17015
17168
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
17016
17169
|
await ensureGitignoreExe(input.baseDir);
|
|
17017
17170
|
} catch {
|
|
@@ -17127,12 +17280,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
17127
17280
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
17128
17281
|
try {
|
|
17129
17282
|
const since = new Date(taskCreatedAt).toISOString();
|
|
17130
|
-
const branch =
|
|
17283
|
+
const branch = execSync9(
|
|
17131
17284
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
17132
17285
|
{ encoding: "utf8", timeout: 3e3 }
|
|
17133
17286
|
).trim();
|
|
17134
17287
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
17135
|
-
const commitCount =
|
|
17288
|
+
const commitCount = execSync9(
|
|
17136
17289
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
17137
17290
|
{ encoding: "utf8", timeout: 5e3 }
|
|
17138
17291
|
).trim();
|
|
@@ -17235,7 +17388,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
17235
17388
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
17236
17389
|
}
|
|
17237
17390
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
17238
|
-
const archPath =
|
|
17391
|
+
const archPath = path26.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
17239
17392
|
try {
|
|
17240
17393
|
if (existsSync18(archPath)) return;
|
|
17241
17394
|
const template = [
|
|
@@ -17270,10 +17423,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
17270
17423
|
}
|
|
17271
17424
|
}
|
|
17272
17425
|
async function ensureGitignoreExe(baseDir) {
|
|
17273
|
-
const gitignorePath =
|
|
17426
|
+
const gitignorePath = path26.join(baseDir, ".gitignore");
|
|
17274
17427
|
try {
|
|
17275
17428
|
if (existsSync18(gitignorePath)) {
|
|
17276
|
-
const content =
|
|
17429
|
+
const content = readFileSync15(gitignorePath, "utf-8");
|
|
17277
17430
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
17278
17431
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
17279
17432
|
} else {
|
|
@@ -17293,7 +17446,7 @@ var init_tasks_crud = __esm({
|
|
|
17293
17446
|
});
|
|
17294
17447
|
|
|
17295
17448
|
// src/lib/tasks-review.ts
|
|
17296
|
-
import
|
|
17449
|
+
import path27 from "path";
|
|
17297
17450
|
import { existsSync as existsSync19, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
|
|
17298
17451
|
async function countPendingReviews() {
|
|
17299
17452
|
const client = getClient();
|
|
@@ -17312,8 +17465,18 @@ async function countNewPendingReviewsSince(sinceIso) {
|
|
|
17312
17465
|
});
|
|
17313
17466
|
return Number(result.rows[0]?.cnt) || 0;
|
|
17314
17467
|
}
|
|
17315
|
-
async function listPendingReviews(limit) {
|
|
17468
|
+
async function listPendingReviews(limit, sessionScope) {
|
|
17316
17469
|
const client = getClient();
|
|
17470
|
+
if (sessionScope) {
|
|
17471
|
+
const result2 = await client.execute({
|
|
17472
|
+
sql: `SELECT title, assigned_to, project_name FROM tasks
|
|
17473
|
+
WHERE status = 'needs_review'
|
|
17474
|
+
AND (session_scope = ? OR session_scope IS NULL)
|
|
17475
|
+
ORDER BY priority ASC, created_at DESC LIMIT ?`,
|
|
17476
|
+
args: [sessionScope, limit]
|
|
17477
|
+
});
|
|
17478
|
+
return result2.rows;
|
|
17479
|
+
}
|
|
17317
17480
|
const result = await client.execute({
|
|
17318
17481
|
sql: `SELECT title, assigned_to, project_name FROM tasks
|
|
17319
17482
|
WHERE status = 'needs_review'
|
|
@@ -17442,11 +17605,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
17442
17605
|
);
|
|
17443
17606
|
}
|
|
17444
17607
|
try {
|
|
17445
|
-
const cacheDir =
|
|
17608
|
+
const cacheDir = path27.join(EXE_AI_DIR, "session-cache");
|
|
17446
17609
|
if (existsSync19(cacheDir)) {
|
|
17447
17610
|
for (const f of readdirSync4(cacheDir)) {
|
|
17448
17611
|
if (f.startsWith("review-notified-")) {
|
|
17449
|
-
unlinkSync6(
|
|
17612
|
+
unlinkSync6(path27.join(cacheDir, f));
|
|
17450
17613
|
}
|
|
17451
17614
|
}
|
|
17452
17615
|
}
|
|
@@ -17468,7 +17631,7 @@ var init_tasks_review = __esm({
|
|
|
17468
17631
|
});
|
|
17469
17632
|
|
|
17470
17633
|
// src/lib/tasks-chain.ts
|
|
17471
|
-
import
|
|
17634
|
+
import path28 from "path";
|
|
17472
17635
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
17473
17636
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
17474
17637
|
const client = getClient();
|
|
@@ -17484,7 +17647,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
17484
17647
|
});
|
|
17485
17648
|
for (const ur of unblockedRows.rows) {
|
|
17486
17649
|
try {
|
|
17487
|
-
const ubFile =
|
|
17650
|
+
const ubFile = path28.join(baseDir, String(ur.task_file));
|
|
17488
17651
|
let ubContent = await readFile5(ubFile, "utf-8");
|
|
17489
17652
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
17490
17653
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -17549,34 +17712,34 @@ var init_tasks_chain = __esm({
|
|
|
17549
17712
|
});
|
|
17550
17713
|
|
|
17551
17714
|
// src/lib/project-name.ts
|
|
17552
|
-
import { execSync as
|
|
17553
|
-
import
|
|
17715
|
+
import { execSync as execSync10 } from "child_process";
|
|
17716
|
+
import path29 from "path";
|
|
17554
17717
|
function getProjectName(cwd2) {
|
|
17555
17718
|
const dir = cwd2 ?? process.cwd();
|
|
17556
17719
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
17557
17720
|
try {
|
|
17558
17721
|
let repoRoot;
|
|
17559
17722
|
try {
|
|
17560
|
-
const gitCommonDir =
|
|
17723
|
+
const gitCommonDir = execSync10("git rev-parse --path-format=absolute --git-common-dir", {
|
|
17561
17724
|
cwd: dir,
|
|
17562
17725
|
encoding: "utf8",
|
|
17563
17726
|
timeout: 2e3,
|
|
17564
17727
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17565
17728
|
}).trim();
|
|
17566
|
-
repoRoot =
|
|
17729
|
+
repoRoot = path29.dirname(gitCommonDir);
|
|
17567
17730
|
} catch {
|
|
17568
|
-
repoRoot =
|
|
17731
|
+
repoRoot = execSync10("git rev-parse --show-toplevel", {
|
|
17569
17732
|
cwd: dir,
|
|
17570
17733
|
encoding: "utf8",
|
|
17571
17734
|
timeout: 2e3,
|
|
17572
17735
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17573
17736
|
}).trim();
|
|
17574
17737
|
}
|
|
17575
|
-
_cached2 =
|
|
17738
|
+
_cached2 = path29.basename(repoRoot);
|
|
17576
17739
|
_cachedCwd = dir;
|
|
17577
17740
|
return _cached2;
|
|
17578
17741
|
} catch {
|
|
17579
|
-
_cached2 =
|
|
17742
|
+
_cached2 = path29.basename(dir);
|
|
17580
17743
|
_cachedCwd = dir;
|
|
17581
17744
|
return _cached2;
|
|
17582
17745
|
}
|
|
@@ -18048,7 +18211,7 @@ __export(tasks_exports, {
|
|
|
18048
18211
|
updateTaskStatus: () => updateTaskStatus,
|
|
18049
18212
|
writeCheckpoint: () => writeCheckpoint
|
|
18050
18213
|
});
|
|
18051
|
-
import
|
|
18214
|
+
import path30 from "path";
|
|
18052
18215
|
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
|
|
18053
18216
|
async function createTask(input) {
|
|
18054
18217
|
const result = await createTaskCore(input);
|
|
@@ -18068,8 +18231,8 @@ async function updateTask(input) {
|
|
|
18068
18231
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
18069
18232
|
try {
|
|
18070
18233
|
const agent = String(row.assigned_to);
|
|
18071
|
-
const cacheDir =
|
|
18072
|
-
const cachePath =
|
|
18234
|
+
const cacheDir = path30.join(EXE_AI_DIR, "session-cache");
|
|
18235
|
+
const cachePath = path30.join(cacheDir, `current-task-${agent}.json`);
|
|
18073
18236
|
if (input.status === "in_progress") {
|
|
18074
18237
|
mkdirSync8(cacheDir, { recursive: true });
|
|
18075
18238
|
writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
@@ -18512,14 +18675,14 @@ __export(tmux_routing_exports, {
|
|
|
18512
18675
|
spawnEmployee: () => spawnEmployee,
|
|
18513
18676
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
18514
18677
|
});
|
|
18515
|
-
import { execFileSync as execFileSync3, execSync as
|
|
18516
|
-
import { readFileSync as
|
|
18517
|
-
import
|
|
18678
|
+
import { execFileSync as execFileSync3, execSync as execSync11 } from "child_process";
|
|
18679
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync20, appendFileSync } from "fs";
|
|
18680
|
+
import path31 from "path";
|
|
18518
18681
|
import os10 from "os";
|
|
18519
18682
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
18520
18683
|
import { unlinkSync as unlinkSync8 } from "fs";
|
|
18521
18684
|
function spawnLockPath(sessionName) {
|
|
18522
|
-
return
|
|
18685
|
+
return path31.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
18523
18686
|
}
|
|
18524
18687
|
function isProcessAlive(pid) {
|
|
18525
18688
|
try {
|
|
@@ -18536,7 +18699,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
18536
18699
|
const lockFile = spawnLockPath(sessionName);
|
|
18537
18700
|
if (existsSync20(lockFile)) {
|
|
18538
18701
|
try {
|
|
18539
|
-
const lock = JSON.parse(
|
|
18702
|
+
const lock = JSON.parse(readFileSync16(lockFile, "utf8"));
|
|
18540
18703
|
const age = Date.now() - lock.timestamp;
|
|
18541
18704
|
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
18542
18705
|
return false;
|
|
@@ -18556,8 +18719,8 @@ function releaseSpawnLock2(sessionName) {
|
|
|
18556
18719
|
function resolveBehaviorsExporterScript() {
|
|
18557
18720
|
try {
|
|
18558
18721
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
18559
|
-
const scriptPath =
|
|
18560
|
-
|
|
18722
|
+
const scriptPath = path31.join(
|
|
18723
|
+
path31.dirname(thisFile),
|
|
18561
18724
|
"..",
|
|
18562
18725
|
"bin",
|
|
18563
18726
|
"exe-export-behaviors.js"
|
|
@@ -18627,7 +18790,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
18627
18790
|
mkdirSync9(SESSION_CACHE, { recursive: true });
|
|
18628
18791
|
}
|
|
18629
18792
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
18630
|
-
const filePath =
|
|
18793
|
+
const filePath = path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
18631
18794
|
writeFileSync8(filePath, JSON.stringify({
|
|
18632
18795
|
parentExe: rootExe,
|
|
18633
18796
|
dispatchedBy: dispatchedBy || rootExe,
|
|
@@ -18636,7 +18799,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
18636
18799
|
}
|
|
18637
18800
|
function getParentExe(sessionKey) {
|
|
18638
18801
|
try {
|
|
18639
|
-
const data = JSON.parse(
|
|
18802
|
+
const data = JSON.parse(readFileSync16(path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
18640
18803
|
return data.parentExe || null;
|
|
18641
18804
|
} catch {
|
|
18642
18805
|
return null;
|
|
@@ -18644,8 +18807,8 @@ function getParentExe(sessionKey) {
|
|
|
18644
18807
|
}
|
|
18645
18808
|
function getDispatchedBy(sessionKey) {
|
|
18646
18809
|
try {
|
|
18647
|
-
const data = JSON.parse(
|
|
18648
|
-
|
|
18810
|
+
const data = JSON.parse(readFileSync16(
|
|
18811
|
+
path31.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
18649
18812
|
"utf8"
|
|
18650
18813
|
));
|
|
18651
18814
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -18707,7 +18870,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
18707
18870
|
function readDebounceState() {
|
|
18708
18871
|
try {
|
|
18709
18872
|
if (!existsSync20(DEBOUNCE_FILE)) return {};
|
|
18710
|
-
return JSON.parse(
|
|
18873
|
+
return JSON.parse(readFileSync16(DEBOUNCE_FILE, "utf8"));
|
|
18711
18874
|
} catch {
|
|
18712
18875
|
return {};
|
|
18713
18876
|
}
|
|
@@ -18904,8 +19067,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18904
19067
|
const transport = getTransport();
|
|
18905
19068
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
18906
19069
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
18907
|
-
const logDir =
|
|
18908
|
-
const logFile =
|
|
19070
|
+
const logDir = path31.join(os10.homedir(), ".exe-os", "session-logs");
|
|
19071
|
+
const logFile = path31.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
18909
19072
|
if (!existsSync20(logDir)) {
|
|
18910
19073
|
mkdirSync9(logDir, { recursive: true });
|
|
18911
19074
|
}
|
|
@@ -18913,17 +19076,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18913
19076
|
let cleanupSuffix = "";
|
|
18914
19077
|
try {
|
|
18915
19078
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
18916
|
-
const cleanupScript =
|
|
19079
|
+
const cleanupScript = path31.join(path31.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
18917
19080
|
if (existsSync20(cleanupScript)) {
|
|
18918
19081
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
18919
19082
|
}
|
|
18920
19083
|
} catch {
|
|
18921
19084
|
}
|
|
18922
19085
|
try {
|
|
18923
|
-
const claudeJsonPath =
|
|
19086
|
+
const claudeJsonPath = path31.join(os10.homedir(), ".claude.json");
|
|
18924
19087
|
let claudeJson = {};
|
|
18925
19088
|
try {
|
|
18926
|
-
claudeJson = JSON.parse(
|
|
19089
|
+
claudeJson = JSON.parse(readFileSync16(claudeJsonPath, "utf8"));
|
|
18927
19090
|
} catch {
|
|
18928
19091
|
}
|
|
18929
19092
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -18935,13 +19098,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18935
19098
|
} catch {
|
|
18936
19099
|
}
|
|
18937
19100
|
try {
|
|
18938
|
-
const settingsDir =
|
|
19101
|
+
const settingsDir = path31.join(os10.homedir(), ".claude", "projects");
|
|
18939
19102
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
18940
|
-
const projSettingsDir =
|
|
18941
|
-
const settingsPath =
|
|
19103
|
+
const projSettingsDir = path31.join(settingsDir, normalizedKey);
|
|
19104
|
+
const settingsPath = path31.join(projSettingsDir, "settings.json");
|
|
18942
19105
|
let settings = {};
|
|
18943
19106
|
try {
|
|
18944
|
-
settings = JSON.parse(
|
|
19107
|
+
settings = JSON.parse(readFileSync16(settingsPath, "utf8"));
|
|
18945
19108
|
} catch {
|
|
18946
19109
|
}
|
|
18947
19110
|
const perms = settings.permissions ?? {};
|
|
@@ -18982,7 +19145,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18982
19145
|
let behaviorsFlag = "";
|
|
18983
19146
|
let legacyFallbackWarned = false;
|
|
18984
19147
|
if (!useExeAgent && !useBinSymlink) {
|
|
18985
|
-
const identityPath2 =
|
|
19148
|
+
const identityPath2 = path31.join(
|
|
18986
19149
|
os10.homedir(),
|
|
18987
19150
|
".exe-os",
|
|
18988
19151
|
"identity",
|
|
@@ -18998,7 +19161,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
18998
19161
|
}
|
|
18999
19162
|
const behaviorsFile = exportBehaviorsSync(
|
|
19000
19163
|
employeeName,
|
|
19001
|
-
|
|
19164
|
+
path31.basename(spawnCwd),
|
|
19002
19165
|
sessionName
|
|
19003
19166
|
);
|
|
19004
19167
|
if (behaviorsFile) {
|
|
@@ -19013,9 +19176,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
19013
19176
|
}
|
|
19014
19177
|
let sessionContextFlag = "";
|
|
19015
19178
|
try {
|
|
19016
|
-
const ctxDir =
|
|
19179
|
+
const ctxDir = path31.join(os10.homedir(), ".exe-os", "session-cache");
|
|
19017
19180
|
mkdirSync9(ctxDir, { recursive: true });
|
|
19018
|
-
const ctxFile =
|
|
19181
|
+
const ctxFile = path31.join(ctxDir, `session-context-${sessionName}.md`);
|
|
19019
19182
|
const ctxContent = [
|
|
19020
19183
|
`## Session Context`,
|
|
19021
19184
|
`You are running in tmux session: ${sessionName}.`,
|
|
@@ -19060,7 +19223,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
19060
19223
|
transport.pipeLog(sessionName, logFile);
|
|
19061
19224
|
try {
|
|
19062
19225
|
const mySession = getMySession();
|
|
19063
|
-
const dispatchInfo =
|
|
19226
|
+
const dispatchInfo = path31.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
19064
19227
|
writeFileSync8(dispatchInfo, JSON.stringify({
|
|
19065
19228
|
dispatchedBy: mySession,
|
|
19066
19229
|
rootExe: exeSession,
|
|
@@ -19072,7 +19235,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
19072
19235
|
let booted = false;
|
|
19073
19236
|
for (let i = 0; i < 30; i++) {
|
|
19074
19237
|
try {
|
|
19075
|
-
|
|
19238
|
+
execSync11("sleep 0.5");
|
|
19076
19239
|
} catch {
|
|
19077
19240
|
}
|
|
19078
19241
|
try {
|
|
@@ -19124,14 +19287,14 @@ var init_tmux_routing = __esm({
|
|
|
19124
19287
|
init_provider_table();
|
|
19125
19288
|
init_intercom_queue();
|
|
19126
19289
|
init_plan_limits();
|
|
19127
|
-
SPAWN_LOCK_DIR =
|
|
19128
|
-
SESSION_CACHE =
|
|
19290
|
+
SPAWN_LOCK_DIR = path31.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
19291
|
+
SESSION_CACHE = path31.join(os10.homedir(), ".exe-os", "session-cache");
|
|
19129
19292
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
19130
19293
|
VALID_SESSION_NAME = /^[a-z]+-exe\d+$|^[a-z]+\d+-exe\d+$/;
|
|
19131
19294
|
VERIFY_PANE_LINES = 200;
|
|
19132
19295
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
19133
|
-
INTERCOM_LOG2 =
|
|
19134
|
-
DEBOUNCE_FILE =
|
|
19296
|
+
INTERCOM_LOG2 = path31.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
19297
|
+
DEBOUNCE_FILE = path31.join(SESSION_CACHE, "intercom-debounce.json");
|
|
19135
19298
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
19136
19299
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
19137
19300
|
}
|
|
@@ -19519,7 +19682,7 @@ var init_useOrchestrator = __esm({
|
|
|
19519
19682
|
|
|
19520
19683
|
// src/tui/views/Sessions.tsx
|
|
19521
19684
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
19522
|
-
import
|
|
19685
|
+
import path32 from "path";
|
|
19523
19686
|
import { homedir as homedir4 } from "os";
|
|
19524
19687
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
19525
19688
|
function SessionsView({
|
|
@@ -19554,7 +19717,7 @@ function SessionsView({
|
|
|
19554
19717
|
if (demo) {
|
|
19555
19718
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
19556
19719
|
...p,
|
|
19557
|
-
projectDir:
|
|
19720
|
+
projectDir: path32.join(homedir4(), p.projectName),
|
|
19558
19721
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
19559
19722
|
})));
|
|
19560
19723
|
return;
|
|
@@ -21147,10 +21310,10 @@ var init_Gateway = __esm({
|
|
|
21147
21310
|
});
|
|
21148
21311
|
|
|
21149
21312
|
// src/tui/utils/agent-status.ts
|
|
21150
|
-
import { execSync as
|
|
21313
|
+
import { execSync as execSync12 } from "child_process";
|
|
21151
21314
|
function getAgentStatus(agentId) {
|
|
21152
21315
|
try {
|
|
21153
|
-
const sessions =
|
|
21316
|
+
const sessions = execSync12("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
21154
21317
|
encoding: "utf8",
|
|
21155
21318
|
timeout: 2e3
|
|
21156
21319
|
}).trim().split("\n");
|
|
@@ -21161,7 +21324,7 @@ function getAgentStatus(agentId) {
|
|
|
21161
21324
|
return /^\d?-/.test(suffix) || /^\d+$/.test(suffix);
|
|
21162
21325
|
});
|
|
21163
21326
|
if (!agentSession) return { label: "offline", color: "gray" };
|
|
21164
|
-
const pane =
|
|
21327
|
+
const pane = execSync12(`tmux capture-pane -t "${agentSession}" -p 2>/dev/null | tail -3`, {
|
|
21165
21328
|
encoding: "utf8",
|
|
21166
21329
|
timeout: 2e3
|
|
21167
21330
|
});
|
|
@@ -22522,8 +22685,6 @@ function App2() {
|
|
|
22522
22685
|
setSection(SECTIONS[tabIdx].key);
|
|
22523
22686
|
setFocus("sidebar");
|
|
22524
22687
|
}
|
|
22525
|
-
} else {
|
|
22526
|
-
setFocus("content");
|
|
22527
22688
|
}
|
|
22528
22689
|
}, []));
|
|
22529
22690
|
const [focus, setFocus] = useState16("sidebar");
|
|
@@ -22736,100 +22897,36 @@ var init_App2 = __esm({
|
|
|
22736
22897
|
}
|
|
22737
22898
|
}
|
|
22738
22899
|
render_default(/* @__PURE__ */ jsx17(App2, {}));
|
|
22739
|
-
|
|
22740
|
-
|
|
22741
|
-
|
|
22742
|
-
// src/lib/update-check.ts
|
|
22743
|
-
import { execSync as execSync11 } from "child_process";
|
|
22744
|
-
import { readFileSync as readFileSync16 } from "fs";
|
|
22745
|
-
import path32 from "path";
|
|
22746
|
-
function getLocalVersion(packageRoot) {
|
|
22747
|
-
const pkgPath = path32.join(packageRoot, "package.json");
|
|
22748
|
-
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
22749
|
-
return pkg.version;
|
|
22750
|
-
}
|
|
22751
|
-
function getRemoteVersion() {
|
|
22752
|
-
try {
|
|
22753
|
-
const output = execSync11("npm view @askexenow/exe-os version", {
|
|
22754
|
-
encoding: "utf-8",
|
|
22755
|
-
timeout: 15e3,
|
|
22756
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
22757
|
-
});
|
|
22758
|
-
return output.trim();
|
|
22759
|
-
} catch {
|
|
22760
|
-
return null;
|
|
22761
|
-
}
|
|
22762
|
-
}
|
|
22763
|
-
function checkForUpdate(packageRoot) {
|
|
22764
|
-
const localVersion = getLocalVersion(packageRoot);
|
|
22765
|
-
const remoteVersion = getRemoteVersion();
|
|
22766
|
-
if (!remoteVersion) {
|
|
22767
|
-
return {
|
|
22768
|
-
updateAvailable: false,
|
|
22769
|
-
localVersion,
|
|
22770
|
-
error: "Could not reach npm registry or package not published yet"
|
|
22771
|
-
};
|
|
22772
|
-
}
|
|
22773
|
-
if (remoteVersion === localVersion) {
|
|
22774
|
-
return { updateAvailable: false, localVersion, remoteVersion };
|
|
22775
|
-
}
|
|
22776
|
-
return { updateAvailable: true, localVersion, remoteVersion };
|
|
22777
|
-
}
|
|
22778
|
-
var init_update_check = __esm({
|
|
22779
|
-
"src/lib/update-check.ts"() {
|
|
22780
|
-
"use strict";
|
|
22781
|
-
}
|
|
22782
|
-
});
|
|
22783
|
-
|
|
22784
|
-
// src/bin/update.ts
|
|
22785
|
-
var update_exports = {};
|
|
22786
|
-
__export(update_exports, {
|
|
22787
|
-
checkForUpdate: () => checkForUpdate,
|
|
22788
|
-
getLocalVersion: () => getLocalVersion,
|
|
22789
|
-
getRemoteVersion: () => getRemoteVersion
|
|
22790
|
-
});
|
|
22791
|
-
import { execSync as execSync12 } from "child_process";
|
|
22792
|
-
import { createInterface as createInterface3 } from "readline";
|
|
22793
|
-
var init_update = __esm({
|
|
22794
|
-
async "src/bin/update.ts"() {
|
|
22795
|
-
"use strict";
|
|
22796
|
-
init_is_main();
|
|
22797
|
-
init_update_check();
|
|
22798
|
-
init_update_check();
|
|
22799
|
-
if (isMainModule(import.meta.url)) {
|
|
22800
|
-
const packageRoot = new URL("../..", import.meta.url).pathname;
|
|
22801
|
-
const result = checkForUpdate(packageRoot);
|
|
22802
|
-
if (result.error) {
|
|
22803
|
-
console.error(result.error);
|
|
22804
|
-
process.exit(0);
|
|
22805
|
-
}
|
|
22806
|
-
if (!result.updateAvailable) {
|
|
22807
|
-
console.log(`exe-os is up to date (v${result.localVersion})`);
|
|
22808
|
-
process.exit(0);
|
|
22809
|
-
}
|
|
22810
|
-
console.log(
|
|
22811
|
-
`Update available: v${result.localVersion} -> v${result.remoteVersion}`
|
|
22812
|
-
);
|
|
22813
|
-
console.log("");
|
|
22814
|
-
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
22815
|
-
const answer = await new Promise((resolve) => {
|
|
22816
|
-
rl.question("Install update? (y/N) ", resolve);
|
|
22817
|
-
});
|
|
22818
|
-
rl.close();
|
|
22819
|
-
if (answer.toLowerCase() === "y") {
|
|
22820
|
-
console.log("Updating...");
|
|
22900
|
+
{
|
|
22901
|
+
const CLEANUP_SEQ = "\x1B[?1006l\x1B[?1002l\x1B[?1000l\x1B[?25h\x1B[?1049l";
|
|
22902
|
+
const terminalCleanup = () => {
|
|
22821
22903
|
try {
|
|
22822
|
-
|
|
22823
|
-
console.log("Update complete!");
|
|
22904
|
+
process.stdout.write(CLEANUP_SEQ);
|
|
22824
22905
|
} catch {
|
|
22825
|
-
console.error(
|
|
22826
|
-
"Update failed. Try running manually: npx exe-os --global"
|
|
22827
|
-
);
|
|
22828
|
-
process.exit(1);
|
|
22829
22906
|
}
|
|
22830
|
-
}
|
|
22831
|
-
|
|
22907
|
+
};
|
|
22908
|
+
process.on("exit", terminalCleanup);
|
|
22909
|
+
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
22910
|
+
process.on(sig, () => {
|
|
22911
|
+
terminalCleanup();
|
|
22912
|
+
process.removeAllListeners(sig);
|
|
22913
|
+
process.kill(process.pid, sig);
|
|
22914
|
+
});
|
|
22832
22915
|
}
|
|
22916
|
+
process.on("uncaughtException", (err) => {
|
|
22917
|
+
terminalCleanup();
|
|
22918
|
+
process.stderr.write(`
|
|
22919
|
+
${err.stack || err.message}
|
|
22920
|
+
`);
|
|
22921
|
+
process.exit(1);
|
|
22922
|
+
});
|
|
22923
|
+
process.on("unhandledRejection", (reason) => {
|
|
22924
|
+
terminalCleanup();
|
|
22925
|
+
process.stderr.write(`
|
|
22926
|
+
Unhandled rejection: ${reason}
|
|
22927
|
+
`);
|
|
22928
|
+
process.exit(1);
|
|
22929
|
+
});
|
|
22833
22930
|
}
|
|
22834
22931
|
}
|
|
22835
22932
|
});
|
|
@@ -22892,6 +22989,9 @@ if (args.includes("--global")) {
|
|
|
22892
22989
|
} else if (args[0] === "setup" || args[0] === "-setup" || args[0] === "--setup") {
|
|
22893
22990
|
const { runSetupWizard: runSetupWizard2 } = await Promise.resolve().then(() => (init_setup_wizard(), setup_wizard_exports));
|
|
22894
22991
|
await runSetupWizard2({ skipModel: args.includes("--skip-model") });
|
|
22992
|
+
} else if (args[0] === "update") {
|
|
22993
|
+
const { runUpdate: runUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
22994
|
+
await runUpdate2(args.slice(1));
|
|
22895
22995
|
} else {
|
|
22896
22996
|
checkForUpdateOnBoot().catch(() => {
|
|
22897
22997
|
});
|
|
@@ -23217,7 +23317,7 @@ async function checkForUpdateOnBoot() {
|
|
|
23217
23317
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
23218
23318
|
const config = await loadConfig2();
|
|
23219
23319
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
23220
|
-
const { checkForUpdate: checkForUpdate2 } = await
|
|
23320
|
+
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
23221
23321
|
const packageRoot = path33.resolve(
|
|
23222
23322
|
new URL("../..", import.meta.url).pathname
|
|
23223
23323
|
);
|