context-mode 1.0.111 → 1.0.112

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 (150) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/index.ts +3 -2
  4. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  5. package/.openclaw-plugin/package.json +1 -1
  6. package/README.md +152 -34
  7. package/bin/statusline.mjs +144 -127
  8. package/build/adapters/base.d.ts +8 -5
  9. package/build/adapters/base.js +8 -18
  10. package/build/adapters/claude-code/index.d.ts +24 -3
  11. package/build/adapters/claude-code/index.js +44 -11
  12. package/build/adapters/codex/hooks.d.ts +10 -5
  13. package/build/adapters/codex/hooks.js +10 -5
  14. package/build/adapters/codex/index.d.ts +17 -5
  15. package/build/adapters/codex/index.js +337 -37
  16. package/build/adapters/codex/paths.d.ts +1 -0
  17. package/build/adapters/codex/paths.js +12 -0
  18. package/build/adapters/cursor/index.d.ts +6 -0
  19. package/build/adapters/cursor/index.js +83 -2
  20. package/build/adapters/detect.d.ts +1 -1
  21. package/build/adapters/detect.js +29 -6
  22. package/build/adapters/omp/index.d.ts +65 -0
  23. package/build/adapters/omp/index.js +182 -0
  24. package/build/adapters/omp/plugin.d.ts +75 -0
  25. package/build/adapters/omp/plugin.js +220 -0
  26. package/build/adapters/openclaw/mcp-tools.d.ts +54 -0
  27. package/build/adapters/openclaw/mcp-tools.js +198 -0
  28. package/build/adapters/openclaw/plugin.d.ts +130 -0
  29. package/build/adapters/openclaw/plugin.js +629 -0
  30. package/build/adapters/openclaw/workspace-router.d.ts +29 -0
  31. package/build/adapters/openclaw/workspace-router.js +64 -0
  32. package/build/adapters/opencode/plugin.d.ts +145 -0
  33. package/build/adapters/opencode/plugin.js +457 -0
  34. package/build/adapters/pi/extension.d.ts +26 -0
  35. package/build/adapters/pi/extension.js +552 -0
  36. package/build/adapters/pi/index.d.ts +57 -0
  37. package/build/adapters/pi/index.js +173 -0
  38. package/build/adapters/pi/mcp-bridge.d.ts +113 -0
  39. package/build/adapters/pi/mcp-bridge.js +251 -0
  40. package/build/adapters/types.d.ts +11 -6
  41. package/build/cli.js +186 -170
  42. package/build/db-base.d.ts +15 -2
  43. package/build/db-base.js +50 -5
  44. package/build/executor.d.ts +2 -0
  45. package/build/executor.js +15 -2
  46. package/build/runPool.d.ts +36 -0
  47. package/build/runPool.js +51 -0
  48. package/build/runtime.js +64 -5
  49. package/build/search/auto-memory.js +6 -4
  50. package/build/security.js +30 -10
  51. package/build/server.d.ts +23 -1
  52. package/build/server.js +652 -174
  53. package/build/session/analytics.d.ts +404 -1
  54. package/build/session/analytics.js +1347 -42
  55. package/build/session/db.d.ts +114 -5
  56. package/build/session/db.js +275 -27
  57. package/build/session/event-emit.d.ts +48 -0
  58. package/build/session/event-emit.js +101 -0
  59. package/build/session/extract.d.ts +1 -0
  60. package/build/session/extract.js +79 -12
  61. package/build/session/purge.d.ts +111 -0
  62. package/build/session/purge.js +138 -0
  63. package/build/store.d.ts +7 -0
  64. package/build/store.js +69 -6
  65. package/build/util/claude-config.d.ts +26 -0
  66. package/build/util/claude-config.js +91 -0
  67. package/build/util/hook-config.d.ts +4 -0
  68. package/build/util/hook-config.js +39 -0
  69. package/cli.bundle.mjs +411 -208
  70. package/configs/antigravity/GEMINI.md +0 -3
  71. package/configs/claude-code/CLAUDE.md +1 -4
  72. package/configs/codex/AGENTS.md +1 -4
  73. package/configs/codex/config.toml +3 -0
  74. package/configs/codex/hooks.json +8 -0
  75. package/configs/cursor/context-mode.mdc +0 -3
  76. package/configs/gemini-cli/GEMINI.md +0 -3
  77. package/configs/jetbrains-copilot/copilot-instructions.md +0 -3
  78. package/configs/kilo/AGENTS.md +0 -3
  79. package/configs/kiro/KIRO.md +0 -3
  80. package/configs/omp/SYSTEM.md +85 -0
  81. package/configs/omp/mcp.json +7 -0
  82. package/configs/openclaw/AGENTS.md +0 -3
  83. package/configs/opencode/AGENTS.md +0 -3
  84. package/configs/pi/AGENTS.md +0 -3
  85. package/configs/qwen-code/QWEN.md +1 -4
  86. package/configs/vscode-copilot/copilot-instructions.md +0 -3
  87. package/configs/zed/AGENTS.md +0 -3
  88. package/hooks/codex/posttooluse.mjs +9 -2
  89. package/hooks/codex/precompact.mjs +69 -0
  90. package/hooks/codex/sessionstart.mjs +13 -9
  91. package/hooks/codex/stop.mjs +1 -2
  92. package/hooks/codex/userpromptsubmit.mjs +1 -2
  93. package/hooks/core/routing.mjs +237 -18
  94. package/hooks/cursor/afteragentresponse.mjs +1 -1
  95. package/hooks/cursor/hooks.json +31 -0
  96. package/hooks/cursor/posttooluse.mjs +1 -1
  97. package/hooks/cursor/sessionstart.mjs +5 -5
  98. package/hooks/cursor/stop.mjs +1 -1
  99. package/hooks/ensure-deps.mjs +12 -13
  100. package/hooks/gemini-cli/aftertool.mjs +1 -1
  101. package/hooks/gemini-cli/beforeagent.mjs +1 -1
  102. package/hooks/gemini-cli/precompress.mjs +3 -2
  103. package/hooks/gemini-cli/sessionstart.mjs +9 -9
  104. package/hooks/jetbrains-copilot/posttooluse.mjs +1 -1
  105. package/hooks/jetbrains-copilot/precompact.mjs +3 -2
  106. package/hooks/jetbrains-copilot/sessionstart.mjs +9 -9
  107. package/hooks/kiro/agentspawn.mjs +5 -5
  108. package/hooks/kiro/posttooluse.mjs +2 -2
  109. package/hooks/kiro/userpromptsubmit.mjs +1 -1
  110. package/hooks/posttooluse.mjs +45 -0
  111. package/hooks/precompact.mjs +17 -0
  112. package/hooks/pretooluse.mjs +23 -0
  113. package/hooks/routing-block.mjs +0 -12
  114. package/hooks/run-hook.mjs +16 -3
  115. package/hooks/session-db.bundle.mjs +27 -18
  116. package/hooks/session-extract.bundle.mjs +2 -2
  117. package/hooks/session-helpers.mjs +101 -64
  118. package/hooks/sessionstart.mjs +51 -2
  119. package/hooks/vscode-copilot/posttooluse.mjs +1 -1
  120. package/hooks/vscode-copilot/precompact.mjs +3 -2
  121. package/hooks/vscode-copilot/sessionstart.mjs +9 -9
  122. package/openclaw.plugin.json +1 -1
  123. package/package.json +14 -8
  124. package/server.bundle.mjs +349 -147
  125. package/skills/UPSTREAM-CREDITS.md +0 -51
  126. package/skills/context-mode-ops/SKILL.md +0 -299
  127. package/skills/context-mode-ops/agent-teams.md +0 -198
  128. package/skills/context-mode-ops/communication.md +0 -224
  129. package/skills/context-mode-ops/marketing.md +0 -124
  130. package/skills/context-mode-ops/release.md +0 -214
  131. package/skills/context-mode-ops/review-pr.md +0 -269
  132. package/skills/context-mode-ops/tdd.md +0 -329
  133. package/skills/context-mode-ops/triage-issue.md +0 -266
  134. package/skills/context-mode-ops/validation.md +0 -307
  135. package/skills/diagnose/SKILL.md +0 -122
  136. package/skills/diagnose/scripts/hitl-loop.template.sh +0 -41
  137. package/skills/grill-me/SKILL.md +0 -15
  138. package/skills/grill-with-docs/ADR-FORMAT.md +0 -47
  139. package/skills/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  140. package/skills/grill-with-docs/SKILL.md +0 -93
  141. package/skills/improve-codebase-architecture/DEEPENING.md +0 -37
  142. package/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  143. package/skills/improve-codebase-architecture/LANGUAGE.md +0 -53
  144. package/skills/improve-codebase-architecture/SKILL.md +0 -76
  145. package/skills/tdd/SKILL.md +0 -114
  146. package/skills/tdd/deep-modules.md +0 -33
  147. package/skills/tdd/interface-design.md +0 -31
  148. package/skills/tdd/mocking.md +0 -59
  149. package/skills/tdd/refactoring.md +0 -10
  150. package/skills/tdd/tests.md +0 -61
@@ -20,7 +20,7 @@ const ROUTING_BLOCK = createRoutingBlock(toolNamer);
20
20
  import { writeSessionEventsFile, buildSessionDirective, getSessionEvents } from "../session-directive.mjs";
21
21
  import {
22
22
  readStdin, parseStdin, getSessionId, getSessionDBPath, getSessionEventsPath, getCleanupFlagPath,
23
- getProjectDir, JETBRAINS_OPTS,
23
+ getInputProjectDir, JETBRAINS_OPTS,
24
24
  } from "../session-helpers.mjs";
25
25
  import { join } from "node:path";
26
26
  import { readFileSync, unlinkSync } from "node:fs";
@@ -37,10 +37,11 @@ try {
37
37
  const raw = await readStdin();
38
38
  const input = parseStdin(raw);
39
39
  const source = input.source ?? "startup";
40
+ const projectDir = getInputProjectDir(input, OPTS);
40
41
 
41
42
  if (source === "compact") {
42
43
  const { SessionDB } = await loadSessionDB();
43
- const dbPath = getSessionDBPath(OPTS);
44
+ const dbPath = getSessionDBPath(OPTS, projectDir);
44
45
  const db = new SessionDB({ dbPath });
45
46
  const sessionId = getSessionId(input, OPTS);
46
47
  const resume = db.getResume(sessionId);
@@ -51,16 +52,16 @@ try {
51
52
 
52
53
  const events = getSessionEvents(db, sessionId);
53
54
  if (events.length > 0) {
54
- const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS));
55
+ const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS, projectDir));
55
56
  additionalContext += buildSessionDirective("compact", eventMeta, toolNamer);
56
57
  }
57
58
 
58
59
  db.close();
59
60
  } else if (source === "resume") {
60
- try { unlinkSync(getCleanupFlagPath(OPTS)); } catch { /* no flag */ }
61
+ try { unlinkSync(getCleanupFlagPath(OPTS, projectDir)); } catch { /* no flag */ }
61
62
 
62
63
  const { SessionDB } = await loadSessionDB();
63
- const dbPath = getSessionDBPath(OPTS);
64
+ const dbPath = getSessionDBPath(OPTS, projectDir);
64
65
  const db = new SessionDB({ dbPath });
65
66
 
66
67
  // Filter events to the session being resumed. Falling back to
@@ -70,22 +71,21 @@ try {
70
71
  const sessionId = getSessionId(input, OPTS);
71
72
  const events = sessionId ? getSessionEvents(db, sessionId) : [];
72
73
  if (events.length > 0) {
73
- const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS));
74
+ const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS, projectDir));
74
75
  additionalContext += buildSessionDirective("resume", eventMeta, toolNamer);
75
76
  }
76
77
 
77
78
  db.close();
78
79
  } else if (source === "startup") {
79
80
  const { SessionDB } = await loadSessionDB();
80
- const dbPath = getSessionDBPath(OPTS);
81
+ const dbPath = getSessionDBPath(OPTS, projectDir);
81
82
  const db = new SessionDB({ dbPath });
82
- try { unlinkSync(getSessionEventsPath(OPTS)); } catch { /* no stale file */ }
83
+ try { unlinkSync(getSessionEventsPath(OPTS, projectDir)); } catch { /* no stale file */ }
83
84
 
84
85
  db.cleanupOldSessions(7);
85
86
  db.db.exec(`DELETE FROM session_events WHERE session_id NOT IN (SELECT session_id FROM session_meta)`);
86
87
 
87
88
  const sessionId = getSessionId(input, OPTS);
88
- const projectDir = getProjectDir(OPTS);
89
89
  db.ensureSession(sessionId, projectDir);
90
90
 
91
91
  const ruleFilePaths = [
@@ -51,7 +51,7 @@ try {
51
51
 
52
52
  if (source === "compact" || source === "resume") {
53
53
  const { SessionDB } = await loadSessionDB();
54
- const dbPath = getSessionDBPath(OPTS);
54
+ const dbPath = getSessionDBPath(OPTS, projectDir);
55
55
  const db = new SessionDB({ dbPath });
56
56
 
57
57
  if (source === "compact") {
@@ -61,22 +61,22 @@ try {
61
61
  db.markResumeConsumed(sessionId);
62
62
  }
63
63
  } else {
64
- try { unlinkSync(getCleanupFlagPath(OPTS)); } catch { /* no flag */ }
64
+ try { unlinkSync(getCleanupFlagPath(OPTS, projectDir)); } catch { /* no flag */ }
65
65
  }
66
66
 
67
67
  const sessionId = getSessionId(input, OPTS);
68
68
  const events = sessionId ? getSessionEvents(db, sessionId) : [];
69
69
  if (events.length > 0) {
70
- const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS));
70
+ const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS, projectDir));
71
71
  additionalContext += buildSessionDirective(source, eventMeta, toolNamer);
72
72
  }
73
73
 
74
74
  db.close();
75
75
  } else if (source === "startup") {
76
76
  const { SessionDB } = await loadSessionDB();
77
- const dbPath = getSessionDBPath(OPTS);
77
+ const dbPath = getSessionDBPath(OPTS, projectDir);
78
78
  const db = new SessionDB({ dbPath });
79
- try { unlinkSync(getSessionEventsPath(OPTS)); } catch { /* no stale file */ }
79
+ try { unlinkSync(getSessionEventsPath(OPTS, projectDir)); } catch { /* no stale file */ }
80
80
 
81
81
  db.cleanupOldSessions(7);
82
82
  db.db.exec(`DELETE FROM session_events WHERE session_id NOT IN (SELECT session_id FROM session_meta)`);
@@ -25,10 +25,10 @@ try {
25
25
  const { resolveProjectAttributions } = await loadProjectAttribution();
26
26
  const { SessionDB } = await loadSessionDB();
27
27
 
28
- const dbPath = getSessionDBPath(OPTS);
29
- const db = new SessionDB({ dbPath });
30
28
  const sessionId = getSessionId(input, OPTS);
31
29
  const projectDir = getInputProjectDir(input, OPTS);
30
+ const dbPath = getSessionDBPath(OPTS, projectDir);
31
+ const db = new SessionDB({ dbPath });
32
32
 
33
33
  db.ensureSession(sessionId, projectDir);
34
34
 
@@ -43,7 +43,7 @@ try {
43
43
  const { SessionDB } = await loadSessionDB();
44
44
  const { extractUserEvents } = await loadExtract();
45
45
  const { resolveProjectAttributions } = await loadProjectAttribution();
46
- const dbPath = getSessionDBPath(OPTS);
46
+ const dbPath = getSessionDBPath(OPTS, projectDir);
47
47
  const db = new SessionDB({ dbPath });
48
48
  const sessionId = getSessionId(input, OPTS);
49
49
 
@@ -80,6 +80,51 @@ await runHook(async () => {
80
80
  }
81
81
  } catch { /* best-effort */ }
82
82
 
83
+ // ─── D2 PRD Phase 3/4: redirect marker — emit byte-accounting event ───
84
+ // PreToolUse wrote `context-mode-redirect-${sessionId}.txt` for tools whose
85
+ // output we kept out of the model's context window (curl/wget, WebFetch,
86
+ // large Read). Format: `tool:type:bytesAvoided:commandSummary` (Override C).
87
+ try {
88
+ const redirectPath = resolve(tmpdir(), `context-mode-redirect-${sessionId}.txt`);
89
+ let redirectData;
90
+ try {
91
+ redirectData = readFileSync(redirectPath, "utf-8").trim();
92
+ // Slice 3.3: unlink so the next PostToolUse for an unrelated tool call
93
+ // does NOT re-emit the same event (no double-accounting).
94
+ unlinkSync(redirectPath);
95
+ } catch { /* no marker — Slice 3.4: phantom-event guard */ }
96
+
97
+ if (redirectData) {
98
+ // Parse first 3 colons; the rest (commandSummary) may itself contain
99
+ // colons (URLs do — `https://`). Avoid `split(":", 4)` which would
100
+ // truncate the summary at any embedded colon.
101
+ const i1 = redirectData.indexOf(":");
102
+ const i2 = i1 >= 0 ? redirectData.indexOf(":", i1 + 1) : -1;
103
+ const i3 = i2 >= 0 ? redirectData.indexOf(":", i2 + 1) : -1;
104
+ if (i1 > 0 && i2 > i1 && i3 > i2) {
105
+ const tool = redirectData.slice(0, i1);
106
+ const type = redirectData.slice(i1 + 1, i2);
107
+ const bytesRaw = redirectData.slice(i2 + 1, i3);
108
+ const summary = redirectData.slice(i3 + 1);
109
+ const bytesAvoided = Number.parseInt(bytesRaw, 10);
110
+ if (Number.isFinite(bytesAvoided) && bytesAvoided > 0) {
111
+ db.insertEvent(
112
+ sessionId,
113
+ {
114
+ type,
115
+ category: "redirect",
116
+ data: `${tool}: ${summary}`,
117
+ priority: 2,
118
+ },
119
+ "PreToolUse",
120
+ undefined,
121
+ { bytesAvoided, bytesReturned: 0 },
122
+ );
123
+ }
124
+ }
125
+ }
126
+ } catch { /* best-effort — never block hook */ }
127
+
83
128
  // ─── Category 27: Latency — read cross-hook marker and emit event if slow ───
84
129
  try {
85
130
  const toolName = input.tool_name ?? "";
@@ -60,6 +60,23 @@ await runHook(async () => {
60
60
  data: `Session compacted. ${events.length} events, ${fileEvents.length} files touched.`,
61
61
  priority: 1,
62
62
  }, "PreCompact");
63
+
64
+ // D2 PRD Phase 6.1: emit snapshot-built event with bytes_avoided=snapshot.length
65
+ // Snapshot bytes are bytes the model would have re-read on resume but didn't.
66
+ try {
67
+ db.insertEvent(
68
+ sessionId,
69
+ {
70
+ type: "snapshot-built",
71
+ category: "compaction",
72
+ data: `Snapshot built. ${snapshot.length} bytes for ${events.length} events.`,
73
+ priority: 1,
74
+ },
75
+ "PreCompact",
76
+ undefined,
77
+ { bytesAvoided: snapshot.length, bytesReturned: 0 },
78
+ );
79
+ } catch { /* best-effort */ }
63
80
  }
64
81
 
65
82
  db.close();
@@ -185,6 +185,29 @@ await runHook(async () => {
185
185
  } catch { /* best-effort — never block hook */ }
186
186
  }
187
187
 
188
+ // ─── D2 PRD Phase 3/4: redirect marker for byte-accounting events ───
189
+ // routing.mjs attaches `redirectMeta` to decisions for tools whose output we
190
+ // kept out of the model's context window (curl/wget, WebFetch, large Read).
191
+ // PostToolUse reads this marker to emit a `category=redirect` event with the
192
+ // estimated `bytes_avoided`. PreToolUse cannot load SessionDB safely (native
193
+ // module load breaks hook stdout), hence the marker indirection.
194
+ if (decision && decision.redirectMeta) {
195
+ try {
196
+ const sessionId = getSessionId(input);
197
+ const meta = decision.redirectMeta;
198
+ const summary = String(meta.commandSummary ?? "").slice(0, 200);
199
+ const markerPath = resolve(tmpdir(), `context-mode-redirect-${sessionId}.txt`);
200
+ // Format: tool:type:bytesAvoided:commandSummary (matches Override C).
201
+ // commandSummary may legitimately contain `:` (URLs) — don't quote it,
202
+ // PostToolUse parses only the first 3 colons and treats the rest as data.
203
+ writeFileSync(
204
+ markerPath,
205
+ `${meta.tool}:${meta.type}:${meta.bytesAvoided}:${summary}`,
206
+ "utf-8",
207
+ );
208
+ } catch { /* best-effort — never block hook */ }
209
+ }
210
+
188
211
  // ─── stdout write is the LAST action — process exits immediately after ───
189
212
  if (response !== null) {
190
213
  process.stdout.write(JSON.stringify(response) + "\n");
@@ -50,22 +50,10 @@ export function createRoutingBlock(t, options = {}) {
50
50
  </file_writing_policy>
51
51
 
52
52
  <output_constraints>
53
- <communication_style>
54
- Terse like caveman. Technical substance exact. Only fluff die.
55
- Use fragments when clear. Short synonyms (fix not "implement a solution for").
56
- Technical terms exact. Code blocks unchanged.
57
- Auto-expand for: security warnings, irreversible actions, user confusion.
58
- </communication_style>
59
53
  <artifact_policy>
60
54
  Write artifacts (code, configs, PRDs) to FILES. NEVER inline.
61
55
  Return only: file path + 1-line description.
62
56
  </artifact_policy>
63
- <response_format>
64
- Concise summary:
65
- - Actions taken (2-3 bullets)
66
- - File paths created/modified
67
- - Key findings
68
- </response_format>
69
57
  </output_constraints>
70
58
  <session_continuity>
71
59
  Skills, roles, and decisions set during this session remain active until the user revokes them.
@@ -13,7 +13,9 @@
13
13
  * wrapper, where the handler is guaranteed to be live.
14
14
  *
15
15
  * Contract:
16
- * - logs every failure to ~/.claude/context-mode/hook-errors.log
16
+ * - logs every failure to <configDir>/context-mode/hook-errors.log,
17
+ * where configDir honors $CLAUDE_CONFIG_DIR (incl. leading ~) and
18
+ * falls back to ~/.claude — same contract as session-helpers.mjs (#453)
17
19
  * - never propagates a non-zero exit (Claude Code surfaces non-zero as a
18
20
  * "non-blocking hook error" on every tool call, which spams the user)
19
21
  * - one-liner adoption for new hooks:
@@ -22,12 +24,23 @@
22
24
  */
23
25
 
24
26
  import { homedir } from "node:os";
25
- import { resolve } from "node:path";
27
+ import { resolve, join } from "node:path";
26
28
  import { existsSync, mkdirSync, appendFileSync } from "node:fs";
27
29
 
30
+ // Inlined to keep this wrapper dependency-free (parse-time imports must be
31
+ // failure-proof). Mirrors session-helpers.mjs::resolveConfigDir for #453.
32
+ function resolveClaudeConfigDir() {
33
+ const envVal = process.env.CLAUDE_CONFIG_DIR;
34
+ if (envVal) {
35
+ if (envVal.startsWith("~")) return join(homedir(), envVal.replace(/^~[/\\]?/, ""));
36
+ return envVal;
37
+ }
38
+ return resolve(homedir(), ".claude");
39
+ }
40
+
28
41
  function logError(err) {
29
42
  try {
30
- const dir = resolve(homedir(), ".claude", "context-mode");
43
+ const dir = resolve(resolveClaudeConfigDir(), "context-mode");
31
44
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
32
45
  const line = `[${new Date().toISOString()}] pid=${process.pid} ${err?.stack || err?.message || String(err)}\n`;
33
46
  appendFileSync(resolve(dir, "hook-errors.log"), line);
@@ -1,4 +1,4 @@
1
- import{createRequire as I}from"node:module";import{existsSync as U,unlinkSync as v,renameSync as M}from"node:fs";import{tmpdir as x}from"node:os";import{join as F}from"node:path";var g=class{#t;constructor(t){this.#t=t}pragma(t){let s=this.#t.prepare(`PRAGMA ${t}`).all();if(!s||s.length===0)return;if(s.length>1)return s;let r=Object.values(s[0]);return r.length===1?r[0]:s[0]}exec(t){let e="",s=null;for(let o=0;o<t.length;o++){let a=t[o];if(s)e+=a,a===s&&(s=null);else if(a==="'"||a==='"')e+=a,s=a;else if(a===";"){let c=e.trim();c&&this.#t.prepare(c).run(),e=""}else e+=a}let r=e.trim();return r&&this.#t.prepare(r).run(),this}prepare(t){let e=this.#t.prepare(t);return{run:(...s)=>e.run(...s),get:(...s)=>{let r=e.get(...s);return r===null?void 0:r},all:(...s)=>e.all(...s),iterate:(...s)=>e.iterate(...s)}}transaction(t){return this.#t.transaction(t)}close(){this.#t.close()}},h=class{#t;constructor(t){this.#t=t}pragma(t){let s=this.#t.prepare(`PRAGMA ${t}`).all();if(!s||s.length===0)return;if(s.length>1)return s;let r=Object.values(s[0]);return r.length===1?r[0]:s[0]}exec(t){return this.#t.exec(t),this}prepare(t){let e=this.#t.prepare(t);return{run:(...s)=>e.run(...s),get:(...s)=>e.get(...s),all:(...s)=>e.all(...s),iterate:(...s)=>typeof e.iterate=="function"?e.iterate(...s):e.all(...s)[Symbol.iterator]()}}transaction(t){return(...e)=>{this.#t.exec("BEGIN");try{let s=t(...e);return this.#t.exec("COMMIT"),s}catch(s){throw this.#t.exec("ROLLBACK"),s}}}close(){this.#t.close()}},d=null;function B(){if(!d){let i=I(import.meta.url);if(globalThis.Bun){let t=i(["bun","sqlite"].join(":")).Database;d=function(s,r){let o=new t(s,{readonly:r?.readonly,create:!0}),a=new g(o);return r?.timeout&&a.pragma(`busy_timeout = ${r.timeout}`),a}}else if(process.platform==="linux")try{let{DatabaseSync:t}=i(["node","sqlite"].join(":"));d=function(s,r){let o=new t(s,{readOnly:r?.readonly??!1});return new h(o)}}catch{d=i("better-sqlite3")}else d=i("better-sqlite3")}return d}function b(i){i.pragma("journal_mode = WAL"),i.pragma("synchronous = NORMAL");try{i.pragma("mmap_size = 268435456")}catch{}}function N(i){if(!U(i))for(let t of["-wal","-shm"])try{v(i+t)}catch{}}function P(i){for(let t of["","-wal","-shm"])try{v(i+t)}catch{}}function y(i){try{i.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{i.close()}catch{}}function C(i="context-mode"){return F(x(),`${i}-${process.pid}.db`)}function k(i,t=[100,500,2e3]){let e;for(let s=0;s<=t.length;s++)try{return i()}catch(r){let o=r instanceof Error?r.message:String(r);if(!o.includes("SQLITE_BUSY")&&!o.includes("database is locked"))throw r;if(e=r instanceof Error?r:new Error(o),s<t.length){let a=t[s],c=Date.now();for(;Date.now()-c<a;);}}throw new Error(`SQLITE_BUSY: database is locked after ${t.length} retries. Original error: ${e?.message}`)}function j(i){return i.includes("SQLITE_CORRUPT")||i.includes("SQLITE_NOTADB")||i.includes("database disk image is malformed")||i.includes("file is not a database")}function X(i){let t=Date.now();for(let e of["","-wal","-shm"])try{M(i+e,`${i}${e}.corrupt-${t}`)}catch{}}var m=Symbol.for("__context_mode_live_dbs__"),p=(()=>{let i=globalThis;return i[m]||(i[m]=new Set,process.on("exit",()=>{for(let t of i[m])y(t);i[m].clear()})),i[m]})(),T=class{#t;#e;constructor(t){let e=B();this.#t=t,N(t);let s;try{s=new e(t,{timeout:3e4}),b(s)}catch(r){let o=r instanceof Error?r.message:String(r);if(j(o)){X(t),N(t);try{s=new e(t,{timeout:3e4}),b(s)}catch(a){throw new Error(`Failed to create fresh DB after renaming corrupt file: ${a instanceof Error?a.message:String(a)}`)}}else throw r}this.#e=s,p.add(this.#e),this.initSchema(),this.prepareStatements()}get db(){return this.#e}get dbPath(){return this.#t}close(){p.delete(this.#e),y(this.#e)}withRetry(t){return k(t)}cleanup(){p.delete(this.#e),y(this.#e),P(this.#t)}};import{createHash as f}from"node:crypto";import{execFileSync as W}from"node:child_process";var l;function z(){let i=process.env.CONTEXT_MODE_SESSION_SUFFIX,t=process.cwd();if(l&&l.cwd===t&&l.envSuffix===i)return l.suffix;let e="";if(i!==void 0)e=i?`__${i}`:"";else try{let s=W("git",["worktree","list","--porcelain"],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).find(r=>r.startsWith("worktree "))?.replace("worktree ","")?.trim();s&&t!==s&&(e=`__${f("sha256").update(t).digest("hex").slice(0,8)}`)}catch{}return l={cwd:t,envSuffix:i,suffix:e},e}function J(){l=void 0}var O=1e3,D=5,n={insertEvent:"insertEvent",getEvents:"getEvents",getEventsByType:"getEventsByType",getEventsByPriority:"getEventsByPriority",getEventsByTypeAndPriority:"getEventsByTypeAndPriority",getEventCount:"getEventCount",getLatestAttributedProject:"getLatestAttributedProject",checkDuplicate:"checkDuplicate",evictLowestPriority:"evictLowestPriority",updateMetaLastEvent:"updateMetaLastEvent",ensureSession:"ensureSession",getSessionStats:"getSessionStats",incrementCompactCount:"incrementCompactCount",upsertResume:"upsertResume",getResume:"getResume",markResumeConsumed:"markResumeConsumed",claimLatestUnconsumedResume:"claimLatestUnconsumedResume",deleteEvents:"deleteEvents",deleteMeta:"deleteMeta",deleteResume:"deleteResume",getOldSessions:"getOldSessions",searchEvents:"searchEvents",incrementToolCall:"incrementToolCall",getToolCallTotals:"getToolCallTotals",getToolCallByTool:"getToolCallByTool"},A=class extends T{constructor(t){super(t?.dbPath??C("session"))}stmt(t){return this.stmts.get(t)}initSchema(){try{let e=this.db.pragma("table_xinfo(session_events)").find(s=>s.name==="data_hash");e&&e.hidden!==0&&this.db.exec("DROP TABLE session_events")}catch{}this.db.exec(`
1
+ import{createRequire as Y}from"node:module";import{existsSync as G,unlinkSync as x,renameSync as q}from"node:fs";import{tmpdir as z}from"node:os";import{join as K}from"node:path";var N=class{#t;constructor(t){this.#t=t}pragma(t){let s=this.#t.prepare(`PRAGMA ${t}`).all();if(!s||s.length===0)return;if(s.length>1)return s;let r=Object.values(s[0]);return r.length===1?r[0]:s[0]}exec(t){let e="",s=null;for(let o=0;o<t.length;o++){let a=t[o];if(s)e+=a,a===s&&(s=null);else if(a==="'"||a==='"')e+=a,s=a;else if(a===";"){let u=e.trim();u&&this.#t.prepare(u).run(),e=""}else e+=a}let r=e.trim();return r&&this.#t.prepare(r).run(),this}prepare(t){let e=this.#t.prepare(t);return{run:(...s)=>e.run(...s),get:(...s)=>{let r=e.get(...s);return r===null?void 0:r},all:(...s)=>e.all(...s),iterate:(...s)=>e.iterate(...s)}}transaction(t){return this.#t.transaction(t)}close(){this.#t.close()}},A=class{#t;constructor(t){this.#t=t}pragma(t){let s=this.#t.prepare(`PRAGMA ${t}`).all();if(!s||s.length===0)return;if(s.length>1)return s;let r=Object.values(s[0]);return r.length===1?r[0]:s[0]}exec(t){return this.#t.exec(t),this}prepare(t){let e=this.#t.prepare(t);return{run:(...s)=>e.run(...s),get:(...s)=>e.get(...s),all:(...s)=>e.all(...s),iterate:(...s)=>typeof e.iterate=="function"?e.iterate(...s):e.all(...s)[Symbol.iterator]()}}transaction(t){return(...e)=>{this.#t.exec("BEGIN");try{let s=t(...e);return this.#t.exec("COMMIT"),s}catch(s){throw this.#t.exec("ROLLBACK"),s}}}close(){this.#t.close()}},l=null;function V(n){let t=null;try{return t=new n(":memory:"),t.exec("CREATE VIRTUAL TABLE __fts5_probe USING fts5(x)"),!0}catch{return!1}finally{try{t?.close()}catch{}}}function Q(){if(!l){let n=Y(import.meta.url);if(globalThis.Bun){let t=n(["bun","sqlite"].join(":")).Database;l=function(s,r){let o=new t(s,{readonly:r?.readonly,create:!0}),a=new N(o);return r?.timeout&&a.pragma(`busy_timeout = ${r.timeout}`),a}}else if(process.platform==="linux"){let t=null;try{({DatabaseSync:t}=n(["node","sqlite"].join(":")))}catch{t=null}t&&V(t)?l=function(s,r){let o=new t(s,{readOnly:r?.readonly??!1});return new A(o)}:l=n("better-sqlite3")}else l=n("better-sqlite3")}return l}function I(n){n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL");try{n.pragma("mmap_size = 268435456")}catch{}}function U(n){if(!G(n))for(let t of["-wal","-shm"])try{x(n+t)}catch{}}function Z(n){for(let t of["","-wal","-shm"])try{x(n+t)}catch{}}function D(n){try{n.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{n.close()}catch{}}function M(n="context-mode"){return K(z(),`${n}-${process.pid}.db`)}function J(n,t=[100,500,2e3]){let e;for(let s=0;s<=t.length;s++)try{return n()}catch(r){let o=r instanceof Error?r.message:String(r);if(!o.includes("SQLITE_BUSY")&&!o.includes("database is locked"))throw r;if(e=r instanceof Error?r:new Error(o),s<t.length){let a=t[s],u=Date.now();for(;Date.now()-u<a;);}}throw new Error(`SQLITE_BUSY: database is locked after ${t.length} retries. Original error: ${e?.message}`)}function tt(n){return n.includes("SQLITE_CORRUPT")||n.includes("SQLITE_NOTADB")||n.includes("database disk image is malformed")||n.includes("file is not a database")}function et(n){let t=Date.now();for(let e of["","-wal","-shm"])try{q(n+e,`${n}${e}.corrupt-${t}`)}catch{}}var _=Symbol.for("__context_mode_live_dbs__"),v=(()=>{let n=globalThis;return n[_]||(n[_]=new Set,process.on("exit",()=>{for(let t of n[_])D(t);n[_].clear()})),n[_]})(),y=class{#t;#e;constructor(t){let e=Q();this.#t=t,U(t);let s;try{s=new e(t,{timeout:3e4}),I(s)}catch(r){let o=r instanceof Error?r.message:String(r);if(tt(o)){et(t),U(t);try{s=new e(t,{timeout:3e4}),I(s)}catch(a){throw new Error(`Failed to create fresh DB after renaming corrupt file: ${a instanceof Error?a.message:String(a)}`)}}else throw r}this.#e=s,v.add(this.#e),this.initSchema(),this.prepareStatements()}get db(){return this.#e}get dbPath(){return this.#t}close(){v.delete(this.#e),D(this.#e)}withRetry(t){return J(t)}cleanup(){v.delete(this.#e),D(this.#e),Z(this.#t)}};import{createHash as p}from"node:crypto";import{execFileSync as st}from"node:child_process";import{existsSync as f,realpathSync as nt,renameSync as C}from"node:fs";import{join as b}from"node:path";var E;function g(n){let t=n.replace(/\\/g,"/");return/^\/+$/.test(t)?"/":/^[A-Za-z]:\/+$/.test(t)?`${t.slice(0,2)}/`:t.replace(/\/+$/,"")}function F(n){let t=n;try{t=nt.native(n)}catch{}let e=g(t);return process.platform==="win32"||process.platform==="darwin"?e.toLowerCase():e}function j(n,t){return st("git",["-C",n,...t],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}function rt(n){let t=j(n,["rev-parse","--show-toplevel"]);return t.length>0?g(t):null}function it(n){let t=j(n,["worktree","list","--porcelain"]).split(/\r?\n/).find(e=>e.startsWith("worktree "))?.replace("worktree ","")?.trim();return t?g(t):null}function ot(n=process.cwd()){let t=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(E&&E.projectDir===n&&E.envSuffix===t)return E.suffix;let e="";if(t!==void 0)e=t?`__${t}`:"";else try{let s=rt(n),r=it(n);if(s&&r){let o=F(s),a=F(r);o!==a&&(e=`__${p("sha256").update(o).digest("hex").slice(0,8)}`)}}catch{}return E={projectDir:n,envSuffix:t,suffix:e},e}function yt(){E=void 0}function X(n){return p("sha256").update(g(n)).digest("hex").slice(0,16)}function W(n){let t=g(n),e=process.platform==="darwin"||process.platform==="win32"?t.toLowerCase():t;return p("sha256").update(e).digest("hex").slice(0,16)}function ht(n){let{projectDir:t,contentDir:e}=n,s=W(t),r=b(e,`${s}.db`);if(f(r))return r;let o=X(t);if(o===s)return r;let a=b(e,`${o}.db`);if(f(a))try{C(a,r);for(let u of["-wal","-shm"])try{C(a+u,r+u)}catch{}}catch{}return r}function ft(n){return at({...n,ext:".db"})}function at(n){let{projectDir:t,sessionsDir:e,ext:s}=n,r=n.suffix??ot(t),o=W(t),a=b(e,`${o}${r}${s}`);if(f(a))return a;let u=X(t);if(u===o)return a;let d=b(e,`${u}${r}${s}`);if(f(d))try{C(d,a)}catch{}return a}var B=1e3,P=5;function h(n){let t=Number(n);return!Number.isFinite(t)||t<=0?0:Math.floor(t)}var i={insertEvent:"insertEvent",getEvents:"getEvents",getEventsByType:"getEventsByType",getEventsByPriority:"getEventsByPriority",getEventsByTypeAndPriority:"getEventsByTypeAndPriority",getEventCount:"getEventCount",getLatestAttributedProject:"getLatestAttributedProject",checkDuplicate:"checkDuplicate",evictLowestPriority:"evictLowestPriority",updateMetaLastEvent:"updateMetaLastEvent",ensureSession:"ensureSession",getSessionStats:"getSessionStats",incrementCompactCount:"incrementCompactCount",upsertResume:"upsertResume",getResume:"getResume",markResumeConsumed:"markResumeConsumed",claimLatestUnconsumedResume:"claimLatestUnconsumedResume",deleteEvents:"deleteEvents",deleteMeta:"deleteMeta",deleteResume:"deleteResume",getOldSessions:"getOldSessions",searchEvents:"searchEvents",incrementToolCall:"incrementToolCall",getToolCallTotals:"getToolCallTotals",getToolCallByTool:"getToolCallByTool",getEventBytesSummary:"getEventBytesSummary"},k=class extends y{constructor(t){super(t?.dbPath??M("session"))}stmt(t){return this.stmts.get(t)}initSchema(){try{let e=this.db.pragma("table_xinfo(session_events)").find(s=>s.name==="data_hash");e&&e.hidden!==0&&this.db.exec("DROP TABLE session_events")}catch{}this.db.exec(`
2
2
  CREATE TABLE IF NOT EXISTS session_events (
3
3
  id INTEGER PRIMARY KEY AUTOINCREMENT,
4
4
  session_id TEXT NOT NULL,
@@ -9,6 +9,8 @@ import{createRequire as I}from"node:module";import{existsSync as U,unlinkSync as
9
9
  project_dir TEXT NOT NULL DEFAULT '',
10
10
  attribution_source TEXT NOT NULL DEFAULT 'unknown',
11
11
  attribution_confidence REAL NOT NULL DEFAULT 0,
12
+ bytes_avoided INTEGER NOT NULL DEFAULT 0,
13
+ bytes_returned INTEGER NOT NULL DEFAULT 0,
12
14
  source_hook TEXT NOT NULL,
13
15
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
14
16
  data_hash TEXT NOT NULL DEFAULT ''
@@ -46,45 +48,50 @@ import{createRequire as I}from"node:module";import{existsSync as U,unlinkSync as
46
48
  );
47
49
 
48
50
  CREATE INDEX IF NOT EXISTS idx_tool_calls_session ON tool_calls(session_id);
49
- `);try{let t=this.db.pragma("table_xinfo(session_events)"),e=new Set(t.map(s=>s.name));e.has("project_dir")||this.db.exec("ALTER TABLE session_events ADD COLUMN project_dir TEXT NOT NULL DEFAULT ''"),e.has("attribution_source")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_source TEXT NOT NULL DEFAULT 'unknown'"),e.has("attribution_confidence")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_confidence REAL NOT NULL DEFAULT 0"),this.db.exec("CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(session_id, project_dir)")}catch{}}prepareStatements(){this.stmts=new Map;let t=(e,s)=>{this.stmts.set(e,this.db.prepare(s))};t(n.insertEvent,`INSERT INTO session_events (
51
+ `);try{let t=this.db.pragma("table_xinfo(session_events)"),e=new Set(t.map(s=>s.name));e.has("project_dir")||this.db.exec("ALTER TABLE session_events ADD COLUMN project_dir TEXT NOT NULL DEFAULT ''"),e.has("attribution_source")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_source TEXT NOT NULL DEFAULT 'unknown'"),e.has("attribution_confidence")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_confidence REAL NOT NULL DEFAULT 0"),e.has("bytes_avoided")||this.db.exec("ALTER TABLE session_events ADD COLUMN bytes_avoided INTEGER NOT NULL DEFAULT 0"),e.has("bytes_returned")||this.db.exec("ALTER TABLE session_events ADD COLUMN bytes_returned INTEGER NOT NULL DEFAULT 0"),this.db.exec("CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(session_id, project_dir)")}catch{}}prepareStatements(){this.stmts=new Map;let t=(e,s)=>{this.stmts.set(e,this.db.prepare(s))};t(i.insertEvent,`INSERT INTO session_events (
50
52
  session_id, type, category, priority, data,
51
53
  project_dir, attribution_source, attribution_confidence,
54
+ bytes_avoided, bytes_returned,
52
55
  source_hook, data_hash
53
56
  )
54
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),t(n.getEvents,`SELECT id, session_id, type, category, priority, data,
57
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),t(i.getEvents,`SELECT id, session_id, type, category, priority, data,
55
58
  project_dir, attribution_source, attribution_confidence,
59
+ bytes_avoided, bytes_returned,
56
60
  source_hook, created_at, data_hash
57
- FROM session_events WHERE session_id = ? ORDER BY id ASC LIMIT ?`),t(n.getEventsByType,`SELECT id, session_id, type, category, priority, data,
61
+ FROM session_events WHERE session_id = ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByType,`SELECT id, session_id, type, category, priority, data,
58
62
  project_dir, attribution_source, attribution_confidence,
63
+ bytes_avoided, bytes_returned,
59
64
  source_hook, created_at, data_hash
60
- FROM session_events WHERE session_id = ? AND type = ? ORDER BY id ASC LIMIT ?`),t(n.getEventsByPriority,`SELECT id, session_id, type, category, priority, data,
65
+ FROM session_events WHERE session_id = ? AND type = ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByPriority,`SELECT id, session_id, type, category, priority, data,
61
66
  project_dir, attribution_source, attribution_confidence,
67
+ bytes_avoided, bytes_returned,
62
68
  source_hook, created_at, data_hash
63
- FROM session_events WHERE session_id = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(n.getEventsByTypeAndPriority,`SELECT id, session_id, type, category, priority, data,
69
+ FROM session_events WHERE session_id = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByTypeAndPriority,`SELECT id, session_id, type, category, priority, data,
64
70
  project_dir, attribution_source, attribution_confidence,
71
+ bytes_avoided, bytes_returned,
65
72
  source_hook, created_at, data_hash
66
- FROM session_events WHERE session_id = ? AND type = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(n.getEventCount,"SELECT COUNT(*) AS cnt FROM session_events WHERE session_id = ?"),t(n.getLatestAttributedProject,`SELECT project_dir
73
+ FROM session_events WHERE session_id = ? AND type = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(i.getEventCount,"SELECT COUNT(*) AS cnt FROM session_events WHERE session_id = ?"),t(i.getLatestAttributedProject,`SELECT project_dir
67
74
  FROM session_events
68
75
  WHERE session_id = ? AND project_dir != ''
69
76
  ORDER BY id DESC
70
- LIMIT 1`),t(n.checkDuplicate,`SELECT 1 FROM (
77
+ LIMIT 1`),t(i.checkDuplicate,`SELECT 1 FROM (
71
78
  SELECT type, data_hash FROM session_events
72
79
  WHERE session_id = ? ORDER BY id DESC LIMIT ?
73
80
  ) AS recent
74
81
  WHERE recent.type = ? AND recent.data_hash = ?
75
- LIMIT 1`),t(n.evictLowestPriority,`DELETE FROM session_events WHERE id = (
82
+ LIMIT 1`),t(i.evictLowestPriority,`DELETE FROM session_events WHERE id = (
76
83
  SELECT id FROM session_events WHERE session_id = ?
77
84
  ORDER BY priority ASC, id ASC LIMIT 1
78
- )`),t(n.updateMetaLastEvent,`UPDATE session_meta
85
+ )`),t(i.updateMetaLastEvent,`UPDATE session_meta
79
86
  SET last_event_at = datetime('now'), event_count = event_count + 1
80
- WHERE session_id = ?`),t(n.ensureSession,"INSERT OR IGNORE INTO session_meta (session_id, project_dir) VALUES (?, ?)"),t(n.getSessionStats,`SELECT session_id, project_dir, started_at, last_event_at, event_count, compact_count
81
- FROM session_meta WHERE session_id = ?`),t(n.incrementCompactCount,"UPDATE session_meta SET compact_count = compact_count + 1 WHERE session_id = ?"),t(n.upsertResume,`INSERT INTO session_resume (session_id, snapshot, event_count)
87
+ WHERE session_id = ?`),t(i.ensureSession,"INSERT OR IGNORE INTO session_meta (session_id, project_dir) VALUES (?, ?)"),t(i.getSessionStats,`SELECT session_id, project_dir, started_at, last_event_at, event_count, compact_count
88
+ FROM session_meta WHERE session_id = ?`),t(i.incrementCompactCount,"UPDATE session_meta SET compact_count = compact_count + 1 WHERE session_id = ?"),t(i.upsertResume,`INSERT INTO session_resume (session_id, snapshot, event_count)
82
89
  VALUES (?, ?, ?)
83
90
  ON CONFLICT(session_id) DO UPDATE SET
84
91
  snapshot = excluded.snapshot,
85
92
  event_count = excluded.event_count,
86
93
  created_at = datetime('now'),
87
- consumed = 0`),t(n.getResume,"SELECT snapshot, event_count, consumed FROM session_resume WHERE session_id = ?"),t(n.markResumeConsumed,"UPDATE session_resume SET consumed = 1 WHERE session_id = ?"),t(n.claimLatestUnconsumedResume,`UPDATE session_resume
94
+ consumed = 0`),t(i.getResume,"SELECT snapshot, event_count, consumed FROM session_resume WHERE session_id = ?"),t(i.markResumeConsumed,"UPDATE session_resume SET consumed = 1 WHERE session_id = ?"),t(i.claimLatestUnconsumedResume,`UPDATE session_resume
88
95
  SET consumed = 1
89
96
  WHERE id = (
90
97
  SELECT id FROM session_resume
@@ -93,18 +100,20 @@ import{createRequire as I}from"node:module";import{existsSync as U,unlinkSync as
93
100
  ORDER BY created_at DESC, id DESC
94
101
  LIMIT 1
95
102
  )
96
- RETURNING session_id, snapshot`),t(n.deleteEvents,"DELETE FROM session_events WHERE session_id = ?"),t(n.deleteMeta,"DELETE FROM session_meta WHERE session_id = ?"),t(n.deleteResume,"DELETE FROM session_resume WHERE session_id = ?"),t(n.searchEvents,`SELECT id, session_id, category, type, data, created_at
103
+ RETURNING session_id, snapshot`),t(i.deleteEvents,"DELETE FROM session_events WHERE session_id = ?"),t(i.deleteMeta,"DELETE FROM session_meta WHERE session_id = ?"),t(i.deleteResume,"DELETE FROM session_resume WHERE session_id = ?"),t(i.searchEvents,`SELECT id, session_id, category, type, data, created_at
97
104
  FROM session_events
98
105
  WHERE project_dir = ?
99
106
  AND (data LIKE '%' || ? || '%' ESCAPE '\\' OR category LIKE '%' || ? || '%' ESCAPE '\\')
100
107
  AND (? IS NULL OR category = ?)
101
108
  ORDER BY id ASC
102
- LIMIT ?`),t(n.getOldSessions,"SELECT session_id FROM session_meta WHERE started_at < datetime('now', ? || ' days')"),t(n.incrementToolCall,`INSERT INTO tool_calls (session_id, tool, calls, bytes_returned)
109
+ LIMIT ?`),t(i.getOldSessions,"SELECT session_id FROM session_meta WHERE started_at < datetime('now', ? || ' days')"),t(i.incrementToolCall,`INSERT INTO tool_calls (session_id, tool, calls, bytes_returned)
103
110
  VALUES (?, ?, 1, ?)
104
111
  ON CONFLICT(session_id, tool) DO UPDATE SET
105
112
  calls = calls + 1,
106
113
  bytes_returned = bytes_returned + excluded.bytes_returned,
107
- updated_at = datetime('now')`),t(n.getToolCallTotals,`SELECT COALESCE(SUM(calls), 0) AS calls,
114
+ updated_at = datetime('now')`),t(i.getToolCallTotals,`SELECT COALESCE(SUM(calls), 0) AS calls,
115
+ COALESCE(SUM(bytes_returned), 0) AS bytes_returned
116
+ FROM tool_calls WHERE session_id = ?`),t(i.getToolCallByTool,`SELECT tool, calls, bytes_returned
117
+ FROM tool_calls WHERE session_id = ? ORDER BY calls DESC`),t(i.getEventBytesSummary,`SELECT COALESCE(SUM(bytes_avoided), 0) AS bytes_avoided,
108
118
  COALESCE(SUM(bytes_returned), 0) AS bytes_returned
109
- FROM tool_calls WHERE session_id = ?`),t(n.getToolCallByTool,`SELECT tool, calls, bytes_returned
110
- FROM tool_calls WHERE session_id = ? ORDER BY calls DESC`)}insertEvent(t,e,s="PostToolUse",r){let o=f("sha256").update(e.data).digest("hex").slice(0,16).toUpperCase(),a=String(r?.projectDir??e.project_dir??"").trim(),c=String(r?.source??e.attribution_source??"unknown"),u=Number(r?.confidence??e.attribution_confidence??0),_=Number.isFinite(u)?Math.max(0,Math.min(1,u)):0,E=this.db.transaction(()=>{if(this.stmt(n.checkDuplicate).get(t,D,e.type,o))return;this.stmt(n.getEventCount).get(t).cnt>=O&&this.stmt(n.evictLowestPriority).run(t),this.stmt(n.insertEvent).run(t,e.type,e.category,e.priority,e.data,a,c,_,s,o),this.stmt(n.updateMetaLastEvent).run(t)});this.withRetry(()=>E())}bulkInsertEvents(t,e,s="PostToolUse",r){if(!e||e.length===0)return;if(e.length===1){this.insertEvent(t,e[0],s,r?.[0]);return}let o=e.map((c,u)=>{let _=f("sha256").update(c.data).digest("hex").slice(0,16).toUpperCase(),E=r?.[u],S=String(E?.projectDir??c.project_dir??"").trim(),L=String(E?.source??c.attribution_source??"unknown"),R=Number(E?.confidence??c.attribution_confidence??0),w=Number.isFinite(R)?Math.max(0,Math.min(1,R)):0;return{event:c,dataHash:_,projectDir:S,attributionSource:L,attributionConfidence:w}}),a=this.db.transaction(()=>{let c=this.stmt(n.getEventCount).get(t).cnt;for(let u of o)this.stmt(n.checkDuplicate).get(t,D,u.event.type,u.dataHash)||(c>=O?this.stmt(n.evictLowestPriority).run(t):c++,this.stmt(n.insertEvent).run(t,u.event.type,u.event.category,u.event.priority,u.event.data,u.projectDir,u.attributionSource,u.attributionConfidence,s,u.dataHash));this.stmt(n.updateMetaLastEvent).run(t)});this.withRetry(()=>a())}getEvents(t,e){let s=e?.limit??1e3,r=e?.type,o=e?.minPriority;return r&&o!==void 0?this.stmt(n.getEventsByTypeAndPriority).all(t,r,o,s):r?this.stmt(n.getEventsByType).all(t,r,s):o!==void 0?this.stmt(n.getEventsByPriority).all(t,o,s):this.stmt(n.getEvents).all(t,s)}getEventCount(t){return this.stmt(n.getEventCount).get(t).cnt}getLatestAttributedProjectDir(t){return this.stmt(n.getLatestAttributedProject).get(t)?.project_dir||null}searchEvents(t,e,s,r){try{let o=t.replace(/[%_]/g,c=>"\\"+c),a=r??null;return this.stmt(n.searchEvents).all(s,o,o,a,a,e)}catch{return[]}}ensureSession(t,e){this.stmt(n.ensureSession).run(t,e)}getSessionStats(t){return this.stmt(n.getSessionStats).get(t)??null}incrementCompactCount(t){this.stmt(n.incrementCompactCount).run(t)}upsertResume(t,e,s){this.stmt(n.upsertResume).run(t,e,s??0)}getResume(t){return this.stmt(n.getResume).get(t)??null}markResumeConsumed(t){this.stmt(n.markResumeConsumed).run(t)}claimLatestUnconsumedResume(t){let e=this.stmt(n.claimLatestUnconsumedResume).get(t);return e?{sessionId:e.session_id,snapshot:e.snapshot}:null}getLatestSessionId(){try{return this.db.prepare("SELECT session_id FROM session_meta ORDER BY started_at DESC LIMIT 1").get()?.session_id??null}catch{return null}}incrementToolCall(t,e,s=0){let r=Number.isFinite(s)&&s>0?Math.round(s):0;try{this.stmt(n.incrementToolCall).run(t,e,r)}catch{}}getToolCallStats(t){try{let e=this.stmt(n.getToolCallTotals).get(t),s=this.stmt(n.getToolCallByTool).all(t),r={};for(let o of s)r[o.tool]={calls:o.calls,bytesReturned:o.bytes_returned};return{totalCalls:e?.calls??0,totalBytesReturned:e?.bytes_returned??0,byTool:r}}catch{return{totalCalls:0,totalBytesReturned:0,byTool:{}}}}deleteSession(t){this.db.transaction(()=>{this.stmt(n.deleteEvents).run(t),this.stmt(n.deleteResume).run(t),this.stmt(n.deleteMeta).run(t)})()}cleanupOldSessions(t=7){let e=`-${t}`,s=this.stmt(n.getOldSessions).all(e);for(let{session_id:r}of s)this.deleteSession(r);return s.length}};export{A as SessionDB,J as _resetWorktreeSuffixCacheForTests,z as getWorktreeSuffix};
119
+ FROM session_events WHERE session_id = ?`)}insertEvent(t,e,s="PostToolUse",r,o){let a=p("sha256").update(e.data).digest("hex").slice(0,16).toUpperCase(),u=String(r?.projectDir??e.project_dir??"").trim(),d=String(r?.source??e.attribution_source??"unknown"),c=Number(r?.confidence??e.attribution_confidence??0),T=Number.isFinite(c)?Math.max(0,Math.min(1,c)):0,m=h(o?.bytesAvoided),L=h(o?.bytesReturned),R=this.db.transaction(()=>{if(this.stmt(i.checkDuplicate).get(t,P,e.type,a))return;this.stmt(i.getEventCount).get(t).cnt>=B&&this.stmt(i.evictLowestPriority).run(t),this.stmt(i.insertEvent).run(t,e.type,e.category,e.priority,e.data,u,d,T,m,L,s,a),this.stmt(i.updateMetaLastEvent).run(t)});this.withRetry(()=>R())}bulkInsertEvents(t,e,s="PostToolUse",r,o){if(!e||e.length===0)return;if(e.length===1){this.insertEvent(t,e[0],s,r?.[0],o?.[0]);return}let a=e.map((d,c)=>{let T=p("sha256").update(d.data).digest("hex").slice(0,16).toUpperCase(),m=r?.[c],L=String(m?.projectDir??d.project_dir??"").trim(),R=String(m?.source??d.attribution_source??"unknown"),S=Number(m?.confidence??d.attribution_confidence??0),O=Number.isFinite(S)?Math.max(0,Math.min(1,S)):0,w=o?.[c],H=h(w?.bytesAvoided),$=h(w?.bytesReturned);return{event:d,dataHash:T,projectDir:L,attributionSource:R,attributionConfidence:O,bytesAvoided:H,bytesReturned:$}}),u=this.db.transaction(()=>{let d=this.stmt(i.getEventCount).get(t).cnt;for(let c of a)this.stmt(i.checkDuplicate).get(t,P,c.event.type,c.dataHash)||(d>=B?this.stmt(i.evictLowestPriority).run(t):d++,this.stmt(i.insertEvent).run(t,c.event.type,c.event.category,c.event.priority,c.event.data,c.projectDir,c.attributionSource,c.attributionConfidence,c.bytesAvoided,c.bytesReturned,s,c.dataHash));this.stmt(i.updateMetaLastEvent).run(t)});this.withRetry(()=>u())}getEvents(t,e){let s=e?.limit??1e3,r=e?.type,o=e?.minPriority;return r&&o!==void 0?this.stmt(i.getEventsByTypeAndPriority).all(t,r,o,s):r?this.stmt(i.getEventsByType).all(t,r,s):o!==void 0?this.stmt(i.getEventsByPriority).all(t,o,s):this.stmt(i.getEvents).all(t,s)}getEventCount(t){return this.stmt(i.getEventCount).get(t).cnt}getEventBytesSummary(t){let e=this.stmt(i.getEventBytesSummary).get(t);return{bytesAvoided:Number(e?.bytes_avoided??0),bytesReturned:Number(e?.bytes_returned??0)}}getLatestAttributedProjectDir(t){return this.stmt(i.getLatestAttributedProject).get(t)?.project_dir||null}searchEvents(t,e,s,r){try{let o=t.replace(/[%_]/g,u=>"\\"+u),a=r??null;return this.stmt(i.searchEvents).all(s,o,o,a,a,e)}catch{return[]}}ensureSession(t,e){this.stmt(i.ensureSession).run(t,e)}getSessionStats(t){return this.stmt(i.getSessionStats).get(t)??null}incrementCompactCount(t){this.stmt(i.incrementCompactCount).run(t)}upsertResume(t,e,s){this.stmt(i.upsertResume).run(t,e,s??0)}getResume(t){return this.stmt(i.getResume).get(t)??null}markResumeConsumed(t){this.stmt(i.markResumeConsumed).run(t)}claimLatestUnconsumedResume(t){let e=this.stmt(i.claimLatestUnconsumedResume).get(t);return e?{sessionId:e.session_id,snapshot:e.snapshot}:null}getLatestSessionId(){try{return this.db.prepare("SELECT session_id FROM session_meta ORDER BY started_at DESC LIMIT 1").get()?.session_id??null}catch{return null}}incrementToolCall(t,e,s=0){let r=Number.isFinite(s)&&s>0?Math.round(s):0;try{this.stmt(i.incrementToolCall).run(t,e,r)}catch{}}getToolCallStats(t){try{let e=this.stmt(i.getToolCallTotals).get(t),s=this.stmt(i.getToolCallByTool).all(t),r={};for(let o of s)r[o.tool]={calls:o.calls,bytesReturned:o.bytes_returned};return{totalCalls:e?.calls??0,totalBytesReturned:e?.bytes_returned??0,byTool:r}}catch{return{totalCalls:0,totalBytesReturned:0,byTool:{}}}}deleteSession(t){this.db.transaction(()=>{this.stmt(i.deleteEvents).run(t),this.stmt(i.deleteResume).run(t),this.stmt(i.deleteMeta).run(t)})()}cleanupOldSessions(t=7){let e=`-${t}`,s=this.stmt(i.getOldSessions).all(e);for(let{session_id:r}of s)this.deleteSession(r);return s.length}};export{k as SessionDB,yt as _resetWorktreeSuffixCacheForTests,ot as getWorktreeSuffix,W as hashProjectDirCanonical,X as hashProjectDirLegacy,g as normalizeWorktreePath,ht as resolveContentStorePath,ft as resolveSessionDbPath,at as resolveSessionPath};
@@ -1,2 +1,2 @@
1
- function s(t){return t==null?"":String(t)}function f(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function b(t){let{tool_name:e,tool_input:o,tool_response:i}=t,n=[];if(e==="Read"){let r=String(o.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(r)||/\/copilot-instructions\.md$/i.test(r)||/\/context-mode\.mdc$/i.test(r)||/\.claude[\\/]/i.test(r)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(r))&&(n.push({type:"rule",category:"rule",data:s(r),priority:1}),i&&i.length>0&&n.push({type:"rule_content",category:"rule",data:s(i),priority:1})),n.push({type:"file_read",category:"file",data:s(r),priority:1}),n}if(e==="Edit"){let r=String(o.file_path??"");return n.push({type:"file_edit",category:"file",data:s(r),priority:1}),n}if(e==="NotebookEdit"){let r=String(o.notebook_path??"");return n.push({type:"file_edit",category:"file",data:s(r),priority:1}),n}if(e==="Write"){let r=String(o.file_path??"");return n.push({type:"file_write",category:"file",data:s(r),priority:1}),n}if(e==="Glob"){let r=String(o.pattern??"");return n.push({type:"file_glob",category:"file",data:s(r),priority:3}),n}if(e==="Grep"){let r=String(o.pattern??""),a=String(o.path??"");return n.push({type:"file_search",category:"file",data:s(`${r} in ${a}`),priority:3}),n}return n}function y(t){if(t.tool_name!=="Bash")return[];let o=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!o)return[];let i=o[2]??o[3]??o[4]??"";return[{type:"cwd",category:"cwd",data:s(i),priority:2}]}function h(t){let{tool_name:e,tool_input:o,tool_response:i,tool_output:n}=t,r=String(i??""),a=n?.isError===!0;return!(e==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(r))&&!a?[]:[{type:"error_tool",category:"error",data:s(r),priority:2}]}var _=[{pattern:/\bgit\s+checkout\b/,operation:"branch"},{pattern:/\bgit\s+commit\b/,operation:"commit"},{pattern:/\bgit\s+merge\s+\S+/,operation:"merge"},{pattern:/\bgit\s+rebase\b/,operation:"rebase"},{pattern:/\bgit\s+stash\b/,operation:"stash"},{pattern:/\bgit\s+push\b/,operation:"push"},{pattern:/\bgit\s+pull\b/,operation:"pull"},{pattern:/\bgit\s+log\b/,operation:"log"},{pattern:/\bgit\s+diff\b/,operation:"diff"},{pattern:/\bgit\s+status\b/,operation:"status"},{pattern:/\bgit\s+branch\b/,operation:"branch"},{pattern:/\bgit\s+reset\b/,operation:"reset"},{pattern:/\bgit\s+add\b/,operation:"add"},{pattern:/\bgit\s+cherry-pick\b/,operation:"cherry-pick"},{pattern:/\bgit\s+tag\b/,operation:"tag"},{pattern:/\bgit\s+fetch\b/,operation:"fetch"},{pattern:/\bgit\s+clone\b/,operation:"clone"},{pattern:/\bgit\s+worktree\b/,operation:"worktree"}];function m(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),o=_.find(i=>i.pattern.test(e));return o?[{type:"git",category:"git",data:s(o.operation),priority:2}]:[]}function S(t){return new Set(["TodoWrite","TaskCreate","TaskUpdate"]).has(t.tool_name)?[{type:t.tool_name==="TaskUpdate"?"task_update":t.tool_name==="TaskCreate"?"task_create":"task",category:"task",data:s(JSON.stringify(t.tool_input)),priority:1}]:[]}function E(t){if(t.tool_name==="EnterPlanMode")return[{type:"plan_enter",category:"plan",data:"entered plan mode",priority:2}];if(t.tool_name==="ExitPlanMode"){let e=[],o=t.tool_input.allowedPrompts,i=Array.isArray(o)&&o.length>0?`exited plan mode (allowed: ${f(o.map(r=>typeof r=="object"&&r!==null&&"prompt"in r?String(r.prompt):String(r)).join(", "))})`:"exited plan mode";e.push({type:"plan_exit",category:"plan",data:s(i),priority:2});let n=String(t.tool_response??"").toLowerCase();return n.includes("approved")||n.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(n.includes("rejected")||n.includes("decline")||n.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:s(`plan rejected: ${t.tool_response??""}`),priority:2}),e}if(t.tool_name==="Write"||t.tool_name==="Edit"){let e=String(t.tool_input.file_path??"");if(/[/\\]\.claude[/\\]plans[/\\]/.test(e))return[{type:"plan_file_write",category:"plan",data:s(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return[]}var k=[/\bsource\s+\S*activate\b/,/\bexport\s+\w+=/,/\bnvm\s+use\b/,/\bpyenv\s+(shell|local|global)\b/,/\bconda\s+activate\b/,/\brbenv\s+(shell|local|global)\b/,/\bnpm\s+install\b/,/\bnpm\s+ci\b/,/\bpip\s+install\b/,/\bbun\s+install\b/,/\byarn\s+(add|install)\b/,/\bpnpm\s+(add|install)\b/,/\bcargo\s+(install|add)\b/,/\bgo\s+(install|get)\b/,/\brustup\b/,/\basdf\b/,/\bvolta\b/,/\bdeno\s+install\b/];function v(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!k.some(n=>n.test(e)))return[];let i=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:s(i),priority:2}]}function x(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:s(e),priority:2}]}function w(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),o=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let i of o){let n=e.match(i);if(n){let r=e.toLowerCase().indexOf(n[0].toLowerCase()),a=e.slice(Math.max(0,r-50),Math.min(e.length,r+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:s(a),priority:2}]}}return[]}function R(t){if(t.tool_name!=="Agent")return[];let e=s(String(t.tool_input.prompt??t.tool_input.description??"")),o=t.tool_response?s(String(t.tool_response)):"",i=o.length>0;return[{type:i?"subagent_completed":"subagent_launched",category:"subagent",data:s(i?`[completed] ${e} \u2192 ${o}`:`[launched] ${e}`),priority:i?2:3}]}function A(t){let{tool_name:e,tool_input:o,tool_response:i}=t;if(!e.startsWith("mcp__"))return[];let n=e.split("__"),r=n[n.length-1]||e,a=Object.values(o).find(d=>typeof d=="string"),p=a?`: ${s(String(a))}`:"",u=i&&i.length>0?`
2
- response: ${s(i)}`:"";return[{type:"mcp",category:"mcp",data:s(`${r}${p}${u}`),priority:3}]}var T=2048;function I(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let o=Buffer.from(t,"utf8"),i=e;for(;i>0&&(o[i]&192)===128;)i--;return{value:o.subarray(0,i).toString("utf8"),truncated:!0}}var $=/(authorization|auth_token|access_token|refresh_token|bearer|token|secret|password|passwd|pwd|api[-_]?key|apikey|cookie|set-cookie|signature|private[-_]?key|client[-_]?secret|x[-_]?api[-_]?key)/i,H="[REDACTED]";function g(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let o;if(Array.isArray(t))o=t.map(i=>g(i,e));else{let i={};for(let[n,r]of Object.entries(t))$.test(n)?i[n]=H:i[n]=g(r,e);o=i}return e.delete(t),o}function N(t){let{tool_name:e,tool_input:o}=t;if(!e.startsWith("mcp__"))return[];let i=g(o??{}),n;try{n=JSON.stringify(i)}catch{n="{}"}let{value:r,truncated:a}=I(n,T),p=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(r)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${r}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:s(p),priority:4}]}function B(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,o=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",i=s(String(t.tool_response??"")),n=o?`Q: ${s(o)} \u2192 A: ${i}`:`answer: ${i}`;return[{type:"decision_question",category:"decision",data:s(n),priority:2}]}function O(t){if(t.tool_name!=="Agent")return[];if(!t.tool_response||t.tool_response.length===0)return[];let e=t.tool_response.length>500?t.tool_response.slice(0,500):t.tool_response;return[{type:"agent_finding",category:"agent-finding",data:s(e),priority:2}]}function C(t){let e=[f(t.tool_input),s(t.tool_response)].join(" ");if(e.length===0)return[];let o=new Set,i=e.match(/https?:\/\/[^\s)]+/g);if(i)for(let r of i)r=r.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(r)||o.add(r);let n=e.match(/(?<!\w)#(\d+)/g);if(n)for(let r of n)o.add(r);return o.size===0?[]:[{type:"external_ref",category:"external-ref",data:s(Array.from(o).join(", ")),priority:3}]}function P(t){if(t.tool_name!=="EnterWorktree")return[];let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:s(`entered worktree: ${e}`),priority:2}]}var L=[/\b(don'?t|do not|never|always|instead|rather|prefer)\b/i,/\b(use|switch to|go with|pick|choose)\s+\w+\s+(instead|over|not)\b/i,/\b(no,?\s+(use|do|try|make))\b/i,/\b(hayır|hayir|evet|böyle|boyle|degil|değil|yerine|kullan)\b/i];function M(t){return L.some(o=>o.test(t))?[{type:"decision",category:"decision",data:s(t),priority:2}]:[]}var j=[/\b(act as|you are|behave like|pretend|role of|persona)\b/i,/\b(senior|staff|principal|lead)\s+(engineer|developer|architect)\b/i,/\b(gibi davran|rolünde|olarak çalış)\b/i];function W(t){return j.some(o=>o.test(t))?[{type:"role",category:"role",data:s(t),priority:3}]:[]}var D=[{mode:"investigate",pattern:/\b(why|how does|explain|understand|what is|analyze|debug|look into)\b/i},{mode:"implement",pattern:/\b(create|add|build|implement|write|make|develop|fix)\b/i},{mode:"discuss",pattern:/\b(think about|consider|should we|what if|pros and cons|opinion)\b/i},{mode:"review",pattern:/\b(review|check|audit|verify|test|validate)\b/i}];function F(t){let e=D.find(({pattern:o})=>o.test(t));return e?[{type:"intent",category:"intent",data:s(e.mode),priority:4}]:[]}var G=[/\bblocked on\b/i,/\bwaiting for\b/i,/\bneed\s+\S+\s+before\b/i,/\bcan'?t proceed until\b/i,/\bdepends on\b/i,/\bblocked\b/i,/\bbekliyor\b/i,/\bbekliyorum\b/i],U=[/\bunblocked\b/i,/\bresolved\b/i,/\bgot the\s+\S+/i,/\bis ready now\b/i,/\bcan proceed\b/i];function J(t){let e=[];return U.some(n=>n.test(t))?(e.push({type:"blocker_resolved",category:"blocked-on",data:s(t),priority:2}),e):(G.some(n=>n.test(t))&&e.push({type:"blocker",category:"blocked-on",data:s(t),priority:2}),e)}function q(t){return t.length<=1024?[]:[{type:"data",category:"data",data:s(t),priority:4}]}var c=null;function z(t){let{tool_name:e,tool_response:o,tool_output:i}=t,n=String(o??""),r=i?.isError===!0;if(e==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(n)||r)return c={tool:e,error:n.slice(0,200),callsSince:0},[];if(!c)return[];if(c.callsSince++,c.callsSince>10)return c=null,[];let p=e===c.tool,u=c.tool==="Read"&&(e==="Edit"||e==="Write");if(p||u){let d={type:"error_resolved",category:"error-resolution",data:s(`Error in ${c.tool}: ${c.error} \u2192 Fixed`),priority:2};return c=null,[d]}return[]}function Z(){c=null}var l=[];function K(t){return`${t.length}:${t.slice(0,20)}`}function Q(t){let{tool_name:e,tool_input:o}=t,i=K(JSON.stringify(o).slice(0,200));if(l.push({tool:e,inputHash:i}),l.length>50&&l.splice(0,l.length-50),l.length<3)return[];let n=0;for(let r=l.length-1;r>=0&&(l[r].tool===e&&l[r].inputHash===i);r--)n++;return n>=3?(l.splice(l.length-n),[{type:"retry_detected",category:"iteration-loop",data:s(`${e} called ${n} times with similar input`),priority:2}]):[]}function X(){l.length=0}var V={run_shell_command:"Bash",read_file:"Read",read_many_files:"Read",grep_search:"Grep",search_file_content:"Grep",web_fetch:"WebFetch",write_file:"Write",edit:"Edit",glob:"Glob",todo_write:"TodoWrite",ask_user_question:"AskUserQuestion",list_directory:"LS",save_memory:"Memory",skill:"Skill",exit_plan_mode:"ExitPlanMode",agent:"Agent",bash:"Bash",view:"Read",grep:"Grep",fetch:"WebFetch",shell:"Bash",shell_command:"Bash",exec_command:"Bash","container.exec":"Bash",local_shell:"Bash",grep_files:"Grep"};function Y(t){let e=V[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function tt(t){try{let e=Y(t),o=[];return o.push(...b(e)),o.push(...y(e)),o.push(...h(e)),o.push(...m(e)),o.push(...v(e)),o.push(...S(e)),o.push(...E(e)),o.push(...x(e)),o.push(...R(e)),o.push(...A(e)),o.push(...N(e)),o.push(...B(e)),o.push(...w(e)),o.push(...P(e)),o.push(...O(e)),o.push(...C(e)),o.push(...z(e)),o.push(...Q(e)),o}catch{return[]}}function et(t){try{let e=[];return e.push(...M(t)),e.push(...W(t)),e.push(...F(t)),e.push(...J(t)),e.push(...q(t)),e}catch{return[]}}export{tt as extractEvents,et as extractUserEvents,Z as resetErrorResolutionState,X as resetIterationLoopState};
1
+ function s(t){return t==null?"":String(t)}function g(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function u(t){let e=String(t.tool_response??""),o=t.tool_output?.isError===!0||t.tool_output?.is_error===!0;return t.tool_name==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(e)||o}function h(t){if(!t)return[];let e=[];for(let r of t.split(/\r?\n/)){if(r.startsWith("*** Add File: ")){e.push({path:r.slice(14).trim(),type:"file_write"});continue}if(r.startsWith("*** Update File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}if(r.startsWith("*** Delete File: ")){e.push({path:r.slice(17).trim(),type:"file_edit"});continue}r.startsWith("*** Move to: ")&&e.push({path:r.slice(13).trim(),type:"file_edit"})}let o=new Set;return e.filter(r=>{if(!r.path)return!1;let n=`${r.type}:${r.path}`;return o.has(n)?!1:(o.add(n),!0)})}function f(t){return/(?:^|[/\\])\.claude[/\\]plans[/\\]/.test(t)}function _(t){let{tool_name:e,tool_input:o,tool_response:r}=t,n=[];if(e==="Read"){let i=String(o.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(i)||/\/copilot-instructions\.md$/i.test(i)||/\/context-mode\.mdc$/i.test(i)||/\.claude[\\/]/i.test(i)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(i))&&(n.push({type:"rule",category:"rule",data:s(i),priority:1}),r&&r.length>0&&n.push({type:"rule_content",category:"rule",data:s(r),priority:1})),n.push({type:"file_read",category:"file",data:s(i),priority:1}),n}if(e==="Edit"){let i=String(o.file_path??"");return n.push({type:"file_edit",category:"file",data:s(i),priority:1}),n}if(e==="NotebookEdit"){let i=String(o.notebook_path??"");return n.push({type:"file_edit",category:"file",data:s(i),priority:1}),n}if(e==="Write"){let i=String(o.file_path??"");return n.push({type:"file_write",category:"file",data:s(i),priority:1}),n}if(e==="apply_patch"){if(u(t))return[];let i=h(String(o.command??o.patch??""));for(let a of i)n.push({type:a.type,category:"file",data:s(a.path),priority:1});return n}if(e==="Glob"){let i=String(o.pattern??"");return n.push({type:"file_glob",category:"file",data:s(i),priority:3}),n}if(e==="Grep"){let i=String(o.pattern??""),a=String(o.path??"");return n.push({type:"file_search",category:"file",data:s(`${i} in ${a}`),priority:3}),n}return n}function m(t){if(t.tool_name!=="Bash")return[];let o=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!o)return[];let r=o[2]??o[3]??o[4]??"";return[{type:"cwd",category:"cwd",data:s(r),priority:2}]}function S(t){let{tool_response:e}=t,o=String(e??"");return u(t)?[{type:"error_tool",category:"error",data:s(o),priority:2}]:[]}var k=[{pattern:/\bgit\s+checkout\b/,operation:"branch"},{pattern:/\bgit\s+commit\b/,operation:"commit"},{pattern:/\bgit\s+merge\s+\S+/,operation:"merge"},{pattern:/\bgit\s+rebase\b/,operation:"rebase"},{pattern:/\bgit\s+stash\b/,operation:"stash"},{pattern:/\bgit\s+push\b/,operation:"push"},{pattern:/\bgit\s+pull\b/,operation:"pull"},{pattern:/\bgit\s+log\b/,operation:"log"},{pattern:/\bgit\s+diff\b/,operation:"diff"},{pattern:/\bgit\s+status\b/,operation:"status"},{pattern:/\bgit\s+branch\b/,operation:"branch"},{pattern:/\bgit\s+reset\b/,operation:"reset"},{pattern:/\bgit\s+add\b/,operation:"add"},{pattern:/\bgit\s+cherry-pick\b/,operation:"cherry-pick"},{pattern:/\bgit\s+tag\b/,operation:"tag"},{pattern:/\bgit\s+fetch\b/,operation:"fetch"},{pattern:/\bgit\s+clone\b/,operation:"clone"},{pattern:/\bgit\s+worktree\b/,operation:"worktree"}];function E(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),o=k.find(r=>r.pattern.test(e));return o?[{type:"git",category:"git",data:s(o.operation),priority:2}]:[]}function v(t){return new Set(["TodoWrite","TaskCreate","TaskUpdate"]).has(t.tool_name)?[{type:t.tool_name==="TaskUpdate"?"task_update":t.tool_name==="TaskCreate"?"task_create":"task",category:"task",data:s(JSON.stringify(t.tool_input)),priority:1}]:[]}function x(t){if(t.tool_name==="EnterPlanMode")return[{type:"plan_enter",category:"plan",data:"entered plan mode",priority:2}];if(t.tool_name==="ExitPlanMode"){let e=[],o=t.tool_input.allowedPrompts,r=Array.isArray(o)&&o.length>0?`exited plan mode (allowed: ${g(o.map(i=>typeof i=="object"&&i!==null&&"prompt"in i?String(i.prompt):String(i)).join(", "))})`:"exited plan mode";e.push({type:"plan_exit",category:"plan",data:s(r),priority:2});let n=String(t.tool_response??"").toLowerCase();return n.includes("approved")||n.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(n.includes("rejected")||n.includes("decline")||n.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:s(`plan rejected: ${t.tool_response??""}`),priority:2}),e}if(t.tool_name==="Write"||t.tool_name==="Edit"){let e=String(t.tool_input.file_path??"");if(f(e))return[{type:"plan_file_write",category:"plan",data:s(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return t.tool_name==="apply_patch"?u(t)?[]:h(String(t.tool_input.command??t.tool_input.patch??"")).filter(o=>f(o.path)).map(o=>({type:"plan_file_write",category:"plan",data:s(`plan file: ${o.path.split(/[/\\]/).pop()??o.path}`),priority:2})):[]}var w=[/\bsource\s+\S*activate\b/,/\bexport\s+\w+=/,/\bnvm\s+use\b/,/\bpyenv\s+(shell|local|global)\b/,/\bconda\s+activate\b/,/\brbenv\s+(shell|local|global)\b/,/\bnpm\s+install\b/,/\bnpm\s+ci\b/,/\bpip\s+install\b/,/\bbun\s+install\b/,/\byarn\s+(add|install)\b/,/\bpnpm\s+(add|install)\b/,/\bcargo\s+(install|add)\b/,/\bgo\s+(install|get)\b/,/\brustup\b/,/\basdf\b/,/\bvolta\b/,/\bdeno\s+install\b/];function R(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!w.some(n=>n.test(e)))return[];let r=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:s(r),priority:2}]}function T(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:s(e),priority:2}]}function A(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),o=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let r of o){let n=e.match(r);if(n){let i=e.toLowerCase().indexOf(n[0].toLowerCase()),a=e.slice(Math.max(0,i-50),Math.min(e.length,i+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:s(a),priority:2}]}}return[]}function I(t){if(t.tool_name!=="Agent")return[];let e=s(String(t.tool_input.prompt??t.tool_input.description??"")),o=t.tool_response?s(String(t.tool_response)):"",r=o.length>0;return[{type:r?"subagent_completed":"subagent_launched",category:"subagent",data:s(r?`[completed] ${e} \u2192 ${o}`:`[launched] ${e}`),priority:r?2:3}]}function $(t){let{tool_name:e,tool_input:o,tool_response:r}=t;if(!e.startsWith("mcp__"))return[];let n=e.split("__"),i=n[n.length-1]||e,a=Object.values(o).find(b=>typeof b=="string"),p=a?`: ${s(String(a))}`:"",y=r&&r.length>0?`
2
+ response: ${s(r)}`:"";return[{type:"mcp",category:"mcp",data:s(`${i}${p}${y}`),priority:3}]}var H=2048;function P(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let o=Buffer.from(t,"utf8"),r=e;for(;r>0&&(o[r]&192)===128;)r--;return{value:o.subarray(0,r).toString("utf8"),truncated:!0}}var N=/(authorization|auth_token|access_token|refresh_token|bearer|token|secret|password|passwd|pwd|api[-_]?key|apikey|cookie|set-cookie|signature|private[-_]?key|client[-_]?secret|x[-_]?api[-_]?key)/i,O="[REDACTED]";function d(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let o;if(Array.isArray(t))o=t.map(r=>d(r,e));else{let r={};for(let[n,i]of Object.entries(t))N.test(n)?r[n]=O:r[n]=d(i,e);o=r}return e.delete(t),o}function B(t){let{tool_name:e,tool_input:o}=t;if(!e.startsWith("mcp__"))return[];let r=d(o??{}),n;try{n=JSON.stringify(r)}catch{n="{}"}let{value:i,truncated:a}=P(n,H),p=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(i)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${i}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:s(p),priority:4}]}function C(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,o=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",r=s(String(t.tool_response??"")),n=o?`Q: ${s(o)} \u2192 A: ${r}`:`answer: ${r}`;return[{type:"decision_question",category:"decision",data:s(n),priority:2}]}function L(t){if(t.tool_name!=="Agent")return[];if(!t.tool_response||t.tool_response.length===0)return[];let e=t.tool_response.length>500?t.tool_response.slice(0,500):t.tool_response;return[{type:"agent_finding",category:"agent-finding",data:s(e),priority:2}]}function W(t){let e=[g(t.tool_input),s(t.tool_response)].join(" ");if(e.length===0)return[];let o=new Set,r=e.match(/https?:\/\/[^\s)]+/g);if(r)for(let i of r)i=i.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(i)||o.add(i);let n=e.match(/(?<!\w)#(\d+)/g);if(n)for(let i of n)o.add(i);return o.size===0?[]:[{type:"external_ref",category:"external-ref",data:s(Array.from(o).join(", ")),priority:3}]}function M(t){if(t.tool_name!=="EnterWorktree")return[];let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:s(`entered worktree: ${e}`),priority:2}]}var j=[/\b(don'?t|do not|never|always|instead|rather|prefer)\b/i,/\b(use|switch to|go with|pick|choose)\s+\w+\s+(instead|over|not)\b/i,/\b(no,?\s+(use|do|try|make))\b/i,/\b(hayır|hayir|evet|böyle|boyle|degil|değil|yerine|kullan)\b/i];function D(t){return j.some(o=>o.test(t))?[{type:"decision",category:"decision",data:s(t),priority:2}]:[]}var F=[/\b(act as|you are|behave like|pretend|role of|persona)\b/i,/\b(senior|staff|principal|lead)\s+(engineer|developer|architect)\b/i,/\b(gibi davran|rolünde|olarak çalış)\b/i];function G(t){return F.some(o=>o.test(t))?[{type:"role",category:"role",data:s(t),priority:3}]:[]}var U=[{mode:"investigate",pattern:/\b(why|how does|explain|understand|what is|analyze|debug|look into)\b/i},{mode:"implement",pattern:/\b(create|add|build|implement|write|make|develop|fix)\b/i},{mode:"discuss",pattern:/\b(think about|consider|should we|what if|pros and cons|opinion)\b/i},{mode:"review",pattern:/\b(review|check|audit|verify|test|validate)\b/i}];function J(t){let e=U.find(({pattern:o})=>o.test(t));return e?[{type:"intent",category:"intent",data:s(e.mode),priority:4}]:[]}var q=[/\bblocked on\b/i,/\bwaiting for\b/i,/\bneed\s+\S+\s+before\b/i,/\bcan'?t proceed until\b/i,/\bdepends on\b/i,/\bblocked\b/i,/\bbekliyor\b/i,/\bbekliyorum\b/i],z=[/\bunblocked\b/i,/\bresolved\b/i,/\bgot the\s+\S+/i,/\bis ready now\b/i,/\bcan proceed\b/i];function K(t){let e=[];return z.some(n=>n.test(t))?(e.push({type:"blocker_resolved",category:"blocked-on",data:s(t),priority:2}),e):(q.some(n=>n.test(t))&&e.push({type:"blocker",category:"blocked-on",data:s(t),priority:2}),e)}function Q(t){return t.length<=1024?[]:[{type:"data",category:"data",data:s(t),priority:4}]}var c=null;function V(t){let{tool_name:e,tool_response:o}=t,r=String(o??"");if(u(t))return c={tool:e,error:r.slice(0,200),callsSince:0},[];if(!c)return[];if(c.callsSince++,c.callsSince>10)return c=null,[];if(!!u(t))return[];let i=e===c.tool,a=c.tool==="Read"&&(e==="Edit"||e==="Write"||e==="apply_patch");if(i||a){let p={type:"error_resolved",category:"error-resolution",data:s(`Error in ${c.tool}: ${c.error} \u2192 Fixed`),priority:2};return c=null,[p]}return[]}function et(){c=null}var l=[];function Y(t){return`${t.length}:${t.slice(0,20)}`}function Z(t){let{tool_name:e,tool_input:o}=t,r=Y(JSON.stringify(o).slice(0,200));if(l.push({tool:e,inputHash:r}),l.length>50&&l.splice(0,l.length-50),l.length<3)return[];let n=0;for(let i=l.length-1;i>=0&&(l[i].tool===e&&l[i].inputHash===r);i--)n++;return n>=3?(l.splice(l.length-n),[{type:"retry_detected",category:"iteration-loop",data:s(`${e} called ${n} times with similar input`),priority:2}]):[]}function ot(){l.length=0}var X={run_shell_command:"Bash",read_file:"Read",read_many_files:"Read",grep_search:"Grep",search_file_content:"Grep",web_fetch:"WebFetch",write_file:"Write",edit:"Edit",glob:"Glob",todo_write:"TodoWrite",ask_user_question:"AskUserQuestion",list_directory:"LS",save_memory:"Memory",skill:"Skill",exit_plan_mode:"ExitPlanMode",agent:"Agent",bash:"Bash",view:"Read",grep:"Grep",fetch:"WebFetch",shell:"Bash",shell_command:"Bash",exec_command:"Bash","container.exec":"Bash",local_shell:"Bash",grep_files:"Grep"};function tt(t){let e=X[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function rt(t){try{let e=tt(t),o=[];return o.push(..._(e)),o.push(...m(e)),o.push(...S(e)),o.push(...E(e)),o.push(...R(e)),o.push(...v(e)),o.push(...x(e)),o.push(...T(e)),o.push(...I(e)),o.push(...$(e)),o.push(...B(e)),o.push(...C(e)),o.push(...A(e)),o.push(...M(e)),o.push(...L(e)),o.push(...W(e)),o.push(...V(e)),o.push(...Z(e)),o}catch{return[]}}function nt(t){try{let e=[];return e.push(...D(t)),e.push(...G(t)),e.push(...J(t)),e.push(...K(t)),e.push(...Q(t)),e}catch{return[]}}export{rt as extractEvents,nt as extractUserEvents,et as resetErrorResolutionState,ot as resetIterationLoopState};