@askexenow/exe-os 0.9.61 → 0.9.63

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 (103) hide show
  1. package/deploy/stack-manifests/v0.9.json +62 -13
  2. package/dist/bin/backfill-conversations.js +210 -2
  3. package/dist/bin/backfill-responses.js +210 -2
  4. package/dist/bin/backfill-vectors.js +47 -2
  5. package/dist/bin/cleanup-stale-review-tasks.js +210 -2
  6. package/dist/bin/cli.js +488 -25
  7. package/dist/bin/exe-agent-config.js +2 -2
  8. package/dist/bin/exe-agent.js +2 -2
  9. package/dist/bin/exe-assign.js +210 -2
  10. package/dist/bin/exe-boot.js +47 -2
  11. package/dist/bin/exe-call.js +2 -2
  12. package/dist/bin/exe-cloud.js +2 -2
  13. package/dist/bin/exe-dispatch.js +210 -2
  14. package/dist/bin/exe-doctor.js +2691 -1212
  15. package/dist/bin/exe-export-behaviors.js +210 -2
  16. package/dist/bin/exe-forget.js +264 -2
  17. package/dist/bin/exe-gateway.js +210 -2
  18. package/dist/bin/exe-heartbeat.js +212 -4
  19. package/dist/bin/exe-kill.js +210 -2
  20. package/dist/bin/exe-launch-agent.js +210 -2
  21. package/dist/bin/exe-link.js +47 -2
  22. package/dist/bin/exe-new-employee.js +113 -3
  23. package/dist/bin/exe-pending-messages.js +210 -2
  24. package/dist/bin/exe-pending-notifications.js +210 -2
  25. package/dist/bin/exe-pending-reviews.js +210 -2
  26. package/dist/bin/exe-rename.js +210 -2
  27. package/dist/bin/exe-review.js +210 -2
  28. package/dist/bin/exe-search.js +234 -3
  29. package/dist/bin/exe-session-cleanup.js +210 -2
  30. package/dist/bin/exe-settings.js +2 -2
  31. package/dist/bin/exe-start-codex.js +322 -4
  32. package/dist/bin/exe-start-opencode.js +336 -4
  33. package/dist/bin/exe-status.js +210 -2
  34. package/dist/bin/exe-team.js +210 -2
  35. package/dist/bin/git-sweep.js +210 -2
  36. package/dist/bin/graph-backfill.js +210 -2
  37. package/dist/bin/graph-export.js +210 -2
  38. package/dist/bin/install.js +113 -3
  39. package/dist/bin/intercom-check.js +210 -2
  40. package/dist/bin/scan-tasks.js +210 -2
  41. package/dist/bin/setup.js +47 -2
  42. package/dist/bin/shard-migrate.js +210 -2
  43. package/dist/bin/stack-update.js +158 -13
  44. package/dist/bin/update.js +2 -2
  45. package/dist/gateway/index.js +210 -2
  46. package/dist/hooks/bug-report-worker.js +321 -44
  47. package/dist/hooks/codex-stop-task-finalizer.js +210 -2
  48. package/dist/hooks/commit-complete.js +210 -2
  49. package/dist/hooks/error-recall.js +234 -3
  50. package/dist/hooks/exe-heartbeat-hook.js +2 -2
  51. package/dist/hooks/ingest-worker.js +2 -2
  52. package/dist/hooks/ingest.js +210 -2
  53. package/dist/hooks/instructions-loaded.js +210 -2
  54. package/dist/hooks/notification.js +210 -2
  55. package/dist/hooks/post-compact.js +210 -2
  56. package/dist/hooks/post-tool-combined.js +234 -3
  57. package/dist/hooks/pre-compact.js +446 -111
  58. package/dist/hooks/pre-tool-use.js +210 -2
  59. package/dist/hooks/prompt-submit.js +234 -3
  60. package/dist/hooks/session-end.js +347 -124
  61. package/dist/hooks/session-start.js +236 -5
  62. package/dist/hooks/stop.js +210 -2
  63. package/dist/hooks/subagent-stop.js +210 -2
  64. package/dist/hooks/summary-worker.js +171 -74
  65. package/dist/index.js +210 -2
  66. package/dist/lib/agent-config.js +2 -2
  67. package/dist/lib/cloud-sync.js +47 -2
  68. package/dist/lib/config.js +2 -2
  69. package/dist/lib/consolidation.js +2 -2
  70. package/dist/lib/database.js +47 -2
  71. package/dist/lib/db-daemon-client.js +2 -2
  72. package/dist/lib/db.js +47 -2
  73. package/dist/lib/device-registry.js +47 -2
  74. package/dist/lib/embedder.js +2 -2
  75. package/dist/lib/employee-templates.js +2 -2
  76. package/dist/lib/employees.js +2 -2
  77. package/dist/lib/exe-daemon-client.js +2 -2
  78. package/dist/lib/exe-daemon.js +592 -10
  79. package/dist/lib/hybrid-search.js +234 -3
  80. package/dist/lib/identity.js +2 -2
  81. package/dist/lib/license.js +2 -2
  82. package/dist/lib/messaging.js +2 -2
  83. package/dist/lib/reminders.js +2 -2
  84. package/dist/lib/schedules.js +47 -2
  85. package/dist/lib/skill-learning.js +2 -2
  86. package/dist/lib/store.js +210 -2
  87. package/dist/lib/task-router.js +2 -2
  88. package/dist/lib/tasks.js +2 -2
  89. package/dist/lib/tmux-routing.js +2 -2
  90. package/dist/lib/token-spend.js +2 -2
  91. package/dist/mcp/server.js +608 -10
  92. package/dist/mcp/tools/complete-reminder.js +2 -2
  93. package/dist/mcp/tools/create-reminder.js +2 -2
  94. package/dist/mcp/tools/create-task.js +2 -2
  95. package/dist/mcp/tools/deactivate-behavior.js +2 -2
  96. package/dist/mcp/tools/list-reminders.js +2 -2
  97. package/dist/mcp/tools/list-tasks.js +2 -2
  98. package/dist/mcp/tools/send-message.js +2 -2
  99. package/dist/mcp/tools/update-task.js +2 -2
  100. package/dist/runtime/index.js +210 -2
  101. package/dist/tui/App.js +210 -2
  102. package/package.json +3 -2
  103. package/stack.release.json +23 -7
@@ -257,8 +257,8 @@ var init_config = __esm({
257
257
  rerankerAutoTrigger: {
258
258
  enabled: true,
259
259
  broadQueryMinCardinality: 5e4,
260
- fetchTopK: 150,
261
- returnTopK: 5
260
+ fetchTopK: 200,
261
+ returnTopK: 20
262
262
  }
263
263
  },
264
264
  graphRagEnabled: true,
@@ -3302,6 +3302,51 @@ async function ensureSchema() {
3302
3302
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
3303
3303
  END;
3304
3304
  `);
3305
+ await client.executeMultiple(`
3306
+ CREATE TABLE IF NOT EXISTS memory_cards (
3307
+ id TEXT PRIMARY KEY,
3308
+ memory_id TEXT NOT NULL,
3309
+ agent_id TEXT NOT NULL,
3310
+ session_id TEXT NOT NULL,
3311
+ project_name TEXT,
3312
+ timestamp TEXT NOT NULL,
3313
+ card_type TEXT NOT NULL,
3314
+ subject TEXT,
3315
+ predicate TEXT,
3316
+ object TEXT,
3317
+ content TEXT NOT NULL,
3318
+ source_ref TEXT,
3319
+ confidence REAL DEFAULT 0.6,
3320
+ active INTEGER DEFAULT 1,
3321
+ created_at TEXT NOT NULL
3322
+ );
3323
+
3324
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_agent
3325
+ ON memory_cards(agent_id, active, timestamp);
3326
+
3327
+ CREATE INDEX IF NOT EXISTS idx_memory_cards_memory
3328
+ ON memory_cards(memory_id);
3329
+
3330
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_cards_fts
3331
+ USING fts5(content, subject, predicate, object, content='memory_cards', content_rowid='rowid');
3332
+
3333
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ai AFTER INSERT ON memory_cards BEGIN
3334
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
3335
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3336
+ END;
3337
+
3338
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_ad AFTER DELETE ON memory_cards BEGIN
3339
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
3340
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
3341
+ END;
3342
+
3343
+ CREATE TRIGGER IF NOT EXISTS memory_cards_fts_au AFTER UPDATE ON memory_cards BEGIN
3344
+ INSERT INTO memory_cards_fts(memory_cards_fts, rowid, content, subject, predicate, object)
3345
+ VALUES('delete', old.rowid, old.content, old.subject, old.predicate, old.object);
3346
+ INSERT INTO memory_cards_fts(rowid, content, subject, predicate, object)
3347
+ VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3348
+ END;
3349
+ `);
3305
3350
  try {
3306
3351
  await client.execute({
3307
3352
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
@@ -6889,15 +6934,15 @@ var init_task_scope = __esm({
6889
6934
 
6890
6935
  // src/lib/keychain.ts
6891
6936
  import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6892
- import { existsSync as existsSync17 } from "fs";
6937
+ import { existsSync as existsSync18 } from "fs";
6893
6938
  import { execSync as execSync8 } from "child_process";
6894
- import path21 from "path";
6939
+ import path22 from "path";
6895
6940
  import os13 from "os";
6896
6941
  function getKeyDir() {
6897
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path21.join(os13.homedir(), ".exe-os");
6942
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os13.homedir(), ".exe-os");
6898
6943
  }
6899
6944
  function getKeyPath() {
6900
- return path21.join(getKeyDir(), "master.key");
6945
+ return path22.join(getKeyDir(), "master.key");
6901
6946
  }
6902
6947
  function macKeychainGet() {
6903
6948
  if (process.platform !== "darwin") return null;
@@ -7045,7 +7090,7 @@ async function getMasterKey() {
7045
7090
  }
7046
7091
  }
7047
7092
  const keyPath = getKeyPath();
7048
- if (!existsSync17(keyPath)) {
7093
+ if (!existsSync18(keyPath)) {
7049
7094
  process.stderr.write(
7050
7095
  `[keychain] Key not found at ${keyPath} (HOME=${os13.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
7051
7096
  `
@@ -7319,12 +7364,12 @@ __export(shard_manager_exports, {
7319
7364
  listShards: () => listShards,
7320
7365
  shardExists: () => shardExists
7321
7366
  });
7322
- import path22 from "path";
7323
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, readdirSync as readdirSync5, renameSync as renameSync4, statSync as statSync2 } from "fs";
7367
+ import path23 from "path";
7368
+ import { existsSync as existsSync19, mkdirSync as mkdirSync10, readdirSync as readdirSync5, renameSync as renameSync5, statSync as statSync3 } from "fs";
7324
7369
  import { createClient as createClient2 } from "@libsql/client";
7325
7370
  function initShardManager(encryptionKey) {
7326
7371
  _encryptionKey = encryptionKey;
7327
- if (!existsSync18(SHARDS_DIR)) {
7372
+ if (!existsSync19(SHARDS_DIR)) {
7328
7373
  mkdirSync10(SHARDS_DIR, { recursive: true });
7329
7374
  }
7330
7375
  _shardingEnabled = true;
@@ -7354,7 +7399,7 @@ function getShardClient(projectName) {
7354
7399
  while (_shards.size >= MAX_OPEN_SHARDS) {
7355
7400
  evictLRU();
7356
7401
  }
7357
- const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
7402
+ const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
7358
7403
  const client = createClient2({
7359
7404
  url: `file:${dbPath}`,
7360
7405
  encryptionKey: _encryptionKey
@@ -7365,13 +7410,13 @@ function getShardClient(projectName) {
7365
7410
  }
7366
7411
  function shardExists(projectName) {
7367
7412
  const safeName = safeShardName(projectName);
7368
- return existsSync18(path22.join(SHARDS_DIR, `${safeName}.db`));
7413
+ return existsSync19(path23.join(SHARDS_DIR, `${safeName}.db`));
7369
7414
  }
7370
7415
  function safeShardName(projectName) {
7371
7416
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7372
7417
  }
7373
7418
  function listShards() {
7374
- if (!existsSync18(SHARDS_DIR)) return [];
7419
+ if (!existsSync19(SHARDS_DIR)) return [];
7375
7420
  return readdirSync5(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
7376
7421
  }
7377
7422
  async function auditShardHealth(options = {}) {
@@ -7383,8 +7428,8 @@ async function auditShardHealth(options = {}) {
7383
7428
  const names = listShards();
7384
7429
  const shards = [];
7385
7430
  for (const name of names) {
7386
- const dbPath = path22.join(SHARDS_DIR, `${name}.db`);
7387
- const stat = statSync2(dbPath);
7431
+ const dbPath = path23.join(SHARDS_DIR, `${name}.db`);
7432
+ const stat = statSync3(dbPath);
7388
7433
  const item = {
7389
7434
  name,
7390
7435
  path: dbPath,
@@ -7418,8 +7463,8 @@ async function auditShardHealth(options = {}) {
7418
7463
  _shards.delete(name);
7419
7464
  _shardLastAccess.delete(name);
7420
7465
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7421
- const archivedPath = path22.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7422
- renameSync4(dbPath, archivedPath);
7466
+ const archivedPath = path23.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
7467
+ renameSync5(dbPath, archivedPath);
7423
7468
  item.archivedPath = archivedPath;
7424
7469
  }
7425
7470
  } finally {
@@ -7635,12 +7680,12 @@ async function getReadyShardClient(projectName) {
7635
7680
  client.close();
7636
7681
  _shards.delete(safeName);
7637
7682
  _shardLastAccess.delete(safeName);
7638
- const dbPath = path22.join(SHARDS_DIR, `${safeName}.db`);
7639
- if (existsSync18(dbPath)) {
7640
- const stat = statSync2(dbPath);
7683
+ const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
7684
+ if (existsSync19(dbPath)) {
7685
+ const stat = statSync3(dbPath);
7641
7686
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
7642
- const archivedPath = path22.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7643
- renameSync4(dbPath, archivedPath);
7687
+ const archivedPath = path23.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
7688
+ renameSync5(dbPath, archivedPath);
7644
7689
  process.stderr.write(
7645
7690
  `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
7646
7691
  `
@@ -7707,7 +7752,7 @@ var init_shard_manager = __esm({
7707
7752
  "src/lib/shard-manager.ts"() {
7708
7753
  "use strict";
7709
7754
  init_config();
7710
- SHARDS_DIR = path22.join(EXE_AI_DIR, "shards");
7755
+ SHARDS_DIR = path23.join(EXE_AI_DIR, "shards");
7711
7756
  SHARD_IDLE_MS = 5 * 60 * 1e3;
7712
7757
  MAX_OPEN_SHARDS = 10;
7713
7758
  EVICTION_INTERVAL_MS = 60 * 1e3;
@@ -7974,6 +8019,164 @@ ${p.content}`).join("\n\n");
7974
8019
  }
7975
8020
  });
7976
8021
 
8022
+ // src/lib/memory-cards.ts
8023
+ var memory_cards_exports = {};
8024
+ __export(memory_cards_exports, {
8025
+ extractMemoryCards: () => extractMemoryCards,
8026
+ insertMemoryCardsForBatch: () => insertMemoryCardsForBatch,
8027
+ searchMemoryCards: () => searchMemoryCards
8028
+ });
8029
+ import { createHash as createHash2 } from "crypto";
8030
+ function stableId(memoryId, type, content) {
8031
+ return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
8032
+ }
8033
+ function cleanText(text) {
8034
+ return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
8035
+ }
8036
+ function splitSentences(text) {
8037
+ return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
8038
+ }
8039
+ function inferCardType(sentence, toolName) {
8040
+ const lower = sentence.toLowerCase();
8041
+ if (toolName === "store_decision" || /\b(decided|decision|adr|approved|rejected)\b/.test(lower)) return "decision";
8042
+ if (/\b(prefers|preference|likes|dislikes|wants|doesn't want|does not want)\b/.test(lower)) return "preference";
8043
+ if (/\b(changed|updated|replaced|now|no longer|instead|supersedes)\b/.test(lower)) return "belief_update";
8044
+ if (toolName && ["Read", "Write", "Edit", "Bash"].includes(toolName)) return "code";
8045
+ if (/\b(meeting|deadline|shipped|launched|completed|failed|blocked|assigned|created)\b/.test(lower)) return "event";
8046
+ return "fact";
8047
+ }
8048
+ function extractSubject(sentence, agentId) {
8049
+ const explicit = sentence.match(/\b([A-Z][a-zA-Z0-9_-]{2,}(?:\s+[A-Z][a-zA-Z0-9_-]{2,})?)\b/);
8050
+ return explicit?.[1] ?? agentId;
8051
+ }
8052
+ function predicateFor(type) {
8053
+ switch (type) {
8054
+ case "preference":
8055
+ return "prefers";
8056
+ case "belief_update":
8057
+ return "updated";
8058
+ case "decision":
8059
+ return "decided";
8060
+ case "event":
8061
+ return "happened";
8062
+ case "code":
8063
+ return "implemented";
8064
+ default:
8065
+ return "states";
8066
+ }
8067
+ }
8068
+ function extractMemoryCards(row) {
8069
+ const sentences = splitSentences(row.raw_text);
8070
+ const cards = [];
8071
+ for (const sentence of sentences) {
8072
+ const type = inferCardType(sentence, row.tool_name);
8073
+ const subject = extractSubject(sentence, row.agent_id);
8074
+ const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
8075
+ cards.push({
8076
+ id: stableId(row.id, type, content),
8077
+ memory_id: row.id,
8078
+ agent_id: row.agent_id,
8079
+ session_id: row.session_id,
8080
+ project_name: row.project_name ?? null,
8081
+ timestamp: row.timestamp,
8082
+ card_type: type,
8083
+ subject,
8084
+ predicate: predicateFor(type),
8085
+ object: content,
8086
+ content,
8087
+ source_ref: row.id,
8088
+ confidence: type === "fact" ? 0.55 : 0.65
8089
+ });
8090
+ if (cards.length >= MAX_CARDS_PER_MEMORY) break;
8091
+ }
8092
+ return cards;
8093
+ }
8094
+ async function insertMemoryCardsForBatch(rows) {
8095
+ const cards = rows.flatMap(extractMemoryCards);
8096
+ if (cards.length === 0) return 0;
8097
+ const now = (/* @__PURE__ */ new Date()).toISOString();
8098
+ const client = getClient();
8099
+ const stmts = cards.map((card) => ({
8100
+ sql: `INSERT OR IGNORE INTO memory_cards
8101
+ (id, memory_id, agent_id, session_id, project_name, timestamp, card_type,
8102
+ subject, predicate, object, content, source_ref, confidence, active, created_at)
8103
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)`,
8104
+ args: [
8105
+ card.id,
8106
+ card.memory_id,
8107
+ card.agent_id,
8108
+ card.session_id,
8109
+ card.project_name,
8110
+ card.timestamp,
8111
+ card.card_type,
8112
+ card.subject,
8113
+ card.predicate,
8114
+ card.object,
8115
+ card.content,
8116
+ card.source_ref,
8117
+ card.confidence,
8118
+ now
8119
+ ]
8120
+ }));
8121
+ await client.batch(stmts, "write");
8122
+ return cards.length;
8123
+ }
8124
+ function buildMatchExpr(queryText) {
8125
+ const terms = queryText.toLowerCase().split(/\s+/).filter((t) => t.length >= 3).map((t) => t.replace(/[^a-z0-9_]/g, "")).filter((t) => t.length >= 3).slice(0, 12);
8126
+ if (terms.length === 0) return null;
8127
+ return terms.map((t) => `${t}*`).join(terms.length >= 3 ? " AND " : " OR ");
8128
+ }
8129
+ async function searchMemoryCards(queryText, agentId, options) {
8130
+ const limit = options?.limit ?? 10;
8131
+ const matchExpr = buildMatchExpr(queryText);
8132
+ if (!matchExpr) return [];
8133
+ let sql = `SELECT c.id, c.memory_id, c.agent_id, c.session_id, c.project_name,
8134
+ c.timestamp, c.card_type, c.content, c.source_ref, c.confidence
8135
+ FROM memory_cards c
8136
+ JOIN memory_cards_fts fts ON c.rowid = fts.rowid
8137
+ WHERE memory_cards_fts MATCH ?
8138
+ AND c.agent_id = ?
8139
+ AND COALESCE(c.active, 1) = 1`;
8140
+ const args = [matchExpr, agentId];
8141
+ if (options?.projectName) {
8142
+ sql += ` AND c.project_name = ?`;
8143
+ args.push(options.projectName);
8144
+ }
8145
+ if (options?.since) {
8146
+ sql += ` AND c.timestamp >= ?`;
8147
+ args.push(options.since);
8148
+ }
8149
+ sql += ` ORDER BY rank LIMIT ?`;
8150
+ args.push(limit);
8151
+ const result = await getClient().execute({ sql, args });
8152
+ return result.rows.map((row) => ({
8153
+ id: `card:${String(row.id)}`,
8154
+ agent_id: String(row.agent_id),
8155
+ agent_role: "memory_card",
8156
+ session_id: String(row.session_id),
8157
+ timestamp: String(row.timestamp),
8158
+ tool_name: `memory_card:${String(row.card_type)}`,
8159
+ project_name: row.project_name == null ? "" : String(row.project_name),
8160
+ has_error: false,
8161
+ raw_text: `[${String(row.card_type)}] ${String(row.content)}
8162
+ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
8163
+ vector: [],
8164
+ importance: 6,
8165
+ status: "active",
8166
+ confidence: Number(row.confidence ?? 0.6),
8167
+ last_accessed: String(row.timestamp)
8168
+ }));
8169
+ }
8170
+ var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
8171
+ var init_memory_cards = __esm({
8172
+ "src/lib/memory-cards.ts"() {
8173
+ "use strict";
8174
+ init_database();
8175
+ MAX_CARDS_PER_MEMORY = 6;
8176
+ MAX_SENTENCE_CHARS = 360;
8177
+ }
8178
+ });
8179
+
7977
8180
  // src/lib/store.ts
7978
8181
  var store_exports = {};
7979
8182
  __export(store_exports, {
@@ -8312,6 +8515,11 @@ async function flushBatch() {
8312
8515
  const globalClient = getClient();
8313
8516
  const globalStmts = batch.map(buildStmt);
8314
8517
  await globalClient.batch(globalStmts, "write");
8518
+ try {
8519
+ const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
8520
+ await insertMemoryCardsForBatch2(batch);
8521
+ } catch {
8522
+ }
8315
8523
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
8316
8524
  _pendingRecords.splice(0, batch.length);
8317
8525
  try {
@@ -8659,78 +8867,6 @@ var init_fast_db_init = __esm({
8659
8867
  }
8660
8868
  });
8661
8869
 
8662
- // src/lib/memory-queue.ts
8663
- import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync5, unlinkSync as unlinkSync9, existsSync as existsSync19, statSync as statSync3 } from "fs";
8664
- import path23 from "path";
8665
- function enqueueMemory(entry) {
8666
- appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
8667
- }
8668
- var QUEUE_PATH2, PROCESSING_PATH, TTL_MS2;
8669
- var init_memory_queue = __esm({
8670
- "src/lib/memory-queue.ts"() {
8671
- "use strict";
8672
- init_config();
8673
- QUEUE_PATH2 = path23.join(EXE_AI_DIR, "memory-queue.jsonl");
8674
- PROCESSING_PATH = QUEUE_PATH2 + ".processing";
8675
- TTL_MS2 = 24 * 60 * 60 * 1e3;
8676
- }
8677
- });
8678
-
8679
- // src/lib/memory-queue-client.ts
8680
- var memory_queue_client_exports = {};
8681
- __export(memory_queue_client_exports, {
8682
- batchWriteMemoryViaDaemon: () => batchWriteMemoryViaDaemon,
8683
- writeMemoryViaDaemon: () => writeMemoryViaDaemon
8684
- });
8685
- async function writeMemoryViaDaemon(entry) {
8686
- if (process.env.EXE_IS_DAEMON === "1") {
8687
- enqueueMemory(entry);
8688
- return false;
8689
- }
8690
- if (!isClientConnected()) {
8691
- enqueueMemory(entry);
8692
- return false;
8693
- }
8694
- try {
8695
- const response = await sendDaemonRequest({
8696
- type: "write-memory",
8697
- entry
8698
- });
8699
- if (response.ok) return true;
8700
- enqueueMemory(entry);
8701
- return false;
8702
- } catch {
8703
- enqueueMemory(entry);
8704
- return false;
8705
- }
8706
- }
8707
- async function batchWriteMemoryViaDaemon(entries) {
8708
- if (entries.length === 0) return 0;
8709
- if (process.env.EXE_IS_DAEMON === "1" || !isClientConnected()) {
8710
- for (const entry of entries) enqueueMemory(entry);
8711
- return 0;
8712
- }
8713
- try {
8714
- const response = await sendDaemonRequest({
8715
- type: "batch-write-memory",
8716
- entries
8717
- });
8718
- if (response.ok) return response.count ?? entries.length;
8719
- for (const entry of entries) enqueueMemory(entry);
8720
- return 0;
8721
- } catch {
8722
- for (const entry of entries) enqueueMemory(entry);
8723
- return 0;
8724
- }
8725
- }
8726
- var init_memory_queue_client = __esm({
8727
- "src/lib/memory-queue-client.ts"() {
8728
- "use strict";
8729
- init_exe_daemon_client();
8730
- init_memory_queue();
8731
- }
8732
- });
8733
-
8734
8870
  // src/lib/git-staleness.ts
8735
8871
  var git_staleness_exports = {};
8736
8872
  __export(git_staleness_exports, {
@@ -9278,6 +9414,119 @@ function buildAutoCheckpoint(input2) {
9278
9414
  };
9279
9415
  }
9280
9416
 
9417
+ // src/lib/memory-queue-client.ts
9418
+ init_exe_daemon_client();
9419
+
9420
+ // src/lib/memory-queue.ts
9421
+ init_config();
9422
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync15, renameSync as renameSync4, unlinkSync as unlinkSync9, existsSync as existsSync17, statSync as statSync2 } from "fs";
9423
+ import path21 from "path";
9424
+ var QUEUE_PATH2 = path21.join(EXE_AI_DIR, "memory-queue.jsonl");
9425
+ var PROCESSING_PATH = QUEUE_PATH2 + ".processing";
9426
+ var TTL_MS2 = 24 * 60 * 60 * 1e3;
9427
+ function enqueueMemory(entry) {
9428
+ appendFileSync2(QUEUE_PATH2, JSON.stringify(entry) + "\n");
9429
+ }
9430
+
9431
+ // src/lib/memory-queue-client.ts
9432
+ async function writeMemoryViaDaemon(entry) {
9433
+ if (process.env.EXE_IS_DAEMON === "1") {
9434
+ enqueueMemory(entry);
9435
+ return false;
9436
+ }
9437
+ if (!isClientConnected()) {
9438
+ enqueueMemory(entry);
9439
+ return false;
9440
+ }
9441
+ try {
9442
+ const response = await sendDaemonRequest({
9443
+ type: "write-memory",
9444
+ entry
9445
+ });
9446
+ if (response.ok) return true;
9447
+ enqueueMemory(entry);
9448
+ return false;
9449
+ } catch {
9450
+ enqueueMemory(entry);
9451
+ return false;
9452
+ }
9453
+ }
9454
+
9455
+ // src/lib/checkpoint-orchestrator.ts
9456
+ function toolNameForReason(reason) {
9457
+ switch (reason) {
9458
+ case "periodic":
9459
+ return "auto-summary";
9460
+ case "session-end":
9461
+ return "SessionEnd";
9462
+ case "pre-compact":
9463
+ return "pre-compact-hook";
9464
+ case "capacity-signal":
9465
+ return "auto-checkpoint";
9466
+ }
9467
+ }
9468
+ function importanceForReason(reason, override) {
9469
+ if (override !== void 0) return override;
9470
+ switch (reason) {
9471
+ case "periodic":
9472
+ return 7;
9473
+ case "session-end":
9474
+ case "pre-compact":
9475
+ case "capacity-signal":
9476
+ return 8;
9477
+ }
9478
+ }
9479
+ function buildContinuityCheckpoint(input2) {
9480
+ const { checkpointText, decisionTexts } = buildAutoCheckpoint({
9481
+ agentId: input2.agentId,
9482
+ agentRole: input2.agentRole,
9483
+ sessionId: input2.sessionId,
9484
+ projectName: input2.projectName,
9485
+ reason: input2.reason,
9486
+ memories: input2.memories ?? [],
9487
+ tasks: input2.tasks ?? [],
9488
+ maxSamples: input2.maxSamples
9489
+ });
9490
+ const extra = input2.extraSections?.filter((section) => section.trim().length > 0) ?? [];
9491
+ return {
9492
+ checkpointText: extra.length > 0 ? `${checkpointText}
9493
+
9494
+ ${extra.join("\n\n")}` : checkpointText,
9495
+ decisionTexts
9496
+ };
9497
+ }
9498
+ async function writeContinuityCheckpoint(input2) {
9499
+ const result = buildContinuityCheckpoint(input2);
9500
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9501
+ await writeMemoryViaDaemon({
9502
+ raw_text: result.checkpointText,
9503
+ agent_id: input2.agentId,
9504
+ agent_role: input2.agentRole,
9505
+ session_id: input2.sessionId,
9506
+ tool_name: toolNameForReason(input2.reason),
9507
+ project_name: input2.projectName,
9508
+ timestamp: now,
9509
+ importance: importanceForReason(input2.reason, input2.importance),
9510
+ task_id: input2.taskId,
9511
+ memory_type: "checkpoint"
9512
+ });
9513
+ const decisionLimit = input2.reason === "periodic" ? 3 : 5;
9514
+ for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
9515
+ await writeMemoryViaDaemon({
9516
+ raw_text: decisionText,
9517
+ agent_id: input2.agentId,
9518
+ agent_role: input2.agentRole,
9519
+ session_id: input2.sessionId,
9520
+ tool_name: "auto-decision",
9521
+ project_name: input2.projectName,
9522
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9523
+ importance: 8,
9524
+ memory_type: "decision"
9525
+ });
9526
+ }
9527
+ return result;
9528
+ }
9529
+
9281
9530
  // src/adapters/claude/hooks/session-end.ts
9282
9531
  if (!process.env.AGENT_ID) {
9283
9532
  process.env.AGENT_ID = "default";
@@ -9327,7 +9576,7 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
9327
9576
  ORDER BY priority ASC, updated_at DESC LIMIT 10`,
9328
9577
  args: [agent.agentId, ...seScope.args]
9329
9578
  });
9330
- const { checkpointText, decisionTexts } = buildAutoCheckpoint({
9579
+ await writeContinuityCheckpoint({
9331
9580
  agentId: agent.agentId,
9332
9581
  agentRole: agent.agentRole,
9333
9582
  sessionId: data.session_id,
@@ -9335,35 +9584,9 @@ Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title
9335
9584
  reason: "session-end",
9336
9585
  memories: recent.rows,
9337
9586
  tasks: taskRows.rows,
9338
- maxSamples: 12
9339
- });
9340
- const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
9341
- await writeMemoryViaDaemon2({
9342
- raw_text: `${checkpointText}${orphanInfo ? `
9343
-
9344
- ## Session-End Warnings${orphanInfo}` : ""}`,
9345
- agent_id: agent.agentId,
9346
- agent_role: agent.agentRole,
9347
- session_id: data.session_id,
9348
- tool_name: "SessionEnd",
9349
- project_name: projectName,
9350
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9351
- importance: 8,
9352
- memory_type: "checkpoint"
9587
+ maxSamples: 12,
9588
+ extraSections: orphanInfo ? [`## Session-End Warnings${orphanInfo}`] : []
9353
9589
  });
9354
- for (const decisionText of decisionTexts.slice(0, 5)) {
9355
- await writeMemoryViaDaemon2({
9356
- raw_text: decisionText,
9357
- agent_id: agent.agentId,
9358
- agent_role: agent.agentRole,
9359
- session_id: data.session_id,
9360
- tool_name: "auto-decision",
9361
- project_name: projectName,
9362
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9363
- importance: 8,
9364
- memory_type: "decision"
9365
- });
9366
- }
9367
9590
  try {
9368
9591
  const { clearSessionFileReads: clearSessionFileReads2 } = await Promise.resolve().then(() => (init_git_staleness(), git_staleness_exports));
9369
9592
  await clearSessionFileReads2(data.session_id);