@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
package/dist/bin/install.js
CHANGED
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// src/lib/agent-symlinks.ts
|
|
12
|
-
import os2 from "os";
|
|
13
|
-
import path3 from "path";
|
|
14
|
-
import {
|
|
15
|
-
existsSync as existsSync3,
|
|
16
|
-
lstatSync,
|
|
17
|
-
mkdirSync,
|
|
18
|
-
readlinkSync as readlinkSync2,
|
|
19
|
-
symlinkSync as symlinkSync2
|
|
20
|
-
} from "fs";
|
|
21
|
-
|
|
22
|
-
// src/lib/employees.ts
|
|
23
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
24
|
-
import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2 } from "fs";
|
|
25
|
-
import { execSync } from "child_process";
|
|
26
|
-
import path2 from "path";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
27
11
|
|
|
28
12
|
// src/lib/config.ts
|
|
29
13
|
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
@@ -46,78 +30,119 @@ function resolveDataDir() {
|
|
|
46
30
|
}
|
|
47
31
|
return newDir;
|
|
48
32
|
}
|
|
49
|
-
var EXE_AI_DIR
|
|
50
|
-
var
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
33
|
+
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG;
|
|
34
|
+
var init_config = __esm({
|
|
35
|
+
"src/lib/config.ts"() {
|
|
36
|
+
"use strict";
|
|
37
|
+
EXE_AI_DIR = resolveDataDir();
|
|
38
|
+
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
39
|
+
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
40
|
+
CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
41
|
+
LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
42
|
+
CURRENT_CONFIG_VERSION = 1;
|
|
43
|
+
DEFAULT_CONFIG = {
|
|
44
|
+
config_version: CURRENT_CONFIG_VERSION,
|
|
45
|
+
dbPath: DB_PATH,
|
|
46
|
+
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
47
|
+
embeddingDim: 1024,
|
|
48
|
+
batchSize: 20,
|
|
49
|
+
flushIntervalMs: 1e4,
|
|
50
|
+
autoIngestion: true,
|
|
51
|
+
autoRetrieval: true,
|
|
52
|
+
searchMode: "hybrid",
|
|
53
|
+
hookSearchMode: "hybrid",
|
|
54
|
+
fileGrepEnabled: true,
|
|
55
|
+
splashEffect: true,
|
|
56
|
+
consolidationEnabled: true,
|
|
57
|
+
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
58
|
+
consolidationModel: "claude-haiku-4-5-20251001",
|
|
59
|
+
consolidationMaxCallsPerRun: 20,
|
|
60
|
+
selfQueryRouter: true,
|
|
61
|
+
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
62
|
+
rerankerEnabled: true,
|
|
63
|
+
scalingRoadmap: {
|
|
64
|
+
rerankerAutoTrigger: {
|
|
65
|
+
enabled: true,
|
|
66
|
+
broadQueryMinCardinality: 5e4,
|
|
67
|
+
fetchTopK: 150,
|
|
68
|
+
returnTopK: 5
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
graphRagEnabled: true,
|
|
72
|
+
wikiEnabled: false,
|
|
73
|
+
wikiUrl: "",
|
|
74
|
+
wikiApiKey: "",
|
|
75
|
+
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
76
|
+
wikiWorkspaceMapping: {
|
|
77
|
+
exe: "Executive",
|
|
78
|
+
yoshi: "Engineering",
|
|
79
|
+
mari: "Marketing",
|
|
80
|
+
tom: "Engineering",
|
|
81
|
+
sasha: "Production"
|
|
82
|
+
},
|
|
83
|
+
wikiAutoUpdate: true,
|
|
84
|
+
wikiAutoUpdateThreshold: 0.5,
|
|
85
|
+
wikiAutoUpdateCreateNew: true,
|
|
86
|
+
skillLearning: true,
|
|
87
|
+
skillThreshold: 3,
|
|
88
|
+
skillModel: "claude-haiku-4-5-20251001",
|
|
89
|
+
exeHeartbeat: {
|
|
90
|
+
enabled: true,
|
|
91
|
+
intervalSeconds: 60,
|
|
92
|
+
staleInProgressThresholdHours: 2
|
|
93
|
+
},
|
|
94
|
+
sessionLifecycle: {
|
|
95
|
+
idleKillEnabled: true,
|
|
96
|
+
idleKillTicksRequired: 3,
|
|
97
|
+
idleKillIntercomAckWindowMs: 1e4,
|
|
98
|
+
maxAutoInstances: 10
|
|
99
|
+
},
|
|
100
|
+
autoUpdate: {
|
|
101
|
+
checkOnBoot: true,
|
|
102
|
+
autoInstall: false,
|
|
103
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
104
|
+
}
|
|
105
|
+
};
|
|
116
106
|
}
|
|
117
|
-
};
|
|
107
|
+
});
|
|
118
108
|
|
|
119
109
|
// src/lib/employees.ts
|
|
120
|
-
var
|
|
110
|
+
var employees_exports = {};
|
|
111
|
+
__export(employees_exports, {
|
|
112
|
+
EMPLOYEES_PATH: () => EMPLOYEES_PATH,
|
|
113
|
+
addEmployee: () => addEmployee,
|
|
114
|
+
getEmployee: () => getEmployee,
|
|
115
|
+
getEmployeeByRole: () => getEmployeeByRole,
|
|
116
|
+
getEmployeeNamesByRole: () => getEmployeeNamesByRole,
|
|
117
|
+
hasRole: () => hasRole,
|
|
118
|
+
isMultiInstance: () => isMultiInstance,
|
|
119
|
+
loadEmployees: () => loadEmployees,
|
|
120
|
+
loadEmployeesSync: () => loadEmployeesSync,
|
|
121
|
+
normalizeRosterCase: () => normalizeRosterCase,
|
|
122
|
+
registerBinSymlinks: () => registerBinSymlinks,
|
|
123
|
+
saveEmployees: () => saveEmployees,
|
|
124
|
+
validateEmployeeName: () => validateEmployeeName
|
|
125
|
+
});
|
|
126
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
127
|
+
import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
128
|
+
import { execSync } from "child_process";
|
|
129
|
+
import path2 from "path";
|
|
130
|
+
import os2 from "os";
|
|
131
|
+
function validateEmployeeName(name) {
|
|
132
|
+
if (!name) {
|
|
133
|
+
return { valid: false, error: "Name is required" };
|
|
134
|
+
}
|
|
135
|
+
if (name.length > 32) {
|
|
136
|
+
return { valid: false, error: "Name must be 32 characters or fewer" };
|
|
137
|
+
}
|
|
138
|
+
if (!/^[a-z][a-z0-9]*$/.test(name)) {
|
|
139
|
+
return {
|
|
140
|
+
valid: false,
|
|
141
|
+
error: "Name must start with a letter and contain only lowercase alphanumeric characters"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return { valid: true };
|
|
145
|
+
}
|
|
121
146
|
async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
122
147
|
if (!existsSync2(employeesPath)) {
|
|
123
148
|
return [];
|
|
@@ -129,8 +154,146 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
|
129
154
|
return [];
|
|
130
155
|
}
|
|
131
156
|
}
|
|
157
|
+
async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
158
|
+
await mkdir2(path2.dirname(employeesPath), { recursive: true });
|
|
159
|
+
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
160
|
+
}
|
|
161
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
162
|
+
if (!existsSync2(employeesPath)) return [];
|
|
163
|
+
try {
|
|
164
|
+
return JSON.parse(readFileSync2(employeesPath, "utf-8"));
|
|
165
|
+
} catch {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function getEmployee(employees, name) {
|
|
170
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
171
|
+
}
|
|
172
|
+
function getEmployeeByRole(employees, role) {
|
|
173
|
+
const lower = role.toLowerCase();
|
|
174
|
+
return employees.find((e) => e.role.toLowerCase() === lower);
|
|
175
|
+
}
|
|
176
|
+
function getEmployeeNamesByRole(employees, role) {
|
|
177
|
+
const lower = role.toLowerCase();
|
|
178
|
+
return employees.filter((e) => e.role.toLowerCase() === lower).map((e) => e.name);
|
|
179
|
+
}
|
|
180
|
+
function hasRole(agentName, role) {
|
|
181
|
+
const employees = loadEmployeesSync();
|
|
182
|
+
const emp = getEmployee(employees, agentName);
|
|
183
|
+
return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
|
|
184
|
+
}
|
|
185
|
+
function isMultiInstance(agentName, employees) {
|
|
186
|
+
const roster = employees ?? loadEmployeesSync();
|
|
187
|
+
const emp = getEmployee(roster, agentName);
|
|
188
|
+
if (!emp) return false;
|
|
189
|
+
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
190
|
+
}
|
|
191
|
+
function addEmployee(employees, employee) {
|
|
192
|
+
const normalized = { ...employee, name: employee.name.toLowerCase() };
|
|
193
|
+
if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
|
|
194
|
+
throw new Error(`Employee '${normalized.name}' already exists`);
|
|
195
|
+
}
|
|
196
|
+
return [...employees, normalized];
|
|
197
|
+
}
|
|
198
|
+
async function normalizeRosterCase(rosterPath) {
|
|
199
|
+
const employees = await loadEmployees(rosterPath);
|
|
200
|
+
let changed = false;
|
|
201
|
+
for (const emp of employees) {
|
|
202
|
+
if (emp.name !== emp.name.toLowerCase()) {
|
|
203
|
+
const oldName = emp.name;
|
|
204
|
+
emp.name = emp.name.toLowerCase();
|
|
205
|
+
changed = true;
|
|
206
|
+
try {
|
|
207
|
+
const identityDir = path2.join(os2.homedir(), ".exe-os", "identity");
|
|
208
|
+
const oldPath = path2.join(identityDir, `${oldName}.md`);
|
|
209
|
+
const newPath = path2.join(identityDir, `${emp.name}.md`);
|
|
210
|
+
if (existsSync2(oldPath) && !existsSync2(newPath)) {
|
|
211
|
+
renameSync2(oldPath, newPath);
|
|
212
|
+
} else if (existsSync2(oldPath) && oldPath !== newPath) {
|
|
213
|
+
const content = readFileSync2(oldPath, "utf-8");
|
|
214
|
+
writeFileSync(newPath, content, "utf-8");
|
|
215
|
+
if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
|
|
216
|
+
unlinkSync(oldPath);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (changed) {
|
|
224
|
+
await saveEmployees(employees, rosterPath);
|
|
225
|
+
}
|
|
226
|
+
return changed;
|
|
227
|
+
}
|
|
228
|
+
function findExeBin() {
|
|
229
|
+
try {
|
|
230
|
+
return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function registerBinSymlinks(name) {
|
|
236
|
+
const created = [];
|
|
237
|
+
const skipped = [];
|
|
238
|
+
const errors = [];
|
|
239
|
+
const exeBinPath = findExeBin();
|
|
240
|
+
if (!exeBinPath) {
|
|
241
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
242
|
+
return { created, skipped, errors };
|
|
243
|
+
}
|
|
244
|
+
const binDir = path2.dirname(exeBinPath);
|
|
245
|
+
let target;
|
|
246
|
+
try {
|
|
247
|
+
target = readlinkSync(exeBinPath);
|
|
248
|
+
} catch {
|
|
249
|
+
errors.push("Could not read 'exe' symlink");
|
|
250
|
+
return { created, skipped, errors };
|
|
251
|
+
}
|
|
252
|
+
for (const suffix of ["", "-opencode"]) {
|
|
253
|
+
const linkName = `${name}${suffix}`;
|
|
254
|
+
const linkPath = path2.join(binDir, linkName);
|
|
255
|
+
if (existsSync2(linkPath)) {
|
|
256
|
+
skipped.push(linkName);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
symlinkSync(target, linkPath);
|
|
261
|
+
created.push(linkName);
|
|
262
|
+
} catch (err) {
|
|
263
|
+
errors.push(`${linkName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return { created, skipped, errors };
|
|
267
|
+
}
|
|
268
|
+
var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
|
|
269
|
+
var init_employees = __esm({
|
|
270
|
+
"src/lib/employees.ts"() {
|
|
271
|
+
"use strict";
|
|
272
|
+
init_config();
|
|
273
|
+
EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
274
|
+
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// src/adapters/claude/installer.ts
|
|
279
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
280
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2, copyFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
281
|
+
import path4 from "path";
|
|
282
|
+
import os4 from "os";
|
|
283
|
+
import { execSync as execSync2 } from "child_process";
|
|
284
|
+
import { fileURLToPath } from "url";
|
|
132
285
|
|
|
133
286
|
// src/lib/agent-symlinks.ts
|
|
287
|
+
init_employees();
|
|
288
|
+
import os3 from "os";
|
|
289
|
+
import path3 from "path";
|
|
290
|
+
import {
|
|
291
|
+
existsSync as existsSync3,
|
|
292
|
+
lstatSync,
|
|
293
|
+
mkdirSync,
|
|
294
|
+
readlinkSync as readlinkSync2,
|
|
295
|
+
symlinkSync as symlinkSync2
|
|
296
|
+
} from "fs";
|
|
134
297
|
function claudeAgentsDir(homeDir) {
|
|
135
298
|
return path3.join(homeDir, ".claude", "agents");
|
|
136
299
|
}
|
|
@@ -140,7 +303,7 @@ function identitySourcePath(homeDir, agentId) {
|
|
|
140
303
|
function claudeAgentLinkPath(homeDir, agentId) {
|
|
141
304
|
return path3.join(claudeAgentsDir(homeDir), `${agentId}.md`);
|
|
142
305
|
}
|
|
143
|
-
function ensureAgentSymlink(agentId, homeDir =
|
|
306
|
+
function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
|
|
144
307
|
const target = identitySourcePath(homeDir, agentId);
|
|
145
308
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
146
309
|
mkdirSync(claudeAgentsDir(homeDir), { recursive: true });
|
|
@@ -178,7 +341,7 @@ function ensureAgentSymlink(agentId, homeDir = os2.homedir()) {
|
|
|
178
341
|
}
|
|
179
342
|
return { agentId, action: "created", target, link };
|
|
180
343
|
}
|
|
181
|
-
async function ensureAllAgentSymlinks(homeDir =
|
|
344
|
+
async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
|
|
182
345
|
const employees = await loadEmployees();
|
|
183
346
|
return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
|
|
184
347
|
}
|
|
@@ -218,7 +381,7 @@ function resolvePackageRoot() {
|
|
|
218
381
|
}
|
|
219
382
|
return path4.resolve(path4.dirname(thisFile), "..", "..", "..");
|
|
220
383
|
}
|
|
221
|
-
async function copySlashCommands(packageRoot, homeDir =
|
|
384
|
+
async function copySlashCommands(packageRoot, homeDir = os4.homedir()) {
|
|
222
385
|
let copied = 0;
|
|
223
386
|
let skipped = 0;
|
|
224
387
|
const skillsBase = path4.join(homeDir, ".claude", "skills");
|
|
@@ -271,7 +434,7 @@ name: ${skillName}
|
|
|
271
434
|
await writeFile3(destPath, content);
|
|
272
435
|
return true;
|
|
273
436
|
}
|
|
274
|
-
async function registerMcpServer(packageRoot, homeDir =
|
|
437
|
+
async function registerMcpServer(packageRoot, homeDir = os4.homedir()) {
|
|
275
438
|
const claudeJsonPath = path4.join(homeDir, ".claude.json");
|
|
276
439
|
let claudeJson = {};
|
|
277
440
|
if (existsSync4(claudeJsonPath)) {
|
|
@@ -303,7 +466,7 @@ async function registerMcpServer(packageRoot, homeDir = os3.homedir()) {
|
|
|
303
466
|
await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
304
467
|
return true;
|
|
305
468
|
}
|
|
306
|
-
async function mergeHooks(packageRoot, homeDir =
|
|
469
|
+
async function mergeHooks(packageRoot, homeDir = os4.homedir()) {
|
|
307
470
|
const settingsPath = path4.join(homeDir, ".claude", "settings.json");
|
|
308
471
|
let settings = {};
|
|
309
472
|
if (existsSync4(settingsPath)) {
|
|
@@ -631,7 +794,7 @@ async function runInstaller(homeDir) {
|
|
|
631
794
|
`Hooks: ${hookResult.added} added, ${hookResult.skipped} unchanged
|
|
632
795
|
`
|
|
633
796
|
);
|
|
634
|
-
const resolvedHome = homeDir ??
|
|
797
|
+
const resolvedHome = homeDir ?? os4.homedir();
|
|
635
798
|
const exeWorkspace = path4.join(resolvedHome, "exe");
|
|
636
799
|
if (!existsSync4(exeWorkspace)) {
|
|
637
800
|
try {
|
|
@@ -660,7 +823,7 @@ exe-os installed successfully.
|
|
|
660
823
|
`);
|
|
661
824
|
}
|
|
662
825
|
function setupTmux(home) {
|
|
663
|
-
const homeDir = home ??
|
|
826
|
+
const homeDir = home ?? os4.homedir();
|
|
664
827
|
const exeDir = path4.join(homeDir, ".exe-os");
|
|
665
828
|
const exeTmuxConf = path4.join(exeDir, "tmux.conf");
|
|
666
829
|
const userTmuxConf = path4.join(homeDir, ".tmux.conf");
|
|
@@ -683,11 +846,11 @@ function setupTmux(home) {
|
|
|
683
846
|
process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
|
|
684
847
|
`);
|
|
685
848
|
}
|
|
686
|
-
|
|
849
|
+
writeFileSync2(userTmuxConf, `${sourceLine}
|
|
687
850
|
${existing}`);
|
|
688
851
|
}
|
|
689
852
|
} else {
|
|
690
|
-
|
|
853
|
+
writeFileSync2(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
|
|
691
854
|
${sourceLine}
|
|
692
855
|
`);
|
|
693
856
|
}
|
|
@@ -711,7 +874,7 @@ function summarizeSymlinkResults(results) {
|
|
|
711
874
|
}
|
|
712
875
|
|
|
713
876
|
// src/bin/install.ts
|
|
714
|
-
import { existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync as
|
|
877
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, unlinkSync as unlinkSync3, readdirSync as readdirSync2, openSync, closeSync } from "fs";
|
|
715
878
|
import { spawn, execSync as execSync3 } from "child_process";
|
|
716
879
|
import path6 from "path";
|
|
717
880
|
import { homedir as homedir2 } from "os";
|
|
@@ -720,11 +883,11 @@ import { homedir as homedir2 } from "os";
|
|
|
720
883
|
import {
|
|
721
884
|
existsSync as existsSync5,
|
|
722
885
|
readFileSync as readFileSync4,
|
|
723
|
-
writeFileSync as
|
|
886
|
+
writeFileSync as writeFileSync3,
|
|
724
887
|
mkdirSync as mkdirSync3,
|
|
725
888
|
chmodSync,
|
|
726
889
|
readdirSync,
|
|
727
|
-
unlinkSync
|
|
890
|
+
unlinkSync as unlinkSync2
|
|
728
891
|
} from "fs";
|
|
729
892
|
import path5 from "path";
|
|
730
893
|
import { homedir } from "os";
|
|
@@ -741,7 +904,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
741
904
|
];
|
|
742
905
|
for (const src of candidates) {
|
|
743
906
|
if (existsSync5(src)) {
|
|
744
|
-
|
|
907
|
+
writeFileSync3(exeStartDst, readFileSync4(src));
|
|
745
908
|
chmodSync(exeStartDst, 493);
|
|
746
909
|
break;
|
|
747
910
|
}
|
|
@@ -762,7 +925,7 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
762
925
|
try {
|
|
763
926
|
const content = readFileSync4(fPath, "utf8");
|
|
764
927
|
if (content.includes("exe-start")) {
|
|
765
|
-
|
|
928
|
+
unlinkSync2(fPath);
|
|
766
929
|
}
|
|
767
930
|
} catch {
|
|
768
931
|
}
|
|
@@ -776,7 +939,7 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
776
939
|
for (const emp of employees) {
|
|
777
940
|
for (let n = 1; n <= MAX_N; n++) {
|
|
778
941
|
const wrapperPath = path5.join(binDir, `${emp.name}${n}`);
|
|
779
|
-
|
|
942
|
+
writeFileSync3(wrapperPath, wrapperContent);
|
|
780
943
|
chmodSync(wrapperPath, 493);
|
|
781
944
|
created++;
|
|
782
945
|
}
|
|
@@ -812,7 +975,7 @@ export PATH="${binDir}:$PATH"
|
|
|
812
975
|
if (content.includes(".exe-os/bin")) {
|
|
813
976
|
return false;
|
|
814
977
|
}
|
|
815
|
-
|
|
978
|
+
writeFileSync3(profilePath, content + exportLine);
|
|
816
979
|
return true;
|
|
817
980
|
} catch {
|
|
818
981
|
continue;
|
|
@@ -836,7 +999,7 @@ function restartDaemon() {
|
|
|
836
999
|
}
|
|
837
1000
|
}
|
|
838
1001
|
try {
|
|
839
|
-
|
|
1002
|
+
unlinkSync3(pidPath);
|
|
840
1003
|
} catch {
|
|
841
1004
|
}
|
|
842
1005
|
}
|
|
@@ -873,7 +1036,7 @@ function restartDaemon() {
|
|
|
873
1036
|
if (existsSync6(wpDir)) {
|
|
874
1037
|
for (const f of readdirSync2(wpDir)) {
|
|
875
1038
|
try {
|
|
876
|
-
|
|
1039
|
+
unlinkSync3(path6.join(wpDir, f));
|
|
877
1040
|
} catch {
|
|
878
1041
|
}
|
|
879
1042
|
}
|
|
@@ -881,7 +1044,7 @@ function restartDaemon() {
|
|
|
881
1044
|
} catch {
|
|
882
1045
|
}
|
|
883
1046
|
try {
|
|
884
|
-
|
|
1047
|
+
unlinkSync3(sockPath);
|
|
885
1048
|
} catch {
|
|
886
1049
|
}
|
|
887
1050
|
try {
|
|
@@ -944,6 +1107,14 @@ if (args.includes("--commands-only")) {
|
|
|
944
1107
|
try {
|
|
945
1108
|
await runInstaller();
|
|
946
1109
|
setupTmux();
|
|
1110
|
+
try {
|
|
1111
|
+
const { normalizeRosterCase: normalizeRosterCase2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
1112
|
+
const changed = await normalizeRosterCase2();
|
|
1113
|
+
if (changed) {
|
|
1114
|
+
process.stderr.write("exe-os: normalized employee names to lowercase\n");
|
|
1115
|
+
}
|
|
1116
|
+
} catch {
|
|
1117
|
+
}
|
|
947
1118
|
try {
|
|
948
1119
|
const pkgRoot = resolvePackageRoot();
|
|
949
1120
|
const wrapResult = generateSessionWrappers(pkgRoot);
|