@askexenow/exe-os 0.9.65 → 0.9.67

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 (113) hide show
  1. package/deploy/stack-manifests/v0.9.json +54 -5
  2. package/dist/bin/age-ontology-load.js +61 -0
  3. package/dist/bin/agentic-ontology-backfill.js +4708 -0
  4. package/dist/bin/agentic-reflection-backfill.js +4144 -0
  5. package/dist/bin/{exe-link.js → agentic-semantic-label.js} +1532 -2173
  6. package/dist/bin/backfill-conversations.js +528 -20
  7. package/dist/bin/backfill-responses.js +528 -20
  8. package/dist/bin/backfill-vectors.js +255 -20
  9. package/dist/bin/bulk-sync-postgres.js +4876 -0
  10. package/dist/bin/cleanup-stale-review-tasks.js +529 -21
  11. package/dist/bin/cli.js +3471 -1491
  12. package/dist/bin/exe-agent-config.js +4 -0
  13. package/dist/bin/exe-agent.js +16 -0
  14. package/dist/bin/exe-assign.js +528 -20
  15. package/dist/bin/exe-boot.js +492 -54
  16. package/dist/bin/exe-call.js +16 -0
  17. package/dist/bin/exe-cloud.js +7415 -518
  18. package/dist/bin/exe-dispatch.js +540 -22
  19. package/dist/bin/exe-doctor.js +3404 -1225
  20. package/dist/bin/exe-export-behaviors.js +542 -24
  21. package/dist/bin/exe-forget.js +529 -21
  22. package/dist/bin/exe-gateway.js +595 -25
  23. package/dist/bin/exe-heartbeat.js +541 -24
  24. package/dist/bin/exe-kill.js +529 -21
  25. package/dist/bin/exe-launch-agent.js +2334 -1067
  26. package/dist/bin/exe-new-employee.js +324 -166
  27. package/dist/bin/exe-pending-messages.js +529 -21
  28. package/dist/bin/exe-pending-notifications.js +529 -21
  29. package/dist/bin/exe-pending-reviews.js +529 -21
  30. package/dist/bin/exe-rename.js +529 -21
  31. package/dist/bin/exe-review.js +529 -21
  32. package/dist/bin/exe-search.js +542 -24
  33. package/dist/bin/exe-session-cleanup.js +540 -22
  34. package/dist/bin/exe-settings.js +14 -0
  35. package/dist/bin/exe-start-codex.js +817 -144
  36. package/dist/bin/exe-start-opencode.js +776 -80
  37. package/dist/bin/exe-status.js +529 -21
  38. package/dist/bin/exe-team.js +529 -21
  39. package/dist/bin/git-sweep.js +540 -22
  40. package/dist/bin/graph-backfill.js +580 -21
  41. package/dist/bin/graph-export.js +529 -21
  42. package/dist/bin/graph-layer-benchmark.js +109 -0
  43. package/dist/bin/install.js +420 -289
  44. package/dist/bin/intercom-check.js +540 -22
  45. package/dist/bin/postgres-agentic-reflection-backfill.js +187 -0
  46. package/dist/bin/postgres-agentic-semantic-backfill.js +237 -0
  47. package/dist/bin/scan-tasks.js +540 -22
  48. package/dist/bin/setup.js +790 -206
  49. package/dist/bin/shard-migrate.js +528 -20
  50. package/dist/bin/update.js +4 -0
  51. package/dist/gateway/index.js +593 -23
  52. package/dist/hooks/bug-report-worker.js +651 -64
  53. package/dist/hooks/codex-stop-task-finalizer.js +540 -22
  54. package/dist/hooks/commit-complete.js +540 -22
  55. package/dist/hooks/error-recall.js +542 -24
  56. package/dist/hooks/exe-heartbeat-hook.js +4 -0
  57. package/dist/hooks/ingest-worker.js +4 -0
  58. package/dist/hooks/ingest.js +539 -22
  59. package/dist/hooks/instructions-loaded.js +529 -21
  60. package/dist/hooks/notification.js +529 -21
  61. package/dist/hooks/post-compact.js +529 -21
  62. package/dist/hooks/post-tool-combined.js +543 -25
  63. package/dist/hooks/pre-compact.js +772 -127
  64. package/dist/hooks/pre-tool-use.js +529 -21
  65. package/dist/hooks/prompt-submit.js +543 -25
  66. package/dist/hooks/session-end.js +673 -140
  67. package/dist/hooks/session-start.js +662 -26
  68. package/dist/hooks/stop.js +540 -23
  69. package/dist/hooks/subagent-stop.js +529 -21
  70. package/dist/hooks/summary-worker.js +571 -126
  71. package/dist/index.js +593 -23
  72. package/dist/lib/agent-config.js +4 -0
  73. package/dist/lib/cloud-sync.js +408 -47
  74. package/dist/lib/config.js +25 -1
  75. package/dist/lib/consolidation.js +5 -1
  76. package/dist/lib/database.js +128 -0
  77. package/dist/lib/db-daemon-client.js +4 -0
  78. package/dist/lib/db.js +128 -0
  79. package/dist/lib/device-registry.js +128 -0
  80. package/dist/lib/embedder.js +25 -1
  81. package/dist/lib/employee-templates.js +16 -0
  82. package/dist/lib/employees.js +4 -0
  83. package/dist/lib/exe-daemon-client.js +4 -0
  84. package/dist/lib/exe-daemon.js +3158 -930
  85. package/dist/lib/hybrid-search.js +542 -24
  86. package/dist/lib/identity.js +7 -0
  87. package/dist/lib/keychain.js +178 -22
  88. package/dist/lib/license.js +4 -0
  89. package/dist/lib/messaging.js +7 -0
  90. package/dist/lib/reminders.js +7 -0
  91. package/dist/lib/schedules.js +255 -20
  92. package/dist/lib/skill-learning.js +28 -1
  93. package/dist/lib/status-brief.js +39 -0
  94. package/dist/lib/store.js +528 -20
  95. package/dist/lib/task-router.js +4 -0
  96. package/dist/lib/tasks.js +28 -1
  97. package/dist/lib/tmux-routing.js +28 -1
  98. package/dist/lib/token-spend.js +7 -0
  99. package/dist/mcp/server.js +2739 -813
  100. package/dist/mcp/tools/complete-reminder.js +7 -0
  101. package/dist/mcp/tools/create-reminder.js +7 -0
  102. package/dist/mcp/tools/create-task.js +28 -1
  103. package/dist/mcp/tools/deactivate-behavior.js +7 -0
  104. package/dist/mcp/tools/list-reminders.js +7 -0
  105. package/dist/mcp/tools/list-tasks.js +7 -0
  106. package/dist/mcp/tools/send-message.js +7 -0
  107. package/dist/mcp/tools/update-task.js +28 -1
  108. package/dist/runtime/index.js +540 -22
  109. package/dist/tui/App.js +618 -29
  110. package/package.json +9 -5
  111. package/src/commands/exe/cloud.md +11 -8
  112. package/stack.release.json +3 -3
  113. package/src/commands/exe/link.md +0 -17
@@ -99,6 +99,10 @@ var init_config = __esm({
99
99
  checkOnBoot: true,
100
100
  autoInstall: false,
101
101
  checkIntervalMs: 24 * 60 * 60 * 1e3
102
+ },
103
+ orchestration: {
104
+ phase: "phase_1_coo",
105
+ phaseSetBy: "default"
102
106
  }
103
107
  };
104
108
  }
@@ -156,6 +160,9 @@ function getClient() {
156
160
  if (_daemonClient && _daemonClient._isDaemonActive()) {
157
161
  return _daemonClient;
158
162
  }
163
+ if (!_resilientClient) {
164
+ return _adapterClient;
165
+ }
159
166
  return _resilientClient;
160
167
  }
161
168
 
@@ -7,11 +7,12 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
 
8
8
  // src/lib/keychain.ts
9
9
  import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
10
- import { existsSync } from "fs";
10
+ import { existsSync, statSync } from "fs";
11
11
  import { execSync } from "child_process";
12
12
  import path from "path";
13
13
  import os from "os";
14
- var SERVICE = "exe-mem";
14
+ var SERVICE = "exe-os";
15
+ var LEGACY_SERVICE = "exe-mem";
15
16
  var ACCOUNT = "master-key";
16
17
  function getKeyDir() {
17
18
  return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
@@ -19,29 +20,66 @@ function getKeyDir() {
19
20
  function getKeyPath() {
20
21
  return path.join(getKeyDir(), "master.key");
21
22
  }
22
- function macKeychainGet() {
23
+ function nativeKeychainAllowed() {
24
+ return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
25
+ }
26
+ var linuxSecretAvailability = null;
27
+ function linuxSecretAvailable() {
28
+ if (!nativeKeychainAllowed()) return false;
29
+ if (process.platform !== "linux") return false;
30
+ if (linuxSecretAvailability !== null) return linuxSecretAvailability;
31
+ try {
32
+ execSync("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
33
+ } catch {
34
+ linuxSecretAvailability = false;
35
+ return false;
36
+ }
37
+ try {
38
+ execSync("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
39
+ linuxSecretAvailability = true;
40
+ } catch {
41
+ linuxSecretAvailability = false;
42
+ }
43
+ return linuxSecretAvailability;
44
+ }
45
+ function isRootOnlyTrustedServerKeyFile(keyPath) {
46
+ if (process.platform !== "linux") return false;
47
+ try {
48
+ const uid = typeof os.userInfo().uid === "number" ? os.userInfo().uid : -1;
49
+ const st = statSync(keyPath);
50
+ if (!st.isFile() || (st.mode & 63) !== 0) return false;
51
+ if (uid === 0) return true;
52
+ const exeOsDir = process.env.EXE_OS_DIR;
53
+ return Boolean(exeOsDir && path.resolve(keyPath).startsWith(path.resolve(exeOsDir) + path.sep));
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+ function macKeychainGet(service = SERVICE) {
59
+ if (!nativeKeychainAllowed()) return null;
23
60
  if (process.platform !== "darwin") return null;
24
61
  try {
25
62
  return execSync(
26
- `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
63
+ `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
27
64
  { encoding: "utf-8", timeout: 5e3 }
28
65
  ).trim();
29
66
  } catch {
30
67
  return null;
31
68
  }
32
69
  }
33
- function macKeychainSet(value) {
70
+ function macKeychainSet(value, service = SERVICE) {
71
+ if (!nativeKeychainAllowed()) return false;
34
72
  if (process.platform !== "darwin") return false;
35
73
  try {
36
74
  try {
37
75
  execSync(
38
- `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
76
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
39
77
  { timeout: 5e3 }
40
78
  );
41
79
  } catch {
42
80
  }
43
81
  execSync(
44
- `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
82
+ `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
45
83
  { timeout: 5e3 }
46
84
  );
47
85
  return true;
@@ -49,11 +87,12 @@ function macKeychainSet(value) {
49
87
  return false;
50
88
  }
51
89
  }
52
- function macKeychainDelete() {
90
+ function macKeychainDelete(service = SERVICE) {
91
+ if (!nativeKeychainAllowed()) return false;
53
92
  if (process.platform !== "darwin") return false;
54
93
  try {
55
94
  execSync(
56
- `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
95
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
57
96
  { timeout: 5e3 }
58
97
  );
59
98
  return true;
@@ -61,22 +100,22 @@ function macKeychainDelete() {
61
100
  return false;
62
101
  }
63
102
  }
64
- function linuxSecretGet() {
65
- if (process.platform !== "linux") return null;
103
+ function linuxSecretGet(service = SERVICE) {
104
+ if (!linuxSecretAvailable()) return null;
66
105
  try {
67
106
  return execSync(
68
- `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
107
+ `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
69
108
  { encoding: "utf-8", timeout: 5e3 }
70
109
  ).trim();
71
110
  } catch {
72
111
  return null;
73
112
  }
74
113
  }
75
- function linuxSecretSet(value) {
76
- if (process.platform !== "linux") return false;
114
+ function linuxSecretSet(value, service = SERVICE) {
115
+ if (!linuxSecretAvailable()) return false;
77
116
  try {
78
117
  execSync(
79
- `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
118
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
80
119
  { timeout: 5e3 }
81
120
  );
82
121
  return true;
@@ -84,11 +123,12 @@ function linuxSecretSet(value) {
84
123
  return false;
85
124
  }
86
125
  }
87
- function linuxSecretDelete() {
126
+ function linuxSecretDelete(service = SERVICE) {
127
+ if (!nativeKeychainAllowed()) return false;
88
128
  if (process.platform !== "linux") return false;
89
129
  try {
90
130
  execSync(
91
- `secret-tool clear service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
131
+ `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
92
132
  { timeout: 5e3 }
93
133
  );
94
134
  return true;
@@ -97,6 +137,7 @@ function linuxSecretDelete() {
97
137
  }
98
138
  }
99
139
  async function tryKeytar() {
140
+ if (!nativeKeychainAllowed()) return null;
100
141
  try {
101
142
  return await import("keytar");
102
143
  } catch {
@@ -171,7 +212,19 @@ async function writeMachineBoundFileFallback(b64) {
171
212
  return "plaintext";
172
213
  }
173
214
  async function getMasterKey() {
174
- const nativeValue = macKeychainGet() ?? linuxSecretGet();
215
+ let nativeValue = macKeychainGet() ?? linuxSecretGet();
216
+ if (!nativeValue) {
217
+ const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
218
+ if (legacyValue) {
219
+ const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
220
+ if (migrated) {
221
+ macKeychainDelete(LEGACY_SERVICE);
222
+ linuxSecretDelete(LEGACY_SERVICE);
223
+ process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
224
+ }
225
+ nativeValue = legacyValue;
226
+ }
227
+ }
175
228
  if (nativeValue) {
176
229
  return Buffer.from(nativeValue, "base64");
177
230
  }
@@ -179,12 +232,17 @@ async function getMasterKey() {
179
232
  if (keytar) {
180
233
  try {
181
234
  const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
182
- if (keytarValue) {
183
- const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
235
+ const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
236
+ if (legacyKeytarValue) {
237
+ const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
184
238
  if (migrated) {
185
239
  process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
240
+ try {
241
+ await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
242
+ } catch {
243
+ }
186
244
  }
187
- return Buffer.from(keytarValue, "base64");
245
+ return Buffer.from(legacyKeytarValue, "base64");
188
246
  }
189
247
  } catch {
190
248
  }
@@ -209,7 +267,7 @@ async function getMasterKey() {
209
267
  const decrypted = decryptWithMachineKey(content, machineKey);
210
268
  if (!decrypted) {
211
269
  process.stderr.write(
212
- "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
270
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
213
271
  );
214
272
  return null;
215
273
  }
@@ -218,6 +276,9 @@ async function getMasterKey() {
218
276
  b64Value = content;
219
277
  }
220
278
  const key = Buffer.from(b64Value, "base64");
279
+ if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
280
+ return key;
281
+ }
221
282
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
222
283
  if (migrated) {
223
284
  process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
@@ -245,6 +306,97 @@ async function getMasterKey() {
245
306
  return null;
246
307
  }
247
308
  }
309
+ async function getKeyStorageInfo() {
310
+ if (macKeychainGet()) {
311
+ return {
312
+ kind: "macos-keychain",
313
+ secure: true,
314
+ note: "stored in macOS Keychain via built-in security CLI"
315
+ };
316
+ }
317
+ if (macKeychainGet(LEGACY_SERVICE)) {
318
+ return {
319
+ kind: "macos-keychain",
320
+ secure: true,
321
+ note: "stored in legacy macOS Keychain service exe-mem; next key read migrates it to exe-os"
322
+ };
323
+ }
324
+ if (linuxSecretGet()) {
325
+ return {
326
+ kind: "linux-secret-service",
327
+ secure: true,
328
+ note: "stored in Linux Secret Service via secret-tool"
329
+ };
330
+ }
331
+ if (linuxSecretGet(LEGACY_SERVICE)) {
332
+ return {
333
+ kind: "linux-secret-service",
334
+ secure: true,
335
+ note: "stored in legacy Linux Secret Service service exe-mem; next key read migrates it to exe-os"
336
+ };
337
+ }
338
+ const keytar = await tryKeytar();
339
+ if (keytar) {
340
+ try {
341
+ if (await keytar.getPassword(SERVICE, ACCOUNT)) {
342
+ return {
343
+ kind: "legacy-keytar",
344
+ secure: true,
345
+ note: "stored in legacy keytar backend; will migrate to native keychain when possible"
346
+ };
347
+ }
348
+ if (await keytar.getPassword(LEGACY_SERVICE, ACCOUNT)) {
349
+ return {
350
+ kind: "legacy-keytar",
351
+ secure: true,
352
+ note: "stored in legacy keytar service exe-mem; will migrate to native exe-os keychain when possible"
353
+ };
354
+ }
355
+ } catch {
356
+ }
357
+ }
358
+ const keyPath = getKeyPath();
359
+ if (!existsSync(keyPath)) {
360
+ return {
361
+ kind: "missing",
362
+ secure: false,
363
+ path: keyPath,
364
+ note: "no key found in OS keychain, legacy keytar, or file fallback"
365
+ };
366
+ }
367
+ try {
368
+ const content = (await readFile(keyPath, "utf-8")).trim();
369
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
370
+ return {
371
+ kind: "encrypted-file",
372
+ secure: true,
373
+ path: keyPath,
374
+ note: "stored in machine-bound encrypted file fallback"
375
+ };
376
+ }
377
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
378
+ return {
379
+ kind: "server-secret-file",
380
+ secure: true,
381
+ path: keyPath,
382
+ note: "stored as root-only trusted server secret file"
383
+ };
384
+ }
385
+ return {
386
+ kind: "plaintext-file",
387
+ secure: false,
388
+ path: keyPath,
389
+ note: "stored in legacy plaintext file; reading it will migrate or encrypt it"
390
+ };
391
+ } catch {
392
+ return {
393
+ kind: "missing",
394
+ secure: false,
395
+ path: keyPath,
396
+ note: "key file exists but could not be read"
397
+ };
398
+ }
399
+ }
248
400
  async function setMasterKey(key) {
249
401
  const b64 = key.toString("base64");
250
402
  if (macKeychainSet(b64) || linuxSecretSet(b64)) {
@@ -270,10 +422,13 @@ async function setMasterKey(key) {
270
422
  async function deleteMasterKey() {
271
423
  macKeychainDelete();
272
424
  linuxSecretDelete();
425
+ macKeychainDelete(LEGACY_SERVICE);
426
+ linuxSecretDelete(LEGACY_SERVICE);
273
427
  const keytar = await tryKeytar();
274
428
  if (keytar) {
275
429
  try {
276
430
  await keytar.deletePassword(SERVICE, ACCOUNT);
431
+ await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
277
432
  } catch {
278
433
  }
279
434
  }
@@ -314,6 +469,7 @@ async function importMnemonic(mnemonic) {
314
469
  export {
315
470
  deleteMasterKey,
316
471
  exportMnemonic,
472
+ getKeyStorageInfo,
317
473
  getMasterKey,
318
474
  importMnemonic,
319
475
  setMasterKey
@@ -102,6 +102,10 @@ var DEFAULT_CONFIG = {
102
102
  checkOnBoot: true,
103
103
  autoInstall: false,
104
104
  checkIntervalMs: 24 * 60 * 60 * 1e3
105
+ },
106
+ orchestration: {
107
+ phase: "phase_1_coo",
108
+ phaseSetBy: "default"
105
109
  }
106
110
  };
107
111
 
@@ -122,6 +122,10 @@ var init_config = __esm({
122
122
  checkOnBoot: true,
123
123
  autoInstall: false,
124
124
  checkIntervalMs: 24 * 60 * 60 * 1e3
125
+ },
126
+ orchestration: {
127
+ phase: "phase_1_coo",
128
+ phaseSetBy: "default"
125
129
  }
126
130
  };
127
131
  }
@@ -219,6 +223,9 @@ function getClient() {
219
223
  if (_daemonClient && _daemonClient._isDaemonActive()) {
220
224
  return _daemonClient;
221
225
  }
226
+ if (!_resilientClient) {
227
+ return _adapterClient;
228
+ }
222
229
  return _resilientClient;
223
230
  }
224
231
  var _resilientClient, _daemonClient, _adapterClient;
@@ -99,6 +99,10 @@ var init_config = __esm({
99
99
  checkOnBoot: true,
100
100
  autoInstall: false,
101
101
  checkIntervalMs: 24 * 60 * 60 * 1e3
102
+ },
103
+ orchestration: {
104
+ phase: "phase_1_coo",
105
+ phaseSetBy: "default"
102
106
  }
103
107
  };
104
108
  }
@@ -152,6 +156,9 @@ function getClient() {
152
156
  if (_daemonClient && _daemonClient._isDaemonActive()) {
153
157
  return _daemonClient;
154
158
  }
159
+ if (!_resilientClient) {
160
+ return _adapterClient;
161
+ }
155
162
  return _resilientClient;
156
163
  }
157
164