@askexenow/exe-os 0.8.108 → 0.8.109
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 +134 -0
- package/dist/bin/exe-new-employee.js +134 -0
- package/dist/bin/install.js +133 -0
- package/dist/lib/exe-daemon.js +21 -22
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -607,6 +607,7 @@ var init_preferences = __esm({
|
|
|
607
607
|
// src/adapters/claude/installer.ts
|
|
608
608
|
var installer_exports = {};
|
|
609
609
|
__export(installer_exports, {
|
|
610
|
+
cleanOldShellFunctions: () => cleanOldShellFunctions,
|
|
610
611
|
copySlashCommands: () => copySlashCommands,
|
|
611
612
|
installStatusLine: () => installStatusLine,
|
|
612
613
|
mergeHooks: () => mergeHooks,
|
|
@@ -1015,6 +1016,132 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1015
1016
|
await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1016
1017
|
return { added, skipped };
|
|
1017
1018
|
}
|
|
1019
|
+
async function cleanOldShellFunctions(homeDir = os5.homedir()) {
|
|
1020
|
+
const rosterPath = path5.join(homeDir, ".exe-os", "exe-employees.json");
|
|
1021
|
+
if (!existsSync5(rosterPath)) return 0;
|
|
1022
|
+
let employees;
|
|
1023
|
+
try {
|
|
1024
|
+
employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
|
|
1025
|
+
} catch {
|
|
1026
|
+
return 0;
|
|
1027
|
+
}
|
|
1028
|
+
if (employees.length === 0) return 0;
|
|
1029
|
+
const names = employees.map((e) => e.name);
|
|
1030
|
+
const funcPatterns = names.map((n) => {
|
|
1031
|
+
const funcDef = new RegExp(`^\\s*(function\\s+)?${escapeRegExp(n)}\\d+\\s*\\(\\)`, "m");
|
|
1032
|
+
const forLoop = new RegExp(`${escapeRegExp(n)}\\$\\{?[a-zA-Z_][a-zA-Z0-9_]*\\}?`, "m");
|
|
1033
|
+
return { name: n, funcDef, forLoop };
|
|
1034
|
+
});
|
|
1035
|
+
const rcFiles = [
|
|
1036
|
+
path5.join(homeDir, ".zshrc"),
|
|
1037
|
+
path5.join(homeDir, ".bashrc")
|
|
1038
|
+
];
|
|
1039
|
+
const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
|
|
1040
|
+
let totalRemoved = 0;
|
|
1041
|
+
for (const rcPath of rcFiles) {
|
|
1042
|
+
if (!existsSync5(rcPath)) continue;
|
|
1043
|
+
let content;
|
|
1044
|
+
try {
|
|
1045
|
+
content = await readFile3(rcPath, "utf-8");
|
|
1046
|
+
} catch {
|
|
1047
|
+
continue;
|
|
1048
|
+
}
|
|
1049
|
+
if (content.includes(REMOVED_MARKER)) continue;
|
|
1050
|
+
const lines = content.split("\n");
|
|
1051
|
+
let changed = false;
|
|
1052
|
+
let inForLoop = false;
|
|
1053
|
+
let forLoopMatchesEmployee = false;
|
|
1054
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1055
|
+
const line = lines[i];
|
|
1056
|
+
const trimmed = line.trim();
|
|
1057
|
+
if (trimmed.startsWith("#")) continue;
|
|
1058
|
+
if (/^\s*for\s+/.test(trimmed)) {
|
|
1059
|
+
inForLoop = true;
|
|
1060
|
+
forLoopMatchesEmployee = false;
|
|
1061
|
+
for (const { forLoop } of funcPatterns) {
|
|
1062
|
+
if (forLoop.test(trimmed)) {
|
|
1063
|
+
forLoopMatchesEmployee = true;
|
|
1064
|
+
break;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
if (forLoopMatchesEmployee) {
|
|
1068
|
+
lines[i] = `${REMOVED_MARKER}
|
|
1069
|
+
# ${line}`;
|
|
1070
|
+
changed = true;
|
|
1071
|
+
totalRemoved++;
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
if (inForLoop) {
|
|
1076
|
+
if (!forLoopMatchesEmployee) {
|
|
1077
|
+
for (const { forLoop } of funcPatterns) {
|
|
1078
|
+
if (forLoop.test(trimmed)) {
|
|
1079
|
+
forLoopMatchesEmployee = true;
|
|
1080
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1081
|
+
if (/^\s*for\s+/.test(lines[j].replace(/^#\s*/, ""))) {
|
|
1082
|
+
if (!lines[j].startsWith("#")) {
|
|
1083
|
+
lines[j] = `${REMOVED_MARKER}
|
|
1084
|
+
# ${lines[j]}`;
|
|
1085
|
+
totalRemoved++;
|
|
1086
|
+
}
|
|
1087
|
+
break;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
if (forLoopMatchesEmployee && !trimmed.startsWith("#")) {
|
|
1095
|
+
lines[i] = `# ${line}`;
|
|
1096
|
+
changed = true;
|
|
1097
|
+
totalRemoved++;
|
|
1098
|
+
}
|
|
1099
|
+
if (trimmed === "done" || trimmed.startsWith("done;") || trimmed.startsWith("done ")) {
|
|
1100
|
+
inForLoop = false;
|
|
1101
|
+
forLoopMatchesEmployee = false;
|
|
1102
|
+
}
|
|
1103
|
+
continue;
|
|
1104
|
+
}
|
|
1105
|
+
for (const { funcDef } of funcPatterns) {
|
|
1106
|
+
if (funcDef.test(trimmed)) {
|
|
1107
|
+
lines[i] = `${REMOVED_MARKER}
|
|
1108
|
+
# ${line}`;
|
|
1109
|
+
changed = true;
|
|
1110
|
+
totalRemoved++;
|
|
1111
|
+
let braceDepth = 0;
|
|
1112
|
+
const hasBrace = trimmed.includes("{");
|
|
1113
|
+
if (hasBrace) braceDepth = 1;
|
|
1114
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
1115
|
+
const bodyLine = lines[j].trim();
|
|
1116
|
+
if (!hasBrace && braceDepth === 0) {
|
|
1117
|
+
if (bodyLine === "{") {
|
|
1118
|
+
braceDepth = 1;
|
|
1119
|
+
lines[j] = `# ${lines[j]}`;
|
|
1120
|
+
totalRemoved++;
|
|
1121
|
+
continue;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
if (braceDepth > 0) {
|
|
1125
|
+
braceDepth += (bodyLine.match(/{/g) ?? []).length;
|
|
1126
|
+
braceDepth -= (bodyLine.match(/}/g) ?? []).length;
|
|
1127
|
+
lines[j] = `# ${lines[j]}`;
|
|
1128
|
+
totalRemoved++;
|
|
1129
|
+
if (braceDepth <= 0) break;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
if (changed) {
|
|
1137
|
+
await writeFile3(rcPath, lines.join("\n"));
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return totalRemoved;
|
|
1141
|
+
}
|
|
1142
|
+
function escapeRegExp(s) {
|
|
1143
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1144
|
+
}
|
|
1018
1145
|
async function injectOrchestrationRules(homeDir) {
|
|
1019
1146
|
const claudeDir = path5.join(homeDir, ".claude");
|
|
1020
1147
|
const claudeMdPath = path5.join(claudeDir, "CLAUDE.md");
|
|
@@ -1117,6 +1244,13 @@ async function runInstaller(homeDir) {
|
|
|
1117
1244
|
`Status line: ${statusLineResult}
|
|
1118
1245
|
`
|
|
1119
1246
|
);
|
|
1247
|
+
const shellFuncsCleaned = await cleanOldShellFunctions(resolvedHome);
|
|
1248
|
+
if (shellFuncsCleaned > 0) {
|
|
1249
|
+
process.stderr.write(
|
|
1250
|
+
`Shell cleanup: removed ${shellFuncsCleaned} old shell function(s) that were shadowing exe-os wrappers
|
|
1251
|
+
`
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1120
1254
|
process.stderr.write(`
|
|
1121
1255
|
exe-os installed successfully.
|
|
1122
1256
|
`);
|
|
@@ -1020,6 +1020,7 @@ var init_preferences = __esm({
|
|
|
1020
1020
|
// src/adapters/claude/installer.ts
|
|
1021
1021
|
var installer_exports = {};
|
|
1022
1022
|
__export(installer_exports, {
|
|
1023
|
+
cleanOldShellFunctions: () => cleanOldShellFunctions,
|
|
1023
1024
|
copySlashCommands: () => copySlashCommands,
|
|
1024
1025
|
installStatusLine: () => installStatusLine,
|
|
1025
1026
|
mergeHooks: () => mergeHooks,
|
|
@@ -1428,6 +1429,132 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1428
1429
|
await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1429
1430
|
return { added, skipped };
|
|
1430
1431
|
}
|
|
1432
|
+
async function cleanOldShellFunctions(homeDir = os5.homedir()) {
|
|
1433
|
+
const rosterPath = path9.join(homeDir, ".exe-os", "exe-employees.json");
|
|
1434
|
+
if (!existsSync9(rosterPath)) return 0;
|
|
1435
|
+
let employees;
|
|
1436
|
+
try {
|
|
1437
|
+
employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
|
|
1438
|
+
} catch {
|
|
1439
|
+
return 0;
|
|
1440
|
+
}
|
|
1441
|
+
if (employees.length === 0) return 0;
|
|
1442
|
+
const names = employees.map((e) => e.name);
|
|
1443
|
+
const funcPatterns = names.map((n) => {
|
|
1444
|
+
const funcDef = new RegExp(`^\\s*(function\\s+)?${escapeRegExp(n)}\\d+\\s*\\(\\)`, "m");
|
|
1445
|
+
const forLoop = new RegExp(`${escapeRegExp(n)}\\$\\{?[a-zA-Z_][a-zA-Z0-9_]*\\}?`, "m");
|
|
1446
|
+
return { name: n, funcDef, forLoop };
|
|
1447
|
+
});
|
|
1448
|
+
const rcFiles = [
|
|
1449
|
+
path9.join(homeDir, ".zshrc"),
|
|
1450
|
+
path9.join(homeDir, ".bashrc")
|
|
1451
|
+
];
|
|
1452
|
+
const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
|
|
1453
|
+
let totalRemoved = 0;
|
|
1454
|
+
for (const rcPath of rcFiles) {
|
|
1455
|
+
if (!existsSync9(rcPath)) continue;
|
|
1456
|
+
let content;
|
|
1457
|
+
try {
|
|
1458
|
+
content = await readFile3(rcPath, "utf-8");
|
|
1459
|
+
} catch {
|
|
1460
|
+
continue;
|
|
1461
|
+
}
|
|
1462
|
+
if (content.includes(REMOVED_MARKER)) continue;
|
|
1463
|
+
const lines = content.split("\n");
|
|
1464
|
+
let changed = false;
|
|
1465
|
+
let inForLoop = false;
|
|
1466
|
+
let forLoopMatchesEmployee = false;
|
|
1467
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1468
|
+
const line = lines[i];
|
|
1469
|
+
const trimmed = line.trim();
|
|
1470
|
+
if (trimmed.startsWith("#")) continue;
|
|
1471
|
+
if (/^\s*for\s+/.test(trimmed)) {
|
|
1472
|
+
inForLoop = true;
|
|
1473
|
+
forLoopMatchesEmployee = false;
|
|
1474
|
+
for (const { forLoop } of funcPatterns) {
|
|
1475
|
+
if (forLoop.test(trimmed)) {
|
|
1476
|
+
forLoopMatchesEmployee = true;
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
if (forLoopMatchesEmployee) {
|
|
1481
|
+
lines[i] = `${REMOVED_MARKER}
|
|
1482
|
+
# ${line}`;
|
|
1483
|
+
changed = true;
|
|
1484
|
+
totalRemoved++;
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
if (inForLoop) {
|
|
1489
|
+
if (!forLoopMatchesEmployee) {
|
|
1490
|
+
for (const { forLoop } of funcPatterns) {
|
|
1491
|
+
if (forLoop.test(trimmed)) {
|
|
1492
|
+
forLoopMatchesEmployee = true;
|
|
1493
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
1494
|
+
if (/^\s*for\s+/.test(lines[j].replace(/^#\s*/, ""))) {
|
|
1495
|
+
if (!lines[j].startsWith("#")) {
|
|
1496
|
+
lines[j] = `${REMOVED_MARKER}
|
|
1497
|
+
# ${lines[j]}`;
|
|
1498
|
+
totalRemoved++;
|
|
1499
|
+
}
|
|
1500
|
+
break;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
break;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
if (forLoopMatchesEmployee && !trimmed.startsWith("#")) {
|
|
1508
|
+
lines[i] = `# ${line}`;
|
|
1509
|
+
changed = true;
|
|
1510
|
+
totalRemoved++;
|
|
1511
|
+
}
|
|
1512
|
+
if (trimmed === "done" || trimmed.startsWith("done;") || trimmed.startsWith("done ")) {
|
|
1513
|
+
inForLoop = false;
|
|
1514
|
+
forLoopMatchesEmployee = false;
|
|
1515
|
+
}
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
for (const { funcDef } of funcPatterns) {
|
|
1519
|
+
if (funcDef.test(trimmed)) {
|
|
1520
|
+
lines[i] = `${REMOVED_MARKER}
|
|
1521
|
+
# ${line}`;
|
|
1522
|
+
changed = true;
|
|
1523
|
+
totalRemoved++;
|
|
1524
|
+
let braceDepth = 0;
|
|
1525
|
+
const hasBrace = trimmed.includes("{");
|
|
1526
|
+
if (hasBrace) braceDepth = 1;
|
|
1527
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
1528
|
+
const bodyLine = lines[j].trim();
|
|
1529
|
+
if (!hasBrace && braceDepth === 0) {
|
|
1530
|
+
if (bodyLine === "{") {
|
|
1531
|
+
braceDepth = 1;
|
|
1532
|
+
lines[j] = `# ${lines[j]}`;
|
|
1533
|
+
totalRemoved++;
|
|
1534
|
+
continue;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
if (braceDepth > 0) {
|
|
1538
|
+
braceDepth += (bodyLine.match(/{/g) ?? []).length;
|
|
1539
|
+
braceDepth -= (bodyLine.match(/}/g) ?? []).length;
|
|
1540
|
+
lines[j] = `# ${lines[j]}`;
|
|
1541
|
+
totalRemoved++;
|
|
1542
|
+
if (braceDepth <= 0) break;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
break;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
if (changed) {
|
|
1550
|
+
await writeFile3(rcPath, lines.join("\n"));
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
return totalRemoved;
|
|
1554
|
+
}
|
|
1555
|
+
function escapeRegExp(s) {
|
|
1556
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1557
|
+
}
|
|
1431
1558
|
async function injectOrchestrationRules(homeDir) {
|
|
1432
1559
|
const claudeDir = path9.join(homeDir, ".claude");
|
|
1433
1560
|
const claudeMdPath = path9.join(claudeDir, "CLAUDE.md");
|
|
@@ -1530,6 +1657,13 @@ async function runInstaller(homeDir) {
|
|
|
1530
1657
|
`Status line: ${statusLineResult}
|
|
1531
1658
|
`
|
|
1532
1659
|
);
|
|
1660
|
+
const shellFuncsCleaned = await cleanOldShellFunctions(resolvedHome);
|
|
1661
|
+
if (shellFuncsCleaned > 0) {
|
|
1662
|
+
process.stderr.write(
|
|
1663
|
+
`Shell cleanup: removed ${shellFuncsCleaned} old shell function(s) that were shadowing exe-os wrappers
|
|
1664
|
+
`
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1533
1667
|
process.stderr.write(`
|
|
1534
1668
|
exe-os installed successfully.
|
|
1535
1669
|
`);
|
package/dist/bin/install.js
CHANGED
|
@@ -804,6 +804,132 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
804
804
|
await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
805
805
|
return { added, skipped };
|
|
806
806
|
}
|
|
807
|
+
async function cleanOldShellFunctions(homeDir = os5.homedir()) {
|
|
808
|
+
const rosterPath = path5.join(homeDir, ".exe-os", "exe-employees.json");
|
|
809
|
+
if (!existsSync5(rosterPath)) return 0;
|
|
810
|
+
let employees;
|
|
811
|
+
try {
|
|
812
|
+
employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
|
|
813
|
+
} catch {
|
|
814
|
+
return 0;
|
|
815
|
+
}
|
|
816
|
+
if (employees.length === 0) return 0;
|
|
817
|
+
const names = employees.map((e) => e.name);
|
|
818
|
+
const funcPatterns = names.map((n) => {
|
|
819
|
+
const funcDef = new RegExp(`^\\s*(function\\s+)?${escapeRegExp(n)}\\d+\\s*\\(\\)`, "m");
|
|
820
|
+
const forLoop = new RegExp(`${escapeRegExp(n)}\\$\\{?[a-zA-Z_][a-zA-Z0-9_]*\\}?`, "m");
|
|
821
|
+
return { name: n, funcDef, forLoop };
|
|
822
|
+
});
|
|
823
|
+
const rcFiles = [
|
|
824
|
+
path5.join(homeDir, ".zshrc"),
|
|
825
|
+
path5.join(homeDir, ".bashrc")
|
|
826
|
+
];
|
|
827
|
+
const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
|
|
828
|
+
let totalRemoved = 0;
|
|
829
|
+
for (const rcPath of rcFiles) {
|
|
830
|
+
if (!existsSync5(rcPath)) continue;
|
|
831
|
+
let content;
|
|
832
|
+
try {
|
|
833
|
+
content = await readFile3(rcPath, "utf-8");
|
|
834
|
+
} catch {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
if (content.includes(REMOVED_MARKER)) continue;
|
|
838
|
+
const lines = content.split("\n");
|
|
839
|
+
let changed = false;
|
|
840
|
+
let inForLoop = false;
|
|
841
|
+
let forLoopMatchesEmployee = false;
|
|
842
|
+
for (let i = 0; i < lines.length; i++) {
|
|
843
|
+
const line = lines[i];
|
|
844
|
+
const trimmed = line.trim();
|
|
845
|
+
if (trimmed.startsWith("#")) continue;
|
|
846
|
+
if (/^\s*for\s+/.test(trimmed)) {
|
|
847
|
+
inForLoop = true;
|
|
848
|
+
forLoopMatchesEmployee = false;
|
|
849
|
+
for (const { forLoop } of funcPatterns) {
|
|
850
|
+
if (forLoop.test(trimmed)) {
|
|
851
|
+
forLoopMatchesEmployee = true;
|
|
852
|
+
break;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
if (forLoopMatchesEmployee) {
|
|
856
|
+
lines[i] = `${REMOVED_MARKER}
|
|
857
|
+
# ${line}`;
|
|
858
|
+
changed = true;
|
|
859
|
+
totalRemoved++;
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (inForLoop) {
|
|
864
|
+
if (!forLoopMatchesEmployee) {
|
|
865
|
+
for (const { forLoop } of funcPatterns) {
|
|
866
|
+
if (forLoop.test(trimmed)) {
|
|
867
|
+
forLoopMatchesEmployee = true;
|
|
868
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
869
|
+
if (/^\s*for\s+/.test(lines[j].replace(/^#\s*/, ""))) {
|
|
870
|
+
if (!lines[j].startsWith("#")) {
|
|
871
|
+
lines[j] = `${REMOVED_MARKER}
|
|
872
|
+
# ${lines[j]}`;
|
|
873
|
+
totalRemoved++;
|
|
874
|
+
}
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
if (forLoopMatchesEmployee && !trimmed.startsWith("#")) {
|
|
883
|
+
lines[i] = `# ${line}`;
|
|
884
|
+
changed = true;
|
|
885
|
+
totalRemoved++;
|
|
886
|
+
}
|
|
887
|
+
if (trimmed === "done" || trimmed.startsWith("done;") || trimmed.startsWith("done ")) {
|
|
888
|
+
inForLoop = false;
|
|
889
|
+
forLoopMatchesEmployee = false;
|
|
890
|
+
}
|
|
891
|
+
continue;
|
|
892
|
+
}
|
|
893
|
+
for (const { funcDef } of funcPatterns) {
|
|
894
|
+
if (funcDef.test(trimmed)) {
|
|
895
|
+
lines[i] = `${REMOVED_MARKER}
|
|
896
|
+
# ${line}`;
|
|
897
|
+
changed = true;
|
|
898
|
+
totalRemoved++;
|
|
899
|
+
let braceDepth = 0;
|
|
900
|
+
const hasBrace = trimmed.includes("{");
|
|
901
|
+
if (hasBrace) braceDepth = 1;
|
|
902
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
903
|
+
const bodyLine = lines[j].trim();
|
|
904
|
+
if (!hasBrace && braceDepth === 0) {
|
|
905
|
+
if (bodyLine === "{") {
|
|
906
|
+
braceDepth = 1;
|
|
907
|
+
lines[j] = `# ${lines[j]}`;
|
|
908
|
+
totalRemoved++;
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
if (braceDepth > 0) {
|
|
913
|
+
braceDepth += (bodyLine.match(/{/g) ?? []).length;
|
|
914
|
+
braceDepth -= (bodyLine.match(/}/g) ?? []).length;
|
|
915
|
+
lines[j] = `# ${lines[j]}`;
|
|
916
|
+
totalRemoved++;
|
|
917
|
+
if (braceDepth <= 0) break;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (changed) {
|
|
925
|
+
await writeFile3(rcPath, lines.join("\n"));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return totalRemoved;
|
|
929
|
+
}
|
|
930
|
+
function escapeRegExp(s) {
|
|
931
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
932
|
+
}
|
|
807
933
|
var EXE_SECTION_START = "<!-- exe-os:orchestration-start -->";
|
|
808
934
|
var EXE_SECTION_END = "<!-- exe-os:orchestration-end -->";
|
|
809
935
|
var ORCHESTRATION_RULES = `${EXE_SECTION_START}
|
|
@@ -919,6 +1045,13 @@ async function runInstaller(homeDir) {
|
|
|
919
1045
|
`Status line: ${statusLineResult}
|
|
920
1046
|
`
|
|
921
1047
|
);
|
|
1048
|
+
const shellFuncsCleaned = await cleanOldShellFunctions(resolvedHome);
|
|
1049
|
+
if (shellFuncsCleaned > 0) {
|
|
1050
|
+
process.stderr.write(
|
|
1051
|
+
`Shell cleanup: removed ${shellFuncsCleaned} old shell function(s) that were shadowing exe-os wrappers
|
|
1052
|
+
`
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
922
1055
|
process.stderr.write(`
|
|
923
1056
|
exe-os installed successfully.
|
|
924
1057
|
`);
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -2937,11 +2937,6 @@ var init_session_kill_telemetry = __esm({
|
|
|
2937
2937
|
});
|
|
2938
2938
|
|
|
2939
2939
|
// src/lib/task-scope.ts
|
|
2940
|
-
var task_scope_exports = {};
|
|
2941
|
-
__export(task_scope_exports, {
|
|
2942
|
-
getCurrentSessionScope: () => getCurrentSessionScope,
|
|
2943
|
-
sessionScopeFilter: () => sessionScopeFilter
|
|
2944
|
-
});
|
|
2945
2940
|
function getCurrentSessionScope() {
|
|
2946
2941
|
try {
|
|
2947
2942
|
return resolveExeSession();
|
|
@@ -6482,6 +6477,7 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
6482
6477
|
const agent = deps.parseAgentFromSession(session);
|
|
6483
6478
|
if (agent) liveAgents.add(agent);
|
|
6484
6479
|
}
|
|
6480
|
+
const coordinatorSessions = liveSessions.filter((s) => isExeSession(s));
|
|
6485
6481
|
let tasksByAgent;
|
|
6486
6482
|
try {
|
|
6487
6483
|
tasksByAgent = await deps.queryTasksByAgent();
|
|
@@ -6490,12 +6486,17 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
6490
6486
|
}
|
|
6491
6487
|
const agentTasks = /* @__PURE__ */ new Map();
|
|
6492
6488
|
for (const t of tasksByAgent) {
|
|
6493
|
-
const
|
|
6494
|
-
|
|
6495
|
-
|
|
6489
|
+
const scope = t.sessionScope || coordinatorSessions[0] || null;
|
|
6490
|
+
if (!scope) continue;
|
|
6491
|
+
const key = `${t.agentId}::${scope}`;
|
|
6492
|
+
const existing = agentTasks.get(key) ?? [];
|
|
6493
|
+
existing.push({ taskId: t.taskId, priority: t.priority, sessionScope: scope });
|
|
6494
|
+
agentTasks.set(key, existing);
|
|
6496
6495
|
}
|
|
6497
6496
|
const woken = [];
|
|
6498
|
-
for (const [
|
|
6497
|
+
for (const [key, tasks] of agentTasks) {
|
|
6498
|
+
const agentId = key.split("::")[0];
|
|
6499
|
+
const sessionScope = tasks[0].sessionScope;
|
|
6499
6500
|
if (!shouldAutoWake({
|
|
6500
6501
|
agentId,
|
|
6501
6502
|
hasRunningSession: liveAgents.has(agentId),
|
|
@@ -6522,11 +6523,11 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
6522
6523
|
continue;
|
|
6523
6524
|
}
|
|
6524
6525
|
process.stderr.write(
|
|
6525
|
-
`[auto-wake] ${agentId} has ${tasks.length} pending task(s) but no session \u2014 spawning (attempt ${retries + 1} for task ${topTask.taskId})
|
|
6526
|
+
`[auto-wake] ${agentId} has ${tasks.length} pending task(s) but no session \u2014 spawning in ${sessionScope} (attempt ${retries + 1} for task ${topTask.taskId})
|
|
6526
6527
|
`
|
|
6527
6528
|
);
|
|
6528
6529
|
try {
|
|
6529
|
-
const result = deps.ensureEmployee(agentId);
|
|
6530
|
+
const result = deps.ensureEmployee(agentId, sessionScope);
|
|
6530
6531
|
if (result.status === "failed") {
|
|
6531
6532
|
process.stderr.write(
|
|
6532
6533
|
`[auto-wake] Failed to spawn ${agentId}: ${result.error ?? "unknown"}
|
|
@@ -6546,7 +6547,7 @@ async function pollOrphanedTasks(deps, nowMs = Date.now()) {
|
|
|
6546
6547
|
}
|
|
6547
6548
|
return woken;
|
|
6548
6549
|
}
|
|
6549
|
-
function createAutoWakeRealDeps(getClient2,
|
|
6550
|
+
function createAutoWakeRealDeps(getClient2, projectDir) {
|
|
6550
6551
|
return {
|
|
6551
6552
|
listTmuxSessions: () => {
|
|
6552
6553
|
const { listTmuxSessions: listTmuxSessions2 } = (init_tmux_status(), __toCommonJS(tmux_status_exports));
|
|
@@ -6554,24 +6555,24 @@ function createAutoWakeRealDeps(getClient2, sessionScope, projectDir) {
|
|
|
6554
6555
|
},
|
|
6555
6556
|
queryTasksByAgent: async () => {
|
|
6556
6557
|
const client = getClient2();
|
|
6557
|
-
const scope = sessionScopeFilter(sessionScope);
|
|
6558
6558
|
const result = await client.execute({
|
|
6559
|
-
sql: `SELECT assigned_to, id, priority FROM tasks
|
|
6560
|
-
WHERE status IN ('open', 'in_progress')
|
|
6559
|
+
sql: `SELECT assigned_to, id, priority, session_scope FROM tasks
|
|
6560
|
+
WHERE status IN ('open', 'in_progress')
|
|
6561
6561
|
ORDER BY
|
|
6562
6562
|
CASE priority WHEN 'p0' THEN 0 WHEN 'p1' THEN 1 WHEN 'p2' THEN 2 ELSE 3 END,
|
|
6563
6563
|
created_at ASC`,
|
|
6564
|
-
args: [
|
|
6564
|
+
args: []
|
|
6565
6565
|
});
|
|
6566
6566
|
return result.rows.map((r) => ({
|
|
6567
6567
|
agentId: String(r.assigned_to),
|
|
6568
6568
|
taskId: String(r.id),
|
|
6569
|
-
priority: String(r.priority)
|
|
6569
|
+
priority: String(r.priority),
|
|
6570
|
+
sessionScope: r.session_scope ? String(r.session_scope) : null
|
|
6570
6571
|
}));
|
|
6571
6572
|
},
|
|
6572
|
-
ensureEmployee: (agentName) => {
|
|
6573
|
+
ensureEmployee: (agentName, scope) => {
|
|
6573
6574
|
const { ensureEmployee: ensureEmployee2 } = (init_tmux_routing(), __toCommonJS(tmux_routing_exports));
|
|
6574
|
-
return ensureEmployee2(agentName,
|
|
6575
|
+
return ensureEmployee2(agentName, scope, projectDir);
|
|
6575
6576
|
},
|
|
6576
6577
|
markTaskBlocked: async (taskId, reason) => {
|
|
6577
6578
|
const client = getClient2();
|
|
@@ -10800,9 +10801,7 @@ function startAutoWake() {
|
|
|
10800
10801
|
try {
|
|
10801
10802
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
10802
10803
|
const { pollOrphanedTasks: pollOrphanedTasks2, createAutoWakeRealDeps: createAutoWakeRealDeps2 } = await Promise.resolve().then(() => (init_daemon_orchestration(), daemon_orchestration_exports));
|
|
10803
|
-
const
|
|
10804
|
-
const sessionScope = getCurrentSessionScope2() ?? "";
|
|
10805
|
-
const deps = createAutoWakeRealDeps2(getClient2, sessionScope, process.cwd());
|
|
10804
|
+
const deps = createAutoWakeRealDeps2(getClient2, process.cwd());
|
|
10806
10805
|
const woken = await pollOrphanedTasks2(deps);
|
|
10807
10806
|
for (const agent of woken) {
|
|
10808
10807
|
process.stderr.write(`[exed] Auto-wake: spawned ${agent}
|
package/package.json
CHANGED