@askexenow/exe-os 0.8.0

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/bin/backfill-responses.js +1912 -0
  4. package/dist/bin/backfill-vectors.js +1642 -0
  5. package/dist/bin/cleanup-stale-review-tasks.js +1339 -0
  6. package/dist/bin/cli.js +18800 -0
  7. package/dist/bin/exe-agent.js +1858 -0
  8. package/dist/bin/exe-assign.js +1957 -0
  9. package/dist/bin/exe-boot.js +6460 -0
  10. package/dist/bin/exe-call.js +197 -0
  11. package/dist/bin/exe-cloud.js +850 -0
  12. package/dist/bin/exe-dispatch.js +1146 -0
  13. package/dist/bin/exe-doctor.js +1657 -0
  14. package/dist/bin/exe-export-behaviors.js +1494 -0
  15. package/dist/bin/exe-forget.js +1627 -0
  16. package/dist/bin/exe-gateway.js +7732 -0
  17. package/dist/bin/exe-healthcheck.js +207 -0
  18. package/dist/bin/exe-heartbeat.js +1647 -0
  19. package/dist/bin/exe-kill.js +1479 -0
  20. package/dist/bin/exe-launch-agent.js +1704 -0
  21. package/dist/bin/exe-link.js +192 -0
  22. package/dist/bin/exe-new-employee.js +852 -0
  23. package/dist/bin/exe-pending-messages.js +1446 -0
  24. package/dist/bin/exe-pending-notifications.js +1321 -0
  25. package/dist/bin/exe-pending-reviews.js +1468 -0
  26. package/dist/bin/exe-repo-drift.js +95 -0
  27. package/dist/bin/exe-review.js +1590 -0
  28. package/dist/bin/exe-search.js +2651 -0
  29. package/dist/bin/exe-session-cleanup.js +3173 -0
  30. package/dist/bin/exe-settings.js +354 -0
  31. package/dist/bin/exe-status.js +1532 -0
  32. package/dist/bin/exe-team.js +1324 -0
  33. package/dist/bin/git-sweep.js +2185 -0
  34. package/dist/bin/graph-backfill.js +1968 -0
  35. package/dist/bin/graph-export.js +1604 -0
  36. package/dist/bin/install.js +656 -0
  37. package/dist/bin/list-providers.js +140 -0
  38. package/dist/bin/scan-tasks.js +1820 -0
  39. package/dist/bin/setup.js +951 -0
  40. package/dist/bin/shard-migrate.js +1494 -0
  41. package/dist/bin/update.js +95 -0
  42. package/dist/bin/wiki-sync.js +1514 -0
  43. package/dist/gateway/index.js +8848 -0
  44. package/dist/hooks/bug-report-worker.js +2743 -0
  45. package/dist/hooks/commit-complete.js +2108 -0
  46. package/dist/hooks/error-recall.js +2861 -0
  47. package/dist/hooks/exe-heartbeat-hook.js +232 -0
  48. package/dist/hooks/ingest-worker.js +4793 -0
  49. package/dist/hooks/ingest.js +684 -0
  50. package/dist/hooks/instructions-loaded.js +1880 -0
  51. package/dist/hooks/notification.js +1726 -0
  52. package/dist/hooks/post-compact.js +1751 -0
  53. package/dist/hooks/pre-compact.js +1746 -0
  54. package/dist/hooks/pre-tool-use.js +2191 -0
  55. package/dist/hooks/prompt-ingest-worker.js +2126 -0
  56. package/dist/hooks/prompt-submit.js +4693 -0
  57. package/dist/hooks/response-ingest-worker.js +1936 -0
  58. package/dist/hooks/session-end.js +1752 -0
  59. package/dist/hooks/session-start.js +2795 -0
  60. package/dist/hooks/stop.js +1835 -0
  61. package/dist/hooks/subagent-stop.js +1726 -0
  62. package/dist/hooks/summary-worker.js +2661 -0
  63. package/dist/index.js +11834 -0
  64. package/dist/lib/cloud-sync.js +495 -0
  65. package/dist/lib/config.js +222 -0
  66. package/dist/lib/consolidation.js +476 -0
  67. package/dist/lib/crypto.js +51 -0
  68. package/dist/lib/database.js +730 -0
  69. package/dist/lib/device-registry.js +900 -0
  70. package/dist/lib/embedder.js +632 -0
  71. package/dist/lib/employee-templates.js +543 -0
  72. package/dist/lib/employees.js +177 -0
  73. package/dist/lib/error-detector.js +156 -0
  74. package/dist/lib/exe-daemon-client.js +451 -0
  75. package/dist/lib/exe-daemon.js +8285 -0
  76. package/dist/lib/file-grep.js +199 -0
  77. package/dist/lib/hybrid-search.js +1819 -0
  78. package/dist/lib/identity-templates.js +320 -0
  79. package/dist/lib/identity.js +223 -0
  80. package/dist/lib/keychain.js +145 -0
  81. package/dist/lib/license.js +377 -0
  82. package/dist/lib/messaging.js +1376 -0
  83. package/dist/lib/reminders.js +63 -0
  84. package/dist/lib/schedules.js +1396 -0
  85. package/dist/lib/session-registry.js +52 -0
  86. package/dist/lib/skill-learning.js +477 -0
  87. package/dist/lib/status-brief.js +235 -0
  88. package/dist/lib/store.js +1551 -0
  89. package/dist/lib/task-router.js +62 -0
  90. package/dist/lib/tasks.js +2456 -0
  91. package/dist/lib/tmux-routing.js +2836 -0
  92. package/dist/lib/tmux-status.js +261 -0
  93. package/dist/lib/tmux-transport.js +83 -0
  94. package/dist/lib/transport.js +128 -0
  95. package/dist/lib/ws-auth.js +19 -0
  96. package/dist/lib/ws-client.js +160 -0
  97. package/dist/mcp/server.js +10538 -0
  98. package/dist/mcp/tools/complete-reminder.js +67 -0
  99. package/dist/mcp/tools/create-reminder.js +52 -0
  100. package/dist/mcp/tools/create-task.js +1853 -0
  101. package/dist/mcp/tools/deactivate-behavior.js +263 -0
  102. package/dist/mcp/tools/list-reminders.js +62 -0
  103. package/dist/mcp/tools/list-tasks.js +463 -0
  104. package/dist/mcp/tools/send-message.js +1382 -0
  105. package/dist/mcp/tools/update-task.js +1692 -0
  106. package/dist/runtime/index.js +6809 -0
  107. package/dist/tui/App.js +17479 -0
  108. package/package.json +104 -0
  109. package/src/commands/exe/assign.md +17 -0
  110. package/src/commands/exe/build-adv.md +381 -0
  111. package/src/commands/exe/call.md +133 -0
  112. package/src/commands/exe/cloud.md +17 -0
  113. package/src/commands/exe/employee-heartbeat.md +44 -0
  114. package/src/commands/exe/forget.md +15 -0
  115. package/src/commands/exe/heartbeat.md +92 -0
  116. package/src/commands/exe/intercom.md +81 -0
  117. package/src/commands/exe/kill.md +34 -0
  118. package/src/commands/exe/launch.md +52 -0
  119. package/src/commands/exe/link.md +17 -0
  120. package/src/commands/exe/logs.md +22 -0
  121. package/src/commands/exe/new-employee.md +12 -0
  122. package/src/commands/exe/review.md +14 -0
  123. package/src/commands/exe/schedule.md +108 -0
  124. package/src/commands/exe/search.md +13 -0
  125. package/src/commands/exe/sessions.md +25 -0
  126. package/src/commands/exe/settings.md +13 -0
  127. package/src/commands/exe/setup.md +171 -0
  128. package/src/commands/exe/status.md +15 -0
  129. package/src/commands/exe/team.md +11 -0
  130. package/src/commands/exe/update.md +11 -0
  131. package/src/commands/exe.md +181 -0
@@ -0,0 +1,177 @@
1
+ // src/lib/employees.ts
2
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
3
+ import { existsSync as existsSync2, symlinkSync, readlinkSync } from "fs";
4
+ import { execSync } from "child_process";
5
+ import path2 from "path";
6
+
7
+ // src/lib/config.ts
8
+ import { readFile, writeFile, mkdir } 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
+ exe: "Executive",
69
+ yoshi: "Engineering",
70
+ mari: "Marketing",
71
+ tom: "Engineering",
72
+ sasha: "Production"
73
+ },
74
+ wikiAutoUpdate: true,
75
+ wikiAutoUpdateThreshold: 0.5,
76
+ wikiAutoUpdateCreateNew: true,
77
+ skillLearning: true,
78
+ skillThreshold: 3,
79
+ skillModel: "claude-haiku-4-5-20251001",
80
+ exeHeartbeat: {
81
+ enabled: true,
82
+ intervalSeconds: 60,
83
+ staleInProgressThresholdHours: 2
84
+ },
85
+ sessionLifecycle: {
86
+ idleKillEnabled: true,
87
+ idleKillTicksRequired: 3,
88
+ idleKillIntercomAckWindowMs: 1e4,
89
+ maxAutoInstances: 10
90
+ }
91
+ };
92
+
93
+ // src/lib/employees.ts
94
+ var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
95
+ function validateEmployeeName(name) {
96
+ if (!name) {
97
+ return { valid: false, error: "Name is required" };
98
+ }
99
+ if (name.length > 32) {
100
+ return { valid: false, error: "Name must be 32 characters or fewer" };
101
+ }
102
+ if (!/^[a-z][a-z0-9]*$/.test(name)) {
103
+ return {
104
+ valid: false,
105
+ error: "Name must start with a letter and contain only lowercase alphanumeric characters"
106
+ };
107
+ }
108
+ return { valid: true };
109
+ }
110
+ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
111
+ if (!existsSync2(employeesPath)) {
112
+ return [];
113
+ }
114
+ const raw = await readFile2(employeesPath, "utf-8");
115
+ try {
116
+ return JSON.parse(raw);
117
+ } catch {
118
+ return [];
119
+ }
120
+ }
121
+ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
122
+ await mkdir2(path2.dirname(employeesPath), { recursive: true });
123
+ await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
124
+ }
125
+ function getEmployee(employees, name) {
126
+ return employees.find((e) => e.name === name);
127
+ }
128
+ function addEmployee(employees, employee) {
129
+ if (employees.some((e) => e.name === employee.name)) {
130
+ throw new Error(`Employee '${employee.name}' already exists`);
131
+ }
132
+ return [...employees, employee];
133
+ }
134
+ function registerBinSymlinks(name) {
135
+ const created = [];
136
+ const skipped = [];
137
+ const errors = [];
138
+ let exeBinPath;
139
+ try {
140
+ exeBinPath = execSync("which exe", { encoding: "utf-8" }).trim();
141
+ } catch {
142
+ errors.push("Could not find 'exe' in PATH");
143
+ return { created, skipped, errors };
144
+ }
145
+ const binDir = path2.dirname(exeBinPath);
146
+ let target;
147
+ try {
148
+ target = readlinkSync(exeBinPath);
149
+ } catch {
150
+ errors.push("Could not read 'exe' symlink");
151
+ return { created, skipped, errors };
152
+ }
153
+ for (const suffix of ["", "-opencode"]) {
154
+ const linkName = `${name}${suffix}`;
155
+ const linkPath = path2.join(binDir, linkName);
156
+ if (existsSync2(linkPath)) {
157
+ skipped.push(linkName);
158
+ continue;
159
+ }
160
+ try {
161
+ symlinkSync(target, linkPath);
162
+ created.push(linkName);
163
+ } catch (err) {
164
+ errors.push(`${linkName}: ${err instanceof Error ? err.message : String(err)}`);
165
+ }
166
+ }
167
+ return { created, skipped, errors };
168
+ }
169
+ export {
170
+ EMPLOYEES_PATH,
171
+ addEmployee,
172
+ getEmployee,
173
+ loadEmployees,
174
+ registerBinSymlinks,
175
+ saveEmployees,
176
+ validateEmployeeName
177
+ };
@@ -0,0 +1,156 @@
1
+ // src/lib/error-detector.ts
2
+ import crypto from "crypto";
3
+
4
+ // src/lib/mcp-prefix.ts
5
+ var MCP_PRIMARY_KEY = "exe-os";
6
+ var MCP_LEGACY_KEY = "exe-mem";
7
+ var MCP_TOOL_PREFIXES = [
8
+ `mcp__${MCP_PRIMARY_KEY}__`,
9
+ `mcp__${MCP_LEGACY_KEY}__`
10
+ ];
11
+ function isExeMcpTool(toolName) {
12
+ if (!toolName) return false;
13
+ return MCP_TOOL_PREFIXES.some((p) => toolName.startsWith(p));
14
+ }
15
+
16
+ // src/lib/error-detector.ts
17
+ var ERROR_PATTERNS = [
18
+ /\bError\b/i,
19
+ /\bERR!\b/,
20
+ /\bFAIL(ED|URE)?\b/i,
21
+ /\bException\b/i,
22
+ /\bTraceback\b/,
23
+ /\bpanic\b/,
24
+ /\bSIGSEGV\b/,
25
+ /\bSIGABRT\b/,
26
+ /exit code [1-9]/i,
27
+ /non-zero (exit|status)/i,
28
+ /command not found/i,
29
+ /permission denied/i,
30
+ /ENOENT/,
31
+ /EACCES/,
32
+ /ENOMEM/
33
+ ];
34
+ var FILE_CONTENT_TOOLS = /* @__PURE__ */ new Set([
35
+ "Read",
36
+ "Write",
37
+ "Edit",
38
+ "Glob",
39
+ "Grep",
40
+ "NotebookEdit"
41
+ ]);
42
+ var STDERR_IGNORE_PATTERNS = [
43
+ /^warning\b/i,
44
+ /\bDeprecationWarning\b/,
45
+ /^hint:/i,
46
+ /^npm warn\b/i,
47
+ /^npm notice\b/i,
48
+ /^\(node:\d+\) \w*Warning:/,
49
+ /^Cloning into/,
50
+ /^Already on/,
51
+ /^Switched to/,
52
+ /^Your branch is/,
53
+ /^Auto-merging/,
54
+ /^\s*$/
55
+ ];
56
+ function isRealStderr(stderr) {
57
+ const lines = stderr.trim().split("\n");
58
+ const meaningful = lines.filter(
59
+ (line) => line.trim().length > 0 && !STDERR_IGNORE_PATTERNS.some((p) => p.test(line))
60
+ );
61
+ return meaningful.length > 0;
62
+ }
63
+ function logSuppression(exitCode, stderr, stdout) {
64
+ process.stderr.write(
65
+ `[error-detector] suppressed bash non-zero exit: code=${exitCode} stderr_len=${stderr.length} stdout_len=${stdout.length}
66
+ `
67
+ );
68
+ }
69
+ function detectError(data) {
70
+ const response = data.tool_response;
71
+ if (!response) return false;
72
+ const toolName = data.tool_name ?? "";
73
+ if (FILE_CONTENT_TOOLS.has(toolName)) {
74
+ return response.type === "error" || response.error != null;
75
+ }
76
+ if (toolName === "Bash") {
77
+ const exitCode = typeof response.exitCode === "number" ? response.exitCode : 0;
78
+ const stderr = typeof response.stderr === "string" ? response.stderr : "";
79
+ const stdout = typeof response.stdout === "string" ? response.stdout : "";
80
+ if (exitCode === 141) {
81
+ logSuppression(exitCode, stderr, stdout);
82
+ return false;
83
+ }
84
+ if (stderr.trim().length > 0 && isRealStderr(stderr)) return true;
85
+ if (exitCode !== 0 && !isRealStderr(stderr) && stdout.trim().length > 0) {
86
+ logSuppression(exitCode, stderr, stdout);
87
+ return false;
88
+ }
89
+ if (exitCode !== 0) return true;
90
+ return false;
91
+ }
92
+ if (response.type === "error" || response.error != null || response.isError === true) {
93
+ return true;
94
+ }
95
+ if (typeof response.stderr === "string" && response.stderr.trim().length > 0) {
96
+ if (isRealStderr(response.stderr)) return true;
97
+ }
98
+ const textParts = [];
99
+ if (typeof response.stdout === "string") textParts.push(response.stdout);
100
+ if (typeof response.output === "string") textParts.push(response.output);
101
+ if (typeof response.text === "string") textParts.push(response.text);
102
+ if (typeof response.message === "string") textParts.push(response.message);
103
+ if (textParts.length === 0) return false;
104
+ const text = textParts.join("\n");
105
+ return ERROR_PATTERNS.some((pattern) => pattern.test(text));
106
+ }
107
+ function isExeOsError(data) {
108
+ const toolName = data.tool_name ?? "";
109
+ if (isExeMcpTool(toolName)) return true;
110
+ if (toolName === "Bash") {
111
+ const cmd = String(data.tool_input?.command ?? "");
112
+ if (/\bexe-os\b|exe-boot|exe-healthcheck|scan-tasks|exe-call/.test(cmd)) return true;
113
+ if (/node.*dist\/(bin|hooks|lib)\//.test(cmd)) return true;
114
+ }
115
+ return false;
116
+ }
117
+ var USER_ERROR_PATTERNS = [
118
+ /not found:?\s/i,
119
+ /expected \d+ words/i,
120
+ /provide either/i,
121
+ /invalid.*parameter/i,
122
+ /already exists/i,
123
+ /Multiple tasks match/i,
124
+ /Use a more specific identifier/i
125
+ ];
126
+ var SYSTEM_BUG_PATTERNS = [
127
+ /SQLITE_ERROR/,
128
+ /Cannot find module/,
129
+ /ERR_MODULE_NOT_FOUND/,
130
+ /TypeError:/,
131
+ /ReferenceError:/,
132
+ /Cannot read propert/,
133
+ /is not a function/,
134
+ /ENOENT.*dist\//,
135
+ /dimension mismatch/i,
136
+ /unhealthy.*model/i,
137
+ /constraint.*violat/i
138
+ ];
139
+ function classifyError(errorText) {
140
+ if (USER_ERROR_PATTERNS.some((p) => p.test(errorText))) return "user";
141
+ if (SYSTEM_BUG_PATTERNS.some((p) => p.test(errorText))) return "system";
142
+ if (/at\s+\S+\s+\(.*exe-os.*\)/m.test(errorText)) return "system";
143
+ if (/at\s+\S+\s+\(.*dist\/(lib|bin|hooks|mcp)\//m.test(errorText)) return "system";
144
+ return "unknown";
145
+ }
146
+ function errorFingerprint(toolName, errorText) {
147
+ const normalized = errorText.replace(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/g, "TIMESTAMP").replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "UUID").replace(/\/Users\/[^\s]+/g, "PATH").replace(/:\d+:\d+/g, ":LINE:COL").slice(0, 200);
148
+ return crypto.createHash("sha256").update(`${toolName}:${normalized}`).digest("hex").slice(0, 16);
149
+ }
150
+ export {
151
+ ERROR_PATTERNS,
152
+ classifyError,
153
+ detectError,
154
+ errorFingerprint,
155
+ isExeOsError
156
+ };