context-mode 1.0.99 → 1.0.100

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 (46) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  4. package/.openclaw-plugin/package.json +1 -1
  5. package/build/pi-extension.js +1 -1
  6. package/build/search/auto-memory.d.ts +29 -0
  7. package/build/search/auto-memory.js +121 -0
  8. package/build/search/unified.d.ts +41 -0
  9. package/build/search/unified.js +89 -0
  10. package/build/server.js +69 -21
  11. package/build/session/analytics.js +1 -1
  12. package/build/session/db.d.ts +17 -0
  13. package/build/session/db.js +28 -0
  14. package/build/session/extract.d.ts +4 -0
  15. package/build/session/extract.js +232 -1
  16. package/build/session/snapshot.js +31 -0
  17. package/build/store.js +67 -4
  18. package/build/types.d.ts +1 -0
  19. package/cli.bundle.mjs +254 -119
  20. package/configs/claude-code/CLAUDE.md +21 -1
  21. package/configs/codex/AGENTS.md +22 -1
  22. package/configs/cursor/context-mode.mdc +18 -1
  23. package/configs/gemini-cli/GEMINI.md +22 -1
  24. package/configs/jetbrains-copilot/copilot-instructions.md +22 -1
  25. package/configs/kilo/AGENTS.md +19 -2
  26. package/configs/kiro/KIRO.md +18 -1
  27. package/configs/openclaw/AGENTS.md +22 -2
  28. package/configs/opencode/AGENTS.md +18 -1
  29. package/configs/pi/AGENTS.md +18 -1
  30. package/configs/qwen-code/QWEN.md +38 -18
  31. package/configs/vscode-copilot/copilot-instructions.md +22 -1
  32. package/hooks/auto-injection.mjs +76 -0
  33. package/hooks/codex/userpromptsubmit.mjs +1 -1
  34. package/hooks/core/mcp-ready.mjs +7 -1
  35. package/hooks/posttooluse.mjs +50 -1
  36. package/hooks/precompact.mjs +9 -0
  37. package/hooks/pretooluse.mjs +27 -0
  38. package/hooks/routing-block.mjs +7 -1
  39. package/hooks/session-db.bundle.mjs +19 -13
  40. package/hooks/session-extract.bundle.mjs +2 -2
  41. package/hooks/session-snapshot.bundle.mjs +18 -17
  42. package/hooks/sessionstart.mjs +17 -0
  43. package/hooks/userpromptsubmit.mjs +1 -1
  44. package/openclaw.plugin.json +1 -1
  45. package/package.json +1 -1
  46. package/server.bundle.mjs +227 -92
@@ -12,8 +12,10 @@ import "./ensure-deps.mjs";
12
12
 
13
13
  import { readStdin, parseStdin, getSessionId, getSessionDBPath, getInputProjectDir } from "./session-helpers.mjs";
14
14
  import { createSessionLoaders, attributeAndInsertEvents } from "./session-loaders.mjs";
15
- import { dirname } from "node:path";
15
+ import { dirname, resolve } from "node:path";
16
16
  import { fileURLToPath } from "node:url";
17
+ import { readFileSync, unlinkSync } from "node:fs";
18
+ import { tmpdir } from "node:os";
17
19
 
18
20
  // Resolve absolute path for imports — relative dynamic imports can fail
19
21
  // when Claude Code invokes hooks from a different working directory.
@@ -48,6 +50,53 @@ try {
48
50
 
49
51
  attributeAndInsertEvents(db, sessionId, events, input, projectDir, "PostToolUse", resolveProjectAttributions);
50
52
 
53
+ // ─── Category 18: Rejected-approach — read PreToolUse marker ───
54
+ try {
55
+ const rejectedPath = resolve(tmpdir(), `context-mode-rejected-${sessionId}.txt`);
56
+ let rejectedData;
57
+ try {
58
+ rejectedData = readFileSync(rejectedPath, "utf-8").trim();
59
+ unlinkSync(rejectedPath);
60
+ } catch { /* no marker */ }
61
+ if (rejectedData) {
62
+ const colonIdx = rejectedData.indexOf(":");
63
+ const rejTool = colonIdx > 0 ? rejectedData.slice(0, colonIdx) : rejectedData;
64
+ const rejReason = colonIdx > 0 ? rejectedData.slice(colonIdx + 1) : "denied";
65
+ db.insertEvent(sessionId, {
66
+ type: "rejected",
67
+ category: "rejected-approach",
68
+ data: `${rejTool}: ${rejReason}`,
69
+ priority: 2,
70
+ }, "PreToolUse");
71
+ }
72
+ } catch { /* best-effort */ }
73
+
74
+ // ─── Category 27: Latency — read cross-hook marker and emit event if slow ───
75
+ try {
76
+ const toolName = input.tool_name ?? "";
77
+ if (toolName) {
78
+ const markerPath = resolve(tmpdir(), `context-mode-latency-${sessionId}-${toolName}.txt`);
79
+ let startTime;
80
+ try {
81
+ startTime = parseInt(readFileSync(markerPath, "utf-8").trim(), 10);
82
+ unlinkSync(markerPath);
83
+ } catch {
84
+ // No marker — pretooluse didn't write one or already consumed
85
+ }
86
+ if (startTime && !isNaN(startTime)) {
87
+ const duration = Date.now() - startTime;
88
+ if (duration > 5000) {
89
+ db.insertEvent(sessionId, {
90
+ type: "tool_latency",
91
+ category: "latency",
92
+ data: `${toolName}: ${duration}ms`,
93
+ priority: 3,
94
+ }, "PostToolUse");
95
+ }
96
+ }
97
+ }
98
+ } catch { /* latency tracking is best-effort */ }
99
+
51
100
  db.close();
52
101
  } catch {
53
102
  // PostToolUse must never block the session — silent fallback
@@ -42,6 +42,15 @@ try {
42
42
 
43
43
  db.upsertResume(sessionId, snapshot, events.length);
44
44
  db.incrementCompactCount(sessionId);
45
+
46
+ // Write compaction category event for analytics
47
+ const fileEvents = events.filter(e => e.category === "file");
48
+ db.insertEvent(sessionId, {
49
+ type: "compaction_summary",
50
+ category: "compaction",
51
+ data: `Session compacted. ${events.length} events, ${fileEvents.length} files touched.`,
52
+ priority: 1,
53
+ }, "PreCompact");
45
54
  }
46
55
 
47
56
  db.close();
@@ -166,6 +166,33 @@ const toolInput = input.tool_input ?? {};
166
166
  // ─── Route and format response ───
167
167
  const decision = routePreToolUse(tool, toolInput, process.env.CLAUDE_PROJECT_DIR, "claude-code", getSessionId(input));
168
168
  const response = formatDecision("claude-code", decision);
169
+
170
+ // ─── Write latency marker for cross-hook timing (Category 27) ───
171
+ // Marker writes MUST happen before stdout write — stdout is the last action
172
+ // so the process can exit immediately after, avoiding CI test timeouts.
173
+ try {
174
+ const sessionId = getSessionId(input);
175
+ if (tool) {
176
+ const markerPath = resolve(tmpdir(), `context-mode-latency-${sessionId}-${tool}.txt`);
177
+ writeFileSync(markerPath, String(Date.now()), "utf-8");
178
+ }
179
+ } catch { /* latency tracking is best-effort — never block hook */ }
180
+
181
+ // ─── Write rejected-approach marker for PostToolUse to pick up ───
182
+ // PreToolUse cannot safely load SessionDB (native module loading breaks hook stdout).
183
+ // Write a marker file instead; PostToolUse reads it and writes the event.
184
+ if (decision && (decision.action === "deny" || decision.action === "modify")) {
185
+ try {
186
+ const sessionId = getSessionId(input);
187
+ const reason = decision.action === "deny"
188
+ ? (decision.reason || "denied")
189
+ : "Redirected to context-mode sandbox";
190
+ const markerPath = resolve(tmpdir(), `context-mode-rejected-${sessionId}.txt`);
191
+ writeFileSync(markerPath, `${tool}:${reason}`, "utf-8");
192
+ } catch { /* best-effort — never block hook */ }
193
+ }
194
+
195
+ // ─── stdout write is the LAST action — process exits immediately after ───
169
196
  if (response !== null) {
170
197
  process.stdout.write(JSON.stringify(response) + "\n");
171
198
  }
@@ -22,12 +22,14 @@ export function createRoutingBlock(t, options = {}) {
22
22
  </priority_instructions>
23
23
 
24
24
  <tool_selection_hierarchy>
25
+ 0. MEMORY: ${t("ctx_search")}(sort: "timeline")
26
+ - After resume, check prior context before asking user.
25
27
  1. GATHER: ${t("ctx_batch_execute")}(commands, queries)
26
28
  - Primary research tool. Runs commands, auto-indexes, searches. ONE call replaces many steps.
27
29
  - Each command: {label: "section header", command: "shell command"}
28
30
  - label becomes FTS5 chunk title — descriptive labels improve search.
29
31
  2. FOLLOW-UP: ${t("ctx_search")}(queries: ["q1", "q2", ...])
30
- - All follow-up questions. ONE call, many queries.
32
+ - All follow-up questions. ONE call, many queries (default relevance mode).
31
33
  3. PROCESSING: ${t("ctx_execute")}(language, code) | ${t("ctx_execute_file")}(path, language, code)
32
34
  - API calls, log analysis, data processing.
33
35
  </tool_selection_hierarchy>
@@ -65,6 +67,10 @@ export function createRoutingBlock(t, options = {}) {
65
67
  - Key findings
66
68
  </response_format>
67
69
  </output_constraints>
70
+ <session_continuity>
71
+ Skills, roles, and decisions set during this session remain active until the user revokes them.
72
+ Do not drop behavioral directives as context grows.
73
+ </session_continuity>
68
74
  ${includeCommands ? `
69
75
  <ctx_commands>
70
76
  "ctx stats" | "ctx-stats" | "/ctx-stats" | context savings question
@@ -1,4 +1,4 @@
1
- import{createRequire as b}from"node:module";import{existsSync as N,unlinkSync as y,renameSync as D}from"node:fs";import{tmpdir as O}from"node:os";import{join as w}from"node:path";var p=class{#t;constructor(t){this.#t=t}pragma(t){let e=this.#t.prepare(`PRAGMA ${t}`).all();if(!e||e.length===0)return;if(e.length>1)return e;let r=Object.values(e[0]);return r.length===1?r[0]:e[0]}exec(t){let s="",e=null;for(let o=0;o<t.length;o++){let a=t[o];if(e)s+=a,a===e&&(e=null);else if(a==="'"||a==='"')s+=a,e=a;else if(a===";"){let c=s.trim();c&&this.#t.prepare(c).run(),s=""}else s+=a}let r=s.trim();return r&&this.#t.prepare(r).run(),this}prepare(t){let s=this.#t.prepare(t);return{run:(...e)=>s.run(...e),get:(...e)=>{let r=s.get(...e);return r===null?void 0:r},all:(...e)=>s.all(...e),iterate:(...e)=>s.iterate(...e)}}transaction(t){return this.#t.transaction(t)}close(){this.#t.close()}},_=class{#t;constructor(t){this.#t=t}pragma(t){let e=this.#t.prepare(`PRAGMA ${t}`).all();if(!e||e.length===0)return;if(e.length>1)return e;let r=Object.values(e[0]);return r.length===1?r[0]:e[0]}exec(t){return this.#t.exec(t),this}prepare(t){let s=this.#t.prepare(t);return{run:(...e)=>s.run(...e),get:(...e)=>s.get(...e),all:(...e)=>s.all(...e),iterate:(...e)=>typeof s.iterate=="function"?s.iterate(...e):s.all(...e)[Symbol.iterator]()}}transaction(t){return(...s)=>{this.#t.exec("BEGIN");try{let e=t(...s);return this.#t.exec("COMMIT"),e}catch(e){throw this.#t.exec("ROLLBACK"),e}}}close(){this.#t.close()}},u=null;function A(){if(!u){let n=b(import.meta.url);if(globalThis.Bun){let t=n(["bun","sqlite"].join(":")).Database;u=function(e,r){let o=new t(e,{readonly:r?.readonly,create:!0}),a=new p(o);return r?.timeout&&a.pragma(`busy_timeout = ${r.timeout}`),a}}else if(process.platform==="linux")try{let{DatabaseSync:t}=n(["node","sqlite"].join(":"));u=function(e,r){let o=new t(e,{readOnly:r?.readonly??!1});return new _(o)}}catch{u=n("better-sqlite3")}else u=n("better-sqlite3")}return u}function g(n){n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL");try{n.pragma("mmap_size = 268435456")}catch{}}function h(n){if(!N(n))for(let t of["-wal","-shm"])try{y(n+t)}catch{}}function C(n){for(let t of["","-wal","-shm"])try{y(n+t)}catch{}}function l(n){try{n.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{n.close()}catch{}}function f(n="context-mode"){return w(O(),`${n}-${process.pid}.db`)}function I(n,t=[100,500,2e3]){let s;for(let e=0;e<=t.length;e++)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(s=r instanceof Error?r:new Error(o),e<t.length){let a=t[e],c=Date.now();for(;Date.now()-c<a;);}}throw new Error(`SQLITE_BUSY: database is locked after ${t.length} retries. Original error: ${s?.message}`)}function U(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 x(n){let t=Date.now();for(let s of["","-wal","-shm"])try{D(n+s,`${n}${s}.corrupt-${t}`)}catch{}}var d=Symbol.for("__context_mode_live_dbs__"),m=(()=>{let n=globalThis;return n[d]||(n[d]=new Set,process.on("exit",()=>{for(let t of n[d])l(t);n[d].clear()})),n[d]})(),E=class{#t;#e;constructor(t){let s=A();this.#t=t,h(t);let e;try{e=new s(t,{timeout:3e4}),g(e)}catch(r){let o=r instanceof Error?r.message:String(r);if(U(o)){x(t),h(t);try{e=new s(t,{timeout:3e4}),g(e)}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=e,m.add(this.#e),this.initSchema(),this.prepareStatements()}get db(){return this.#e}get dbPath(){return this.#t}close(){m.delete(this.#e),l(this.#e)}withRetry(t){return I(t)}cleanup(){m.delete(this.#e),l(this.#e),C(this.#t)}};import{createHash as R}from"node:crypto";import{execFileSync as M}from"node:child_process";function K(){let n=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(n!==void 0)return n?`__${n}`:"";try{let t=process.cwd(),s=M("git",["worktree","list","--porcelain"],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).find(e=>e.startsWith("worktree "))?.replace("worktree ","")?.trim();if(s&&t!==s)return`__${R("sha256").update(t).digest("hex").slice(0,8)}`}catch{}return""}var k=1e3,F=5,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",deleteEvents:"deleteEvents",deleteMeta:"deleteMeta",deleteResume:"deleteResume",getOldSessions:"getOldSessions"},L=class extends E{constructor(t){super(t?.dbPath??f("session"))}stmt(t){return this.stmts.get(t)}initSchema(){try{let s=this.db.pragma("table_xinfo(session_events)").find(e=>e.name==="data_hash");s&&s.hidden!==0&&this.db.exec("DROP TABLE session_events")}catch{}this.db.exec(`
1
+ import{createRequire as b}from"node:module";import{existsSync as N,unlinkSync as y,renameSync as D}from"node:fs";import{tmpdir as O}from"node:os";import{join as A}from"node:path";var p=class{#t;constructor(t){this.#t=t}pragma(t){let e=this.#t.prepare(`PRAGMA ${t}`).all();if(!e||e.length===0)return;if(e.length>1)return e;let n=Object.values(e[0]);return n.length===1?n[0]:e[0]}exec(t){let s="",e=null;for(let o=0;o<t.length;o++){let a=t[o];if(e)s+=a,a===e&&(e=null);else if(a==="'"||a==='"')s+=a,e=a;else if(a===";"){let c=s.trim();c&&this.#t.prepare(c).run(),s=""}else s+=a}let n=s.trim();return n&&this.#t.prepare(n).run(),this}prepare(t){let s=this.#t.prepare(t);return{run:(...e)=>s.run(...e),get:(...e)=>{let n=s.get(...e);return n===null?void 0:n},all:(...e)=>s.all(...e),iterate:(...e)=>s.iterate(...e)}}transaction(t){return this.#t.transaction(t)}close(){this.#t.close()}},_=class{#t;constructor(t){this.#t=t}pragma(t){let e=this.#t.prepare(`PRAGMA ${t}`).all();if(!e||e.length===0)return;if(e.length>1)return e;let n=Object.values(e[0]);return n.length===1?n[0]:e[0]}exec(t){return this.#t.exec(t),this}prepare(t){let s=this.#t.prepare(t);return{run:(...e)=>s.run(...e),get:(...e)=>s.get(...e),all:(...e)=>s.all(...e),iterate:(...e)=>typeof s.iterate=="function"?s.iterate(...e):s.all(...e)[Symbol.iterator]()}}transaction(t){return(...s)=>{this.#t.exec("BEGIN");try{let e=t(...s);return this.#t.exec("COMMIT"),e}catch(e){throw this.#t.exec("ROLLBACK"),e}}}close(){this.#t.close()}},u=null;function w(){if(!u){let i=b(import.meta.url);if(globalThis.Bun){let t=i(["bun","sqlite"].join(":")).Database;u=function(e,n){let o=new t(e,{readonly:n?.readonly,create:!0}),a=new p(o);return n?.timeout&&a.pragma(`busy_timeout = ${n.timeout}`),a}}else if(process.platform==="linux")try{let{DatabaseSync:t}=i(["node","sqlite"].join(":"));u=function(e,n){let o=new t(e,{readOnly:n?.readonly??!1});return new _(o)}}catch{u=i("better-sqlite3")}else u=i("better-sqlite3")}return u}function T(i){i.pragma("journal_mode = WAL"),i.pragma("synchronous = NORMAL");try{i.pragma("mmap_size = 268435456")}catch{}}function h(i){if(!N(i))for(let t of["-wal","-shm"])try{y(i+t)}catch{}}function C(i){for(let t of["","-wal","-shm"])try{y(i+t)}catch{}}function l(i){try{i.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{i.close()}catch{}}function f(i="context-mode"){return A(O(),`${i}-${process.pid}.db`)}function I(i,t=[100,500,2e3]){let s;for(let e=0;e<=t.length;e++)try{return i()}catch(n){let o=n instanceof Error?n.message:String(n);if(!o.includes("SQLITE_BUSY")&&!o.includes("database is locked"))throw n;if(s=n instanceof Error?n:new Error(o),e<t.length){let a=t[e],c=Date.now();for(;Date.now()-c<a;);}}throw new Error(`SQLITE_BUSY: database is locked after ${t.length} retries. Original error: ${s?.message}`)}function U(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 M(i){let t=Date.now();for(let s of["","-wal","-shm"])try{D(i+s,`${i}${s}.corrupt-${t}`)}catch{}}var d=Symbol.for("__context_mode_live_dbs__"),m=(()=>{let i=globalThis;return i[d]||(i[d]=new Set,process.on("exit",()=>{for(let t of i[d])l(t);i[d].clear()})),i[d]})(),E=class{#t;#e;constructor(t){let s=w();this.#t=t,h(t);let e;try{e=new s(t,{timeout:3e4}),T(e)}catch(n){let o=n instanceof Error?n.message:String(n);if(U(o)){M(t),h(t);try{e=new s(t,{timeout:3e4}),T(e)}catch(a){throw new Error(`Failed to create fresh DB after renaming corrupt file: ${a instanceof Error?a.message:String(a)}`)}}else throw n}this.#e=e,m.add(this.#e),this.initSchema(),this.prepareStatements()}get db(){return this.#e}get dbPath(){return this.#t}close(){m.delete(this.#e),l(this.#e)}withRetry(t){return I(t)}cleanup(){m.delete(this.#e),l(this.#e),C(this.#t)}};import{createHash as R}from"node:crypto";import{execFileSync as x}from"node:child_process";function K(){let i=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(i!==void 0)return i?`__${i}`:"";try{let t=process.cwd(),s=x("git",["worktree","list","--porcelain"],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).find(e=>e.startsWith("worktree "))?.replace("worktree ","")?.trim();if(s&&t!==s)return`__${R("sha256").update(t).digest("hex").slice(0,8)}`}catch{}return""}var k=1e3,F=5,r={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",deleteEvents:"deleteEvents",deleteMeta:"deleteMeta",deleteResume:"deleteResume",getOldSessions:"getOldSessions",searchEvents:"searchEvents"},L=class extends E{constructor(t){super(t?.dbPath??f("session"))}stmt(t){return this.stmts.get(t)}initSchema(){try{let s=this.db.pragma("table_xinfo(session_events)").find(e=>e.name==="data_hash");s&&s.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,
@@ -35,42 +35,48 @@ import{createRequire as b}from"node:module";import{existsSync as N,unlinkSync as
35
35
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
36
36
  consumed INTEGER NOT NULL DEFAULT 0
37
37
  );
38
- `);try{let t=this.db.pragma("table_xinfo(session_events)"),s=new Set(t.map(e=>e.name));s.has("project_dir")||this.db.exec("ALTER TABLE session_events ADD COLUMN project_dir TEXT NOT NULL DEFAULT ''"),s.has("attribution_source")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_source TEXT NOT NULL DEFAULT 'unknown'"),s.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=(s,e)=>{this.stmts.set(s,this.db.prepare(e))};t(i.insertEvent,`INSERT INTO session_events (
38
+ `);try{let t=this.db.pragma("table_xinfo(session_events)"),s=new Set(t.map(e=>e.name));s.has("project_dir")||this.db.exec("ALTER TABLE session_events ADD COLUMN project_dir TEXT NOT NULL DEFAULT ''"),s.has("attribution_source")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_source TEXT NOT NULL DEFAULT 'unknown'"),s.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=(s,e)=>{this.stmts.set(s,this.db.prepare(e))};t(r.insertEvent,`INSERT INTO session_events (
39
39
  session_id, type, category, priority, data,
40
40
  project_dir, attribution_source, attribution_confidence,
41
41
  source_hook, data_hash
42
42
  )
43
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),t(i.getEvents,`SELECT id, session_id, type, category, priority, data,
43
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),t(r.getEvents,`SELECT id, session_id, type, category, priority, data,
44
44
  project_dir, attribution_source, attribution_confidence,
45
45
  source_hook, created_at, data_hash
46
- FROM session_events WHERE session_id = ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByType,`SELECT id, session_id, type, category, priority, data,
46
+ FROM session_events WHERE session_id = ? ORDER BY id ASC LIMIT ?`),t(r.getEventsByType,`SELECT id, session_id, type, category, priority, data,
47
47
  project_dir, attribution_source, attribution_confidence,
48
48
  source_hook, created_at, data_hash
49
- FROM session_events WHERE session_id = ? AND type = ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByPriority,`SELECT id, session_id, type, category, priority, data,
49
+ FROM session_events WHERE session_id = ? AND type = ? ORDER BY id ASC LIMIT ?`),t(r.getEventsByPriority,`SELECT id, session_id, type, category, priority, data,
50
50
  project_dir, attribution_source, attribution_confidence,
51
51
  source_hook, created_at, data_hash
52
- FROM session_events WHERE session_id = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(i.getEventsByTypeAndPriority,`SELECT id, session_id, type, category, priority, data,
52
+ FROM session_events WHERE session_id = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(r.getEventsByTypeAndPriority,`SELECT id, session_id, type, category, priority, data,
53
53
  project_dir, attribution_source, attribution_confidence,
54
54
  source_hook, created_at, data_hash
55
- 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
55
+ FROM session_events WHERE session_id = ? AND type = ? AND priority >= ? ORDER BY id ASC LIMIT ?`),t(r.getEventCount,"SELECT COUNT(*) AS cnt FROM session_events WHERE session_id = ?"),t(r.getLatestAttributedProject,`SELECT project_dir
56
56
  FROM session_events
57
57
  WHERE session_id = ? AND project_dir != ''
58
58
  ORDER BY id DESC
59
- LIMIT 1`),t(i.checkDuplicate,`SELECT 1 FROM (
59
+ LIMIT 1`),t(r.checkDuplicate,`SELECT 1 FROM (
60
60
  SELECT type, data_hash FROM session_events
61
61
  WHERE session_id = ? ORDER BY id DESC LIMIT ?
62
62
  ) AS recent
63
63
  WHERE recent.type = ? AND recent.data_hash = ?
64
- LIMIT 1`),t(i.evictLowestPriority,`DELETE FROM session_events WHERE id = (
64
+ LIMIT 1`),t(r.evictLowestPriority,`DELETE FROM session_events WHERE id = (
65
65
  SELECT id FROM session_events WHERE session_id = ?
66
66
  ORDER BY priority ASC, id ASC LIMIT 1
67
- )`),t(i.updateMetaLastEvent,`UPDATE session_meta
67
+ )`),t(r.updateMetaLastEvent,`UPDATE session_meta
68
68
  SET last_event_at = datetime('now'), event_count = event_count + 1
69
- 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
70
- 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)
69
+ WHERE session_id = ?`),t(r.ensureSession,"INSERT OR IGNORE INTO session_meta (session_id, project_dir) VALUES (?, ?)"),t(r.getSessionStats,`SELECT session_id, project_dir, started_at, last_event_at, event_count, compact_count
70
+ FROM session_meta WHERE session_id = ?`),t(r.incrementCompactCount,"UPDATE session_meta SET compact_count = compact_count + 1 WHERE session_id = ?"),t(r.upsertResume,`INSERT INTO session_resume (session_id, snapshot, event_count)
71
71
  VALUES (?, ?, ?)
72
72
  ON CONFLICT(session_id) DO UPDATE SET
73
73
  snapshot = excluded.snapshot,
74
74
  event_count = excluded.event_count,
75
75
  created_at = datetime('now'),
76
- 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.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.getOldSessions,"SELECT session_id FROM session_meta WHERE started_at < datetime('now', ? || ' days')")}insertEvent(t,s,e="PostToolUse",r){let o=R("sha256").update(s.data).digest("hex").slice(0,16).toUpperCase(),a=String(r?.projectDir??s.project_dir??"").trim(),c=String(r?.source??s.attribution_source??"unknown"),T=Number(r?.confidence??s.attribution_confidence??0),S=Number.isFinite(T)?Math.max(0,Math.min(1,T)):0,v=this.db.transaction(()=>{if(this.stmt(i.checkDuplicate).get(t,F,s.type,o))return;this.stmt(i.getEventCount).get(t).cnt>=k&&this.stmt(i.evictLowestPriority).run(t),this.stmt(i.insertEvent).run(t,s.type,s.category,s.priority,s.data,a,c,S,e,o),this.stmt(i.updateMetaLastEvent).run(t)});this.withRetry(()=>v())}getEvents(t,s){let e=s?.limit??1e3,r=s?.type,o=s?.minPriority;return r&&o!==void 0?this.stmt(i.getEventsByTypeAndPriority).all(t,r,o,e):r?this.stmt(i.getEventsByType).all(t,r,e):o!==void 0?this.stmt(i.getEventsByPriority).all(t,o,e):this.stmt(i.getEvents).all(t,e)}getEventCount(t){return this.stmt(i.getEventCount).get(t).cnt}getLatestAttributedProjectDir(t){return this.stmt(i.getLatestAttributedProject).get(t)?.project_dir||null}ensureSession(t,s){this.stmt(i.ensureSession).run(t,s)}getSessionStats(t){return this.stmt(i.getSessionStats).get(t)??null}incrementCompactCount(t){this.stmt(i.incrementCompactCount).run(t)}upsertResume(t,s,e){this.stmt(i.upsertResume).run(t,s,e??0)}getResume(t){return this.stmt(i.getResume).get(t)??null}markResumeConsumed(t){this.stmt(i.markResumeConsumed).run(t)}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 s=`-${t}`,e=this.stmt(i.getOldSessions).all(s);for(let{session_id:r}of e)this.deleteSession(r);return e.length}};export{L as SessionDB,K as getWorktreeSuffix};
76
+ consumed = 0`),t(r.getResume,"SELECT snapshot, event_count, consumed FROM session_resume WHERE session_id = ?"),t(r.markResumeConsumed,"UPDATE session_resume SET consumed = 1 WHERE session_id = ?"),t(r.deleteEvents,"DELETE FROM session_events WHERE session_id = ?"),t(r.deleteMeta,"DELETE FROM session_meta WHERE session_id = ?"),t(r.deleteResume,"DELETE FROM session_resume WHERE session_id = ?"),t(r.searchEvents,`SELECT id, session_id, category, type, data, created_at
77
+ FROM session_events
78
+ WHERE project_dir = ?
79
+ AND (data LIKE '%' || ? || '%' ESCAPE '\\' OR category LIKE '%' || ? || '%' ESCAPE '\\')
80
+ AND (? IS NULL OR category = ?)
81
+ ORDER BY id ASC
82
+ LIMIT ?`),t(r.getOldSessions,"SELECT session_id FROM session_meta WHERE started_at < datetime('now', ? || ' days')")}insertEvent(t,s,e="PostToolUse",n){let o=R("sha256").update(s.data).digest("hex").slice(0,16).toUpperCase(),a=String(n?.projectDir??s.project_dir??"").trim(),c=String(n?.source??s.attribution_source??"unknown"),g=Number(n?.confidence??s.attribution_confidence??0),S=Number.isFinite(g)?Math.max(0,Math.min(1,g)):0,v=this.db.transaction(()=>{if(this.stmt(r.checkDuplicate).get(t,F,s.type,o))return;this.stmt(r.getEventCount).get(t).cnt>=k&&this.stmt(r.evictLowestPriority).run(t),this.stmt(r.insertEvent).run(t,s.type,s.category,s.priority,s.data,a,c,S,e,o),this.stmt(r.updateMetaLastEvent).run(t)});this.withRetry(()=>v())}getEvents(t,s){let e=s?.limit??1e3,n=s?.type,o=s?.minPriority;return n&&o!==void 0?this.stmt(r.getEventsByTypeAndPriority).all(t,n,o,e):n?this.stmt(r.getEventsByType).all(t,n,e):o!==void 0?this.stmt(r.getEventsByPriority).all(t,o,e):this.stmt(r.getEvents).all(t,e)}getEventCount(t){return this.stmt(r.getEventCount).get(t).cnt}getLatestAttributedProjectDir(t){return this.stmt(r.getLatestAttributedProject).get(t)?.project_dir||null}searchEvents(t,s,e,n){try{let o=t.replace(/[%_]/g,c=>"\\"+c),a=n??null;return this.stmt(r.searchEvents).all(e,o,o,a,a,s)}catch{return[]}}ensureSession(t,s){this.stmt(r.ensureSession).run(t,s)}getSessionStats(t){return this.stmt(r.getSessionStats).get(t)??null}incrementCompactCount(t){this.stmt(r.incrementCompactCount).run(t)}upsertResume(t,s,e){this.stmt(r.upsertResume).run(t,s,e??0)}getResume(t){return this.stmt(r.getResume).get(t)??null}markResumeConsumed(t){this.stmt(r.markResumeConsumed).run(t)}deleteSession(t){this.db.transaction(()=>{this.stmt(r.deleteEvents).run(t),this.stmt(r.deleteResume).run(t),this.stmt(r.deleteMeta).run(t)})()}cleanupOldSessions(t=7){let s=`-${t}`,e=this.stmt(r.getOldSessions).all(s);for(let{session_id:n}of e)this.deleteSession(n);return e.length}};export{L as SessionDB,K as getWorktreeSuffix};
@@ -1,2 +1,2 @@
1
- function o(t){return t==null?"":String(t)}function u(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function d(t){let{tool_name:e,tool_input:n,tool_response:i}=t,r=[];if(e==="Read"){let s=String(n.file_path??"");return/CLAUDE\.md$|\.claude[\\/]/i.test(s)&&(r.push({type:"rule",category:"rule",data:o(s),priority:1}),i&&i.length>0&&r.push({type:"rule_content",category:"rule",data:o(i),priority:1})),r.push({type:"file_read",category:"file",data:o(s),priority:1}),r}if(e==="Edit"){let s=String(n.file_path??"");return r.push({type:"file_edit",category:"file",data:o(s),priority:1}),r}if(e==="NotebookEdit"){let s=String(n.notebook_path??"");return r.push({type:"file_edit",category:"file",data:o(s),priority:1}),r}if(e==="Write"){let s=String(n.file_path??"");return r.push({type:"file_write",category:"file",data:o(s),priority:1}),r}if(e==="Glob"){let s=String(n.pattern??"");return r.push({type:"file_glob",category:"file",data:o(s),priority:3}),r}if(e==="Grep"){let s=String(n.pattern??""),a=String(n.path??"");return r.push({type:"file_search",category:"file",data:o(`${s} in ${a}`),priority:3}),r}return r}function g(t){if(t.tool_name!=="Bash")return[];let n=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!n)return[];let i=n[2]??n[3]??n[4]??"";return[{type:"cwd",category:"cwd",data:o(i),priority:2}]}function b(t){let{tool_name:e,tool_input:n,tool_response:i,tool_output:r}=t,s=String(i??""),a=r?.isError===!0;return!(e==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(s))&&!a?[]:[{type:"error_tool",category:"error",data:o(s),priority:2}]}var y=[{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 f(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),n=y.find(i=>i.pattern.test(e));return n?[{type:"git",category:"git",data:o(n.operation),priority:2}]:[]}function h(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:o(JSON.stringify(t.tool_input)),priority:1}]:[]}function _(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=[],n=t.tool_input.allowedPrompts,i=Array.isArray(n)&&n.length>0?`exited plan mode (allowed: ${u(n.map(s=>typeof s=="object"&&s!==null&&"prompt"in s?String(s.prompt):String(s)).join(", "))})`:"exited plan mode";e.push({type:"plan_exit",category:"plan",data:o(i),priority:2});let r=String(t.tool_response??"").toLowerCase();return r.includes("approved")||r.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(r.includes("rejected")||r.includes("decline")||r.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:o(`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:o(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return[]}var m=[/\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 S(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!m.some(r=>r.test(e)))return[];let i=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:o(i),priority:2}]}function k(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:o(e),priority:3}]}function E(t){if(t.tool_name!=="Agent")return[];let e=o(String(t.tool_input.prompt??t.tool_input.description??"")),n=t.tool_response?o(String(t.tool_response)):"",i=n.length>0;return[{type:i?"subagent_completed":"subagent_launched",category:"subagent",data:o(i?`[completed] ${e} \u2192 ${n}`:`[launched] ${e}`),priority:i?2:3}]}function v(t){let{tool_name:e,tool_input:n,tool_response:i}=t;if(!e.startsWith("mcp__"))return[];let r=e.split("__"),s=r[r.length-1]||e,a=Object.values(n).find(c=>typeof c=="string"),p=a?`: ${o(String(a))}`:"",l=i&&i.length>0?`
2
- response: ${o(i)}`:"";return[{type:"mcp",category:"mcp",data:o(`${s}${p}${l}`),priority:3}]}function x(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,n=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",i=o(String(t.tool_response??"")),r=n?`Q: ${o(n)} \u2192 A: ${i}`:`answer: ${i}`;return[{type:"decision_question",category:"decision",data:o(r),priority:2}]}function w(t){if(t.tool_name!=="EnterWorktree")return[];let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:o(`entered worktree: ${e}`),priority:2}]}var T=[/\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 R(t){return T.some(n=>n.test(t))?[{type:"decision",category:"decision",data:o(t),priority:2}]:[]}var A=[/\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 I(t){return A.some(n=>n.test(t))?[{type:"role",category:"role",data:o(t),priority:3}]:[]}var $=[{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 P(t){let e=$.find(({pattern:n})=>n.test(t));return e?[{type:"intent",category:"intent",data:o(e.mode),priority:4}]:[]}function H(t){return t.length<=1024?[]:[{type:"data",category:"data",data:o(t),priority:4}]}function N(t){try{let e=[];return e.push(...d(t)),e.push(...g(t)),e.push(...b(t)),e.push(...f(t)),e.push(...S(t)),e.push(...h(t)),e.push(..._(t)),e.push(...k(t)),e.push(...E(t)),e.push(...v(t)),e.push(...x(t)),e.push(...w(t)),e}catch{return[]}}function C(t){try{let e=[];return e.push(...R(t)),e.push(...I(t)),e.push(...P(t)),e.push(...H(t)),e}catch{return[]}}export{N as extractEvents,C as extractUserEvents};
1
+ function i(t){return t==null?"":String(t)}function g(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function b(t){let{tool_name:e,tool_input:o,tool_response:s}=t,r=[];if(e==="Read"){let n=String(o.file_path??"");return/CLAUDE\.md$|\.claude[\\/]/i.test(n)&&(r.push({type:"rule",category:"rule",data:i(n),priority:1}),s&&s.length>0&&r.push({type:"rule_content",category:"rule",data:i(s),priority:1})),r.push({type:"file_read",category:"file",data:i(n),priority:1}),r}if(e==="Edit"){let n=String(o.file_path??"");return r.push({type:"file_edit",category:"file",data:i(n),priority:1}),r}if(e==="NotebookEdit"){let n=String(o.notebook_path??"");return r.push({type:"file_edit",category:"file",data:i(n),priority:1}),r}if(e==="Write"){let n=String(o.file_path??"");return r.push({type:"file_write",category:"file",data:i(n),priority:1}),r}if(e==="Glob"){let n=String(o.pattern??"");return r.push({type:"file_glob",category:"file",data:i(n),priority:3}),r}if(e==="Grep"){let n=String(o.pattern??""),c=String(o.path??"");return r.push({type:"file_search",category:"file",data:i(`${n} in ${c}`),priority:3}),r}return r}function f(t){if(t.tool_name!=="Bash")return[];let o=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!o)return[];let s=o[2]??o[3]??o[4]??"";return[{type:"cwd",category:"cwd",data:i(s),priority:2}]}function y(t){let{tool_name:e,tool_input:o,tool_response:s,tool_output:r}=t,n=String(s??""),c=r?.isError===!0;return!(e==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(n))&&!c?[]:[{type:"error_tool",category:"error",data:i(n),priority:2}]}var h=[{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 _(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),o=h.find(s=>s.pattern.test(e));return o?[{type:"git",category:"git",data:i(o.operation),priority:2}]:[]}function m(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:i(JSON.stringify(t.tool_input)),priority:1}]:[]}function S(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,s=Array.isArray(o)&&o.length>0?`exited plan mode (allowed: ${g(o.map(n=>typeof n=="object"&&n!==null&&"prompt"in n?String(n.prompt):String(n)).join(", "))})`:"exited plan mode";e.push({type:"plan_exit",category:"plan",data:i(s),priority:2});let r=String(t.tool_response??"").toLowerCase();return r.includes("approved")||r.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(r.includes("rejected")||r.includes("decline")||r.includes("denied"))&&e.push({type:"plan_rejected",category:"plan",data:i(`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:i(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return[]}var E=[/\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 k(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!E.some(r=>r.test(e)))return[];let s=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:i(s),priority:2}]}function v(t){if(t.tool_name!=="Skill")return[];let e=String(t.tool_input.skill??"");return[{type:"skill",category:"skill",data:i(e),priority:2}]}function x(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 s of o){let r=e.match(s);if(r){let n=e.toLowerCase().indexOf(r[0].toLowerCase()),c=e.slice(Math.max(0,n-50),Math.min(e.length,n+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:i(c),priority:2}]}}return[]}function w(t){if(t.tool_name!=="Agent")return[];let e=i(String(t.tool_input.prompt??t.tool_input.description??"")),o=t.tool_response?i(String(t.tool_response)):"",s=o.length>0;return[{type:s?"subagent_completed":"subagent_launched",category:"subagent",data:i(s?`[completed] ${e} \u2192 ${o}`:`[launched] ${e}`),priority:s?2:3}]}function R(t){let{tool_name:e,tool_input:o,tool_response:s}=t;if(!e.startsWith("mcp__"))return[];let r=e.split("__"),n=r[r.length-1]||e,c=Object.values(o).find(d=>typeof d=="string"),p=c?`: ${i(String(c))}`:"",u=s&&s.length>0?`
2
+ response: ${i(s)}`:"";return[{type:"mcp",category:"mcp",data:i(`${n}${p}${u}`),priority:3}]}function A(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,o=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",s=i(String(t.tool_response??"")),r=o?`Q: ${i(o)} \u2192 A: ${s}`:`answer: ${s}`;return[{type:"decision_question",category:"decision",data:i(r),priority:2}]}function I(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:i(e),priority:2}]}function T(t){let e=[g(t.tool_input),i(t.tool_response)].join(" ");if(e.length===0)return[];let o=new Set,s=e.match(/https?:\/\/[^\s)]+/g);if(s)for(let n of s)n=n.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(n)||o.add(n);let r=e.match(/(?<!\w)#(\d+)/g);if(r)for(let n of r)o.add(n);return o.size===0?[]:[{type:"external_ref",category:"external-ref",data:i(Array.from(o).join(", ")),priority:3}]}function $(t){if(t.tool_name!=="EnterWorktree")return[];let e=String(t.tool_input.name??"unnamed");return[{type:"worktree",category:"env",data:i(`entered worktree: ${e}`),priority:2}]}var H=[/\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 P(t){return H.some(o=>o.test(t))?[{type:"decision",category:"decision",data:i(t),priority:2}]:[]}var N=[/\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 C(t){return N.some(o=>o.test(t))?[{type:"role",category:"role",data:i(t),priority:3}]:[]}var L=[{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 B(t){let e=L.find(({pattern:o})=>o.test(t));return e?[{type:"intent",category:"intent",data:i(e.mode),priority:4}]:[]}var O=[/\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],F=[/\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 F.some(r=>r.test(t))?(e.push({type:"blocker_resolved",category:"blocked-on",data:i(t),priority:2}),e):(O.some(r=>r.test(t))&&e.push({type:"blocker",category:"blocked-on",data:i(t),priority:2}),e)}function D(t){return t.length<=1024?[]:[{type:"data",category:"data",data:i(t),priority:4}]}var a=null;function M(t){let{tool_name:e,tool_response:o,tool_output:s}=t,r=String(o??""),n=s?.isError===!0;if(e==="Bash"&&/exit code [1-9]|error:|Error:|FAIL|failed/i.test(r)||n)return a={tool:e,error:r.slice(0,200),callsSince:0},[];if(!a)return[];if(a.callsSince++,a.callsSince>10)return a=null,[];let p=e===a.tool,u=a.tool==="Read"&&(e==="Edit"||e==="Write");if(p||u){let d={type:"error_resolved",category:"error-resolution",data:i(`Error in ${a.tool}: ${a.error} \u2192 Fixed`),priority:2};return a=null,[d]}return[]}function q(){a=null}var l=[];function W(t){return`${t.length}:${t.slice(0,20)}`}function U(t){let{tool_name:e,tool_input:o}=t,s=W(JSON.stringify(o).slice(0,200));if(l.push({tool:e,inputHash:s}),l.length>50&&l.splice(0,l.length-50),l.length<3)return[];let r=0;for(let n=l.length-1;n>=0&&(l[n].tool===e&&l[n].inputHash===s);n--)r++;return r>=3?(l.splice(l.length-r),[{type:"retry_detected",category:"iteration-loop",data:i(`${e} called ${r} times with similar input`),priority:2}]):[]}function G(){l.length=0}function K(t){try{let e=[];return e.push(...b(t)),e.push(...f(t)),e.push(...y(t)),e.push(..._(t)),e.push(...k(t)),e.push(...m(t)),e.push(...S(t)),e.push(...v(t)),e.push(...w(t)),e.push(...R(t)),e.push(...A(t)),e.push(...x(t)),e.push(...$(t)),e.push(...I(t)),e.push(...T(t)),e.push(...M(t)),e.push(...U(t)),e}catch{return[]}}function z(t){try{let e=[];return e.push(...P(t)),e.push(...C(t)),e.push(...B(t)),e.push(...j(t)),e.push(...D(t)),e}catch{return[]}}export{K as extractEvents,z as extractUserEvents,q as resetErrorResolutionState,G as resetIterationLoopState};
@@ -1,29 +1,30 @@
1
- function a(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}var M=10;function h(t,r=4){return[...new Set(t.filter(o=>o.length>0))].slice(0,r).map(o=>o.length>80?o.slice(0,80):o)}function m(t,r){if(r.length===0)return"";let s=r.map(n=>`"${a(n)}"`).join(", ");return`
1
+ function a(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}var x=10;function h(t,r=4){return[...new Set(t.filter(o=>o.length>0))].slice(0,r).map(o=>o.length>80?o.slice(0,80):o)}function m(t,r){if(r.length===0)return"";let s=r.map(n=>`"${a(n)}"`).join(", ");return`
2
2
  For full details:
3
3
  ${a(t)}(
4
4
  queries: [${s}],
5
5
  source: "session-events"
6
- )`}function A(t,r){if(t.length===0)return"";let s=new Map;for(let l of t){let b=l.data,p=s.get(b);p||(p={ops:new Map},s.set(b,p));let g;l.type==="file_write"?g="write":l.type==="file_read"?g="read":l.type==="file_edit"?g="edit":g=l.type,p.ops.set(g,(p.ops.get(g)??0)+1)}let o=Array.from(s.entries()).slice(-M),u=[],i=[];for(let[l,{ops:b}]of o){let p=Array.from(b.entries()).map(([S,y])=>`${S}\xD7${y}`).join(", "),g=l.split("/").pop()??l;u.push(` ${a(g)} (${a(p)})`),i.push(`${g} ${Array.from(b.keys()).join(" ")}`)}let e=h(i);return[` <files count="${s.size}">`,...u,m(r,e)," </files>"].join(`
7
- `)}function x(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t)s.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <errors count="${t.length}">`,...s,m(r,o)," </errors>"].join(`
8
- `)}function D(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let u=h(o);return[` <decisions count="${n.length}">`,...n,m(r,u)," </decisions>"].join(`
9
- `)}function F(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),e.type==="rule_content"?n.push(` ${a(e.data)}`):n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let u=h(o);return[` <rules count="${n.length}">`,...n,m(r,u)," </rules>"].join(`
10
- `)}function R(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t)s.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...s,m(r,o)," </git>"].join(`
11
- `)}function B(t){if(t.length===0)return"";let r=[],s={};for(let e of t)try{let c=JSON.parse(e.data);typeof c.subject=="string"?r.push(c.subject):typeof c.taskId=="string"&&typeof c.status=="string"&&(s[c.taskId]=c.status)}catch{}if(r.length===0)return"";let n=new Set(["completed","deleted","failed"]),o=Object.keys(s).sort((e,c)=>Number(e)-Number(c)),u=[];for(let e=0;e<r.length;e++){let c=o[e],l=c?s[c]??"pending":"pending";n.has(l)||u.push(r[e])}if(u.length===0)return"";let i=[];for(let e of u)i.push(` [pending] ${a(e)}`);return i.join(`
12
- `)}function J(t,r){let s=B(t);if(!s)return"";let n=[];for(let e of t)try{let c=JSON.parse(e.data);typeof c.subject=="string"&&n.push(c.subject)}catch{}let o=h(n);return[` <task_state count="${s.split(`
6
+ )`}function D(t,r){if(t.length===0)return"";let s=new Map;for(let l of t){let S=l.data,p=s.get(S);p||(p={ops:new Map},s.set(S,p));let d;l.type==="file_write"?d="write":l.type==="file_read"?d="read":l.type==="file_edit"?d="edit":d=l.type,p.ops.set(d,(p.ops.get(d)??0)+1)}let o=Array.from(s.entries()).slice(-x),c=[],i=[];for(let[l,{ops:S}]of o){let p=Array.from(S.entries()).map(([b,y])=>`${b}\xD7${y}`).join(", "),d=l.split("/").pop()??l;c.push(` ${a(d)} (${a(p)})`),i.push(`${d} ${Array.from(S.keys()).join(" ")}`)}let e=h(i);return[` <files count="${s.size}">`,...c,m(r,e)," </files>"].join(`
7
+ `)}function R(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t)s.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <errors count="${t.length}">`,...s,m(r,o)," </errors>"].join(`
8
+ `)}function F(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let c=h(o);return[` <decisions count="${n.length}">`,...n,m(r,c)," </decisions>"].join(`
9
+ `)}function B(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),e.type==="rule_content"?n.push(` ${a(e.data)}`):n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let c=h(o);return[` <rules count="${n.length}">`,...n,m(r,c)," </rules>"].join(`
10
+ `)}function J(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t)s.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...s,m(r,o)," </git>"].join(`
11
+ `)}function X(t){if(t.length===0)return"";let r=[],s={};for(let e of t)try{let u=JSON.parse(e.data);typeof u.subject=="string"?r.push(u.subject):typeof u.taskId=="string"&&typeof u.status=="string"&&(s[u.taskId]=u.status)}catch{}if(r.length===0)return"";let n=new Set(["completed","deleted","failed"]),o=Object.keys(s).sort((e,u)=>Number(e)-Number(u)),c=[];for(let e=0;e<r.length;e++){let u=o[e],l=u?s[u]??"pending":"pending";n.has(l)||c.push(r[e])}if(c.length===0)return"";let i=[];for(let e of c)i.push(` [pending] ${a(e)}`);return i.join(`
12
+ `)}function z(t,r){let s=X(t);if(!s)return"";let n=[];for(let e of t)try{let u=JSON.parse(e.data);typeof u.subject=="string"&&n.push(u.subject)}catch{}let o=h(n);return[` <task_state count="${s.split(`
13
13
  `).length}">`,s,m(r,o)," </task_state>"].join(`
14
- `)}function X(t,r,s){if(t.length===0&&r.length===0)return"";let n=[],o=[];if(t.length>0){let e=t[t.length-1];n.push(` cwd: ${a(e.data)}`),o.push("working directory")}for(let e of r)n.push(` ${a(e.data)}`),o.push(e.data);let u=h(o);return[" <environment>",...n,m(s,u)," </environment>"].join(`
15
- `)}function z(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t){let e=i.type==="subagent_completed"?"completed":i.type==="subagent_launched"?"launched":"unknown";s.push(` [${e}] ${a(i.data)}`),n.push(`subagent ${i.data}`)}let o=h(n);return[` <subagents count="${t.length}">`,...s,m(r,o)," </subagents>"].join(`
16
- `)}function G(t,r){if(t.length===0)return"";let s=new Map;for(let e of t){let c=e.data.split(":")[0].trim();s.set(c,(s.get(c)??0)+1)}let n=[],o=[];for(let[e,c]of s)n.push(` ${a(e)} (${c}\xD7)`),o.push(`skill ${e} invocation`);let u=h(o);return[` <skills count="${t.length}">`,...n,m(r,u)," </skills>"].join(`
17
- `)}function P(t){if(t.length===0)return"";let r=t[t.length-1];return` <intent mode="${a(r.data)}"/>`}function V(t,r){let s=r?.compactCount??1,n=r?.searchTool??"ctx_search",o=new Date().toISOString(),u=[],i=[],e=[],c=[],l=[],b=[],p=[],g=[],S=[],y=[],k=[];for(let d of t)switch(d.category){case"file":u.push(d);break;case"task":i.push(d);break;case"rule":e.push(d);break;case"decision":c.push(d);break;case"cwd":l.push(d);break;case"error":b.push(d);break;case"env":p.push(d);break;case"git":g.push(d);break;case"subagent":S.push(d);break;case"intent":y.push(d);break;case"skill":k.push(d);break}let f=[];f.push(` <how_to_search>
14
+ `)}function G(t,r,s){if(t.length===0&&r.length===0)return"";let n=[],o=[];if(t.length>0){let e=t[t.length-1];n.push(` cwd: ${a(e.data)}`),o.push("working directory")}for(let e of r)n.push(` ${a(e.data)}`),o.push(e.data);let c=h(o);return[" <environment>",...n,m(s,c)," </environment>"].join(`
15
+ `)}function P(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t){let e=i.type==="subagent_completed"?"completed":i.type==="subagent_launched"?"launched":"unknown";s.push(` [${e}] ${a(i.data)}`),n.push(`subagent ${i.data}`)}let o=h(n);return[` <subagents count="${t.length}">`,...s,m(r,o)," </subagents>"].join(`
16
+ `)}function Q(t,r){if(t.length===0)return"";let s=new Map;for(let e of t){let u=e.data.split(":")[0].trim();s.set(u,(s.get(u)??0)+1)}let n=[],o=[];for(let[e,u]of s)n.push(` ${a(e)} (${u}\xD7)`),o.push(`skill ${e} invocation`);let c=h(o);return[` <skills count="${t.length}">`,...n,m(r,c)," </skills>"].join(`
17
+ `)}function U(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let c=h(o);return[` <roles count="${n.length}">`,...n,m(r,c)," </roles>"].join(`
18
+ `)}function V(t){if(t.length===0)return"";let r=t[t.length-1];return` <intent mode="${a(r.data)}"/>`}function W(t,r){let s=r?.compactCount??1,n=r?.searchTool??"ctx_search",o=new Date().toISOString(),c=[],i=[],e=[],u=[],l=[],S=[],p=[],d=[],b=[],y=[],$=[],k=[];for(let f of t)switch(f.category){case"file":c.push(f);break;case"task":i.push(f);break;case"rule":e.push(f);break;case"decision":u.push(f);break;case"cwd":l.push(f);break;case"error":S.push(f);break;case"env":p.push(f);break;case"git":d.push(f);break;case"subagent":b.push(f);break;case"intent":y.push(f);break;case"skill":$.push(f);break;case"role":k.push(f);break}let g=[];g.push(` <how_to_search>
18
19
  Each section below contains a summary of prior work.
19
20
  For FULL DETAILS, run the exact tool call shown under each section.
20
21
  Do NOT ask the user to re-explain prior work. Search first.
21
22
  Do NOT invent your own queries \u2014 use the ones provided.
22
- </how_to_search>`);let $=A(u,n);$&&f.push($);let v=x(b,n);v&&f.push(v);let w=D(c,n);w&&f.push(w);let E=F(e,n);E&&f.push(E);let q=R(g,n);q&&f.push(q);let L=J(i,n);L&&f.push(L);let _=X(l,p,n);_&&f.push(_);let j=z(S,n);j&&f.push(j);let T=G(k,n);T&&f.push(T);let C=P(y);C&&f.push(C);let O=`<session_resume events="${t.length}" compact_count="${s}" generated_at="${o}">`,I="</session_resume>",N=f.join(`
23
+ </how_to_search>`);let v=D(c,n);v&&g.push(v);let w=R(S,n);w&&g.push(w);let E=F(u,n);E&&g.push(E);let q=B(e,n);q&&g.push(q);let L=J(d,n);L&&g.push(L);let j=z(i,n);j&&g.push(j);let _=G(l,p,n);_&&g.push(_);let T=P(b,n);T&&g.push(T);let C=Q($,n);C&&g.push(C);let O=U(k,n);O&&g.push(O);let I=V(y);I&&g.push(I);let N=`<session_resume events="${t.length}" compact_count="${s}" generated_at="${o}">`,M="</session_resume>",A=g.join(`
23
24
 
24
- `);return N?`${O}
25
+ `);return A?`${N}
25
26
 
26
- ${N}
27
+ ${A}
27
28
 
28
- ${I}`:`${O}
29
- ${I}`}export{V as buildResumeSnapshot,B as renderTaskState};
29
+ ${M}`:`${N}
30
+ ${M}`}export{W as buildResumeSnapshot,X as renderTaskState};
@@ -17,6 +17,7 @@ import "./ensure-deps.mjs";
17
17
 
18
18
  import { createRoutingBlock } from "./routing-block.mjs";
19
19
  import { createToolNamer } from "./core/tool-naming.mjs";
20
+ import { buildAutoInjection } from "./auto-injection.mjs";
20
21
 
21
22
  const toolNamer = createToolNamer("claude-code");
22
23
  const ROUTING_BLOCK = createRoutingBlock(toolNamer);
@@ -54,6 +55,22 @@ try {
54
55
  if (events.length > 0) {
55
56
  const eventMeta = writeSessionEventsFile(events, getSessionEventsPath());
56
57
  additionalContext += buildSessionDirective("compact", eventMeta, toolNamer);
58
+
59
+ // Auto-inject behavioral state on compaction (role, decisions, skills, intent)
60
+ const autoInjection = buildAutoInjection(events);
61
+ if (autoInjection) {
62
+ additionalContext += "\n\n" + autoInjection;
63
+ }
64
+
65
+ // Write session-resume event
66
+ try {
67
+ db.insertEvent(sessionId, {
68
+ type: "resume_completed",
69
+ category: "session-resume",
70
+ data: `Session resumed from ${source}. Prior events loaded.`,
71
+ priority: 1,
72
+ }, "SessionStart");
73
+ } catch { /* best-effort */ }
57
74
  }
58
75
 
59
76
  db.close();
@@ -45,7 +45,7 @@ try {
45
45
  // 1. Always save the raw prompt
46
46
  const promptEvent = {
47
47
  type: "user_prompt",
48
- category: "prompt",
48
+ category: "user-prompt",
49
49
  data: prompt,
50
50
  priority: 1,
51
51
  };
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.99",
6
+ "version": "1.0.100",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.99",
3
+ "version": "1.0.100",
4
4
  "type": "module",
5
5
  "description": "MCP plugin that saves 98% of your context window. Works with Claude Code, Gemini CLI, VS Code Copilot, OpenCode, and Codex CLI. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
6
6
  "author": "Mert Koseoğlu",