@askexenow/exe-os 0.9.36 → 0.9.37

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 (51) hide show
  1. package/dist/bin/backfill-conversations.js +3 -0
  2. package/dist/bin/backfill-responses.js +3 -0
  3. package/dist/bin/cleanup-stale-review-tasks.js +3 -0
  4. package/dist/bin/cli.js +3 -0
  5. package/dist/bin/exe-assign.js +3 -0
  6. package/dist/bin/exe-dispatch.js +3 -0
  7. package/dist/bin/exe-export-behaviors.js +3 -0
  8. package/dist/bin/exe-forget.js +3 -0
  9. package/dist/bin/exe-gateway.js +3 -0
  10. package/dist/bin/exe-heartbeat.js +3 -0
  11. package/dist/bin/exe-kill.js +3 -0
  12. package/dist/bin/exe-pending-messages.js +3 -0
  13. package/dist/bin/exe-pending-notifications.js +3 -0
  14. package/dist/bin/exe-pending-reviews.js +3 -0
  15. package/dist/bin/exe-review.js +3 -0
  16. package/dist/bin/exe-search.js +9 -8
  17. package/dist/bin/exe-session-cleanup.js +7 -1
  18. package/dist/bin/exe-status.js +3 -0
  19. package/dist/bin/exe-team.js +3 -0
  20. package/dist/bin/git-sweep.js +3 -0
  21. package/dist/bin/graph-export.js +3 -0
  22. package/dist/bin/intercom-check.js +3 -0
  23. package/dist/bin/scan-tasks.js +3 -0
  24. package/dist/gateway/index.js +3 -0
  25. package/dist/hooks/bug-report-worker.js +3 -0
  26. package/dist/hooks/codex-stop-task-finalizer.js +3 -0
  27. package/dist/hooks/commit-complete.js +3 -0
  28. package/dist/hooks/error-recall.js +9 -8
  29. package/dist/hooks/ingest-worker.js +9 -2
  30. package/dist/hooks/ingest.js +3 -0
  31. package/dist/hooks/instructions-loaded.js +3 -0
  32. package/dist/hooks/notification.js +3 -0
  33. package/dist/hooks/post-compact.js +3 -0
  34. package/dist/hooks/post-tool-combined.js +18 -10
  35. package/dist/hooks/pre-compact.js +5 -1
  36. package/dist/hooks/pre-tool-use.js +3 -0
  37. package/dist/hooks/prompt-submit.js +9 -8
  38. package/dist/hooks/session-end.js +131 -3
  39. package/dist/hooks/session-start.js +9 -8
  40. package/dist/hooks/stop.js +7 -2
  41. package/dist/hooks/subagent-stop.js +3 -0
  42. package/dist/hooks/summary-worker.js +120 -18
  43. package/dist/index.js +25 -14
  44. package/dist/lib/exe-daemon.js +9 -8
  45. package/dist/lib/hybrid-search.js +9 -8
  46. package/dist/lib/store.js +3 -0
  47. package/dist/mcp/server.js +9 -8
  48. package/dist/runtime/index.js +25 -14
  49. package/dist/tui/App.js +3 -0
  50. package/package.json +1 -1
  51. package/src/commands/exe/save.md +9 -5
@@ -3946,6 +3946,9 @@ function classifyMemoryType(input2) {
3946
3946
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3947
3947
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3948
3948
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3949
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3950
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3951
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3949
3952
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3950
3953
  if (tool === "store_memory" || tool === "manual") return "observation";
3951
3954
  return "raw";
@@ -3387,6 +3387,9 @@ function classifyMemoryType(input2) {
3387
3387
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3388
3388
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3389
3389
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3390
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3391
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3392
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3390
3393
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3391
3394
  if (tool === "store_memory" || tool === "manual") return "observation";
3392
3395
  return "raw";
@@ -9872,7 +9875,7 @@ async function hybridSearch(queryText, agentId, options) {
9872
9875
  }
9873
9876
  if (lists.length === 0) return [];
9874
9877
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
9875
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
9878
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
9876
9879
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
9877
9880
  let graphContextMap = /* @__PURE__ */ new Map();
9878
9881
  let entityBoostRan = false;
@@ -9893,6 +9896,7 @@ async function hybridSearch(queryText, agentId, options) {
9893
9896
  returnTopK: 5
9894
9897
  };
9895
9898
  let rerankedAndBlended = null;
9899
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
9896
9900
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
9897
9901
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
9898
9902
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -9904,16 +9908,16 @@ async function hybridSearch(queryText, agentId, options) {
9904
9908
  text: m.raw_text,
9905
9909
  context: graphContextMap.get(m.id)
9906
9910
  }));
9907
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
9911
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
9908
9912
  rerankedRecords = scored.map((s) => merged[s.index]);
9909
9913
  } else {
9910
9914
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
9911
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
9915
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
9912
9916
  }
9913
9917
  if (rerankedRecords.length > 0) {
9914
9918
  rerankedAndBlended = rrfMergeMulti(
9915
9919
  [rerankedRecords],
9916
- auto.returnTopK,
9920
+ rerankReturnLimit,
9917
9921
  RRF_K
9918
9922
  );
9919
9923
  }
@@ -9921,10 +9925,7 @@ async function hybridSearch(queryText, agentId, options) {
9921
9925
  }
9922
9926
  }
9923
9927
  }
9924
- const finalResults = (rerankedAndBlended ?? merged).slice(
9925
- 0,
9926
- rerankedAndBlended ? auto.returnTopK : limit
9927
- );
9928
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
9928
9929
  if (options?.includeSource && finalResults.length > 0) {
9929
9930
  await attachDocumentMetadata(finalResults);
9930
9931
  }
@@ -6946,6 +6946,9 @@ function classifyMemoryType(input2) {
6946
6946
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
6947
6947
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
6948
6948
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
6949
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
6950
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
6951
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
6949
6952
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
6950
6953
  if (tool === "store_memory" || tool === "manual") return "observation";
6951
6954
  return "raw";
@@ -8919,6 +8922,88 @@ function clearCacheState(sessionKey) {
8919
8922
  // src/adapters/claude/hooks/session-end.ts
8920
8923
  init_task_scope();
8921
8924
  init_employees();
8925
+
8926
+ // src/lib/auto-checkpoint.ts
8927
+ var FILE_RE = /(?:^|\s)([\w./-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|go|py|css|scss|html|sh))(?:\b|$)/g;
8928
+ var DECISION_RE = /\b(decision:|decided:|we decided|founder directive|captured in .*architecture|source of truth)\b/i;
8929
+ function asString(value, fallback = "") {
8930
+ if (value == null) return fallback;
8931
+ return String(value);
8932
+ }
8933
+ function compactLine(text, max = 220) {
8934
+ return text.replace(/\s+/g, " ").trim().slice(0, max);
8935
+ }
8936
+ function topEntries(counts, limit) {
8937
+ return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, limit).map(([name, count]) => `${name}(${count})`);
8938
+ }
8939
+ function buildAutoCheckpoint(input2) {
8940
+ const maxSamples = input2.maxSamples ?? 8;
8941
+ const projectCounts = /* @__PURE__ */ new Map();
8942
+ const toolCounts = /* @__PURE__ */ new Map();
8943
+ const files = /* @__PURE__ */ new Set();
8944
+ const errors = [];
8945
+ const samples = [];
8946
+ const decisionTexts = [];
8947
+ for (const row of input2.memories) {
8948
+ const tool = asString(row.tool_name, "unknown");
8949
+ const project = asString(row.project_name, input2.projectName || "unknown");
8950
+ const raw = asString(row.raw_text);
8951
+ const hasError = row.has_error === 1 || row.has_error === true;
8952
+ toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
8953
+ projectCounts.set(project, (projectCounts.get(project) ?? 0) + 1);
8954
+ if (hasError && errors.length < 5) errors.push(compactLine(raw, 180));
8955
+ if (samples.length < maxSamples && raw.length > 30) {
8956
+ samples.push(`[${tool}] ${compactLine(raw)}`);
8957
+ }
8958
+ if (DECISION_RE.test(raw) && decisionTexts.length < 5) {
8959
+ decisionTexts.push(`AUTO DECISION CANDIDATE [${input2.agentId}]: ${compactLine(raw, 500)}`);
8960
+ }
8961
+ for (const match of raw.matchAll(FILE_RE)) {
8962
+ if (match[1]) files.add(match[1]);
8963
+ if (files.size >= 20) break;
8964
+ }
8965
+ }
8966
+ const taskLines = (input2.tasks ?? []).slice(0, 10).map((task) => {
8967
+ const status = asString(task.status, "unknown");
8968
+ const priority = asString(task.priority, "?").toUpperCase();
8969
+ const title = asString(task.title, "untitled");
8970
+ const taskFile = asString(task.task_file);
8971
+ return `- [${status}/${priority}] ${title}${taskFile ? ` (${taskFile})` : ""}`;
8972
+ });
8973
+ const parts = [
8974
+ `CONTEXT CHECKPOINT [auto:${input2.reason}]`,
8975
+ `Agent: ${input2.agentId} (${input2.agentRole})`,
8976
+ `Session: ${input2.sessionId}`,
8977
+ `Project: ${input2.projectName}`,
8978
+ `Time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
8979
+ "",
8980
+ "## Recent Activity",
8981
+ `- Memories scanned: ${input2.memories.length}`,
8982
+ `- Projects: ${topEntries(projectCounts, 5).join(", ") || input2.projectName}`,
8983
+ `- Tools: ${topEntries(toolCounts, 8).join(", ") || "none"}`
8984
+ ];
8985
+ if (taskLines.length > 0) {
8986
+ parts.push("", "## Open / Active Tasks", ...taskLines);
8987
+ }
8988
+ if (files.size > 0) {
8989
+ parts.push("", "## Files Mentioned", ...[...files].slice(0, 20).map((f) => `- ${f}`));
8990
+ }
8991
+ if (samples.length > 0) {
8992
+ parts.push("", "## Important Recent Traces", ...samples.map((s) => `- ${s}`));
8993
+ }
8994
+ if (errors.length > 0) {
8995
+ parts.push("", "## Errors / Risks", ...errors.map((e) => `- ${e}`));
8996
+ }
8997
+ if (decisionTexts.length > 0) {
8998
+ parts.push("", "## Decision Candidates", ...decisionTexts.map((d) => `- ${d.replace(/^AUTO DECISION CANDIDATE \\[[^\\]]+\\]: /, "")}`));
8999
+ }
9000
+ return {
9001
+ checkpointText: parts.join("\n"),
9002
+ decisionTexts
9003
+ };
9004
+ }
9005
+
9006
+ // src/adapters/claude/hooks/session-end.ts
8922
9007
  if (!process.env.AGENT_ID) {
8923
9008
  process.env.AGENT_ID = "default";
8924
9009
  process.env.AGENT_ROLE = "employee";
@@ -8951,16 +9036,59 @@ process.stdin.on("end", async () => {
8951
9036
  });
8952
9037
  const orphanInfo = orphanResult.rows.length > 0 ? `
8953
9038
  Orphaned tasks at session end: ${orphanResult.rows.map((r) => `"${String(r.title)}" (${String(r.status)})`).join(", ")}` : "";
9039
+ const projectName = process.env.EXE_PROJECT_NAME ?? process.cwd().split("/").pop() ?? "unknown";
9040
+ const recent = await client.execute({
9041
+ sql: `SELECT tool_name, project_name, raw_text, has_error, timestamp
9042
+ FROM memories
9043
+ WHERE agent_id = ?
9044
+ ORDER BY timestamp DESC
9045
+ LIMIT 75`,
9046
+ args: [agent.agentId]
9047
+ });
9048
+ const taskRows = await client.execute({
9049
+ sql: `SELECT title, status, task_file, priority
9050
+ FROM tasks
9051
+ WHERE assigned_to = ? AND status IN ('open', 'in_progress')${seScope.sql}
9052
+ ORDER BY priority ASC, updated_at DESC LIMIT 10`,
9053
+ args: [agent.agentId, ...seScope.args]
9054
+ });
9055
+ const { checkpointText, decisionTexts } = buildAutoCheckpoint({
9056
+ agentId: agent.agentId,
9057
+ agentRole: agent.agentRole,
9058
+ sessionId: data.session_id,
9059
+ projectName,
9060
+ reason: "session-end",
9061
+ memories: recent.rows,
9062
+ tasks: taskRows.rows,
9063
+ maxSamples: 12
9064
+ });
8954
9065
  const { writeMemoryViaDaemon: writeMemoryViaDaemon2 } = await Promise.resolve().then(() => (init_memory_queue_client(), memory_queue_client_exports));
8955
9066
  await writeMemoryViaDaemon2({
8956
- raw_text: `Session ended for ${agent.agentId}.${orphanInfo}`,
9067
+ raw_text: `${checkpointText}${orphanInfo ? `
9068
+
9069
+ ## Session-End Warnings${orphanInfo}` : ""}`,
8957
9070
  agent_id: agent.agentId,
8958
9071
  agent_role: agent.agentRole,
8959
9072
  session_id: data.session_id,
8960
9073
  tool_name: "SessionEnd",
8961
- project_name: process.env.EXE_PROJECT_NAME ?? process.cwd().split("/").pop() ?? "unknown",
8962
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
9074
+ project_name: projectName,
9075
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9076
+ importance: 8,
9077
+ memory_type: "checkpoint"
8963
9078
  });
9079
+ for (const decisionText of decisionTexts.slice(0, 5)) {
9080
+ await writeMemoryViaDaemon2({
9081
+ raw_text: decisionText,
9082
+ agent_id: agent.agentId,
9083
+ agent_role: agent.agentRole,
9084
+ session_id: data.session_id,
9085
+ tool_name: "auto-decision",
9086
+ project_name: projectName,
9087
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9088
+ importance: 8,
9089
+ memory_type: "decision"
9090
+ });
9091
+ }
8964
9092
  try {
8965
9093
  const { clearSessionFileReads: clearSessionFileReads2 } = await Promise.resolve().then(() => (init_git_staleness(), git_staleness_exports));
8966
9094
  await clearSessionFileReads2(data.session_id);
@@ -3453,6 +3453,9 @@ function classifyMemoryType(input2) {
3453
3453
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3454
3454
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3455
3455
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3456
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3457
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3458
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3456
3459
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3457
3460
  if (tool === "store_memory" || tool === "manual") return "observation";
3458
3461
  return "raw";
@@ -6070,7 +6073,7 @@ async function hybridSearch(queryText, agentId, options) {
6070
6073
  }
6071
6074
  if (lists.length === 0) return [];
6072
6075
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
6073
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
6076
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
6074
6077
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
6075
6078
  let graphContextMap = /* @__PURE__ */ new Map();
6076
6079
  let entityBoostRan = false;
@@ -6091,6 +6094,7 @@ async function hybridSearch(queryText, agentId, options) {
6091
6094
  returnTopK: 5
6092
6095
  };
6093
6096
  let rerankedAndBlended = null;
6097
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
6094
6098
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
6095
6099
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
6096
6100
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -6102,16 +6106,16 @@ async function hybridSearch(queryText, agentId, options) {
6102
6106
  text: m.raw_text,
6103
6107
  context: graphContextMap.get(m.id)
6104
6108
  }));
6105
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
6109
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
6106
6110
  rerankedRecords = scored.map((s) => merged[s.index]);
6107
6111
  } else {
6108
6112
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
6109
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
6113
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
6110
6114
  }
6111
6115
  if (rerankedRecords.length > 0) {
6112
6116
  rerankedAndBlended = rrfMergeMulti(
6113
6117
  [rerankedRecords],
6114
- auto.returnTopK,
6118
+ rerankReturnLimit,
6115
6119
  RRF_K
6116
6120
  );
6117
6121
  }
@@ -6119,10 +6123,7 @@ async function hybridSearch(queryText, agentId, options) {
6119
6123
  }
6120
6124
  }
6121
6125
  }
6122
- const finalResults = (rerankedAndBlended ?? merged).slice(
6123
- 0,
6124
- rerankedAndBlended ? auto.returnTopK : limit
6125
- );
6126
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
6126
6127
  if (options?.includeSource && finalResults.length > 0) {
6127
6128
  await attachDocumentMetadata(finalResults);
6128
6129
  }
@@ -3502,6 +3502,9 @@ function classifyMemoryType(input2) {
3502
3502
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3503
3503
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3504
3504
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3505
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3506
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3507
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3505
3508
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3506
3509
  if (tool === "store_memory" || tool === "manual") return "observation";
3507
3510
  return "raw";
@@ -5162,7 +5165,7 @@ function spawnDetachedWorker(workerPath, env, cwd) {
5162
5165
  } catch {
5163
5166
  }
5164
5167
  }
5165
- var MIN_LENGTH = 100;
5168
+ var MIN_LENGTH = 20;
5166
5169
  var timeout = setTimeout(() => {
5167
5170
  process.exit(0);
5168
5171
  }, 5e3);
@@ -5235,7 +5238,9 @@ process.stdin.on("end", () => {
5235
5238
  session_id: data.session_id,
5236
5239
  tool_name: "auto-checkpoint",
5237
5240
  project_name: process.env.EXE_PROJECT_NAME ?? "unknown",
5238
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
5241
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5242
+ importance: 8,
5243
+ memory_type: "checkpoint"
5239
5244
  });
5240
5245
  process.stderr.write(`[stop] Context checkpoint stored for ${agent.agentId} (capacity signal detected)
5241
5246
  `);
@@ -3483,6 +3483,9 @@ function classifyMemoryType(input2) {
3483
3483
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3484
3484
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3485
3485
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3486
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3487
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3488
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3486
3489
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3487
3490
  if (tool === "store_memory" || tool === "manual") return "observation";
3488
3491
  return "raw";
@@ -6748,6 +6748,88 @@ init_employees();
6748
6748
  import { execSync as execSync5 } from "child_process";
6749
6749
  import { existsSync as existsSync19, mkdirSync as mkdirSync10, openSync as openSync3, closeSync as closeSync3 } from "fs";
6750
6750
  import path20 from "path";
6751
+
6752
+ // src/lib/auto-checkpoint.ts
6753
+ var FILE_RE = /(?:^|\s)([\w./-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|go|py|css|scss|html|sh))(?:\b|$)/g;
6754
+ var DECISION_RE = /\b(decision:|decided:|we decided|founder directive|captured in .*architecture|source of truth)\b/i;
6755
+ function asString(value, fallback = "") {
6756
+ if (value == null) return fallback;
6757
+ return String(value);
6758
+ }
6759
+ function compactLine(text, max = 220) {
6760
+ return text.replace(/\s+/g, " ").trim().slice(0, max);
6761
+ }
6762
+ function topEntries(counts, limit) {
6763
+ return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, limit).map(([name, count]) => `${name}(${count})`);
6764
+ }
6765
+ function buildAutoCheckpoint(input) {
6766
+ const maxSamples = input.maxSamples ?? 8;
6767
+ const projectCounts = /* @__PURE__ */ new Map();
6768
+ const toolCounts = /* @__PURE__ */ new Map();
6769
+ const files = /* @__PURE__ */ new Set();
6770
+ const errors = [];
6771
+ const samples = [];
6772
+ const decisionTexts = [];
6773
+ for (const row of input.memories) {
6774
+ const tool = asString(row.tool_name, "unknown");
6775
+ const project = asString(row.project_name, input.projectName || "unknown");
6776
+ const raw = asString(row.raw_text);
6777
+ const hasError = row.has_error === 1 || row.has_error === true;
6778
+ toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
6779
+ projectCounts.set(project, (projectCounts.get(project) ?? 0) + 1);
6780
+ if (hasError && errors.length < 5) errors.push(compactLine(raw, 180));
6781
+ if (samples.length < maxSamples && raw.length > 30) {
6782
+ samples.push(`[${tool}] ${compactLine(raw)}`);
6783
+ }
6784
+ if (DECISION_RE.test(raw) && decisionTexts.length < 5) {
6785
+ decisionTexts.push(`AUTO DECISION CANDIDATE [${input.agentId}]: ${compactLine(raw, 500)}`);
6786
+ }
6787
+ for (const match of raw.matchAll(FILE_RE)) {
6788
+ if (match[1]) files.add(match[1]);
6789
+ if (files.size >= 20) break;
6790
+ }
6791
+ }
6792
+ const taskLines = (input.tasks ?? []).slice(0, 10).map((task) => {
6793
+ const status = asString(task.status, "unknown");
6794
+ const priority = asString(task.priority, "?").toUpperCase();
6795
+ const title = asString(task.title, "untitled");
6796
+ const taskFile = asString(task.task_file);
6797
+ return `- [${status}/${priority}] ${title}${taskFile ? ` (${taskFile})` : ""}`;
6798
+ });
6799
+ const parts = [
6800
+ `CONTEXT CHECKPOINT [auto:${input.reason}]`,
6801
+ `Agent: ${input.agentId} (${input.agentRole})`,
6802
+ `Session: ${input.sessionId}`,
6803
+ `Project: ${input.projectName}`,
6804
+ `Time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
6805
+ "",
6806
+ "## Recent Activity",
6807
+ `- Memories scanned: ${input.memories.length}`,
6808
+ `- Projects: ${topEntries(projectCounts, 5).join(", ") || input.projectName}`,
6809
+ `- Tools: ${topEntries(toolCounts, 8).join(", ") || "none"}`
6810
+ ];
6811
+ if (taskLines.length > 0) {
6812
+ parts.push("", "## Open / Active Tasks", ...taskLines);
6813
+ }
6814
+ if (files.size > 0) {
6815
+ parts.push("", "## Files Mentioned", ...[...files].slice(0, 20).map((f) => `- ${f}`));
6816
+ }
6817
+ if (samples.length > 0) {
6818
+ parts.push("", "## Important Recent Traces", ...samples.map((s) => `- ${s}`));
6819
+ }
6820
+ if (errors.length > 0) {
6821
+ parts.push("", "## Errors / Risks", ...errors.map((e) => `- ${e}`));
6822
+ }
6823
+ if (decisionTexts.length > 0) {
6824
+ parts.push("", "## Decision Candidates", ...decisionTexts.map((d) => `- ${d.replace(/^AUTO DECISION CANDIDATE \\[[^\\]]+\\]: /, "")}`));
6825
+ }
6826
+ return {
6827
+ checkpointText: parts.join("\n"),
6828
+ decisionTexts
6829
+ };
6830
+ }
6831
+
6832
+ // src/adapters/claude/hooks/summary-worker.ts
6751
6833
  async function main() {
6752
6834
  const agentId = process.env.AGENT_ID ?? "default";
6753
6835
  const agentRole = process.env.AGENT_ROLE ?? "employee";
@@ -6780,23 +6862,6 @@ async function main() {
6780
6862
  entry.samples.push(rawText.slice(0, 150));
6781
6863
  }
6782
6864
  }
6783
- const parts = [];
6784
- parts.push(`Auto-summary: ${totalCalls} tool calls (${writeCalls} writes)`);
6785
- parts.push(`Agent: ${agentId} (${agentRole})`);
6786
- parts.push(`Time: ${(/* @__PURE__ */ new Date()).toISOString()}`);
6787
- parts.push("");
6788
- for (const [project, data] of projects) {
6789
- parts.push(`Project: ${project}`);
6790
- parts.push(` Tools used: ${[...data.tools].join(", ")}`);
6791
- if (data.errors > 0) {
6792
- parts.push(` Errors encountered: ${data.errors}`);
6793
- }
6794
- for (const sample of data.samples) {
6795
- parts.push(` - ${sample}`);
6796
- }
6797
- parts.push("");
6798
- }
6799
- const summaryText = parts.join("\n");
6800
6865
  let primaryProject = "unknown";
6801
6866
  let maxCount = 0;
6802
6867
  const projectCounts = /* @__PURE__ */ new Map();
@@ -6809,6 +6874,28 @@ async function main() {
6809
6874
  primaryProject = p;
6810
6875
  }
6811
6876
  }
6877
+ let taskRows = [];
6878
+ try {
6879
+ const swScope = sessionScopeFilter();
6880
+ const tasks = await client.execute({
6881
+ sql: `SELECT title, status, task_file, priority
6882
+ FROM tasks
6883
+ WHERE assigned_to = ? AND status IN ('open', 'in_progress')${swScope.sql}
6884
+ ORDER BY priority ASC, updated_at DESC LIMIT 10`,
6885
+ args: [agentId, ...swScope.args]
6886
+ });
6887
+ taskRows = tasks.rows;
6888
+ } catch {
6889
+ }
6890
+ const { checkpointText: summaryText, decisionTexts } = buildAutoCheckpoint({
6891
+ agentId,
6892
+ agentRole,
6893
+ sessionId: `auto-summary-${Date.now()}`,
6894
+ projectName: primaryProject,
6895
+ reason: "periodic",
6896
+ memories: result.rows,
6897
+ tasks: taskRows
6898
+ });
6812
6899
  let limitReached = false;
6813
6900
  try {
6814
6901
  const { assertMemoryLimit: assertMemoryLimit2 } = await Promise.resolve().then(() => (init_plan_limits(), plan_limits_exports));
@@ -6833,8 +6920,23 @@ async function main() {
6833
6920
  session_id: `auto-summary-${Date.now()}`,
6834
6921
  tool_name: "auto-summary",
6835
6922
  project_name: primaryProject,
6836
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
6923
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6924
+ importance: 7,
6925
+ memory_type: "checkpoint"
6837
6926
  });
6927
+ for (const decisionText of decisionTexts.slice(0, 3)) {
6928
+ await writeMemoryViaDaemon({
6929
+ raw_text: decisionText,
6930
+ agent_id: agentId,
6931
+ agent_role: agentRole,
6932
+ session_id: `auto-decision-${Date.now()}`,
6933
+ tool_name: "auto-decision",
6934
+ project_name: primaryProject,
6935
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6936
+ importance: 8,
6937
+ memory_type: "decision"
6938
+ });
6939
+ }
6838
6940
  if (!canCoordinate(agentId, agentRole)) {
6839
6941
  let totalErrors = 0;
6840
6942
  for (const [, data] of projects) {
package/dist/index.js CHANGED
@@ -7027,6 +7027,9 @@ function classifyMemoryType(input) {
7027
7027
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
7028
7028
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
7029
7029
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
7030
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
7031
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
7032
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
7030
7033
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
7031
7034
  if (tool === "store_memory" || tool === "manual") return "observation";
7032
7035
  return "raw";
@@ -12155,20 +12158,28 @@ function createExeOSHooks(config2) {
12155
12158
  async onSessionEnd(_context, summary) {
12156
12159
  try {
12157
12160
  const { writeMemory: writeMemory2 } = await Promise.resolve().then(() => (init_store(), store_exports));
12158
- if (summary) {
12159
- await writeMemory2({
12160
- id: randomUUID5(),
12161
- agent_id: config2.agentId,
12162
- agent_role: "employee",
12163
- session_id: `api-${config2.agentId}`,
12164
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12165
- tool_name: "SessionEnd",
12166
- project_name: config2.projectName,
12167
- has_error: false,
12168
- raw_text: `Session ended. Summary: ${summary}`,
12169
- vector: null
12170
- });
12171
- }
12161
+ await writeMemory2({
12162
+ id: randomUUID5(),
12163
+ agent_id: config2.agentId,
12164
+ agent_role: "employee",
12165
+ session_id: `api-${config2.agentId}`,
12166
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
12167
+ tool_name: "SessionEnd",
12168
+ project_name: config2.projectName,
12169
+ has_error: false,
12170
+ raw_text: [
12171
+ "CONTEXT CHECKPOINT [auto:session-end]",
12172
+ `Agent: ${config2.agentId}`,
12173
+ `Project: ${config2.projectName}`,
12174
+ `Time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
12175
+ "",
12176
+ "## Runtime Summary",
12177
+ summary || "Session ended. No runtime summary was provided."
12178
+ ].join("\n"),
12179
+ vector: null,
12180
+ importance: 8,
12181
+ memory_type: "checkpoint"
12182
+ });
12172
12183
  } catch (err) {
12173
12184
  process.stderr.write(
12174
12185
  `[exe-hooks] session summary store failed: ${err instanceof Error ? err.message : String(err)}
@@ -3201,6 +3201,9 @@ function classifyMemoryType(input) {
3201
3201
  if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
3202
3202
  if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
3203
3203
  if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
3204
+ if (tool.includes("checkpoint") || text.startsWith("context checkpoint")) return "checkpoint";
3205
+ if (tool.includes("sessionsummary") || tool.includes("session-summary")) return "summary";
3206
+ if (tool.includes("sessionend") || text.startsWith("session ended")) return "summary";
3204
3207
  if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
3205
3208
  if (tool === "store_memory" || tool === "manual") return "observation";
3206
3209
  return "raw";
@@ -6508,7 +6511,7 @@ async function hybridSearch(queryText, agentId, options) {
6508
6511
  }
6509
6512
  if (lists.length === 0) return [];
6510
6513
  if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
6511
- const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, 150) : limit;
6514
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
6512
6515
  let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
6513
6516
  let graphContextMap = /* @__PURE__ */ new Map();
6514
6517
  let entityBoostRan = false;
@@ -6529,6 +6532,7 @@ async function hybridSearch(queryText, agentId, options) {
6529
6532
  returnTopK: 5
6530
6533
  };
6531
6534
  let rerankedAndBlended = null;
6535
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
6532
6536
  if (effectiveIsBroad && auto.enabled && rerankerAvailable) {
6533
6537
  const cardinality2 = await estimateCardinality(agentId, effectiveOptions);
6534
6538
  if (cardinality2 > auto.broadQueryMinCardinality) {
@@ -6540,16 +6544,16 @@ async function hybridSearch(queryText, agentId, options) {
6540
6544
  text: m.raw_text,
6541
6545
  context: graphContextMap.get(m.id)
6542
6546
  }));
6543
- const scored = await rerankWithContext2(effectiveQuery, candidates, auto.returnTopK);
6547
+ const scored = await rerankWithContext2(effectiveQuery, candidates, rerankReturnLimit);
6544
6548
  rerankedRecords = scored.map((s) => merged[s.index]);
6545
6549
  } else {
6546
6550
  const { rerank: rerank2 } = await Promise.resolve().then(() => (init_reranker(), reranker_exports));
6547
- rerankedRecords = await rerank2(effectiveQuery, merged, auto.returnTopK);
6551
+ rerankedRecords = await rerank2(effectiveQuery, merged, rerankReturnLimit);
6548
6552
  }
6549
6553
  if (rerankedRecords.length > 0) {
6550
6554
  rerankedAndBlended = rrfMergeMulti(
6551
6555
  [rerankedRecords],
6552
- auto.returnTopK,
6556
+ rerankReturnLimit,
6553
6557
  RRF_K
6554
6558
  );
6555
6559
  }
@@ -6557,10 +6561,7 @@ async function hybridSearch(queryText, agentId, options) {
6557
6561
  }
6558
6562
  }
6559
6563
  }
6560
- const finalResults = (rerankedAndBlended ?? merged).slice(
6561
- 0,
6562
- rerankedAndBlended ? auto.returnTopK : limit
6563
- );
6564
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
6564
6565
  if (options?.includeSource && finalResults.length > 0) {
6565
6566
  await attachDocumentMetadata(finalResults);
6566
6567
  }