@askexenow/exe-os 0.9.30 → 0.9.32

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 (64) hide show
  1. package/dist/bin/backfill-conversations.js +135 -7
  2. package/dist/bin/backfill-responses.js +135 -7
  3. package/dist/bin/backfill-vectors.js +135 -7
  4. package/dist/bin/cleanup-stale-review-tasks.js +139 -11
  5. package/dist/bin/cli.js +812 -486
  6. package/dist/bin/exe-assign.js +135 -7
  7. package/dist/bin/exe-boot.js +422 -113
  8. package/dist/bin/exe-cloud.js +160 -9
  9. package/dist/bin/exe-dispatch.js +136 -8
  10. package/dist/bin/exe-doctor.js +255 -13
  11. package/dist/bin/exe-export-behaviors.js +136 -8
  12. package/dist/bin/exe-forget.js +136 -8
  13. package/dist/bin/exe-gateway.js +171 -24
  14. package/dist/bin/exe-heartbeat.js +141 -13
  15. package/dist/bin/exe-kill.js +140 -12
  16. package/dist/bin/exe-launch-agent.js +143 -15
  17. package/dist/bin/exe-link.js +357 -48
  18. package/dist/bin/exe-pending-messages.js +136 -8
  19. package/dist/bin/exe-pending-notifications.js +136 -8
  20. package/dist/bin/exe-pending-reviews.js +138 -10
  21. package/dist/bin/exe-review.js +136 -8
  22. package/dist/bin/exe-search.js +155 -20
  23. package/dist/bin/exe-session-cleanup.js +166 -38
  24. package/dist/bin/exe-start-codex.js +142 -14
  25. package/dist/bin/exe-start-opencode.js +140 -12
  26. package/dist/bin/exe-status.js +148 -20
  27. package/dist/bin/exe-team.js +136 -8
  28. package/dist/bin/git-sweep.js +138 -10
  29. package/dist/bin/graph-backfill.js +135 -7
  30. package/dist/bin/graph-export.js +136 -8
  31. package/dist/bin/intercom-check.js +153 -25
  32. package/dist/bin/scan-tasks.js +138 -10
  33. package/dist/bin/setup.js +447 -121
  34. package/dist/bin/shard-migrate.js +135 -7
  35. package/dist/gateway/index.js +151 -23
  36. package/dist/hooks/bug-report-worker.js +151 -23
  37. package/dist/hooks/codex-stop-task-finalizer.js +145 -17
  38. package/dist/hooks/commit-complete.js +138 -10
  39. package/dist/hooks/error-recall.js +159 -24
  40. package/dist/hooks/ingest.js +142 -14
  41. package/dist/hooks/instructions-loaded.js +136 -8
  42. package/dist/hooks/notification.js +136 -8
  43. package/dist/hooks/post-compact.js +136 -8
  44. package/dist/hooks/post-tool-combined.js +159 -24
  45. package/dist/hooks/pre-compact.js +136 -8
  46. package/dist/hooks/pre-tool-use.js +144 -16
  47. package/dist/hooks/prompt-submit.js +195 -55
  48. package/dist/hooks/session-end.js +141 -13
  49. package/dist/hooks/session-start.js +165 -30
  50. package/dist/hooks/stop.js +136 -8
  51. package/dist/hooks/subagent-stop.js +136 -8
  52. package/dist/hooks/summary-worker.js +374 -65
  53. package/dist/index.js +136 -8
  54. package/dist/lib/cloud-sync.js +355 -46
  55. package/dist/lib/consolidation.js +1 -0
  56. package/dist/lib/exe-daemon.js +469 -127
  57. package/dist/lib/hybrid-search.js +155 -20
  58. package/dist/lib/keychain.js +191 -7
  59. package/dist/lib/schedules.js +138 -10
  60. package/dist/lib/store.js +135 -7
  61. package/dist/mcp/server.js +706 -213
  62. package/dist/runtime/index.js +136 -8
  63. package/dist/tui/App.js +208 -31
  64. package/package.json +1 -1
@@ -404,8 +404,8 @@ function findPackageRoot() {
404
404
  function getAvailableMemoryGB() {
405
405
  if (process.platform === "darwin") {
406
406
  try {
407
- const { execSync: execSync2 } = __require("child_process");
408
- const vmstat = execSync2("vm_stat", { encoding: "utf8" });
407
+ const { execSync: execSync3 } = __require("child_process");
408
+ const vmstat = execSync3("vm_stat", { encoding: "utf8" });
409
409
  const pageSize = 16384;
410
410
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
411
411
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3437,6 +3437,7 @@ import { createHash } from "crypto";
3437
3437
  // src/lib/keychain.ts
3438
3438
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3439
3439
  import { existsSync as existsSync6 } from "fs";
3440
+ import { execSync as execSync2 } from "child_process";
3440
3441
  import path6 from "path";
3441
3442
  import os5 from "os";
3442
3443
  var SERVICE = "exe-mem";
@@ -3447,6 +3448,59 @@ function getKeyDir() {
3447
3448
  function getKeyPath() {
3448
3449
  return path6.join(getKeyDir(), "master.key");
3449
3450
  }
3451
+ function macKeychainGet() {
3452
+ if (process.platform !== "darwin") return null;
3453
+ try {
3454
+ return execSync2(
3455
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
3456
+ { encoding: "utf-8", timeout: 5e3 }
3457
+ ).trim();
3458
+ } catch {
3459
+ return null;
3460
+ }
3461
+ }
3462
+ function macKeychainSet(value) {
3463
+ if (process.platform !== "darwin") return false;
3464
+ try {
3465
+ try {
3466
+ execSync2(
3467
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3468
+ { timeout: 5e3 }
3469
+ );
3470
+ } catch {
3471
+ }
3472
+ execSync2(
3473
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
3474
+ { timeout: 5e3 }
3475
+ );
3476
+ return true;
3477
+ } catch {
3478
+ return false;
3479
+ }
3480
+ }
3481
+ function linuxSecretGet() {
3482
+ if (process.platform !== "linux") return null;
3483
+ try {
3484
+ return execSync2(
3485
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3486
+ { encoding: "utf-8", timeout: 5e3 }
3487
+ ).trim();
3488
+ } catch {
3489
+ return null;
3490
+ }
3491
+ }
3492
+ function linuxSecretSet(value) {
3493
+ if (process.platform !== "linux") return false;
3494
+ try {
3495
+ execSync2(
3496
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3497
+ { timeout: 5e3 }
3498
+ );
3499
+ return true;
3500
+ } catch {
3501
+ return false;
3502
+ }
3503
+ }
3450
3504
  async function tryKeytar() {
3451
3505
  try {
3452
3506
  return await import("keytar");
@@ -3454,13 +3508,64 @@ async function tryKeytar() {
3454
3508
  return null;
3455
3509
  }
3456
3510
  }
3511
+ var ENCRYPTED_PREFIX = "enc:";
3512
+ function deriveMachineKey() {
3513
+ try {
3514
+ const crypto2 = __require("crypto");
3515
+ const material = [
3516
+ os5.hostname(),
3517
+ os5.userInfo().username,
3518
+ os5.arch(),
3519
+ os5.platform(),
3520
+ // Machine ID on Linux (stable across reboots)
3521
+ process.platform === "linux" ? readMachineId() : ""
3522
+ ].join("|");
3523
+ return crypto2.createHash("sha256").update(material).digest();
3524
+ } catch {
3525
+ return null;
3526
+ }
3527
+ }
3528
+ function readMachineId() {
3529
+ try {
3530
+ const { readFileSync: readFileSync5 } = __require("fs");
3531
+ return readFileSync5("/etc/machine-id", "utf-8").trim();
3532
+ } catch {
3533
+ return "";
3534
+ }
3535
+ }
3536
+ function decryptWithMachineKey(encrypted, machineKey) {
3537
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3538
+ try {
3539
+ const crypto2 = __require("crypto");
3540
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3541
+ if (parts.length !== 3) return null;
3542
+ const [ivB64, tagB64, cipherB64] = parts;
3543
+ const iv = Buffer.from(ivB64, "base64");
3544
+ const authTag = Buffer.from(tagB64, "base64");
3545
+ const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
3546
+ decipher.setAuthTag(authTag);
3547
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3548
+ decrypted += decipher.final("utf-8");
3549
+ return decrypted;
3550
+ } catch {
3551
+ return null;
3552
+ }
3553
+ }
3457
3554
  async function getMasterKey() {
3555
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
3556
+ if (nativeValue) {
3557
+ return Buffer.from(nativeValue, "base64");
3558
+ }
3458
3559
  const keytar = await tryKeytar();
3459
3560
  if (keytar) {
3460
3561
  try {
3461
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
3462
- if (stored) {
3463
- return Buffer.from(stored, "base64");
3562
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3563
+ if (keytarValue) {
3564
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3565
+ if (migrated) {
3566
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3567
+ }
3568
+ return Buffer.from(keytarValue, "base64");
3464
3569
  }
3465
3570
  } catch {
3466
3571
  }
@@ -3474,8 +3579,31 @@ async function getMasterKey() {
3474
3579
  return null;
3475
3580
  }
3476
3581
  try {
3477
- const content = await readFile3(keyPath, "utf-8");
3478
- return Buffer.from(content.trim(), "base64");
3582
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3583
+ let b64Value;
3584
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3585
+ const machineKey = deriveMachineKey();
3586
+ if (!machineKey) {
3587
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
3588
+ return null;
3589
+ }
3590
+ const decrypted = decryptWithMachineKey(content, machineKey);
3591
+ if (!decrypted) {
3592
+ process.stderr.write(
3593
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3594
+ );
3595
+ return null;
3596
+ }
3597
+ b64Value = decrypted;
3598
+ } else {
3599
+ b64Value = content;
3600
+ }
3601
+ const key = Buffer.from(b64Value, "base64");
3602
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3603
+ if (migrated) {
3604
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
3605
+ }
3606
+ return key;
3479
3607
  } catch (err) {
3480
3608
  process.stderr.write(
3481
3609
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}