@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
@@ -1363,8 +1363,8 @@ function findPackageRoot() {
1363
1363
  function getAvailableMemoryGB() {
1364
1364
  if (process.platform === "darwin") {
1365
1365
  try {
1366
- const { execSync: execSync5 } = __require("child_process");
1367
- const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1366
+ const { execSync: execSync6 } = __require("child_process");
1367
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1368
1368
  const pageSize = 16384;
1369
1369
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1370
1370
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3228,6 +3228,7 @@ var init_task_scope = __esm({
3228
3228
  // src/lib/keychain.ts
3229
3229
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3230
3230
  import { existsSync as existsSync11 } from "fs";
3231
+ import { execSync as execSync5 } from "child_process";
3231
3232
  import path13 from "path";
3232
3233
  import os9 from "os";
3233
3234
  function getKeyDir() {
@@ -3236,6 +3237,59 @@ function getKeyDir() {
3236
3237
  function getKeyPath() {
3237
3238
  return path13.join(getKeyDir(), "master.key");
3238
3239
  }
3240
+ function macKeychainGet() {
3241
+ if (process.platform !== "darwin") return null;
3242
+ try {
3243
+ return execSync5(
3244
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
3245
+ { encoding: "utf-8", timeout: 5e3 }
3246
+ ).trim();
3247
+ } catch {
3248
+ return null;
3249
+ }
3250
+ }
3251
+ function macKeychainSet(value) {
3252
+ if (process.platform !== "darwin") return false;
3253
+ try {
3254
+ try {
3255
+ execSync5(
3256
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3257
+ { timeout: 5e3 }
3258
+ );
3259
+ } catch {
3260
+ }
3261
+ execSync5(
3262
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
3263
+ { timeout: 5e3 }
3264
+ );
3265
+ return true;
3266
+ } catch {
3267
+ return false;
3268
+ }
3269
+ }
3270
+ function linuxSecretGet() {
3271
+ if (process.platform !== "linux") return null;
3272
+ try {
3273
+ return execSync5(
3274
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3275
+ { encoding: "utf-8", timeout: 5e3 }
3276
+ ).trim();
3277
+ } catch {
3278
+ return null;
3279
+ }
3280
+ }
3281
+ function linuxSecretSet(value) {
3282
+ if (process.platform !== "linux") return false;
3283
+ try {
3284
+ execSync5(
3285
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3286
+ { timeout: 5e3 }
3287
+ );
3288
+ return true;
3289
+ } catch {
3290
+ return false;
3291
+ }
3292
+ }
3239
3293
  async function tryKeytar() {
3240
3294
  try {
3241
3295
  return await import("keytar");
@@ -3243,13 +3297,63 @@ async function tryKeytar() {
3243
3297
  return null;
3244
3298
  }
3245
3299
  }
3300
+ function deriveMachineKey() {
3301
+ try {
3302
+ const crypto2 = __require("crypto");
3303
+ const material = [
3304
+ os9.hostname(),
3305
+ os9.userInfo().username,
3306
+ os9.arch(),
3307
+ os9.platform(),
3308
+ // Machine ID on Linux (stable across reboots)
3309
+ process.platform === "linux" ? readMachineId() : ""
3310
+ ].join("|");
3311
+ return crypto2.createHash("sha256").update(material).digest();
3312
+ } catch {
3313
+ return null;
3314
+ }
3315
+ }
3316
+ function readMachineId() {
3317
+ try {
3318
+ const { readFileSync: readFileSync12 } = __require("fs");
3319
+ return readFileSync12("/etc/machine-id", "utf-8").trim();
3320
+ } catch {
3321
+ return "";
3322
+ }
3323
+ }
3324
+ function decryptWithMachineKey(encrypted, machineKey) {
3325
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3326
+ try {
3327
+ const crypto2 = __require("crypto");
3328
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3329
+ if (parts.length !== 3) return null;
3330
+ const [ivB64, tagB64, cipherB64] = parts;
3331
+ const iv = Buffer.from(ivB64, "base64");
3332
+ const authTag = Buffer.from(tagB64, "base64");
3333
+ const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
3334
+ decipher.setAuthTag(authTag);
3335
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3336
+ decrypted += decipher.final("utf-8");
3337
+ return decrypted;
3338
+ } catch {
3339
+ return null;
3340
+ }
3341
+ }
3246
3342
  async function getMasterKey() {
3343
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
3344
+ if (nativeValue) {
3345
+ return Buffer.from(nativeValue, "base64");
3346
+ }
3247
3347
  const keytar = await tryKeytar();
3248
3348
  if (keytar) {
3249
3349
  try {
3250
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
3251
- if (stored) {
3252
- return Buffer.from(stored, "base64");
3350
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3351
+ if (keytarValue) {
3352
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3353
+ if (migrated) {
3354
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3355
+ }
3356
+ return Buffer.from(keytarValue, "base64");
3253
3357
  }
3254
3358
  } catch {
3255
3359
  }
@@ -3263,8 +3367,31 @@ async function getMasterKey() {
3263
3367
  return null;
3264
3368
  }
3265
3369
  try {
3266
- const content = await readFile3(keyPath, "utf-8");
3267
- return Buffer.from(content.trim(), "base64");
3370
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3371
+ let b64Value;
3372
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3373
+ const machineKey = deriveMachineKey();
3374
+ if (!machineKey) {
3375
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
3376
+ return null;
3377
+ }
3378
+ const decrypted = decryptWithMachineKey(content, machineKey);
3379
+ if (!decrypted) {
3380
+ process.stderr.write(
3381
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3382
+ );
3383
+ return null;
3384
+ }
3385
+ b64Value = decrypted;
3386
+ } else {
3387
+ b64Value = content;
3388
+ }
3389
+ const key = Buffer.from(b64Value, "base64");
3390
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3391
+ if (migrated) {
3392
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
3393
+ }
3394
+ return key;
3268
3395
  } catch (err) {
3269
3396
  process.stderr.write(
3270
3397
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -3273,12 +3400,13 @@ async function getMasterKey() {
3273
3400
  return null;
3274
3401
  }
3275
3402
  }
3276
- var SERVICE, ACCOUNT;
3403
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
3277
3404
  var init_keychain = __esm({
3278
3405
  "src/lib/keychain.ts"() {
3279
3406
  "use strict";
3280
3407
  SERVICE = "exe-mem";
3281
3408
  ACCOUNT = "master-key";
3409
+ ENCRYPTED_PREFIX = "enc:";
3282
3410
  }
3283
3411
  });
3284
3412
 
@@ -1344,8 +1344,8 @@ function findPackageRoot() {
1344
1344
  function getAvailableMemoryGB() {
1345
1345
  if (process.platform === "darwin") {
1346
1346
  try {
1347
- const { execSync: execSync5 } = __require("child_process");
1348
- const vmstat = execSync5("vm_stat", { encoding: "utf8" });
1347
+ const { execSync: execSync6 } = __require("child_process");
1348
+ const vmstat = execSync6("vm_stat", { encoding: "utf8" });
1349
1349
  const pageSize = 16384;
1350
1350
  const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1351
1351
  const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
@@ -3209,6 +3209,7 @@ var init_task_scope = __esm({
3209
3209
  // src/lib/keychain.ts
3210
3210
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3211
3211
  import { existsSync as existsSync11 } from "fs";
3212
+ import { execSync as execSync5 } from "child_process";
3212
3213
  import path13 from "path";
3213
3214
  import os9 from "os";
3214
3215
  function getKeyDir() {
@@ -3217,6 +3218,59 @@ function getKeyDir() {
3217
3218
  function getKeyPath() {
3218
3219
  return path13.join(getKeyDir(), "master.key");
3219
3220
  }
3221
+ function macKeychainGet() {
3222
+ if (process.platform !== "darwin") return null;
3223
+ try {
3224
+ return execSync5(
3225
+ `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
3226
+ { encoding: "utf-8", timeout: 5e3 }
3227
+ ).trim();
3228
+ } catch {
3229
+ return null;
3230
+ }
3231
+ }
3232
+ function macKeychainSet(value) {
3233
+ if (process.platform !== "darwin") return false;
3234
+ try {
3235
+ try {
3236
+ execSync5(
3237
+ `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3238
+ { timeout: 5e3 }
3239
+ );
3240
+ } catch {
3241
+ }
3242
+ execSync5(
3243
+ `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
3244
+ { timeout: 5e3 }
3245
+ );
3246
+ return true;
3247
+ } catch {
3248
+ return false;
3249
+ }
3250
+ }
3251
+ function linuxSecretGet() {
3252
+ if (process.platform !== "linux") return null;
3253
+ try {
3254
+ return execSync5(
3255
+ `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3256
+ { encoding: "utf-8", timeout: 5e3 }
3257
+ ).trim();
3258
+ } catch {
3259
+ return null;
3260
+ }
3261
+ }
3262
+ function linuxSecretSet(value) {
3263
+ if (process.platform !== "linux") return false;
3264
+ try {
3265
+ execSync5(
3266
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3267
+ { timeout: 5e3 }
3268
+ );
3269
+ return true;
3270
+ } catch {
3271
+ return false;
3272
+ }
3273
+ }
3220
3274
  async function tryKeytar() {
3221
3275
  try {
3222
3276
  return await import("keytar");
@@ -3224,13 +3278,63 @@ async function tryKeytar() {
3224
3278
  return null;
3225
3279
  }
3226
3280
  }
3281
+ function deriveMachineKey() {
3282
+ try {
3283
+ const crypto2 = __require("crypto");
3284
+ const material = [
3285
+ os9.hostname(),
3286
+ os9.userInfo().username,
3287
+ os9.arch(),
3288
+ os9.platform(),
3289
+ // Machine ID on Linux (stable across reboots)
3290
+ process.platform === "linux" ? readMachineId() : ""
3291
+ ].join("|");
3292
+ return crypto2.createHash("sha256").update(material).digest();
3293
+ } catch {
3294
+ return null;
3295
+ }
3296
+ }
3297
+ function readMachineId() {
3298
+ try {
3299
+ const { readFileSync: readFileSync11 } = __require("fs");
3300
+ return readFileSync11("/etc/machine-id", "utf-8").trim();
3301
+ } catch {
3302
+ return "";
3303
+ }
3304
+ }
3305
+ function decryptWithMachineKey(encrypted, machineKey) {
3306
+ if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3307
+ try {
3308
+ const crypto2 = __require("crypto");
3309
+ const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3310
+ if (parts.length !== 3) return null;
3311
+ const [ivB64, tagB64, cipherB64] = parts;
3312
+ const iv = Buffer.from(ivB64, "base64");
3313
+ const authTag = Buffer.from(tagB64, "base64");
3314
+ const decipher = crypto2.createDecipheriv("aes-256-gcm", machineKey, iv);
3315
+ decipher.setAuthTag(authTag);
3316
+ let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3317
+ decrypted += decipher.final("utf-8");
3318
+ return decrypted;
3319
+ } catch {
3320
+ return null;
3321
+ }
3322
+ }
3227
3323
  async function getMasterKey() {
3324
+ const nativeValue = macKeychainGet() ?? linuxSecretGet();
3325
+ if (nativeValue) {
3326
+ return Buffer.from(nativeValue, "base64");
3327
+ }
3228
3328
  const keytar = await tryKeytar();
3229
3329
  if (keytar) {
3230
3330
  try {
3231
- const stored = await keytar.getPassword(SERVICE, ACCOUNT);
3232
- if (stored) {
3233
- return Buffer.from(stored, "base64");
3331
+ const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3332
+ if (keytarValue) {
3333
+ const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3334
+ if (migrated) {
3335
+ process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3336
+ }
3337
+ return Buffer.from(keytarValue, "base64");
3234
3338
  }
3235
3339
  } catch {
3236
3340
  }
@@ -3244,8 +3348,31 @@ async function getMasterKey() {
3244
3348
  return null;
3245
3349
  }
3246
3350
  try {
3247
- const content = await readFile3(keyPath, "utf-8");
3248
- return Buffer.from(content.trim(), "base64");
3351
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3352
+ let b64Value;
3353
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3354
+ const machineKey = deriveMachineKey();
3355
+ if (!machineKey) {
3356
+ process.stderr.write("[keychain] Cannot derive machine key to decrypt stored key.\n");
3357
+ return null;
3358
+ }
3359
+ const decrypted = decryptWithMachineKey(content, machineKey);
3360
+ if (!decrypted) {
3361
+ process.stderr.write(
3362
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3363
+ );
3364
+ return null;
3365
+ }
3366
+ b64Value = decrypted;
3367
+ } else {
3368
+ b64Value = content;
3369
+ }
3370
+ const key = Buffer.from(b64Value, "base64");
3371
+ const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3372
+ if (migrated) {
3373
+ process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
3374
+ }
3375
+ return key;
3249
3376
  } catch (err) {
3250
3377
  process.stderr.write(
3251
3378
  `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
@@ -3254,12 +3381,13 @@ async function getMasterKey() {
3254
3381
  return null;
3255
3382
  }
3256
3383
  }
3257
- var SERVICE, ACCOUNT;
3384
+ var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
3258
3385
  var init_keychain = __esm({
3259
3386
  "src/lib/keychain.ts"() {
3260
3387
  "use strict";
3261
3388
  SERVICE = "exe-mem";
3262
3389
  ACCOUNT = "master-key";
3390
+ ENCRYPTED_PREFIX = "enc:";
3263
3391
  }
3264
3392
  });
3265
3393