@askexenow/exe-os 0.9.113 → 0.9.115

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 (86) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +36 -12
  2. package/dist/bin/agentic-reflection-backfill.js +36 -12
  3. package/dist/bin/agentic-semantic-label.js +36 -12
  4. package/dist/bin/backfill-conversations.js +36 -12
  5. package/dist/bin/backfill-responses.js +36 -12
  6. package/dist/bin/backfill-vectors.js +36 -12
  7. package/dist/bin/bulk-sync-postgres.js +36 -12
  8. package/dist/bin/cleanup-stale-review-tasks.js +470 -113
  9. package/dist/bin/cli.js +413 -62
  10. package/dist/bin/exe-agent.js +27 -0
  11. package/dist/bin/exe-assign.js +36 -12
  12. package/dist/bin/exe-boot.js +246 -54
  13. package/dist/bin/exe-call.js +8 -0
  14. package/dist/bin/exe-cloud.js +47 -12
  15. package/dist/bin/exe-dispatch.js +348 -53
  16. package/dist/bin/exe-doctor.js +51 -13
  17. package/dist/bin/exe-export-behaviors.js +37 -12
  18. package/dist/bin/exe-forget.js +36 -12
  19. package/dist/bin/exe-gateway.js +348 -53
  20. package/dist/bin/exe-heartbeat.js +471 -113
  21. package/dist/bin/exe-kill.js +36 -12
  22. package/dist/bin/exe-launch-agent.js +117 -18
  23. package/dist/bin/exe-new-employee.js +9 -1
  24. package/dist/bin/exe-pending-messages.js +452 -95
  25. package/dist/bin/exe-pending-notifications.js +452 -95
  26. package/dist/bin/exe-pending-reviews.js +452 -95
  27. package/dist/bin/exe-rename.js +36 -12
  28. package/dist/bin/exe-review.js +36 -12
  29. package/dist/bin/exe-search.js +37 -12
  30. package/dist/bin/exe-session-cleanup.js +348 -53
  31. package/dist/bin/exe-settings.js +12 -0
  32. package/dist/bin/exe-start-codex.js +46 -13
  33. package/dist/bin/exe-start-opencode.js +46 -13
  34. package/dist/bin/exe-status.js +460 -114
  35. package/dist/bin/exe-support.js +12 -0
  36. package/dist/bin/exe-team.js +36 -12
  37. package/dist/bin/git-sweep.js +348 -53
  38. package/dist/bin/graph-backfill.js +36 -12
  39. package/dist/bin/graph-export.js +36 -12
  40. package/dist/bin/install.js +9 -1
  41. package/dist/bin/intercom-check.js +255 -53
  42. package/dist/bin/scan-tasks.js +348 -53
  43. package/dist/bin/setup.js +74 -12
  44. package/dist/bin/shard-migrate.js +36 -12
  45. package/dist/gateway/index.js +348 -53
  46. package/dist/hooks/bug-report-worker.js +348 -53
  47. package/dist/hooks/codex-stop-task-finalizer.js +308 -37
  48. package/dist/hooks/commit-complete.js +348 -53
  49. package/dist/hooks/error-recall.js +37 -12
  50. package/dist/hooks/ingest.js +363 -54
  51. package/dist/hooks/instructions-loaded.js +36 -12
  52. package/dist/hooks/notification.js +36 -12
  53. package/dist/hooks/post-compact.js +426 -72
  54. package/dist/hooks/post-tool-combined.js +501 -146
  55. package/dist/hooks/pre-compact.js +348 -53
  56. package/dist/hooks/pre-tool-use.js +92 -13
  57. package/dist/hooks/prompt-submit.js +348 -53
  58. package/dist/hooks/session-end.js +158 -53
  59. package/dist/hooks/session-start.js +66 -13
  60. package/dist/hooks/stop.js +420 -72
  61. package/dist/hooks/subagent-stop.js +419 -72
  62. package/dist/hooks/summary-worker.js +442 -121
  63. package/dist/index.js +375 -53
  64. package/dist/lib/agent-config.js +8 -0
  65. package/dist/lib/cloud-sync.js +35 -12
  66. package/dist/lib/config.js +13 -0
  67. package/dist/lib/consolidation.js +9 -1
  68. package/dist/lib/embedder.js +13 -0
  69. package/dist/lib/employees.js +8 -0
  70. package/dist/lib/exe-daemon.js +524 -60
  71. package/dist/lib/hybrid-search.js +37 -12
  72. package/dist/lib/keychain.js +25 -13
  73. package/dist/lib/messaging.js +395 -74
  74. package/dist/lib/schedules.js +36 -12
  75. package/dist/lib/skill-learning.js +21 -0
  76. package/dist/lib/store.js +36 -12
  77. package/dist/lib/tasks.js +324 -41
  78. package/dist/lib/tmux-routing.js +324 -41
  79. package/dist/mcp/server.js +374 -54
  80. package/dist/mcp/tools/create-task.js +324 -41
  81. package/dist/mcp/tools/list-tasks.js +406 -57
  82. package/dist/mcp/tools/send-message.js +395 -74
  83. package/dist/mcp/tools/update-task.js +324 -41
  84. package/dist/runtime/index.js +375 -53
  85. package/dist/tui/App.js +377 -55
  86. package/package.json +1 -1
@@ -129,6 +129,17 @@ function normalizeOrchestration(raw) {
129
129
  const userOrg = raw.orchestration ?? {};
130
130
  raw.orchestration = { ...defaultOrg, ...userOrg };
131
131
  }
132
+ function normalizeCloudEndpoint(raw) {
133
+ const cloud = raw.cloud;
134
+ if (!cloud?.endpoint) return;
135
+ const ep = String(cloud.endpoint);
136
+ if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
137
+ cloud.endpoint = "https://cloud.askexe.com";
138
+ process.stderr.write(
139
+ "[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
140
+ );
141
+ }
142
+ }
132
143
  async function loadConfig() {
133
144
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
134
145
  await ensurePrivateDir(dir);
@@ -154,6 +165,7 @@ async function loadConfig() {
154
165
  normalizeSessionLifecycle(migratedCfg);
155
166
  normalizeAutoUpdate(migratedCfg);
156
167
  normalizeOrchestration(migratedCfg);
168
+ normalizeCloudEndpoint(migratedCfg);
157
169
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
158
170
  if (config.dbPath.startsWith("~")) {
159
171
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -3546,7 +3558,7 @@ ${p.content}`).join("\n\n");
3546
3558
  });
3547
3559
 
3548
3560
  // src/lib/keychain.ts
3549
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3561
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3550
3562
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3551
3563
  import { execSync as execSync3 } from "child_process";
3552
3564
  import path6 from "path";
@@ -3581,12 +3593,14 @@ function linuxSecretAvailable() {
3581
3593
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3582
3594
  if (process.platform !== "linux") return false;
3583
3595
  try {
3584
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3585
3596
  const st = statSync3(keyPath);
3586
3597
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3598
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3587
3599
  if (uid === 0) return true;
3588
3600
  const exeOsDir = process.env.EXE_OS_DIR;
3589
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3601
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3602
+ if (!linuxSecretAvailable()) return true;
3603
+ return false;
3590
3604
  } catch {
3591
3605
  return false;
3592
3606
  }
@@ -3736,15 +3750,25 @@ async function writeMachineBoundFileFallback(b64) {
3736
3750
  await mkdir3(dir, { recursive: true });
3737
3751
  const keyPath = getKeyPath();
3738
3752
  const machineKey = deriveMachineKey();
3739
- if (machineKey) {
3740
- const encrypted = encryptWithMachineKey(b64, machineKey);
3741
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3742
- await chmod2(keyPath, 384);
3743
- return "encrypted";
3753
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3754
+ const result = machineKey ? "encrypted" : "plaintext";
3755
+ const tmpPath = keyPath + ".tmp";
3756
+ try {
3757
+ if (existsSync7(keyPath)) {
3758
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3759
+ });
3760
+ }
3761
+ await writeFile3(tmpPath, content, "utf-8");
3762
+ await chmod2(tmpPath, 384);
3763
+ await rename(tmpPath, keyPath);
3764
+ } catch (err) {
3765
+ try {
3766
+ await unlink(tmpPath);
3767
+ } catch {
3768
+ }
3769
+ throw err;
3744
3770
  }
3745
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3746
- await chmod2(keyPath, 384);
3747
- return "plaintext";
3771
+ return result;
3748
3772
  }
3749
3773
  async function getMasterKey() {
3750
3774
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3811,7 +3835,7 @@ async function getMasterKey() {
3811
3835
  b64Value = content;
3812
3836
  }
3813
3837
  const key = Buffer.from(b64Value, "base64");
3814
- if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
3838
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
3815
3839
  return key;
3816
3840
  }
3817
3841
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
@@ -129,6 +129,17 @@ function normalizeOrchestration(raw) {
129
129
  const userOrg = raw.orchestration ?? {};
130
130
  raw.orchestration = { ...defaultOrg, ...userOrg };
131
131
  }
132
+ function normalizeCloudEndpoint(raw) {
133
+ const cloud = raw.cloud;
134
+ if (!cloud?.endpoint) return;
135
+ const ep = String(cloud.endpoint);
136
+ if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
137
+ cloud.endpoint = "https://cloud.askexe.com";
138
+ process.stderr.write(
139
+ "[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
140
+ );
141
+ }
142
+ }
132
143
  async function loadConfig() {
133
144
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
134
145
  await ensurePrivateDir(dir);
@@ -154,6 +165,7 @@ async function loadConfig() {
154
165
  normalizeSessionLifecycle(migratedCfg);
155
166
  normalizeAutoUpdate(migratedCfg);
156
167
  normalizeOrchestration(migratedCfg);
168
+ normalizeCloudEndpoint(migratedCfg);
157
169
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
158
170
  if (config.dbPath.startsWith("~")) {
159
171
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -3330,7 +3342,7 @@ var init_database = __esm({
3330
3342
  });
3331
3343
 
3332
3344
  // src/lib/keychain.ts
3333
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3345
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3334
3346
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3335
3347
  import { execSync as execSync3 } from "child_process";
3336
3348
  import path6 from "path";
@@ -3365,12 +3377,14 @@ function linuxSecretAvailable() {
3365
3377
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3366
3378
  if (process.platform !== "linux") return false;
3367
3379
  try {
3368
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3369
3380
  const st = statSync3(keyPath);
3370
3381
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3382
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3371
3383
  if (uid === 0) return true;
3372
3384
  const exeOsDir = process.env.EXE_OS_DIR;
3373
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3385
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3386
+ if (!linuxSecretAvailable()) return true;
3387
+ return false;
3374
3388
  } catch {
3375
3389
  return false;
3376
3390
  }
@@ -3520,15 +3534,25 @@ async function writeMachineBoundFileFallback(b64) {
3520
3534
  await mkdir3(dir, { recursive: true });
3521
3535
  const keyPath = getKeyPath();
3522
3536
  const machineKey = deriveMachineKey();
3523
- if (machineKey) {
3524
- const encrypted = encryptWithMachineKey(b64, machineKey);
3525
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3526
- await chmod2(keyPath, 384);
3527
- return "encrypted";
3537
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3538
+ const result = machineKey ? "encrypted" : "plaintext";
3539
+ const tmpPath = keyPath + ".tmp";
3540
+ try {
3541
+ if (existsSync7(keyPath)) {
3542
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3543
+ });
3544
+ }
3545
+ await writeFile3(tmpPath, content, "utf-8");
3546
+ await chmod2(tmpPath, 384);
3547
+ await rename(tmpPath, keyPath);
3548
+ } catch (err) {
3549
+ try {
3550
+ await unlink(tmpPath);
3551
+ } catch {
3552
+ }
3553
+ throw err;
3528
3554
  }
3529
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3530
- await chmod2(keyPath, 384);
3531
- return "plaintext";
3555
+ return result;
3532
3556
  }
3533
3557
  async function getMasterKey() {
3534
3558
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3595,7 +3619,7 @@ async function getMasterKey() {
3595
3619
  b64Value = content;
3596
3620
  }
3597
3621
  const key = Buffer.from(b64Value, "base64");
3598
- if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
3622
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
3599
3623
  return key;
3600
3624
  }
3601
3625
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
@@ -208,6 +208,17 @@ function normalizeOrchestration(raw) {
208
208
  const userOrg = raw.orchestration ?? {};
209
209
  raw.orchestration = { ...defaultOrg, ...userOrg };
210
210
  }
211
+ function normalizeCloudEndpoint(raw) {
212
+ const cloud = raw.cloud;
213
+ if (!cloud?.endpoint) return;
214
+ const ep = String(cloud.endpoint);
215
+ if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
216
+ cloud.endpoint = "https://cloud.askexe.com";
217
+ process.stderr.write(
218
+ "[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
219
+ );
220
+ }
221
+ }
211
222
  async function loadConfig() {
212
223
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
213
224
  await ensurePrivateDir(dir);
@@ -233,6 +244,7 @@ async function loadConfig() {
233
244
  normalizeSessionLifecycle(migratedCfg);
234
245
  normalizeAutoUpdate(migratedCfg);
235
246
  normalizeOrchestration(migratedCfg);
247
+ normalizeCloudEndpoint(migratedCfg);
236
248
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
237
249
  if (config.dbPath.startsWith("~")) {
238
250
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -261,6 +273,7 @@ function loadConfigSync() {
261
273
  normalizeSessionLifecycle(migratedCfg);
262
274
  normalizeAutoUpdate(migratedCfg);
263
275
  normalizeOrchestration(migratedCfg);
276
+ normalizeCloudEndpoint(migratedCfg);
264
277
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
265
278
  if (config.dbPath.startsWith("~")) {
266
279
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -3315,7 +3328,7 @@ var init_database = __esm({
3315
3328
  });
3316
3329
 
3317
3330
  // src/lib/keychain.ts
3318
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3331
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3319
3332
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3320
3333
  import { execSync as execSync3 } from "child_process";
3321
3334
  import path6 from "path";
@@ -3350,12 +3363,14 @@ function linuxSecretAvailable() {
3350
3363
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3351
3364
  if (process.platform !== "linux") return false;
3352
3365
  try {
3353
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3354
3366
  const st = statSync3(keyPath);
3355
3367
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3368
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3356
3369
  if (uid === 0) return true;
3357
3370
  const exeOsDir = process.env.EXE_OS_DIR;
3358
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3371
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3372
+ if (!linuxSecretAvailable()) return true;
3373
+ return false;
3359
3374
  } catch {
3360
3375
  return false;
3361
3376
  }
@@ -3505,15 +3520,25 @@ async function writeMachineBoundFileFallback(b64) {
3505
3520
  await mkdir3(dir, { recursive: true });
3506
3521
  const keyPath = getKeyPath();
3507
3522
  const machineKey = deriveMachineKey();
3508
- if (machineKey) {
3509
- const encrypted = encryptWithMachineKey(b64, machineKey);
3510
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3511
- await chmod2(keyPath, 384);
3512
- return "encrypted";
3523
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3524
+ const result = machineKey ? "encrypted" : "plaintext";
3525
+ const tmpPath = keyPath + ".tmp";
3526
+ try {
3527
+ if (existsSync7(keyPath)) {
3528
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3529
+ });
3530
+ }
3531
+ await writeFile3(tmpPath, content, "utf-8");
3532
+ await chmod2(tmpPath, 384);
3533
+ await rename(tmpPath, keyPath);
3534
+ } catch (err) {
3535
+ try {
3536
+ await unlink(tmpPath);
3537
+ } catch {
3538
+ }
3539
+ throw err;
3513
3540
  }
3514
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3515
- await chmod2(keyPath, 384);
3516
- return "plaintext";
3541
+ return result;
3517
3542
  }
3518
3543
  async function getMasterKey() {
3519
3544
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3580,7 +3605,7 @@ async function getMasterKey() {
3580
3605
  b64Value = content;
3581
3606
  }
3582
3607
  const key = Buffer.from(b64Value, "base64");
3583
- if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
3608
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
3584
3609
  return key;
3585
3610
  }
3586
3611
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);