@askexenow/exe-os 0.8.85 → 0.8.87
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 +57 -19
- package/dist/bin/cli.js +510 -340
- package/dist/bin/exe-agent-config.js +242 -0
- package/dist/bin/exe-agent.js +3 -3
- package/dist/bin/exe-boot.js +344 -346
- package/dist/bin/exe-dispatch.js +375 -250
- package/dist/bin/exe-forget.js +5 -1
- package/dist/bin/exe-gateway.js +260 -135
- package/dist/bin/exe-healthcheck.js +133 -1
- package/dist/bin/exe-heartbeat.js +72 -31
- package/dist/bin/exe-link.js +25 -2
- package/dist/bin/exe-new-employee.js +22 -0
- package/dist/bin/exe-pending-messages.js +55 -17
- package/dist/bin/exe-pending-reviews.js +57 -19
- package/dist/bin/exe-search.js +6 -2
- package/dist/bin/exe-session-cleanup.js +260 -135
- package/dist/bin/exe-start-codex.js +2598 -0
- package/dist/bin/exe-start.sh +15 -3
- package/dist/bin/exe-status.js +57 -19
- package/dist/bin/git-sweep.js +391 -266
- package/dist/bin/install.js +22 -0
- package/dist/bin/scan-tasks.js +394 -269
- package/dist/bin/setup.js +50 -5
- package/dist/gateway/index.js +257 -132
- package/dist/hooks/bug-report-worker.js +242 -117
- package/dist/hooks/commit-complete.js +389 -264
- package/dist/hooks/error-recall.js +6 -2
- package/dist/hooks/ingest-worker.js +314 -193
- package/dist/hooks/post-compact.js +84 -46
- package/dist/hooks/pre-compact.js +272 -147
- package/dist/hooks/pre-tool-use.js +104 -66
- package/dist/hooks/prompt-submit.js +126 -66
- package/dist/hooks/session-end.js +277 -152
- package/dist/hooks/session-start.js +70 -28
- package/dist/hooks/stop.js +90 -52
- package/dist/hooks/subagent-stop.js +84 -46
- package/dist/hooks/summary-worker.js +175 -114
- package/dist/index.js +296 -171
- package/dist/lib/agent-config.js +167 -0
- package/dist/lib/cloud-sync.js +25 -2
- package/dist/lib/exe-daemon.js +338 -213
- package/dist/lib/hybrid-search.js +7 -2
- package/dist/lib/messaging.js +95 -39
- package/dist/lib/runtime-table.js +16 -0
- package/dist/lib/session-wrappers.js +22 -0
- package/dist/lib/tasks.js +242 -117
- package/dist/lib/tmux-routing.js +314 -189
- package/dist/mcp/server.js +573 -274
- package/dist/mcp/tools/create-task.js +260 -135
- package/dist/mcp/tools/list-tasks.js +68 -30
- package/dist/mcp/tools/send-message.js +100 -44
- package/dist/mcp/tools/update-task.js +123 -67
- package/dist/runtime/index.js +276 -151
- package/dist/tui/App.js +479 -354
- package/package.json +1 -1
- package/src/commands/exe/agent-config.md +27 -0
- package/src/commands/exe/cc-doctor.md +10 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/agent-config.ts
|
|
4
|
+
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
5
|
+
import path2 from "path";
|
|
6
|
+
|
|
7
|
+
// src/lib/config.ts
|
|
8
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
9
|
+
import { readFileSync, existsSync, renameSync } from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
import os from "os";
|
|
12
|
+
function resolveDataDir() {
|
|
13
|
+
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
14
|
+
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
15
|
+
const newDir = path.join(os.homedir(), ".exe-os");
|
|
16
|
+
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
17
|
+
if (!existsSync(newDir) && existsSync(legacyDir)) {
|
|
18
|
+
try {
|
|
19
|
+
renameSync(legacyDir, newDir);
|
|
20
|
+
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
21
|
+
`);
|
|
22
|
+
} catch {
|
|
23
|
+
return legacyDir;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return newDir;
|
|
27
|
+
}
|
|
28
|
+
var EXE_AI_DIR = resolveDataDir();
|
|
29
|
+
var DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
30
|
+
var MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
31
|
+
var CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
32
|
+
var LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
33
|
+
var CURRENT_CONFIG_VERSION = 1;
|
|
34
|
+
var DEFAULT_CONFIG = {
|
|
35
|
+
config_version: CURRENT_CONFIG_VERSION,
|
|
36
|
+
dbPath: DB_PATH,
|
|
37
|
+
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
38
|
+
embeddingDim: 1024,
|
|
39
|
+
batchSize: 20,
|
|
40
|
+
flushIntervalMs: 1e4,
|
|
41
|
+
autoIngestion: true,
|
|
42
|
+
autoRetrieval: true,
|
|
43
|
+
searchMode: "hybrid",
|
|
44
|
+
hookSearchMode: "hybrid",
|
|
45
|
+
fileGrepEnabled: true,
|
|
46
|
+
splashEffect: true,
|
|
47
|
+
consolidationEnabled: true,
|
|
48
|
+
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
49
|
+
consolidationModel: "claude-haiku-4-5-20251001",
|
|
50
|
+
consolidationMaxCallsPerRun: 20,
|
|
51
|
+
selfQueryRouter: true,
|
|
52
|
+
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
53
|
+
rerankerEnabled: true,
|
|
54
|
+
scalingRoadmap: {
|
|
55
|
+
rerankerAutoTrigger: {
|
|
56
|
+
enabled: true,
|
|
57
|
+
broadQueryMinCardinality: 5e4,
|
|
58
|
+
fetchTopK: 150,
|
|
59
|
+
returnTopK: 5
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
graphRagEnabled: true,
|
|
63
|
+
wikiEnabled: false,
|
|
64
|
+
wikiUrl: "",
|
|
65
|
+
wikiApiKey: "",
|
|
66
|
+
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
67
|
+
wikiWorkspaceMapping: {},
|
|
68
|
+
wikiAutoUpdate: true,
|
|
69
|
+
wikiAutoUpdateThreshold: 0.5,
|
|
70
|
+
wikiAutoUpdateCreateNew: true,
|
|
71
|
+
skillLearning: true,
|
|
72
|
+
skillThreshold: 3,
|
|
73
|
+
skillModel: "claude-haiku-4-5-20251001",
|
|
74
|
+
exeHeartbeat: {
|
|
75
|
+
enabled: true,
|
|
76
|
+
intervalSeconds: 60,
|
|
77
|
+
staleInProgressThresholdHours: 2
|
|
78
|
+
},
|
|
79
|
+
sessionLifecycle: {
|
|
80
|
+
idleKillEnabled: true,
|
|
81
|
+
idleKillTicksRequired: 3,
|
|
82
|
+
idleKillIntercomAckWindowMs: 1e4,
|
|
83
|
+
maxAutoInstances: 10
|
|
84
|
+
},
|
|
85
|
+
autoUpdate: {
|
|
86
|
+
checkOnBoot: true,
|
|
87
|
+
autoInstall: false,
|
|
88
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/lib/runtime-table.ts
|
|
93
|
+
var RUNTIME_TABLE = {
|
|
94
|
+
codex: {
|
|
95
|
+
binary: "codex",
|
|
96
|
+
launchMode: "exec",
|
|
97
|
+
autoApproveFlag: "--full-auto",
|
|
98
|
+
inlineFlag: "--no-alt-screen",
|
|
99
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
100
|
+
defaultModel: "gpt-5.4"
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var DEFAULT_RUNTIME = "claude";
|
|
104
|
+
|
|
105
|
+
// src/lib/agent-config.ts
|
|
106
|
+
var AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
|
|
107
|
+
var KNOWN_RUNTIMES = {
|
|
108
|
+
claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-3.5"],
|
|
109
|
+
codex: ["gpt-5.4", "gpt-5.5", "o3", "o4-mini"],
|
|
110
|
+
opencode: ["minimax-m2.7"]
|
|
111
|
+
};
|
|
112
|
+
var DEFAULT_MODELS = {
|
|
113
|
+
claude: "claude-opus-4",
|
|
114
|
+
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
115
|
+
opencode: "minimax-m2.7"
|
|
116
|
+
};
|
|
117
|
+
function loadAgentConfig() {
|
|
118
|
+
if (!existsSync2(AGENT_CONFIG_PATH)) return {};
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
|
|
121
|
+
} catch {
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function saveAgentConfig(config) {
|
|
126
|
+
const dir = path2.dirname(AGENT_CONFIG_PATH);
|
|
127
|
+
if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
|
|
128
|
+
writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
129
|
+
}
|
|
130
|
+
function getAgentRuntime(agentId) {
|
|
131
|
+
const config = loadAgentConfig();
|
|
132
|
+
const entry = config[agentId];
|
|
133
|
+
if (entry) return entry;
|
|
134
|
+
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
135
|
+
}
|
|
136
|
+
function setAgentRuntime(agentId, runtime, model) {
|
|
137
|
+
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
138
|
+
if (!knownModels) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (!knownModels.includes(model)) {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const config = loadAgentConfig();
|
|
151
|
+
config[agentId] = { runtime, model };
|
|
152
|
+
saveAgentConfig(config);
|
|
153
|
+
return { ok: true };
|
|
154
|
+
}
|
|
155
|
+
function clearAgentRuntime(agentId) {
|
|
156
|
+
const config = loadAgentConfig();
|
|
157
|
+
delete config[agentId];
|
|
158
|
+
saveAgentConfig(config);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/lib/employees.ts
|
|
162
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
163
|
+
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
164
|
+
import { execSync } from "child_process";
|
|
165
|
+
import path3 from "path";
|
|
166
|
+
import os2 from "os";
|
|
167
|
+
var EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
|
|
168
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
169
|
+
if (!existsSync3(employeesPath)) return [];
|
|
170
|
+
try {
|
|
171
|
+
return JSON.parse(readFileSync3(employeesPath, "utf-8"));
|
|
172
|
+
} catch {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/bin/exe-agent-config.ts
|
|
178
|
+
function showAll() {
|
|
179
|
+
const config = loadAgentConfig();
|
|
180
|
+
let employees = [];
|
|
181
|
+
try {
|
|
182
|
+
employees = loadEmployeesSync();
|
|
183
|
+
} catch {
|
|
184
|
+
process.stderr.write("Warning: could not load employee roster\n");
|
|
185
|
+
}
|
|
186
|
+
if (employees.length === 0) {
|
|
187
|
+
console.log("No employees in roster.");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
console.log("");
|
|
191
|
+
console.log("Agent Runtime Configuration");
|
|
192
|
+
console.log("\u2550".repeat(65));
|
|
193
|
+
console.log(
|
|
194
|
+
"Agent".padEnd(10) + "Role".padEnd(22) + "Runtime".padEnd(12) + "Model"
|
|
195
|
+
);
|
|
196
|
+
console.log("\u2500".repeat(65));
|
|
197
|
+
for (const emp of employees) {
|
|
198
|
+
const entry = config[emp.name];
|
|
199
|
+
const runtime = entry?.runtime ?? DEFAULT_RUNTIME;
|
|
200
|
+
const model = entry?.model ?? DEFAULT_MODELS[DEFAULT_RUNTIME];
|
|
201
|
+
const configured = entry ? "" : " (default)";
|
|
202
|
+
const role = (emp.role ?? "").length > 20 ? (emp.role ?? "").slice(0, 18) + ".." : emp.role ?? "";
|
|
203
|
+
console.log(
|
|
204
|
+
emp.name.padEnd(10) + role.padEnd(22) + runtime.padEnd(12) + model + configured
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
console.log("\u2500".repeat(65));
|
|
208
|
+
console.log("");
|
|
209
|
+
console.log("Available runtimes:");
|
|
210
|
+
for (const [rt, models] of Object.entries(KNOWN_RUNTIMES)) {
|
|
211
|
+
console.log(` ${rt}: ${models.join(", ")}`);
|
|
212
|
+
}
|
|
213
|
+
console.log("");
|
|
214
|
+
}
|
|
215
|
+
function main() {
|
|
216
|
+
const args = process.argv.slice(2);
|
|
217
|
+
if (args.length === 0) {
|
|
218
|
+
showAll();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const agentId = args[0];
|
|
222
|
+
if (args[1] === "--clear") {
|
|
223
|
+
clearAgentRuntime(agentId);
|
|
224
|
+
console.log(`Cleared config for ${agentId} \u2014 will use defaults.`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (args.length < 3) {
|
|
228
|
+
const rt = getAgentRuntime(agentId);
|
|
229
|
+
console.log(`${agentId}: runtime=${rt.runtime} model=${rt.model}`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const runtime = args[1];
|
|
233
|
+
const model = args[2];
|
|
234
|
+
const result = setAgentRuntime(agentId, runtime, model);
|
|
235
|
+
if (!result.ok) {
|
|
236
|
+
process.stderr.write(`Error: ${result.error}
|
|
237
|
+
`);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
console.log(`Set ${agentId} \u2192 runtime=${runtime} model=${model}`);
|
|
241
|
+
}
|
|
242
|
+
main();
|
package/dist/bin/exe-agent.js
CHANGED
|
@@ -916,7 +916,7 @@ async function renderAgentEvents(events, renderer) {
|
|
|
916
916
|
}
|
|
917
917
|
}
|
|
918
918
|
|
|
919
|
-
// src/
|
|
919
|
+
// src/lib/providers/anthropic.ts
|
|
920
920
|
import Anthropic from "@anthropic-ai/sdk";
|
|
921
921
|
var AnthropicProvider = class {
|
|
922
922
|
name;
|
|
@@ -1012,7 +1012,7 @@ var AnthropicProvider = class {
|
|
|
1012
1012
|
}
|
|
1013
1013
|
};
|
|
1014
1014
|
|
|
1015
|
-
// src/
|
|
1015
|
+
// src/lib/providers/openai-compat.ts
|
|
1016
1016
|
import OpenAI from "openai";
|
|
1017
1017
|
import { randomUUID } from "crypto";
|
|
1018
1018
|
var OpenAICompatProvider = class {
|
|
@@ -1148,7 +1148,7 @@ var OpenAICompatProvider = class {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
};
|
|
1150
1150
|
|
|
1151
|
-
// src/
|
|
1151
|
+
// src/lib/providers/ollama.ts
|
|
1152
1152
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1153
1153
|
var OllamaProvider = class {
|
|
1154
1154
|
name;
|