@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.
Files changed (57) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +57 -19
  2. package/dist/bin/cli.js +510 -340
  3. package/dist/bin/exe-agent-config.js +242 -0
  4. package/dist/bin/exe-agent.js +3 -3
  5. package/dist/bin/exe-boot.js +344 -346
  6. package/dist/bin/exe-dispatch.js +375 -250
  7. package/dist/bin/exe-forget.js +5 -1
  8. package/dist/bin/exe-gateway.js +260 -135
  9. package/dist/bin/exe-healthcheck.js +133 -1
  10. package/dist/bin/exe-heartbeat.js +72 -31
  11. package/dist/bin/exe-link.js +25 -2
  12. package/dist/bin/exe-new-employee.js +22 -0
  13. package/dist/bin/exe-pending-messages.js +55 -17
  14. package/dist/bin/exe-pending-reviews.js +57 -19
  15. package/dist/bin/exe-search.js +6 -2
  16. package/dist/bin/exe-session-cleanup.js +260 -135
  17. package/dist/bin/exe-start-codex.js +2598 -0
  18. package/dist/bin/exe-start.sh +15 -3
  19. package/dist/bin/exe-status.js +57 -19
  20. package/dist/bin/git-sweep.js +391 -266
  21. package/dist/bin/install.js +22 -0
  22. package/dist/bin/scan-tasks.js +394 -269
  23. package/dist/bin/setup.js +50 -5
  24. package/dist/gateway/index.js +257 -132
  25. package/dist/hooks/bug-report-worker.js +242 -117
  26. package/dist/hooks/commit-complete.js +389 -264
  27. package/dist/hooks/error-recall.js +6 -2
  28. package/dist/hooks/ingest-worker.js +314 -193
  29. package/dist/hooks/post-compact.js +84 -46
  30. package/dist/hooks/pre-compact.js +272 -147
  31. package/dist/hooks/pre-tool-use.js +104 -66
  32. package/dist/hooks/prompt-submit.js +126 -66
  33. package/dist/hooks/session-end.js +277 -152
  34. package/dist/hooks/session-start.js +70 -28
  35. package/dist/hooks/stop.js +90 -52
  36. package/dist/hooks/subagent-stop.js +84 -46
  37. package/dist/hooks/summary-worker.js +175 -114
  38. package/dist/index.js +296 -171
  39. package/dist/lib/agent-config.js +167 -0
  40. package/dist/lib/cloud-sync.js +25 -2
  41. package/dist/lib/exe-daemon.js +338 -213
  42. package/dist/lib/hybrid-search.js +7 -2
  43. package/dist/lib/messaging.js +95 -39
  44. package/dist/lib/runtime-table.js +16 -0
  45. package/dist/lib/session-wrappers.js +22 -0
  46. package/dist/lib/tasks.js +242 -117
  47. package/dist/lib/tmux-routing.js +314 -189
  48. package/dist/mcp/server.js +573 -274
  49. package/dist/mcp/tools/create-task.js +260 -135
  50. package/dist/mcp/tools/list-tasks.js +68 -30
  51. package/dist/mcp/tools/send-message.js +100 -44
  52. package/dist/mcp/tools/update-task.js +123 -67
  53. package/dist/runtime/index.js +276 -151
  54. package/dist/tui/App.js +479 -354
  55. package/package.json +1 -1
  56. package/src/commands/exe/agent-config.md +27 -0
  57. 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();
@@ -916,7 +916,7 @@ async function renderAgentEvents(events, renderer) {
916
916
  }
917
917
  }
918
918
 
919
- // src/gateway/providers/anthropic.ts
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/gateway/providers/openai-compat.ts
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/gateway/providers/ollama.ts
1151
+ // src/lib/providers/ollama.ts
1152
1152
  import { randomUUID as randomUUID2 } from "crypto";
1153
1153
  var OllamaProvider = class {
1154
1154
  name;