@askexenow/exe-os 0.9.38 → 0.9.39

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 (69) hide show
  1. package/dist/bin/backfill-conversations.js +34 -7
  2. package/dist/bin/backfill-responses.js +34 -7
  3. package/dist/bin/backfill-vectors.js +34 -7
  4. package/dist/bin/cleanup-stale-review-tasks.js +35 -8
  5. package/dist/bin/cli.js +72 -42
  6. package/dist/bin/exe-agent.js +11 -3
  7. package/dist/bin/exe-assign.js +34 -7
  8. package/dist/bin/exe-boot.js +48 -18
  9. package/dist/bin/exe-call.js +132 -340
  10. package/dist/bin/exe-dispatch.js +34 -7
  11. package/dist/bin/exe-doctor.js +37 -10
  12. package/dist/bin/exe-export-behaviors.js +36 -9
  13. package/dist/bin/exe-forget.js +34 -7
  14. package/dist/bin/exe-gateway.js +40 -12
  15. package/dist/bin/exe-heartbeat.js +35 -8
  16. package/dist/bin/exe-kill.js +34 -7
  17. package/dist/bin/exe-launch-agent.js +285 -1079
  18. package/dist/bin/exe-new-employee.js +29 -10
  19. package/dist/bin/exe-pending-messages.js +34 -7
  20. package/dist/bin/exe-pending-notifications.js +34 -7
  21. package/dist/bin/exe-pending-reviews.js +34 -7
  22. package/dist/bin/exe-rename.js +41 -13
  23. package/dist/bin/exe-review.js +34 -7
  24. package/dist/bin/exe-search.js +36 -9
  25. package/dist/bin/exe-session-cleanup.js +36 -9
  26. package/dist/bin/exe-start-codex.js +36 -9
  27. package/dist/bin/exe-start-opencode.js +36 -9
  28. package/dist/bin/exe-status.js +35 -8
  29. package/dist/bin/exe-team.js +34 -7
  30. package/dist/bin/git-sweep.js +34 -7
  31. package/dist/bin/graph-backfill.js +34 -7
  32. package/dist/bin/graph-export.js +34 -7
  33. package/dist/bin/install.js +2 -1
  34. package/dist/bin/intercom-check.js +36 -9
  35. package/dist/bin/scan-tasks.js +34 -7
  36. package/dist/bin/setup.js +18 -17
  37. package/dist/bin/shard-migrate.js +34 -7
  38. package/dist/gateway/index.js +38 -10
  39. package/dist/hooks/bug-report-worker.js +38 -10
  40. package/dist/hooks/codex-stop-task-finalizer.js +36 -9
  41. package/dist/hooks/commit-complete.js +34 -7
  42. package/dist/hooks/error-recall.js +36 -9
  43. package/dist/hooks/ingest.js +36 -8
  44. package/dist/hooks/instructions-loaded.js +42 -10
  45. package/dist/hooks/notification.js +34 -7
  46. package/dist/hooks/post-compact.js +34 -7
  47. package/dist/hooks/post-tool-combined.js +37 -10
  48. package/dist/hooks/pre-compact.js +35 -8
  49. package/dist/hooks/pre-tool-use.js +36 -8
  50. package/dist/hooks/prompt-submit.js +41 -13
  51. package/dist/hooks/session-end.js +35 -8
  52. package/dist/hooks/session-start.js +47 -14
  53. package/dist/hooks/stop.js +35 -8
  54. package/dist/hooks/subagent-stop.js +34 -7
  55. package/dist/hooks/summary-worker.js +43 -16
  56. package/dist/index.js +36 -8
  57. package/dist/lib/consolidation.js +2 -1
  58. package/dist/lib/employee-templates.js +2 -1
  59. package/dist/lib/employees.js +2 -1
  60. package/dist/lib/exe-daemon.js +136 -36
  61. package/dist/lib/hybrid-search.js +36 -9
  62. package/dist/lib/identity.js +8 -3
  63. package/dist/lib/schedules.js +34 -7
  64. package/dist/lib/store.js +34 -7
  65. package/dist/mcp/server.js +133 -33
  66. package/dist/mcp/tools/create-task.js +10 -4
  67. package/dist/runtime/index.js +34 -7
  68. package/dist/tui/App.js +40 -11
  69. package/package.json +1 -1
@@ -107,7 +107,7 @@ var init_config = __esm({
107
107
 
108
108
  // src/bin/exe-agent.ts
109
109
  import { createInterface } from "readline";
110
- import { readFileSync as readFileSync3 } from "fs";
110
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
111
111
  import path10 from "path";
112
112
  import os5 from "os";
113
113
 
@@ -1613,7 +1613,8 @@ When you need to assign work to another employee (e.g., CTO assigns to an engine
1613
1613
  var PROCEDURES_MARKER = "EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES";
1614
1614
  function getSessionPrompt(storedPrompt) {
1615
1615
  const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
1616
- const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
1616
+ const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
1617
+ const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
1617
1618
  const globalBlock = getGlobalProceduresBlock();
1618
1619
  return `${globalBlock}${rolePrompt}
1619
1620
  ${BASE_OPERATING_PROCEDURES}`;
@@ -2259,9 +2260,16 @@ function parseArgs(argv) {
2259
2260
  }
2260
2261
  function loadEmployee(name) {
2261
2262
  try {
2263
+ const identityPath = path10.join(os5.homedir(), ".exe-os", "identity", `${name}.md`);
2262
2264
  const rosterPath = path10.join(os5.homedir(), ".exe-os", "exe-employees.json");
2263
2265
  const roster = JSON.parse(readFileSync3(rosterPath, "utf8"));
2264
- return roster.find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
2266
+ const employee = roster.find((e) => e.name.toLowerCase() === name.toLowerCase());
2267
+ if (!employee) return null;
2268
+ if (existsSync4(identityPath)) {
2269
+ const identity = readFileSync3(identityPath, "utf8").trim();
2270
+ if (identity.length > 0) return { role: employee.role, systemPrompt: identity };
2271
+ }
2272
+ return employee.systemPrompt ? { role: employee.role, systemPrompt: employee.systemPrompt } : null;
2265
2273
  } catch {
2266
2274
  return null;
2267
2275
  }
@@ -2751,7 +2751,7 @@ __export(shard_manager_exports, {
2751
2751
  shardExists: () => shardExists
2752
2752
  });
2753
2753
  import path7 from "path";
2754
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2754
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2755
2755
  import { createClient as createClient2 } from "@libsql/client";
2756
2756
  function initShardManager(encryptionKey) {
2757
2757
  _encryptionKey = encryptionKey;
@@ -2773,7 +2773,7 @@ function getShardClient(projectName) {
2773
2773
  if (!_encryptionKey) {
2774
2774
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2775
2775
  }
2776
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2776
+ const safeName = safeShardName(projectName);
2777
2777
  if (!safeName || safeName === "unknown") {
2778
2778
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2779
2779
  }
@@ -2795,9 +2795,12 @@ function getShardClient(projectName) {
2795
2795
  return client;
2796
2796
  }
2797
2797
  function shardExists(projectName) {
2798
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2798
+ const safeName = safeShardName(projectName);
2799
2799
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2800
2800
  }
2801
+ function safeShardName(projectName) {
2802
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2803
+ }
2801
2804
  function listShards() {
2802
2805
  if (!existsSync7(SHARDS_DIR)) return [];
2803
2806
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2891,7 +2894,8 @@ async function ensureShardSchema(client) {
2891
2894
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2892
2895
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2893
2896
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2894
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2897
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2898
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2895
2899
  ]) {
2896
2900
  try {
2897
2901
  await client.execute(col);
@@ -2987,9 +2991,32 @@ async function ensureShardSchema(client) {
2987
2991
  }
2988
2992
  }
2989
2993
  async function getReadyShardClient(projectName) {
2990
- const client = getShardClient(projectName);
2991
- await ensureShardSchema(client);
2992
- return client;
2994
+ const safeName = safeShardName(projectName);
2995
+ let client = getShardClient(projectName);
2996
+ try {
2997
+ await ensureShardSchema(client);
2998
+ return client;
2999
+ } catch (err) {
3000
+ const message = err instanceof Error ? err.message : String(err);
3001
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3002
+ client.close();
3003
+ _shards.delete(safeName);
3004
+ _shardLastAccess.delete(safeName);
3005
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3006
+ if (existsSync7(dbPath)) {
3007
+ const stat = statSync2(dbPath);
3008
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3009
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3010
+ renameSync3(dbPath, archivedPath);
3011
+ process.stderr.write(
3012
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3013
+ `
3014
+ );
3015
+ }
3016
+ client = getShardClient(projectName);
3017
+ await ensureShardSchema(client);
3018
+ return client;
3019
+ }
2993
3020
  }
2994
3021
  function evictLRU() {
2995
3022
  let oldest = null;
@@ -3505,7 +3505,7 @@ __export(shard_manager_exports, {
3505
3505
  shardExists: () => shardExists
3506
3506
  });
3507
3507
  import path7 from "path";
3508
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3508
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3509
3509
  import { createClient as createClient2 } from "@libsql/client";
3510
3510
  function initShardManager(encryptionKey) {
3511
3511
  _encryptionKey = encryptionKey;
@@ -3527,7 +3527,7 @@ function getShardClient(projectName) {
3527
3527
  if (!_encryptionKey) {
3528
3528
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3529
3529
  }
3530
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3530
+ const safeName = safeShardName(projectName);
3531
3531
  if (!safeName || safeName === "unknown") {
3532
3532
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3533
3533
  }
@@ -3549,9 +3549,12 @@ function getShardClient(projectName) {
3549
3549
  return client;
3550
3550
  }
3551
3551
  function shardExists(projectName) {
3552
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3552
+ const safeName = safeShardName(projectName);
3553
3553
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3554
3554
  }
3555
+ function safeShardName(projectName) {
3556
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3557
+ }
3555
3558
  function listShards() {
3556
3559
  if (!existsSync7(SHARDS_DIR)) return [];
3557
3560
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3645,7 +3648,8 @@ async function ensureShardSchema(client) {
3645
3648
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3646
3649
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3647
3650
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3648
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3651
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3652
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3649
3653
  ]) {
3650
3654
  try {
3651
3655
  await client.execute(col);
@@ -3741,9 +3745,32 @@ async function ensureShardSchema(client) {
3741
3745
  }
3742
3746
  }
3743
3747
  async function getReadyShardClient(projectName) {
3744
- const client = getShardClient(projectName);
3745
- await ensureShardSchema(client);
3746
- return client;
3748
+ const safeName = safeShardName(projectName);
3749
+ let client = getShardClient(projectName);
3750
+ try {
3751
+ await ensureShardSchema(client);
3752
+ return client;
3753
+ } catch (err) {
3754
+ const message = err instanceof Error ? err.message : String(err);
3755
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3756
+ client.close();
3757
+ _shards.delete(safeName);
3758
+ _shardLastAccess.delete(safeName);
3759
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3760
+ if (existsSync7(dbPath)) {
3761
+ const stat = statSync2(dbPath);
3762
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3763
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3764
+ renameSync3(dbPath, archivedPath);
3765
+ process.stderr.write(
3766
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3767
+ `
3768
+ );
3769
+ }
3770
+ client = getShardClient(projectName);
3771
+ await ensureShardSchema(client);
3772
+ return client;
3773
+ }
3747
3774
  }
3748
3775
  function evictLRU() {
3749
3776
  let oldest = null;
@@ -4310,7 +4337,7 @@ __export(intercom_queue_exports, {
4310
4337
  queueIntercom: () => queueIntercom,
4311
4338
  readQueue: () => readQueue
4312
4339
  });
4313
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as renameSync3, existsSync as existsSync10, mkdirSync as mkdirSync4 } from "fs";
4340
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as existsSync10, mkdirSync as mkdirSync4 } from "fs";
4314
4341
  import path10 from "path";
4315
4342
  import os7 from "os";
4316
4343
  function ensureDir() {
@@ -4329,7 +4356,7 @@ function writeQueue(queue) {
4329
4356
  ensureDir();
4330
4357
  const tmp = `${QUEUE_PATH}.tmp`;
4331
4358
  writeFileSync5(tmp, JSON.stringify(queue, null, 2));
4332
- renameSync3(tmp, QUEUE_PATH);
4359
+ renameSync4(tmp, QUEUE_PATH);
4333
4360
  }
4334
4361
  function queueIntercom(targetSession, reason) {
4335
4362
  const queue = readQueue();
@@ -4688,8 +4715,8 @@ async function validateLicense(apiKey, deviceId) {
4688
4715
  }
4689
4716
  function getCacheAgeMs() {
4690
4717
  try {
4691
- const { statSync: statSync4 } = __require("fs");
4692
- const s = statSync4(CACHE_PATH);
4718
+ const { statSync: statSync5 } = __require("fs");
4719
+ const s = statSync5(CACHE_PATH);
4693
4720
  return Date.now() - s.mtimeMs;
4694
4721
  } catch {
4695
4722
  return Infinity;
@@ -8622,7 +8649,7 @@ __export(db_backup_exports, {
8622
8649
  listBackups: () => listBackups,
8623
8650
  rotateBackups: () => rotateBackups
8624
8651
  });
8625
- import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readdirSync as readdirSync7, unlinkSync as unlinkSync10, statSync as statSync2 } from "fs";
8652
+ import { copyFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readdirSync as readdirSync7, unlinkSync as unlinkSync10, statSync as statSync3 } from "fs";
8626
8653
  import path23 from "path";
8627
8654
  function findActiveDb() {
8628
8655
  for (const name of DB_NAMES) {
@@ -8666,7 +8693,7 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
8666
8693
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
8667
8694
  const filePath = path23.join(BACKUP_DIR, file);
8668
8695
  try {
8669
- const stat = statSync2(filePath);
8696
+ const stat = statSync3(filePath);
8670
8697
  if (stat.mtimeMs < cutoff) {
8671
8698
  unlinkSync10(filePath);
8672
8699
  deleted++;
@@ -8684,7 +8711,7 @@ function listBackups() {
8684
8711
  const files = readdirSync7(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
8685
8712
  return files.map((name) => {
8686
8713
  const p = path23.join(BACKUP_DIR, name);
8687
- const stat = statSync2(p);
8714
+ const stat = statSync3(p);
8688
8715
  return { path: p, name, size: stat.size, date: stat.mtime };
8689
8716
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
8690
8717
  } catch {
@@ -8743,7 +8770,7 @@ __export(cloud_sync_exports, {
8743
8770
  pushToPostgres: () => pushToPostgres,
8744
8771
  recordRosterDeletion: () => recordRosterDeletion
8745
8772
  });
8746
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync20, readdirSync as readdirSync8, mkdirSync as mkdirSync12, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync3 } from "fs";
8773
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync20, readdirSync as readdirSync8, mkdirSync as mkdirSync12, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
8747
8774
  import crypto8 from "crypto";
8748
8775
  import path24 from "path";
8749
8776
  import { homedir as homedir2 } from "os";
@@ -9235,7 +9262,7 @@ async function cloudSync(config) {
9235
9262
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
9236
9263
  const latestBackup = getLatestBackup2();
9237
9264
  if (latestBackup) {
9238
- const backupSize = statSync3(latestBackup).size;
9265
+ const backupSize = statSync4(latestBackup).size;
9239
9266
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
9240
9267
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
9241
9268
  const backupData = readFileSync15(latestBackup);
@@ -10283,7 +10310,8 @@ Use recall_my_memory and ask_team_memory constantly. Store your own summaries (d
10283
10310
  var PROCEDURES_MARKER = "EXE OS \u2014 VISION AND NON-NEGOTIABLE PRINCIPLES";
10284
10311
  function getSessionPrompt(storedPrompt) {
10285
10312
  const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
10286
- const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
10313
+ const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
10314
+ const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
10287
10315
  const globalBlock = getGlobalProceduresBlock();
10288
10316
  return `${globalBlock}${rolePrompt}
10289
10317
  ${BASE_OPERATING_PROCEDURES}`;
@@ -11585,7 +11613,9 @@ async function boot(options) {
11585
11613
  }
11586
11614
  const sessionDir = path25.join(EXE_AI_DIR, "sessions", coordinatorName);
11587
11615
  await mkdir5(sessionDir, { recursive: true });
11588
- const claudeMdContent = `${getSessionPrompt(coordinatorEmployee.systemPrompt)}
11616
+ const coordinatorIdentityPath = path25.join(EXE_AI_DIR, "identity", `${coordinatorName}.md`);
11617
+ const coordinatorPrompt = existsSync21(coordinatorIdentityPath) ? readFileSync16(coordinatorIdentityPath, "utf-8") : coordinatorEmployee.systemPrompt ?? "";
11618
+ const claudeMdContent = `${getSessionPrompt(coordinatorPrompt)}
11589
11619
 
11590
11620
  ---
11591
11621