@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
@@ -2741,7 +2741,7 @@ __export(shard_manager_exports, {
2741
2741
  shardExists: () => shardExists
2742
2742
  });
2743
2743
  import path7 from "path";
2744
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2744
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2745
2745
  import { createClient as createClient2 } from "@libsql/client";
2746
2746
  function initShardManager(encryptionKey) {
2747
2747
  _encryptionKey = encryptionKey;
@@ -2763,7 +2763,7 @@ function getShardClient(projectName) {
2763
2763
  if (!_encryptionKey) {
2764
2764
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2765
2765
  }
2766
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2766
+ const safeName = safeShardName(projectName);
2767
2767
  if (!safeName || safeName === "unknown") {
2768
2768
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2769
2769
  }
@@ -2785,9 +2785,12 @@ function getShardClient(projectName) {
2785
2785
  return client;
2786
2786
  }
2787
2787
  function shardExists(projectName) {
2788
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2788
+ const safeName = safeShardName(projectName);
2789
2789
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2790
2790
  }
2791
+ function safeShardName(projectName) {
2792
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2793
+ }
2791
2794
  function listShards() {
2792
2795
  if (!existsSync7(SHARDS_DIR)) return [];
2793
2796
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2881,7 +2884,8 @@ async function ensureShardSchema(client) {
2881
2884
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2882
2885
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2883
2886
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2884
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2887
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2888
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2885
2889
  ]) {
2886
2890
  try {
2887
2891
  await client.execute(col);
@@ -2977,9 +2981,32 @@ async function ensureShardSchema(client) {
2977
2981
  }
2978
2982
  }
2979
2983
  async function getReadyShardClient(projectName) {
2980
- const client = getShardClient(projectName);
2981
- await ensureShardSchema(client);
2982
- return client;
2984
+ const safeName = safeShardName(projectName);
2985
+ let client = getShardClient(projectName);
2986
+ try {
2987
+ await ensureShardSchema(client);
2988
+ return client;
2989
+ } catch (err) {
2990
+ const message = err instanceof Error ? err.message : String(err);
2991
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
2992
+ client.close();
2993
+ _shards.delete(safeName);
2994
+ _shardLastAccess.delete(safeName);
2995
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
2996
+ if (existsSync7(dbPath)) {
2997
+ const stat2 = statSync2(dbPath);
2998
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2999
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3000
+ renameSync3(dbPath, archivedPath);
3001
+ process.stderr.write(
3002
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat2.size} bytes, mtime ${stat2.mtime.toISOString()})
3003
+ `
3004
+ );
3005
+ }
3006
+ client = getShardClient(projectName);
3007
+ await ensureShardSchema(client);
3008
+ return client;
3009
+ }
2983
3010
  }
2984
3011
  function evictLRU() {
2985
3012
  let oldest = null;
@@ -2741,7 +2741,7 @@ __export(shard_manager_exports, {
2741
2741
  shardExists: () => shardExists
2742
2742
  });
2743
2743
  import path7 from "path";
2744
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2744
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2745
2745
  import { createClient as createClient2 } from "@libsql/client";
2746
2746
  function initShardManager(encryptionKey) {
2747
2747
  _encryptionKey = encryptionKey;
@@ -2763,7 +2763,7 @@ function getShardClient(projectName) {
2763
2763
  if (!_encryptionKey) {
2764
2764
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2765
2765
  }
2766
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2766
+ const safeName = safeShardName(projectName);
2767
2767
  if (!safeName || safeName === "unknown") {
2768
2768
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2769
2769
  }
@@ -2785,9 +2785,12 @@ function getShardClient(projectName) {
2785
2785
  return client;
2786
2786
  }
2787
2787
  function shardExists(projectName) {
2788
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2788
+ const safeName = safeShardName(projectName);
2789
2789
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2790
2790
  }
2791
+ function safeShardName(projectName) {
2792
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2793
+ }
2791
2794
  function listShards() {
2792
2795
  if (!existsSync7(SHARDS_DIR)) return [];
2793
2796
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2881,7 +2884,8 @@ async function ensureShardSchema(client) {
2881
2884
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2882
2885
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2883
2886
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2884
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2887
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2888
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2885
2889
  ]) {
2886
2890
  try {
2887
2891
  await client.execute(col);
@@ -2977,9 +2981,32 @@ async function ensureShardSchema(client) {
2977
2981
  }
2978
2982
  }
2979
2983
  async function getReadyShardClient(projectName) {
2980
- const client = getShardClient(projectName);
2981
- await ensureShardSchema(client);
2982
- return client;
2984
+ const safeName = safeShardName(projectName);
2985
+ let client = getShardClient(projectName);
2986
+ try {
2987
+ await ensureShardSchema(client);
2988
+ return client;
2989
+ } catch (err) {
2990
+ const message = err instanceof Error ? err.message : String(err);
2991
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
2992
+ client.close();
2993
+ _shards.delete(safeName);
2994
+ _shardLastAccess.delete(safeName);
2995
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
2996
+ if (existsSync7(dbPath)) {
2997
+ const stat2 = statSync2(dbPath);
2998
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2999
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3000
+ renameSync3(dbPath, archivedPath);
3001
+ process.stderr.write(
3002
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat2.size} bytes, mtime ${stat2.mtime.toISOString()})
3003
+ `
3004
+ );
3005
+ }
3006
+ client = getShardClient(projectName);
3007
+ await ensureShardSchema(client);
3008
+ return client;
3009
+ }
2983
3010
  }
2984
3011
  function evictLRU() {
2985
3012
  let oldest = null;
@@ -2737,7 +2737,7 @@ __export(shard_manager_exports, {
2737
2737
  shardExists: () => shardExists
2738
2738
  });
2739
2739
  import path7 from "path";
2740
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
2740
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
2741
2741
  import { createClient as createClient2 } from "@libsql/client";
2742
2742
  function initShardManager(encryptionKey) {
2743
2743
  _encryptionKey = encryptionKey;
@@ -2759,7 +2759,7 @@ function getShardClient(projectName) {
2759
2759
  if (!_encryptionKey) {
2760
2760
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
2761
2761
  }
2762
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2762
+ const safeName = safeShardName(projectName);
2763
2763
  if (!safeName || safeName === "unknown") {
2764
2764
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
2765
2765
  }
@@ -2781,9 +2781,12 @@ function getShardClient(projectName) {
2781
2781
  return client;
2782
2782
  }
2783
2783
  function shardExists(projectName) {
2784
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2784
+ const safeName = safeShardName(projectName);
2785
2785
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
2786
2786
  }
2787
+ function safeShardName(projectName) {
2788
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
2789
+ }
2787
2790
  function listShards() {
2788
2791
  if (!existsSync7(SHARDS_DIR)) return [];
2789
2792
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -2877,7 +2880,8 @@ async function ensureShardSchema(client) {
2877
2880
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
2878
2881
  "ALTER TABLE memories ADD COLUMN audience TEXT",
2879
2882
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
2880
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
2883
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
2884
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
2881
2885
  ]) {
2882
2886
  try {
2883
2887
  await client.execute(col);
@@ -2973,9 +2977,32 @@ async function ensureShardSchema(client) {
2973
2977
  }
2974
2978
  }
2975
2979
  async function getReadyShardClient(projectName) {
2976
- const client = getShardClient(projectName);
2977
- await ensureShardSchema(client);
2978
- return client;
2980
+ const safeName = safeShardName(projectName);
2981
+ let client = getShardClient(projectName);
2982
+ try {
2983
+ await ensureShardSchema(client);
2984
+ return client;
2985
+ } catch (err) {
2986
+ const message = err instanceof Error ? err.message : String(err);
2987
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
2988
+ client.close();
2989
+ _shards.delete(safeName);
2990
+ _shardLastAccess.delete(safeName);
2991
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
2992
+ if (existsSync7(dbPath)) {
2993
+ const stat = statSync2(dbPath);
2994
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2995
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
2996
+ renameSync3(dbPath, archivedPath);
2997
+ process.stderr.write(
2998
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
2999
+ `
3000
+ );
3001
+ }
3002
+ client = getShardClient(projectName);
3003
+ await ensureShardSchema(client);
3004
+ return client;
3005
+ }
2979
3006
  }
2980
3007
  function evictLRU() {
2981
3008
  let oldest = null;
@@ -3261,7 +3261,7 @@ __export(shard_manager_exports, {
3261
3261
  shardExists: () => shardExists
3262
3262
  });
3263
3263
  import path7 from "path";
3264
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync } from "fs";
3264
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
3265
3265
  import { createClient as createClient2 } from "@libsql/client";
3266
3266
  function initShardManager(encryptionKey) {
3267
3267
  _encryptionKey = encryptionKey;
@@ -3283,7 +3283,7 @@ function getShardClient(projectName) {
3283
3283
  if (!_encryptionKey) {
3284
3284
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
3285
3285
  }
3286
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3286
+ const safeName = safeShardName(projectName);
3287
3287
  if (!safeName || safeName === "unknown") {
3288
3288
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
3289
3289
  }
@@ -3305,9 +3305,12 @@ function getShardClient(projectName) {
3305
3305
  return client;
3306
3306
  }
3307
3307
  function shardExists(projectName) {
3308
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3308
+ const safeName = safeShardName(projectName);
3309
3309
  return existsSync7(path7.join(SHARDS_DIR, `${safeName}.db`));
3310
3310
  }
3311
+ function safeShardName(projectName) {
3312
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
3313
+ }
3311
3314
  function listShards() {
3312
3315
  if (!existsSync7(SHARDS_DIR)) return [];
3313
3316
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -3401,7 +3404,8 @@ async function ensureShardSchema(client) {
3401
3404
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
3402
3405
  "ALTER TABLE memories ADD COLUMN audience TEXT",
3403
3406
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
3404
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
3407
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
3408
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
3405
3409
  ]) {
3406
3410
  try {
3407
3411
  await client.execute(col);
@@ -3497,9 +3501,32 @@ async function ensureShardSchema(client) {
3497
3501
  }
3498
3502
  }
3499
3503
  async function getReadyShardClient(projectName) {
3500
- const client = getShardClient(projectName);
3501
- await ensureShardSchema(client);
3502
- return client;
3504
+ const safeName = safeShardName(projectName);
3505
+ let client = getShardClient(projectName);
3506
+ try {
3507
+ await ensureShardSchema(client);
3508
+ return client;
3509
+ } catch (err) {
3510
+ const message = err instanceof Error ? err.message : String(err);
3511
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
3512
+ client.close();
3513
+ _shards.delete(safeName);
3514
+ _shardLastAccess.delete(safeName);
3515
+ const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
3516
+ if (existsSync7(dbPath)) {
3517
+ const stat = statSync2(dbPath);
3518
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3519
+ const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
3520
+ renameSync3(dbPath, archivedPath);
3521
+ process.stderr.write(
3522
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
3523
+ `
3524
+ );
3525
+ }
3526
+ client = getShardClient(projectName);
3527
+ await ensureShardSchema(client);
3528
+ return client;
3529
+ }
3503
3530
  }
3504
3531
  function evictLRU() {
3505
3532
  let oldest = null;
@@ -4702,7 +4729,7 @@ var init_agent_config = __esm({
4702
4729
  });
4703
4730
 
4704
4731
  // src/lib/intercom-queue.ts
4705
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "fs";
4732
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync4, existsSync as existsSync9, mkdirSync as mkdirSync3 } from "fs";
4706
4733
  import path10 from "path";
4707
4734
  import os7 from "os";
4708
4735
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
package/dist/bin/cli.js CHANGED
@@ -540,7 +540,8 @@ function isMultiInstance(agentName, employees) {
540
540
  return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
541
541
  }
542
542
  function addEmployee(employees, employee) {
543
- const normalized = { ...employee, name: employee.name.toLowerCase() };
543
+ const { systemPrompt: _legacyPrompt, ...rest } = employee;
544
+ const normalized = { ...rest, name: employee.name.toLowerCase() };
544
545
  if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
545
546
  throw new Error(`Employee '${normalized.name}' already exists`);
546
547
  }
@@ -4864,8 +4865,8 @@ async function validateLicense(apiKey, deviceId) {
4864
4865
  }
4865
4866
  function getCacheAgeMs() {
4866
4867
  try {
4867
- const { statSync: statSync4 } = __require("fs");
4868
- const s = statSync4(CACHE_PATH);
4868
+ const { statSync: statSync5 } = __require("fs");
4869
+ const s = statSync5(CACHE_PATH);
4869
4870
  return Date.now() - s.mtimeMs;
4870
4871
  } catch {
4871
4872
  return Infinity;
@@ -7102,7 +7103,7 @@ __export(shard_manager_exports, {
7102
7103
  shardExists: () => shardExists
7103
7104
  });
7104
7105
  import path15 from "path";
7105
- import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync3 } from "fs";
7106
+ import { existsSync as existsSync15, mkdirSync as mkdirSync8, readdirSync as readdirSync3, renameSync as renameSync3, statSync as statSync4 } from "fs";
7106
7107
  import { createClient as createClient2 } from "@libsql/client";
7107
7108
  function initShardManager(encryptionKey) {
7108
7109
  _encryptionKey = encryptionKey;
@@ -7124,7 +7125,7 @@ function getShardClient(projectName) {
7124
7125
  if (!_encryptionKey) {
7125
7126
  throw new Error("Shard manager not initialized. Call initShardManager() first.");
7126
7127
  }
7127
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7128
+ const safeName = safeShardName(projectName);
7128
7129
  if (!safeName || safeName === "unknown") {
7129
7130
  throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
7130
7131
  }
@@ -7146,9 +7147,12 @@ function getShardClient(projectName) {
7146
7147
  return client;
7147
7148
  }
7148
7149
  function shardExists(projectName) {
7149
- const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7150
+ const safeName = safeShardName(projectName);
7150
7151
  return existsSync15(path15.join(SHARDS_DIR, `${safeName}.db`));
7151
7152
  }
7153
+ function safeShardName(projectName) {
7154
+ return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7155
+ }
7152
7156
  function listShards() {
7153
7157
  if (!existsSync15(SHARDS_DIR)) return [];
7154
7158
  return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
@@ -7242,7 +7246,8 @@ async function ensureShardSchema(client) {
7242
7246
  "ALTER TABLE memories ADD COLUMN token_cost REAL",
7243
7247
  "ALTER TABLE memories ADD COLUMN audience TEXT",
7244
7248
  "ALTER TABLE memories ADD COLUMN language_type TEXT",
7245
- "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
7249
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT",
7250
+ "ALTER TABLE memories ADD COLUMN deleted_at TEXT"
7246
7251
  ]) {
7247
7252
  try {
7248
7253
  await client.execute(col);
@@ -7338,9 +7343,32 @@ async function ensureShardSchema(client) {
7338
7343
  }
7339
7344
  }
7340
7345
  async function getReadyShardClient(projectName) {
7341
- const client = getShardClient(projectName);
7342
- await ensureShardSchema(client);
7343
- return client;
7346
+ const safeName = safeShardName(projectName);
7347
+ let client = getShardClient(projectName);
7348
+ try {
7349
+ await ensureShardSchema(client);
7350
+ return client;
7351
+ } catch (err) {
7352
+ const message = err instanceof Error ? err.message : String(err);
7353
+ if (!/SQLITE_NOTADB|file is not a database/i.test(message)) throw err;
7354
+ client.close();
7355
+ _shards.delete(safeName);
7356
+ _shardLastAccess.delete(safeName);
7357
+ const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
7358
+ if (existsSync15(dbPath)) {
7359
+ const stat2 = statSync4(dbPath);
7360
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7361
+ const archivedPath = path15.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7362
+ renameSync3(dbPath, archivedPath);
7363
+ process.stderr.write(
7364
+ `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat2.size} bytes, mtime ${stat2.mtime.toISOString()})
7365
+ `
7366
+ );
7367
+ }
7368
+ client = getShardClient(projectName);
7369
+ await ensureShardSchema(client);
7370
+ return client;
7371
+ }
7344
7372
  }
7345
7373
  function evictLRU() {
7346
7374
  let oldest = null;
@@ -9264,6 +9292,9 @@ function ensureDir() {
9264
9292
  function identityPath(agentId) {
9265
9293
  return path17.join(IDENTITY_DIR2, `${agentId}.md`);
9266
9294
  }
9295
+ function sanitizeIdentityBody(body) {
9296
+ return body.replace(/<!--[\s\S]*?-->/g, "").trim();
9297
+ }
9267
9298
  function parseFrontmatter(raw) {
9268
9299
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
9269
9300
  if (!match) {
@@ -9276,11 +9307,11 @@ function parseFrontmatter(raw) {
9276
9307
  created_by: "system",
9277
9308
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
9278
9309
  },
9279
- body: raw
9310
+ body: sanitizeIdentityBody(raw)
9280
9311
  };
9281
9312
  }
9282
9313
  const yamlStr = match[1];
9283
- const body = match[2].trim();
9314
+ const body = sanitizeIdentityBody(match[2]);
9284
9315
  const fm = {};
9285
9316
  for (const line of yamlStr.split("\n")) {
9286
9317
  const kv = line.match(/^(\w+):\s*(.+)$/);
@@ -9345,7 +9376,9 @@ function listIdentities() {
9345
9376
  const summary = lines[0]?.trim().slice(0, 120) ?? identity.frontmatter.title;
9346
9377
  results.push({
9347
9378
  agentId,
9348
- title: `${identity.frontmatter.title} (${identity.frontmatter.role.toUpperCase()})`,
9379
+ // User-facing/team-facing title only. `frontmatter.role` is internal
9380
+ // routing metadata and must not leak as an external title.
9381
+ title: identity.frontmatter.title,
9349
9382
  summary
9350
9383
  });
9351
9384
  }
@@ -10176,7 +10209,7 @@ __export(intercom_queue_exports, {
10176
10209
  queueIntercom: () => queueIntercom,
10177
10210
  readQueue: () => readQueue
10178
10211
  });
10179
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as renameSync3, existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
10212
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, renameSync as renameSync4, existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
10180
10213
  import path21 from "path";
10181
10214
  import os12 from "os";
10182
10215
  function ensureDir2() {
@@ -10195,7 +10228,7 @@ function writeQueue(queue) {
10195
10228
  ensureDir2();
10196
10229
  const tmp = `${QUEUE_PATH}.tmp`;
10197
10230
  writeFileSync13(tmp, JSON.stringify(queue, null, 2));
10198
- renameSync3(tmp, QUEUE_PATH);
10231
+ renameSync4(tmp, QUEUE_PATH);
10199
10232
  }
10200
10233
  function queueIntercom(targetSession, reason) {
10201
10234
  const queue = readQueue();
@@ -13875,7 +13908,8 @@ __export(employee_templates_exports, {
13875
13908
  });
13876
13909
  function getSessionPrompt(storedPrompt) {
13877
13910
  const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
13878
- const rolePrompt = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
13911
+ const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
13912
+ const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
13879
13913
  const globalBlock = getGlobalProceduresBlock();
13880
13914
  return `${globalBlock}${rolePrompt}
13881
13915
  ${BASE_OPERATING_PROCEDURES}`;
@@ -14483,7 +14517,7 @@ __export(exe_rename_exports, {
14483
14517
  main: () => main2,
14484
14518
  renameEmployee: () => renameEmployee
14485
14519
  });
14486
- import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as renameSync4, unlinkSync as unlinkSync11, existsSync as existsSync25 } from "fs";
14520
+ import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, renameSync as renameSync5, unlinkSync as unlinkSync11, existsSync as existsSync25 } from "fs";
14487
14521
  import { execSync as execSync11 } from "child_process";
14488
14522
  import path31 from "path";
14489
14523
  import { homedir as homedir4 } from "os";
@@ -14512,7 +14546,8 @@ async function renameEmployee(oldName, newName, opts = {}) {
14512
14546
  const originalName = employee.name;
14513
14547
  const originalPrompt = employee.systemPrompt;
14514
14548
  employee.name = newName;
14515
- employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
14549
+ if (originalPrompt) employee.systemPrompt = personalizePrompt(originalPrompt, rosterOldName, newName);
14550
+ else delete employee.systemPrompt;
14516
14551
  await saveEmployees(employees, rosterPath);
14517
14552
  rollbackStack.push({
14518
14553
  description: "restore roster",
@@ -14530,14 +14565,14 @@ async function renameEmployee(oldName, newName, opts = {}) {
14530
14565
  /^(agent_id:\s*)\S+/m,
14531
14566
  `$1${newName}`
14532
14567
  );
14533
- renameSync4(oldIdentityPath, newIdentityPath);
14568
+ renameSync5(oldIdentityPath, newIdentityPath);
14534
14569
  writeFileSync17(newIdentityPath, updatedContent, "utf-8");
14535
14570
  rollbackStack.push({
14536
14571
  description: "restore identity file",
14537
14572
  undo: () => {
14538
14573
  if (existsSync25(newIdentityPath)) {
14539
14574
  writeFileSync17(newIdentityPath, content, "utf-8");
14540
- renameSync4(newIdentityPath, oldIdentityPath);
14575
+ renameSync5(newIdentityPath, oldIdentityPath);
14541
14576
  }
14542
14577
  }
14543
14578
  });
@@ -14546,12 +14581,12 @@ async function renameEmployee(oldName, newName, opts = {}) {
14546
14581
  const newAgentPath = path31.join(agentsDir, `${newName}.md`);
14547
14582
  if (existsSync25(oldAgentPath)) {
14548
14583
  const agentContent = readFileSync21(oldAgentPath, "utf-8");
14549
- renameSync4(oldAgentPath, newAgentPath);
14584
+ renameSync5(oldAgentPath, newAgentPath);
14550
14585
  rollbackStack.push({
14551
14586
  description: "restore agent file",
14552
14587
  undo: () => {
14553
14588
  if (existsSync25(newAgentPath)) {
14554
- renameSync4(newAgentPath, oldAgentPath);
14589
+ renameSync5(newAgentPath, oldAgentPath);
14555
14590
  writeFileSync17(oldAgentPath, agentContent, "utf-8");
14556
14591
  }
14557
14592
  }
@@ -14680,7 +14715,7 @@ var init_exe_rename = __esm({
14680
14715
  });
14681
14716
 
14682
14717
  // src/lib/model-downloader.ts
14683
- import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync5 } from "fs";
14718
+ import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync6 } from "fs";
14684
14719
  import { mkdir as mkdir6 } from "fs/promises";
14685
14720
  import { createHash as createHash4 } from "crypto";
14686
14721
  import path32 from "path";
@@ -14738,7 +14773,7 @@ async function downloadModel(opts) {
14738
14773
  `SHA256 mismatch: expected ${EXPECTED_SHA256}, got ${actualHash}`
14739
14774
  );
14740
14775
  }
14741
- renameSync5(tmpPath, destPath);
14776
+ renameSync6(tmpPath, destPath);
14742
14777
  return destPath;
14743
14778
  } catch (err) {
14744
14779
  lastErr = err instanceof Error ? err : new Error(String(err));
@@ -15542,8 +15577,8 @@ async function validateModel(log) {
15542
15577
  log("Skipping in-memory model validation (low memory \u2014 will validate on first use).");
15543
15578
  const modelPath = path34.join(MODELS_DIR, LOCAL_FILENAME);
15544
15579
  if (existsSync28(modelPath)) {
15545
- const { statSync: statSync4 } = await import("fs");
15546
- const size = statSync4(modelPath).size;
15580
+ const { statSync: statSync5 } = await import("fs");
15581
+ const size = statSync5(modelPath).size;
15547
15582
  if (size > 300 * 1e6) {
15548
15583
  log(`Model file verified (${(size / 1e6).toFixed(0)} MB).`);
15549
15584
  return;
@@ -15964,15 +15999,9 @@ async function runSetupWizard(opts = {}) {
15964
15999
  cooName = (cooNameInput || DEFAULT_COORDINATOR_TEMPLATE_NAME2).toLowerCase();
15965
16000
  let employees = await loadEmployees2(EMPLOYEES_PATH2).catch(() => []);
15966
16001
  if (!employees.some((e) => e.name === cooName)) {
15967
- const { DEFAULT_EXE: DEFAULT_EXE2, personalizePrompt: personalizePrompt2 } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
15968
16002
  const cooEmployee = {
15969
16003
  name: cooName,
15970
16004
  role: "COO",
15971
- systemPrompt: personalizePrompt2(
15972
- DEFAULT_EXE2.systemPrompt,
15973
- DEFAULT_COORDINATOR_TEMPLATE_NAME2,
15974
- cooName
15975
- ),
15976
16005
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
15977
16006
  templateName: DEFAULT_COORDINATOR_TEMPLATE_NAME2,
15978
16007
  templateVersion: 1
@@ -16066,12 +16095,12 @@ async function runSetupWizard(opts = {}) {
16066
16095
  const ctoNameInput = await ask2(rl, `Name your CTO (default: ${ctoDefault}): `);
16067
16096
  const ctoName = (ctoNameInput || ctoDefault).toLowerCase();
16068
16097
  if (!employees.some((e) => e.name === ctoName)) {
16069
- const { personalizePrompt: personalizeCto } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
16070
16098
  const ctoEmployee = {
16071
16099
  name: ctoName,
16072
16100
  role: "CTO",
16073
- systemPrompt: personalizeCto(ctoTemplate?.systemPrompt ?? "", ctoDefault, ctoName),
16074
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
16101
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
16102
+ templateName: ctoDefault,
16103
+ templateVersion: 1
16075
16104
  };
16076
16105
  employees = addEmployee2(employees, ctoEmployee);
16077
16106
  await saveEmployees2(employees, EMPLOYEES_PATH2);
@@ -16089,12 +16118,12 @@ async function runSetupWizard(opts = {}) {
16089
16118
  const cmoNameInput = await ask2(rl, `Name your CMO (default: ${cmoDefault}): `);
16090
16119
  const cmoName = (cmoNameInput || cmoDefault).toLowerCase();
16091
16120
  if (!employees.some((e) => e.name === cmoName)) {
16092
- const { personalizePrompt: personalizeCmo } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
16093
16121
  const cmoEmployee = {
16094
16122
  name: cmoName,
16095
16123
  role: "CMO",
16096
- systemPrompt: personalizeCmo(cmoTemplate?.systemPrompt ?? "", cmoDefault, cmoName),
16097
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
16124
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
16125
+ templateName: cmoDefault,
16126
+ templateVersion: 1
16098
16127
  };
16099
16128
  employees = addEmployee2(employees, cmoEmployee);
16100
16129
  await saveEmployees2(employees, EMPLOYEES_PATH2);
@@ -16536,7 +16565,7 @@ var init_update = __esm({
16536
16565
 
16537
16566
  // src/lib/stack-update.ts
16538
16567
  import { execFileSync as execFileSync3 } from "child_process";
16539
- import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync25, renameSync as renameSync6, writeFileSync as writeFileSync20 } from "fs";
16568
+ import { existsSync as existsSync30, mkdirSync as mkdirSync19, readFileSync as readFileSync25, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "fs";
16540
16569
  import http from "http";
16541
16570
  import https from "https";
16542
16571
  import path37 from "path";
@@ -16644,7 +16673,7 @@ async function runStackUpdate(options) {
16644
16673
  const patched = patchEnv(envRaw, updates);
16645
16674
  const tmp = `${options.envFile}.tmp-${process.pid}`;
16646
16675
  writeFileSync20(tmp, patched, { mode: 384 });
16647
- renameSync6(tmp, options.envFile);
16676
+ renameSync7(tmp, options.envFile);
16648
16677
  const composeArgs = ["compose", "--file", options.composeFile, "--env-file", options.envFile];
16649
16678
  try {
16650
16679
  exec2("docker", [...composeArgs, "pull"]);
@@ -32111,7 +32140,7 @@ async function runActivate(key) {
32111
32140
  }
32112
32141
  const { saveLicense: saveLicense2, mirrorLicenseKey: mirrorLicenseKey2, validateLicense: validateLicense2 } = await Promise.resolve().then(() => (init_license(), license_exports));
32113
32142
  const { loadEmployees: loadEmployees2, saveEmployees: saveEmployees2, addEmployee: addEmployee2, registerBinSymlinks: registerBinSymlinks2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
32114
- const { getTemplateByRole: getTemplateByRole2, personalizePrompt: personalizePrompt2 } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
32143
+ const { getTemplateByRole: getTemplateByRole2 } = await Promise.resolve().then(() => (init_employee_templates(), employee_templates_exports));
32115
32144
  const { getTemplate: getIdentityTemplate } = await Promise.resolve().then(() => (init_identity_templates(), identity_templates_exports));
32116
32145
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
32117
32146
  const { createInterface: createInterface5 } = await import("readline");
@@ -32143,7 +32172,8 @@ async function runActivate(key) {
32143
32172
  if (create3.toLowerCase() === "n") return;
32144
32173
  const nameInput = await ask3(`Name your ${role} [${defaultName}]: `);
32145
32174
  const name = nameInput || defaultName;
32146
- const emp = { ...template, name, systemPrompt: personalizePrompt2(template.systemPrompt, template.name, name), createdAt: (/* @__PURE__ */ new Date()).toISOString() };
32175
+ const { systemPrompt: _templatePrompt, ...templateMeta } = template;
32176
+ const emp = { ...templateMeta, name, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
32147
32177
  employees = addEmployee2(employees, emp);
32148
32178
  await saveEmployees2(employees);
32149
32179
  registerBinSymlinks2(name);