context-mode 1.0.151 → 1.0.152

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 (106) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/mcp.json +5 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/.openclaw-plugin/openclaw.plugin.json +16 -1
  6. package/.openclaw-plugin/package.json +1 -1
  7. package/README.md +89 -3
  8. package/build/adapters/claude-code/hooks.js +2 -2
  9. package/build/adapters/claude-code/index.js +14 -13
  10. package/build/adapters/client-map.js +3 -0
  11. package/build/adapters/detect.js +13 -1
  12. package/build/adapters/gemini-cli/hooks.d.ts +10 -0
  13. package/build/adapters/gemini-cli/hooks.js +12 -2
  14. package/build/adapters/gemini-cli/index.d.ts +21 -1
  15. package/build/adapters/gemini-cli/index.js +37 -1
  16. package/build/adapters/kimi/config.d.ts +8 -0
  17. package/build/adapters/kimi/config.js +8 -0
  18. package/build/adapters/kimi/hooks.d.ts +28 -0
  19. package/build/adapters/kimi/hooks.js +34 -0
  20. package/build/adapters/kimi/index.d.ts +66 -0
  21. package/build/adapters/kimi/index.js +537 -0
  22. package/build/adapters/kimi/paths.d.ts +1 -0
  23. package/build/adapters/kimi/paths.js +12 -0
  24. package/build/adapters/kiro/hooks.js +2 -2
  25. package/build/adapters/openclaw/plugin.d.ts +14 -13
  26. package/build/adapters/openclaw/plugin.js +140 -40
  27. package/build/adapters/opencode/plugin.js +4 -3
  28. package/build/adapters/opencode/zod3tov4.js +8 -8
  29. package/build/adapters/pi/extension.js +9 -24
  30. package/build/adapters/pi/mcp-bridge.js +37 -0
  31. package/build/adapters/qwen-code/index.js +7 -7
  32. package/build/adapters/types.d.ts +39 -2
  33. package/build/adapters/types.js +55 -2
  34. package/build/cli.js +433 -25
  35. package/build/executor.js +6 -3
  36. package/build/runtime.d.ts +81 -1
  37. package/build/runtime.js +195 -9
  38. package/build/search/ctx-search-schema.d.ts +90 -0
  39. package/build/search/ctx-search-schema.js +135 -0
  40. package/build/search/unified.d.ts +12 -0
  41. package/build/search/unified.js +17 -2
  42. package/build/server.d.ts +2 -1
  43. package/build/server.js +378 -97
  44. package/build/session/analytics.d.ts +36 -13
  45. package/build/session/analytics.js +123 -26
  46. package/build/session/db.d.ts +24 -0
  47. package/build/session/db.js +41 -0
  48. package/build/session/extract.js +30 -0
  49. package/build/session/snapshot.js +24 -0
  50. package/build/store.d.ts +12 -1
  51. package/build/store.js +72 -20
  52. package/build/types.d.ts +7 -0
  53. package/build/util/project-dir.d.ts +19 -16
  54. package/build/util/project-dir.js +80 -45
  55. package/cli.bundle.mjs +371 -320
  56. package/configs/kimi/hooks.json +54 -0
  57. package/configs/pi/AGENTS.md +3 -85
  58. package/hooks/cache-heal-utils.mjs +148 -0
  59. package/hooks/core/formatters.mjs +26 -0
  60. package/hooks/core/routing.mjs +9 -1
  61. package/hooks/core/stdin.mjs +74 -3
  62. package/hooks/core/tool-naming.mjs +1 -0
  63. package/hooks/heal-partial-install.mjs +712 -0
  64. package/hooks/kimi/platform.mjs +1 -0
  65. package/hooks/kimi/posttooluse.mjs +72 -0
  66. package/hooks/kimi/precompact.mjs +80 -0
  67. package/hooks/kimi/pretooluse.mjs +42 -0
  68. package/hooks/kimi/sessionend.mjs +61 -0
  69. package/hooks/kimi/sessionstart.mjs +113 -0
  70. package/hooks/kimi/stop.mjs +61 -0
  71. package/hooks/kimi/userpromptsubmit.mjs +90 -0
  72. package/hooks/normalize-hooks.mjs +66 -12
  73. package/hooks/routing-block.mjs +8 -2
  74. package/hooks/security.bundle.mjs +1 -1
  75. package/hooks/session-db.bundle.mjs +6 -4
  76. package/hooks/session-extract.bundle.mjs +2 -2
  77. package/hooks/session-helpers.mjs +93 -3
  78. package/hooks/session-snapshot.bundle.mjs +20 -19
  79. package/hooks/sessionstart.mjs +64 -0
  80. package/insight/server.mjs +15 -3
  81. package/openclaw.plugin.json +16 -1
  82. package/package.json +1 -1
  83. package/scripts/heal-installed-plugins.mjs +31 -10
  84. package/scripts/postinstall.mjs +10 -0
  85. package/server.bundle.mjs +206 -157
  86. package/skills/ctx-index/SKILL.md +46 -0
  87. package/skills/ctx-search/SKILL.md +35 -0
  88. package/start.mjs +84 -11
  89. package/build/cache-heal.d.ts +0 -48
  90. package/build/cache-heal.js +0 -150
  91. package/build/concurrency/runPool.d.ts +0 -36
  92. package/build/concurrency/runPool.js +0 -51
  93. package/build/openclaw/mcp-tools.d.ts +0 -54
  94. package/build/openclaw/mcp-tools.js +0 -198
  95. package/build/openclaw/workspace-router.d.ts +0 -29
  96. package/build/openclaw/workspace-router.js +0 -64
  97. package/build/openclaw-plugin.d.ts +0 -130
  98. package/build/openclaw-plugin.js +0 -626
  99. package/build/opencode-plugin.d.ts +0 -122
  100. package/build/opencode-plugin.js +0 -375
  101. package/build/pi-extension.d.ts +0 -14
  102. package/build/pi-extension.js +0 -451
  103. package/build/routing-block.d.ts +0 -8
  104. package/build/routing-block.js +0 -86
  105. package/build/tool-naming.d.ts +0 -4
  106. package/build/tool-naming.js +0 -24
@@ -1 +1 @@
1
- var h=(n,t)=>()=>(n&&(t=n(n=0)),t);var _,I=h(()=>{"use strict";_={"claude-code":"claude-code","gemini-cli-mcp-client":"gemini-cli","antigravity-client":"antigravity","cursor-vscode":"cursor","Visual-Studio-Code":"vscode-copilot","JetBrains Client":"jetbrains-copilot","IntelliJ IDEA":"jetbrains-copilot",PyCharm:"jetbrains-copilot",Codex:"codex","codex-mcp-client":"codex","Kilo Code":"kilo","Kiro CLI":"kiro","Pi CLI":"pi","Pi Coding Agent":"pi","omp-coding-agent":"omp",Zed:"zed",zed:"zed","qwen-code":"qwen-code","qwen-cli-mcp-client":"qwen-code"}});import{existsSync as l,readFileSync as N}from"node:fs";import{resolve as a}from"node:path";import{homedir as S}from"node:os";function L(){if(f!==null)return f!=="miss"&&f.hasCM;try{let n=a(S(),".claude","plugins","installed_plugins.json"),t=N(n,"utf-8"),e=JSON.parse(t),r=[...Object.keys(e.plugins??{}),...Object.keys(e.enabledPlugins??{})].some(i=>i.includes("context-mode"));return f={hasCM:r},r}catch{return f="miss",!1}}function A(n){switch(n){case"claude-code":return[".claude"];case"gemini-cli":return[".gemini"];case"antigravity":return[".gemini"];case"openclaw":return[".openclaw"];case"codex":return[".codex"];case"cursor":return[".cursor"];case"vscode-copilot":return[".vscode"];case"kiro":return[".kiro"];case"pi":return[".pi"];case"omp":return[".omp"];case"qwen-code":return[".qwen"];case"kilo":return[".config","kilo"];case"opencode":return[".config","opencode"];case"zed":return[".config","zed"];case"jetbrains-copilot":return[".config","JetBrains"];default:return null}}function O(n){if(n?.name){let o=_[n.name];if(o)return{platform:o,confidence:"high",reason:`MCP clientInfo.name="${n.name}"`};if(n.name.startsWith("qwen-cli-mcp-client"))return{platform:"qwen-code",confidence:"high",reason:`MCP clientInfo.name="${n.name}" (qwen-cli pattern)`}}let t=process.env.CONTEXT_MODE_PLATFORM;if(t&&["claude-code","gemini-cli","kilo","opencode","codex","vscode-copilot","jetbrains-copilot","cursor","antigravity","kiro","pi","omp","zed","qwen-code"].includes(t))return{platform:t,confidence:"high",reason:`CONTEXT_MODE_PLATFORM=${t} override`};for(let[o,r]of F)if(r.some(i=>i.detect!==!1&&process.env[i.name]))return o==="vscode-copilot"&&L()?{platform:"claude-code",confidence:"high",reason:"VSCODE_PID set but ~/.claude/plugins/installed_plugins.json lists context-mode (issue #539 fallback)"}:{platform:o,confidence:"high",reason:`${r.filter(i=>i.detect!==!1).map(i=>i.name).join(" or ")} env var set`};let e=S();return l(a(e,".claude"))?{platform:"claude-code",confidence:"medium",reason:"~/.claude/ directory exists"}:l(a(e,".gemini"))?{platform:"gemini-cli",confidence:"medium",reason:"~/.gemini/ directory exists"}:l(a(e,".codex"))?{platform:"codex",confidence:"medium",reason:"~/.codex/ directory exists"}:l(a(e,".kiro"))?{platform:"kiro",confidence:"medium",reason:"~/.kiro/ directory exists"}:l(a(e,".omp"))?{platform:"omp",confidence:"medium",reason:"~/.omp/ directory exists"}:l(a(e,".pi"))?{platform:"pi",confidence:"medium",reason:"~/.pi/ directory exists"}:l(a(e,".qwen"))?{platform:"qwen-code",confidence:"medium",reason:"~/.qwen/ directory exists"}:l(a(e,".openclaw"))?{platform:"openclaw",confidence:"medium",reason:"~/.openclaw/ directory exists"}:l(a(e,".cursor"))?{platform:"cursor",confidence:"medium",reason:"~/.cursor/ directory exists"}:l(a(e,".config","kilo"))?{platform:"kilo",confidence:"medium",reason:"~/.config/kilo/ directory exists"}:l(a(e,".config","JetBrains"))?{platform:"jetbrains-copilot",confidence:"medium",reason:"~/.config/JetBrains/ directory exists"}:l(a(e,".config","opencode"))?{platform:"opencode",confidence:"medium",reason:"~/.config/opencode/ directory exists"}:l(a(e,".config","zed"))?{platform:"zed",confidence:"medium",reason:"~/.config/zed/ directory exists"}:{platform:"claude-code",confidence:"low",reason:"No platform detected, defaulting to Claude Code"}}var f,M,F,R=h(()=>{"use strict";I();f=null;M=[["claude-code",[{name:"CLAUDE_CODE_ENTRYPOINT",role:"identification"},{name:"CLAUDE_PLUGIN_ROOT",role:"identification"},{name:"CLAUDE_PROJECT_DIR",role:"workspace"},{name:"CLAUDE_SESSION_ID",role:"identification"}]],["antigravity",[{name:"ANTIGRAVITY_CLI_ALIAS",role:"identification"}]],["cursor",[{name:"CURSOR_CWD",role:"workspace"},{name:"CURSOR_TRACE_ID",role:"identification"},{name:"CURSOR_CLI",role:"identification"}]],["kilo",[{name:"KILO",role:"identification"},{name:"KILO_PID",role:"identification"}]],["opencode",[{name:"OPENCODE_PROJECT_DIR",role:"workspace"},{name:"OPENCODE_CLIENT",role:"identification"},{name:"OPENCODE_TERMINAL",role:"identification"},{name:"OPENCODE",role:"identification"},{name:"OPENCODE_PID",role:"identification"}]],["zed",[{name:"ZED_SESSION_ID",role:"identification"},{name:"ZED_TERM",role:"identification"}]],["codex",[{name:"CODEX_THREAD_ID",role:"identification"},{name:"CODEX_CI",role:"identification"}]],["gemini-cli",[{name:"GEMINI_PROJECT_DIR",role:"workspace"},{name:"GEMINI_CLI",role:"identification"}]],["vscode-copilot",[{name:"VSCODE_CWD",role:"workspace"},{name:"VSCODE_PID",role:"identification"}]],["jetbrains-copilot",[{name:"IDEA_INITIAL_DIRECTORY",role:"workspace"}]],["qwen-code",[{name:"QWEN_PROJECT_DIR",role:"workspace"}]],["omp",[{name:"PI_CODING_AGENT_DIR",role:"workspace"}]],["pi",[{name:"PI_WORKSPACE_DIR",role:"workspace",detect:!1},{name:"PI_PROJECT_DIR",role:"workspace",detect:!1},{name:"PI_CONFIG_DIR",role:"identification"},{name:"PI_SESSION_FILE",role:"identification"},{name:"PI_COMPILED",role:"identification"}]]],F=new Map(M)});import{resolve as p}from"node:path";import{homedir as P}from"node:os";function j(n=process.env){let t=n.CLAUDE_CONFIG_DIR;return t&&t.trim()!==""?t.startsWith("~")?p(P(),t.replace(/^~[/\\]?/,"")):p(t):p(P(),".claude")}function G(n=process.env){return p(j(n),"settings.json")}function w(n=process.env){let t=[],e=O();if(e.platform!=="claude-code"){let r=A(e.platform);r&&r.length>0&&t.push(p(P(),...r,"settings.json"))}let o=G(n);return t.includes(o)||t.push(o),t}var v=h(()=>{"use strict";R()});v();import{readFileSync as D,realpathSync as $}from"node:fs";import{resolve as u}from"node:path";function b(n){let t=n.match(/^Bash\((.+)\)$/);return t?t[1]:null}function J(n){let t=n.match(/^(\w+)\((.+)\)$/);return t?{tool:t[1],glob:t[2]}:null}function q(n){return n.replace(/[.*+?^${}()|[\]\\\/\-]/g,"\\$&")}function k(n){return n.replace(/[.+?^${}()|[\]\\\/\-]/g,"\\$&").replace(/\*/g,".*")}function V(n,t=!1){let e,o=n.indexOf(":");if(o!==-1){let r=n.slice(0,o),i=n.slice(o+1),s=q(r),c=k(i);e=`^${s}(\\s${c})?$`}else e=`^${k(n)}$`;return new RegExp(e,t?"i":"")}function z(n,t=!1){let e="",o=0;for(;o<n.length;)n[o]==="*"&&n[o+1]==="*"?o+2<n.length&&n[o+2]==="/"?(e+="(.*/)?",o+=3):(e+=".*",o+=2):n[o]==="*"?(e+="[^/]*",o++):n[o]==="?"?(e+="[^/]",o++):(e+=n[o].replace(/[.+^${}()|[\]\\\/\-]/g,"\\$&"),o++);return new RegExp(`^${e}$`,t?"i":"")}function g(n,t,e=!1){for(let o of t){let r=b(o);if(r&&V(r,e).test(n))return o}return null}function T(n){let t=[],e="",o=!1,r=!1,i=!1;for(let s=0;s<n.length;s++){let c=n[s],d=s>0?n[s-1]:"";c==="'"&&!r&&!i&&d!=="\\"?(o=!o,e+=c):c==='"'&&!o&&!i&&d!=="\\"?(r=!r,e+=c):c==="`"&&!o&&!r&&d!=="\\"?(i=!i,e+=c):!o&&!r&&!i?c===";"?(t.push(e.trim()),e=""):c==="|"&&n[s+1]==="|"||c==="&"&&n[s+1]==="&"?(t.push(e.trim()),e="",s++):c==="|"?(t.push(e.trim()),e=""):e+=c:e+=c}return e.trim()&&t.push(e.trim()),t.filter(s=>s.length>0)}function C(n){let t;try{t=D(n,"utf-8")}catch{return null}let e;try{e=JSON.parse(t)}catch{return null}let o=e?.permissions;if(!o||typeof o!="object")return null;let r=i=>Array.isArray(i)?i.filter(s=>typeof s=="string"&&b(s)!==null):[];return{allow:r(o.allow),deny:r(o.deny),ask:r(o.ask)}}function ce(n,t){let e=[];if(n){let r=u(n,".claude","settings.local.json"),i=C(r);i&&e.push(i);let s=u(n,".claude","settings.json"),c=C(s);c&&e.push(c)}let o=t!==void 0?[t]:w();for(let r of o){let i=C(r);i&&e.push(i)}return e}function ae(n,t,e){let o=[],r=s=>{let c;try{c=D(s,"utf-8")}catch{return null}let d;try{d=JSON.parse(c)}catch{return null}let m=d?.permissions?.deny;if(!Array.isArray(m))return[];let x=[];for(let E of m){if(typeof E!="string")continue;let y=J(E);y&&y.tool===n&&x.push(y.glob)}return x};if(t){let s=r(u(t,".claude","settings.local.json"));s!==null&&o.push(s);let c=r(u(t,".claude","settings.json"));c!==null&&o.push(c)}let i=e!==void 0?[e]:w();for(let s of i){let c=r(s);c!==null&&o.push(c)}return o}function le(n,t,e=process.platform==="win32"){let o=T(n);for(let r of o)for(let i of t){let s=g(r,i.deny,e);if(s)return{decision:"deny",matchedPattern:s}}for(let r of t){let i=g(n,r.ask,e);if(i)return{decision:"ask",matchedPattern:i};let s=g(n,r.allow,e);if(s)return{decision:"allow",matchedPattern:s}}return{decision:"ask"}}function de(n,t,e=process.platform==="win32"){let o=T(n);for(let r of o)for(let i of t){let s=g(r,i.deny,e);if(s)return{decision:"deny",matchedPattern:s}}return{decision:"allow"}}function fe(n,t,e=process.platform==="win32",o){let r=s=>s.replace(/\\/g,"/"),i=new Set;if(i.add(r(n)),o){let s=u(o,n);i.add(r(s));try{i.add(r($(s)))}catch{}}for(let s of t)for(let c of s){let d=z(r(c),e);for(let m of i)if(d.test(m))return{denied:!0,matchedPattern:c}}return{denied:!1}}var B={python:[/os\.system\(\s*(['"])(.*?)\1\s*\)/g,/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*(['"])(.*?)\1/g],javascript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],typescript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],ruby:[/system\(\s*(['"])(.*?)\1/g,/`(.*?)`/g],go:[/exec\.Command\(\s*(['"`])(.*?)\1/g],php:[/shell_exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])system\(\s*(['"`])(.*?)\1/g,/passthru\(\s*(['"`])(.*?)\1/g,/proc_open\(\s*(['"`])(.*?)\1/g],rust:[/Command::new\(\s*(['"`])(.*?)\1/g]};function U(n){let t=[],e=/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*\[([^\]]+)\]/g,o;for(;(o=e.exec(n))!==null;){let i=[...o[1].matchAll(/(['"])(.*?)\1/g)].map(s=>s[2]);i.length>0&&t.push(i.join(" "))}return t}function pe(n,t){let e=B[t];if(!e&&t!=="python")return[];let o=[];if(e)for(let r of e){r.lastIndex=0;let i;for(;(i=r.exec(n))!==null;){let s=i[i.length-1];s&&o.push(s)}}return t==="python"&&o.push(...U(n)),o}export{le as evaluateCommand,de as evaluateCommandDenyOnly,fe as evaluateFilePath,pe as extractShellCommands,z as fileGlobToRegex,V as globToRegex,g as matchesAnyPattern,b as parseBashPattern,J as parseToolPattern,ce as readBashPolicies,ae as readToolDenyPatterns,T as splitChainedCommands};
1
+ var h=(n,t)=>()=>(n&&(t=n(n=0)),t);var _,I=h(()=>{"use strict";_={"claude-code":"claude-code","gemini-cli-mcp-client":"gemini-cli","antigravity-client":"antigravity","cursor-vscode":"cursor","Visual-Studio-Code":"vscode-copilot","JetBrains Client":"jetbrains-copilot","IntelliJ IDEA":"jetbrains-copilot",PyCharm:"jetbrains-copilot",Codex:"codex","codex-mcp-client":"codex","Kilo Code":"kilo","Kiro CLI":"kiro","Pi CLI":"pi","Pi Coding Agent":"pi","omp-coding-agent":"omp",Zed:"zed",zed:"zed","qwen-code":"qwen-code","qwen-cli-mcp-client":"qwen-code","kimi-code":"kimi",kimi:"kimi","Kimi Code":"kimi"}});import{existsSync as l,readFileSync as N}from"node:fs";import{resolve as a}from"node:path";import{homedir as k}from"node:os";function L(){if(f!==null)return f!=="miss"&&f.hasCM;try{let n=a(k(),".claude","plugins","installed_plugins.json"),t=N(n,"utf-8"),e=JSON.parse(t),r=[...Object.keys(e.plugins??{}),...Object.keys(e.enabledPlugins??{})].some(i=>i.includes("context-mode"));return f={hasCM:r},r}catch{return f="miss",!1}}function S(n){switch(n){case"claude-code":return[".claude"];case"gemini-cli":return[".gemini"];case"antigravity":return[".gemini"];case"openclaw":return[".openclaw"];case"codex":return[".codex"];case"cursor":return[".cursor"];case"vscode-copilot":return[".vscode"];case"kiro":return[".kiro"];case"pi":return[".pi"];case"omp":return[".omp"];case"qwen-code":return[".qwen"];case"kimi":return[".kimi-code"];case"kilo":return[".config","kilo"];case"opencode":return[".config","opencode"];case"zed":return[".config","zed"];case"jetbrains-copilot":return[".config","JetBrains"];default:return null}}function A(n){if(n?.name){let o=_[n.name];if(o)return{platform:o,confidence:"high",reason:`MCP clientInfo.name="${n.name}"`};if(n.name.startsWith("qwen-cli-mcp-client"))return{platform:"qwen-code",confidence:"high",reason:`MCP clientInfo.name="${n.name}" (qwen-cli pattern)`}}let t=process.env.CONTEXT_MODE_PLATFORM;if(t&&["claude-code","gemini-cli","kilo","opencode","codex","vscode-copilot","jetbrains-copilot","cursor","antigravity","kiro","pi","omp","zed","qwen-code","kimi"].includes(t))return{platform:t,confidence:"high",reason:`CONTEXT_MODE_PLATFORM=${t} override`};for(let[o,r]of F)if(r.some(i=>i.detect!==!1&&process.env[i.name]))return o==="vscode-copilot"&&L()?{platform:"claude-code",confidence:"high",reason:"VSCODE_PID set but ~/.claude/plugins/installed_plugins.json lists context-mode (issue #539 fallback)"}:{platform:o,confidence:"high",reason:`${r.filter(i=>i.detect!==!1).map(i=>i.name).join(" or ")} env var set`};let e=k();return l(a(e,".claude"))?{platform:"claude-code",confidence:"medium",reason:"~/.claude/ directory exists"}:l(a(e,".gemini"))?{platform:"gemini-cli",confidence:"medium",reason:"~/.gemini/ directory exists"}:l(a(e,".codex"))?{platform:"codex",confidence:"medium",reason:"~/.codex/ directory exists"}:l(a(e,".kiro"))?{platform:"kiro",confidence:"medium",reason:"~/.kiro/ directory exists"}:l(a(e,".omp"))?{platform:"omp",confidence:"medium",reason:"~/.omp/ directory exists"}:l(a(e,".pi"))?{platform:"pi",confidence:"medium",reason:"~/.pi/ directory exists"}:l(a(e,".qwen"))?{platform:"qwen-code",confidence:"medium",reason:"~/.qwen/ directory exists"}:l(a(e,".kimi-code"))?{platform:"kimi",confidence:"medium",reason:"~/.kimi-code/ directory exists"}:l(a(e,".openclaw"))?{platform:"openclaw",confidence:"medium",reason:"~/.openclaw/ directory exists"}:l(a(e,".cursor"))?{platform:"cursor",confidence:"medium",reason:"~/.cursor/ directory exists"}:l(a(e,".config","kilo"))?{platform:"kilo",confidence:"medium",reason:"~/.config/kilo/ directory exists"}:l(a(e,".config","JetBrains"))?{platform:"jetbrains-copilot",confidence:"medium",reason:"~/.config/JetBrains/ directory exists"}:l(a(e,".config","opencode"))?{platform:"opencode",confidence:"medium",reason:"~/.config/opencode/ directory exists"}:l(a(e,".config","zed"))?{platform:"zed",confidence:"medium",reason:"~/.config/zed/ directory exists"}:{platform:"claude-code",confidence:"low",reason:"No platform detected, defaulting to Claude Code"}}var f,M,F,O=h(()=>{"use strict";I();f=null;M=[["claude-code",[{name:"CLAUDE_CODE_ENTRYPOINT",role:"identification"},{name:"CLAUDE_PLUGIN_ROOT",role:"identification"},{name:"CLAUDE_PROJECT_DIR",role:"workspace"},{name:"CLAUDE_SESSION_ID",role:"identification"}]],["antigravity",[{name:"ANTIGRAVITY_CLI_ALIAS",role:"identification"}]],["cursor",[{name:"CURSOR_CWD",role:"workspace"},{name:"CURSOR_TRACE_ID",role:"identification"},{name:"CURSOR_CLI",role:"identification"}]],["kilo",[{name:"KILO",role:"identification"},{name:"KILO_PID",role:"identification"}]],["opencode",[{name:"OPENCODE_PROJECT_DIR",role:"workspace"},{name:"OPENCODE_CLIENT",role:"identification"},{name:"OPENCODE_TERMINAL",role:"identification"},{name:"OPENCODE",role:"identification"},{name:"OPENCODE_PID",role:"identification"}]],["zed",[{name:"ZED_SESSION_ID",role:"identification"},{name:"ZED_TERM",role:"identification"}]],["codex",[{name:"CODEX_THREAD_ID",role:"identification"},{name:"CODEX_CI",role:"identification"}]],["gemini-cli",[{name:"GEMINI_PROJECT_DIR",role:"workspace"},{name:"GEMINI_CLI",role:"identification"}]],["vscode-copilot",[{name:"VSCODE_CWD",role:"workspace"},{name:"VSCODE_PID",role:"identification"}]],["jetbrains-copilot",[{name:"IDEA_INITIAL_DIRECTORY",role:"workspace"}]],["qwen-code",[{name:"QWEN_PROJECT_DIR",role:"workspace"}]],["omp",[{name:"PI_CODING_AGENT_DIR",role:"workspace"}]],["pi",[{name:"PI_WORKSPACE_DIR",role:"workspace",detect:!1},{name:"PI_PROJECT_DIR",role:"workspace",detect:!1},{name:"PI_CONFIG_DIR",role:"identification"},{name:"PI_SESSION_FILE",role:"identification"},{name:"PI_COMPILED",role:"identification"}]]],F=new Map(M)});import{resolve as u}from"node:path";import{homedir as P}from"node:os";function j(n=process.env){let t=n.CLAUDE_CONFIG_DIR;return t&&t.trim()!==""?t.startsWith("~")?u(P(),t.replace(/^~[/\\]?/,"")):u(t):u(P(),".claude")}function G(n=process.env){return u(j(n),"settings.json")}function w(n=process.env){let t=[],e=A();if(e.platform!=="claude-code"){let r=S(e.platform);r&&r.length>0&&t.push(u(P(),...r,"settings.json"))}let o=G(n);return t.includes(o)||t.push(o),t}var R=h(()=>{"use strict";O()});R();import{readFileSync as D,realpathSync as $}from"node:fs";import{resolve as p}from"node:path";function b(n){let t=n.match(/^Bash\((.+)\)$/);return t?t[1]:null}function J(n){let t=n.match(/^(\w+)\((.+)\)$/);return t?{tool:t[1],glob:t[2]}:null}function q(n){return n.replace(/[.*+?^${}()|[\]\\\/\-]/g,"\\$&")}function v(n){return n.replace(/[.+?^${}()|[\]\\\/\-]/g,"\\$&").replace(/\*/g,".*")}function V(n,t=!1){let e,o=n.indexOf(":");if(o!==-1){let r=n.slice(0,o),i=n.slice(o+1),s=q(r),c=v(i);e=`^${s}(\\s${c})?$`}else e=`^${v(n)}$`;return new RegExp(e,t?"i":"")}function z(n,t=!1){let e="",o=0;for(;o<n.length;)n[o]==="*"&&n[o+1]==="*"?o+2<n.length&&n[o+2]==="/"?(e+="(.*/)?",o+=3):(e+=".*",o+=2):n[o]==="*"?(e+="[^/]*",o++):n[o]==="?"?(e+="[^/]",o++):(e+=n[o].replace(/[.+^${}()|[\]\\\/\-]/g,"\\$&"),o++);return new RegExp(`^${e}$`,t?"i":"")}function g(n,t,e=!1){for(let o of t){let r=b(o);if(r&&V(r,e).test(n))return o}return null}function T(n){let t=[],e="",o=!1,r=!1,i=!1;for(let s=0;s<n.length;s++){let c=n[s],d=s>0?n[s-1]:"";c==="'"&&!r&&!i&&d!=="\\"?(o=!o,e+=c):c==='"'&&!o&&!i&&d!=="\\"?(r=!r,e+=c):c==="`"&&!o&&!r&&d!=="\\"?(i=!i,e+=c):!o&&!r&&!i?c===";"?(t.push(e.trim()),e=""):c==="|"&&n[s+1]==="|"||c==="&"&&n[s+1]==="&"?(t.push(e.trim()),e="",s++):c==="|"?(t.push(e.trim()),e=""):e+=c:e+=c}return e.trim()&&t.push(e.trim()),t.filter(s=>s.length>0)}function C(n){let t;try{t=D(n,"utf-8")}catch{return null}let e;try{e=JSON.parse(t)}catch{return null}let o=e?.permissions;if(!o||typeof o!="object")return null;let r=i=>Array.isArray(i)?i.filter(s=>typeof s=="string"&&b(s)!==null):[];return{allow:r(o.allow),deny:r(o.deny),ask:r(o.ask)}}function ce(n,t){let e=[];if(n){let r=p(n,".claude","settings.local.json"),i=C(r);i&&e.push(i);let s=p(n,".claude","settings.json"),c=C(s);c&&e.push(c)}let o=t!==void 0?[t]:w();for(let r of o){let i=C(r);i&&e.push(i)}return e}function ae(n,t,e){let o=[],r=s=>{let c;try{c=D(s,"utf-8")}catch{return null}let d;try{d=JSON.parse(c)}catch{return null}let m=d?.permissions?.deny;if(!Array.isArray(m))return[];let x=[];for(let E of m){if(typeof E!="string")continue;let y=J(E);y&&y.tool===n&&x.push(y.glob)}return x};if(t){let s=r(p(t,".claude","settings.local.json"));s!==null&&o.push(s);let c=r(p(t,".claude","settings.json"));c!==null&&o.push(c)}let i=e!==void 0?[e]:w();for(let s of i){let c=r(s);c!==null&&o.push(c)}return o}function le(n,t,e=process.platform==="win32"){let o=T(n);for(let r of o)for(let i of t){let s=g(r,i.deny,e);if(s)return{decision:"deny",matchedPattern:s}}for(let r of t){let i=g(n,r.ask,e);if(i)return{decision:"ask",matchedPattern:i};let s=g(n,r.allow,e);if(s)return{decision:"allow",matchedPattern:s}}return{decision:"ask"}}function de(n,t,e=process.platform==="win32"){let o=T(n);for(let r of o)for(let i of t){let s=g(r,i.deny,e);if(s)return{decision:"deny",matchedPattern:s}}return{decision:"allow"}}function fe(n,t,e=process.platform==="win32",o){let r=s=>s.replace(/\\/g,"/"),i=new Set;if(i.add(r(n)),o){let s=p(o,n);i.add(r(s));try{i.add(r($(s)))}catch{}}for(let s of t)for(let c of s){let d=z(r(c),e);for(let m of i)if(d.test(m))return{denied:!0,matchedPattern:c}}return{denied:!1}}var B={python:[/os\.system\(\s*(['"])(.*?)\1\s*\)/g,/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*(['"])(.*?)\1/g],javascript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],typescript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],ruby:[/system\(\s*(['"])(.*?)\1/g,/`(.*?)`/g],go:[/exec\.Command\(\s*(['"`])(.*?)\1/g],php:[/shell_exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])system\(\s*(['"`])(.*?)\1/g,/passthru\(\s*(['"`])(.*?)\1/g,/proc_open\(\s*(['"`])(.*?)\1/g],rust:[/Command::new\(\s*(['"`])(.*?)\1/g]};function U(n){let t=[],e=/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*\[([^\]]+)\]/g,o;for(;(o=e.exec(n))!==null;){let i=[...o[1].matchAll(/(['"])(.*?)\1/g)].map(s=>s[2]);i.length>0&&t.push(i.join(" "))}return t}function ue(n,t){let e=B[t];if(!e&&t!=="python")return[];let o=[];if(e)for(let r of e){r.lastIndex=0;let i;for(;(i=r.exec(n))!==null;){let s=i[i.length-1];s&&o.push(s)}}return t==="python"&&o.push(...U(n)),o}export{le as evaluateCommand,de as evaluateCommandDenyOnly,fe as evaluateFilePath,ue as extractShellCommands,z as fileGlobToRegex,V as globToRegex,g as matchesAnyPattern,b as parseBashPattern,J as parseToolPattern,ce as readBashPolicies,ae as readToolDenyPatterns,T as splitChainedCommands};
@@ -1,6 +1,6 @@
1
- import{createRequire as oe}from"node:module";import{existsSync as ie,unlinkSync as P,renameSync as ae}from"node:fs";import{tmpdir as ce}from"node:os";import{join as ue}from"node:path";var A=class{#e;constructor(e){this.#e=e}pragma(e){let r=this.#e.prepare(`PRAGMA ${e}`).all();if(!r||r.length===0)return;if(r.length>1)return r;let s=Object.values(r[0]);return s.length===1?s[0]:r[0]}exec(e){let t="",r=null;for(let a=0;a<e.length;a++){let i=e[a];if(r)t+=i,i===r&&(r=null);else if(i==="'"||i==='"')t+=i,r=i;else if(i===";"){let c=t.trim();c&&this.#e.prepare(c).run(),t=""}else t+=i}let s=t.trim();return s&&this.#e.prepare(s).run(),this}prepare(e){let t=this.#e.prepare(e);return{run:(...r)=>t.run(...r),get:(...r)=>{let s=t.get(...r);return s===null?void 0:s},all:(...r)=>t.all(...r),iterate:(...r)=>t.iterate(...r)}}transaction(e){return this.#e.transaction(e)}close(){this.#e.close()}},w=class{#e;constructor(e){this.#e=e}pragma(e){let r=this.#e.prepare(`PRAGMA ${e}`).all();if(!r||r.length===0)return;if(r.length>1)return r;let s=Object.values(r[0]);return s.length===1?s[0]:r[0]}exec(e){return this.#e.exec(e),this}prepare(e){let t=this.#e.prepare(e);return{run:(...r)=>t.run(...r),get:(...r)=>t.get(...r),all:(...r)=>t.all(...r),iterate:(...r)=>typeof t.iterate=="function"?t.iterate(...r):t.all(...r)[Symbol.iterator]()}}transaction(e){return(...t)=>{this.#e.exec("BEGIN");try{let r=e(...t);return this.#e.exec("COMMIT"),r}catch(r){throw this.#e.exec("ROLLBACK"),r}}}close(){this.#e.close()}},E=null;function de(n){let e=null;try{return e=new n(":memory:"),e.exec("CREATE VIRTUAL TABLE __fts5_probe USING fts5(x)"),!0}catch{return!1}finally{try{e?.close()}catch{}}}function le(n,e){let t=e!==void 0?e:globalThis.Bun;if(typeof t<"u"&&t!==null)return!0;let r=n??process.versions,[s,a]=(r.node??"0.0.0").split("."),i=Number(s),c=Number(a);return!Number.isFinite(i)||!Number.isFinite(c)?!1:i>22||i===22&&c>=5}function ge(){if(!E){let n=oe(import.meta.url);if(globalThis.Bun){let e=n(["bun","sqlite"].join(":")).Database;E=function(r,s){let a=new e(r,{readonly:s?.readonly,create:!0}),i=new A(a);return s?.timeout&&i.pragma(`busy_timeout = ${s.timeout}`),i}}else if(le()){let e=null;try{({DatabaseSync:e}=n(["node","sqlite"].join(":")))}catch{e=null}e&&de(e)?E=function(r,s){let a=new e(r,{readOnly:s?.readonly??!1}),i=new w(a);return s?.timeout&&i.pragma(`busy_timeout = ${s.timeout}`),i}:E=n("better-sqlite3")}else E=n("better-sqlite3")}return E}function M(n){n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL");try{n.pragma("mmap_size = 268435456")}catch{}}function F(n){if(!ie(n))for(let e of["-wal","-shm"])try{P(n+e)}catch{}}function Ee(n){for(let e of["","-wal","-shm"])try{P(n+e)}catch{}}function x(n){try{n.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{n.close()}catch{}}function B(n="context-mode"){return ue(ce(),`${n}-${process.pid}.db`)}function me(n,e=[100,500,2e3]){let t;for(let r=0;r<=e.length;r++)try{return n()}catch(s){let a=s instanceof Error?s.message:String(s);if(!a.includes("SQLITE_BUSY")&&!a.includes("database is locked"))throw s;if(t=s instanceof Error?s:new Error(a),r<e.length){let i=e[r],c=Date.now();for(;Date.now()-c<i;);}}throw new Error(`SQLITE_BUSY: database is locked after ${e.length} retries. Original error: ${t?.message}`)}function pe(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 ye(n){let e=Date.now();for(let t of["","-wal","-shm"])try{ae(n+t,`${n}${t}.corrupt-${e}`)}catch{}}var _=Symbol.for("__context_mode_live_dbs_v3__"),C=(()=>{let n=globalThis;return n[_]||(n[_]=new Set,process.on("exit",()=>{for(let e of n[_])x(e);n[_].clear()})),n[_]})(),T=class{#e;#t;constructor(e){let t=ge();this.#e=e,F(e);let r;try{r=new t(e,{timeout:3e4}),M(r)}catch(s){let a=s instanceof Error?s.message:String(s);if(pe(a)){ye(e),F(e);try{r=new t(e,{timeout:3e4}),M(r)}catch(i){throw new Error(`Failed to create fresh DB after renaming corrupt file: ${i instanceof Error?i.message:String(i)}`)}}else throw s}this.#t=r,C.add(this.#t),this.initSchema(),this.prepareStatements()}get db(){return this.#t}get dbPath(){return this.#e}close(){C.delete(this.#t),x(this.#t)}withRetry(e){return me(e)}cleanup(){C.delete(this.#t),x(this.#t),Ee(this.#e)}};import{createHash as f}from"node:crypto";import{execFileSync as _e}from"node:child_process";import{accessSync as fe,constants as he,existsSync as D,mkdirSync as ve,realpathSync as Se,renameSync as I}from"node:fs";import{homedir as G}from"node:os";import{dirname as Te,isAbsolute as Y,join as g,resolve as p}from"node:path";var l="CONTEXT_MODE_DIR",q="sessions",j="content",h=class extends Error{kind;path;overrideEnvVar;ignoredEnvVar;ignoredReason;constructor(e,t,r=l,s,a,i={}){super(a??Ne(e,t,i),{cause:s}),this.name="StorageDirectoryError",this.kind=e,this.path=t,this.overrideEnvVar=r,this.ignoredEnvVar=i.ignoredEnvVar,this.ignoredReason=i.ignoredReason}},b=new Map;function Ge(n){let e=n.env??process.env,t=n.legacySessionDirEnv,r=t?e[t]?.trim():void 0;return r&&t?(n.onLegacySessionDir?.(t,r),r):g(Re(n.configDir,n.configDirEnv,e),"context-mode","sessions")}function Re(n,e,t){let r=e?t[e]:void 0;return r&&r.trim()!==""?V(r.trim()):V(n,G())}function V(n,e){return n.startsWith("~")?p(G(),n.replace(/^~[/\\]?/,"")):Y(n)?p(n):e?p(e,n):p(n)}function be(n,e,t){return new h(n,e,l,void 0,[`Invalid ${l} for context-mode ${n} directory: ${t}`,J()].join(`
2
- `))}function K(n){let e=process.env[l];if(e===void 0)return{kind:"unset"};let t=e.trim();if(!t)return{kind:"ignored-empty",ignoredEnvVar:l,ignoredReason:"empty"};if(!Y(t))throw be(n,t,`${l} must be an absolute path.`);return{kind:"override",root:p(t)}}function De(n){return n.kind==="ignored-empty"?{ignoredEnvVar:n.ignoredEnvVar,ignoredReason:n.ignoredReason}:{}}function z(n,e){let t=K(n);return t.kind!=="override"?null:{kind:n,path:g(t.root,e),envVar:l,source:"override"}}function Le(n,e,t){return{kind:n,path:p(e()),envVar:null,source:"default",...t}}function Q(n){let e=K("session");return e.kind==="override"?{kind:"session",path:g(e.root,q),envVar:l,source:"override"}:Le("session",n,De(e))}function Ye(n){let e=z("content",j);if(e)return e;let t=Q(n);return{kind:"content",path:g(Te(t.path),j),envVar:t.envVar,source:t.source,ignoredEnvVar:t.ignoredEnvVar,ignoredReason:t.ignoredReason}}function qe(n){let e=z("stats",q);if(e)return e;let t=Q(n);return{kind:"stats",path:t.path,envVar:t.envVar,source:t.source,ignoredEnvVar:t.ignoredEnvVar,ignoredReason:t.ignoredReason}}function Ke(n){return n.message}function ze(n){return n.source==="override"&&n.envVar?`via ${n.envVar}`:n.ignoredEnvVar&&n.ignoredReason==="empty"?`default; ignored empty ${n.ignoredEnvVar}`:"default"}function Qe(){b.clear()}function Je(n){let e=[n.kind,n.path,n.source,n.envVar??"",n.ignoredEnvVar??"",n.ignoredReason??""].join("\0"),t=b.get(e);if(t instanceof h)throw t;if(t===n.path)return t;try{return ve(n.path,{recursive:!0}),fe(n.path,he.W_OK),b.set(e,n.path),n.path}catch(r){let s=new h(n.kind,Ce(r)??n.path,l,r,void 0,{ignoredEnvVar:n.ignoredEnvVar,ignoredReason:n.ignoredReason});throw b.set(e,s),s}}function Ne(n,e,t={}){return[`context-mode ${n} directory is not writable: ${e}`,Oe(t),J()].filter(Boolean).join(`
3
- `)}function Oe(n){return n.ignoredEnvVar&&n.ignoredReason==="empty"?`Ignored empty ${n.ignoredEnvVar}; using adapter default.`:null}function J(){return`Set ${l} to a writable absolute path.`}function Ce(n){if(!n||typeof n!="object")return null;let e=n.path;return typeof e=="string"&&e.length>0?e:null}var m;function v(n){let e=n.replace(/\\/g,"/");return/^\/+$/.test(e)?"/":/^[A-Za-z]:\/+$/.test(e)?`${e.slice(0,2)}/`:e.replace(/\/+$/,"")}function W(n){let e=n;try{e=Se.native(n)}catch{}let t=v(e);return process.platform==="win32"||process.platform==="darwin"?t.toLowerCase():t}function Z(n,e){return _e("git",["-C",n,...e],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}function Ae(n){let e=Z(n,["rev-parse","--show-toplevel"]);return e.length>0?v(e):null}function we(n){let e=Z(n,["worktree","list","--porcelain"]).split(/\r?\n/).find(t=>t.startsWith("worktree "))?.replace("worktree ","")?.trim();return e?v(e):null}function xe(n=process.cwd()){let e=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(m&&m.projectDir===n&&m.envSuffix===e)return m.suffix;let t="";if(e!==void 0)t=e?`__${e}`:"";else try{let r=Ae(n),s=we(n);if(r&&s){let a=W(r),i=W(s);a!==i&&(t=`__${f("sha256").update(a).digest("hex").slice(0,8)}`)}}catch{}return m={projectDir:n,envSuffix:e,suffix:t},t}function Ze(){m=void 0}function ee(n){return f("sha256").update(v(n)).digest("hex").slice(0,16)}function te(n){let e=v(n),t=process.platform==="darwin"||process.platform==="win32"?e.toLowerCase():e;return f("sha256").update(t).digest("hex").slice(0,16)}function et(n){let{projectDir:e,contentDir:t}=n,r=te(e),s=g(t,`${r}.db`);if(D(s))return s;let a=ee(e);if(a===r)return s;let i=g(t,`${a}.db`);if(D(i))try{I(i,s);for(let c of["-wal","-shm"])try{I(i+c,s+c)}catch{}}catch{}return s}function tt(n){return Ie({...n,ext:".db"})}function Ie(n){let{projectDir:e,sessionsDir:t,ext:r}=n,s=n.suffix??xe(e),a=te(e),i=g(t,`${a}${s}${r}`);if(D(i))return i;let c=ee(e);if(c===a)return i;let d=g(t,`${c}${s}${r}`);if(D(d))try{I(d,i)}catch{}return i}var X=1e3,$=5;function R(n){let e=Number(n);return!Number.isFinite(e)||e<=0?0:Math.floor(e)}var o={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"},Ue=[["project_dir","TEXT NOT NULL DEFAULT ''"],["attribution_source","TEXT NOT NULL DEFAULT 'unknown'"],["attribution_confidence","REAL NOT NULL DEFAULT 0"],["bytes_avoided","INTEGER NOT NULL DEFAULT 0"],["bytes_returned","INTEGER NOT NULL DEFAULT 0"]];function ne(n){let e=n.pragma("table_xinfo(session_events)"),t=new Set(e.map(s=>s.name)),r=!1;for(let[s,a]of Ue)t.has(s)||(n.exec(`ALTER TABLE session_events ADD COLUMN ${s} ${a}`),r=!0);return r&&n.exec("CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(session_id, project_dir)"),r}function nt(n,e){let t=null;try{t=new e(n),ne(t)}catch{}finally{try{t?.close()}catch{}}}var H=class extends T{constructor(e){super(e?.dbPath??B("session"))}stmt(e){return this.stmts.get(e)}initSchema(){try{let t=this.db.pragma("table_xinfo(session_events)").find(r=>r.name==="data_hash");t&&t.hidden!==0&&this.db.exec("DROP TABLE session_events")}catch{}this.db.exec(`
1
+ import{createRequire as oe}from"node:module";import{existsSync as ie,unlinkSync as P,renameSync as ae}from"node:fs";import{tmpdir as ce}from"node:os";import{join as ue}from"node:path";var A=class{#e;constructor(e){this.#e=e}pragma(e){let r=this.#e.prepare(`PRAGMA ${e}`).all();if(!r||r.length===0)return;if(r.length>1)return r;let s=Object.values(r[0]);return s.length===1?s[0]:r[0]}exec(e){let t="",r=null;for(let a=0;a<e.length;a++){let i=e[a];if(r)t+=i,i===r&&(r=null);else if(i==="'"||i==='"')t+=i,r=i;else if(i===";"){let c=t.trim();c&&this.#e.prepare(c).run(),t=""}else t+=i}let s=t.trim();return s&&this.#e.prepare(s).run(),this}prepare(e){let t=this.#e.prepare(e);return{run:(...r)=>t.run(...r),get:(...r)=>{let s=t.get(...r);return s===null?void 0:s},all:(...r)=>t.all(...r),iterate:(...r)=>t.iterate(...r)}}transaction(e){return this.#e.transaction(e)}close(){this.#e.close()}},w=class{#e;constructor(e){this.#e=e}pragma(e){let r=this.#e.prepare(`PRAGMA ${e}`).all();if(!r||r.length===0)return;if(r.length>1)return r;let s=Object.values(r[0]);return s.length===1?s[0]:r[0]}exec(e){return this.#e.exec(e),this}prepare(e){let t=this.#e.prepare(e);return{run:(...r)=>t.run(...r),get:(...r)=>t.get(...r),all:(...r)=>t.all(...r),iterate:(...r)=>typeof t.iterate=="function"?t.iterate(...r):t.all(...r)[Symbol.iterator]()}}transaction(e){return(...t)=>{this.#e.exec("BEGIN");try{let r=e(...t);return this.#e.exec("COMMIT"),r}catch(r){throw this.#e.exec("ROLLBACK"),r}}}close(){this.#e.close()}},E=null;function de(n){let e=null;try{return e=new n(":memory:"),e.exec("CREATE VIRTUAL TABLE __fts5_probe USING fts5(x)"),!0}catch{return!1}finally{try{e?.close()}catch{}}}function le(n,e){let t=e!==void 0?e:globalThis.Bun;if(typeof t<"u"&&t!==null)return!0;let r=n??process.versions,[s,a]=(r.node??"0.0.0").split("."),i=Number(s),c=Number(a);return!Number.isFinite(i)||!Number.isFinite(c)?!1:i>22||i===22&&c>=5}function ge(){if(!E){let n=oe(import.meta.url);if(globalThis.Bun){let e=n(["bun","sqlite"].join(":")).Database;E=function(r,s){let a=new e(r,{readonly:s?.readonly,create:!0}),i=new A(a);return s?.timeout&&i.pragma(`busy_timeout = ${s.timeout}`),i}}else if(le()){let e=null;try{({DatabaseSync:e}=n(["node","sqlite"].join(":")))}catch{e=null}e&&de(e)?E=function(r,s){let a=new e(r,{readOnly:s?.readonly??!1}),i=new w(a);return s?.timeout&&i.pragma(`busy_timeout = ${s.timeout}`),i}:E=n("better-sqlite3")}else E=n("better-sqlite3")}return E}function k(n){n.pragma("journal_mode = WAL"),n.pragma("synchronous = NORMAL");try{n.pragma("mmap_size = 268435456")}catch{}}function F(n){if(!ie(n))for(let e of["-wal","-shm"])try{P(n+e)}catch{}}function Ee(n){for(let e of["","-wal","-shm"])try{P(n+e)}catch{}}function I(n){try{n.pragma("wal_checkpoint(TRUNCATE)")}catch{}try{n.close()}catch{}}function j(n="context-mode"){return ue(ce(),`${n}-${process.pid}.db`)}function me(n,e=[100,500,2e3]){let t;for(let r=0;r<=e.length;r++)try{return n()}catch(s){let a=s instanceof Error?s.message:String(s);if(!a.includes("SQLITE_BUSY")&&!a.includes("database is locked"))throw s;if(t=s instanceof Error?s:new Error(a),r<e.length){let i=e[r],c=Date.now();for(;Date.now()-c<i;);}}throw new Error(`SQLITE_BUSY: database is locked after ${e.length} retries. Original error: ${t?.message}`)}function pe(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 ye(n){let e=Date.now();for(let t of["","-wal","-shm"])try{ae(n+t,`${n}${t}.corrupt-${e}`)}catch{}}var _=Symbol.for("__context_mode_live_dbs_v3__"),C=(()=>{let n=globalThis;return n[_]||(n[_]=new Set,process.on("exit",()=>{for(let e of n[_])I(e);n[_].clear()})),n[_]})(),v=class{#e;#t;constructor(e){let t=ge();this.#e=e,F(e);let r;try{r=new t(e,{timeout:3e4}),k(r)}catch(s){let a=s instanceof Error?s.message:String(s);if(pe(a)){ye(e),F(e);try{r=new t(e,{timeout:3e4}),k(r)}catch(i){throw new Error(`Failed to create fresh DB after renaming corrupt file: ${i instanceof Error?i.message:String(i)}`)}}else throw s}this.#t=r,C.add(this.#t),this.initSchema(),this.prepareStatements()}get db(){return this.#t}get dbPath(){return this.#e}close(){C.delete(this.#t),I(this.#t)}withRetry(e){return me(e)}cleanup(){C.delete(this.#t),I(this.#t),Ee(this.#e)}};import{createHash as f}from"node:crypto";import{execFileSync as _e}from"node:child_process";import{accessSync as fe,constants as he,existsSync as D,mkdirSync as Te,realpathSync as Se,renameSync as x}from"node:fs";import{homedir as G}from"node:os";import{dirname as ve,isAbsolute as Y,join as g,resolve as p}from"node:path";var l="CONTEXT_MODE_DIR",q="sessions",B="content",h=class extends Error{kind;path;overrideEnvVar;ignoredEnvVar;ignoredReason;constructor(e,t,r=l,s,a,i={}){super(a??Ne(e,t,i),{cause:s}),this.name="StorageDirectoryError",this.kind=e,this.path=t,this.overrideEnvVar=r,this.ignoredEnvVar=i.ignoredEnvVar,this.ignoredReason=i.ignoredReason}},b=new Map;function Ge(n){let e=n.env??process.env,t=n.legacySessionDirEnv,r=t?e[t]?.trim():void 0;return r&&t?(n.onLegacySessionDir?.(t,r),r):g(Re(n.configDir,n.configDirEnv,e),"context-mode","sessions")}function Re(n,e,t){let r=e?t[e]:void 0;return r&&r.trim()!==""?V(r.trim()):V(n,G())}function V(n,e){return n.startsWith("~")?p(G(),n.replace(/^~[/\\]?/,"")):Y(n)?p(n):e?p(e,n):p(n)}function be(n,e,t){return new h(n,e,l,void 0,[`Invalid ${l} for context-mode ${n} directory: ${t}`,J()].join(`
2
+ `))}function K(n){let e=process.env[l];if(e===void 0)return{kind:"unset"};let t=e.trim();if(!t)return{kind:"ignored-empty",ignoredEnvVar:l,ignoredReason:"empty"};if(!Y(t))throw be(n,t,`${l} must be an absolute path.`);return{kind:"override",root:p(t)}}function De(n){return n.kind==="ignored-empty"?{ignoredEnvVar:n.ignoredEnvVar,ignoredReason:n.ignoredReason}:{}}function z(n,e){let t=K(n);return t.kind!=="override"?null:{kind:n,path:g(t.root,e),envVar:l,source:"override"}}function Le(n,e,t){return{kind:n,path:p(e()),envVar:null,source:"default",...t}}function Q(n){let e=K("session");return e.kind==="override"?{kind:"session",path:g(e.root,q),envVar:l,source:"override"}:Le("session",n,De(e))}function Ye(n){let e=z("content",B);if(e)return e;let t=Q(n);return{kind:"content",path:g(ve(t.path),B),envVar:t.envVar,source:t.source,ignoredEnvVar:t.ignoredEnvVar,ignoredReason:t.ignoredReason}}function qe(n){let e=z("stats",q);if(e)return e;let t=Q(n);return{kind:"stats",path:t.path,envVar:t.envVar,source:t.source,ignoredEnvVar:t.ignoredEnvVar,ignoredReason:t.ignoredReason}}function Ke(n){return n.message}function ze(n){return n.source==="override"&&n.envVar?`via ${n.envVar}`:n.ignoredEnvVar&&n.ignoredReason==="empty"?`default; ignored empty ${n.ignoredEnvVar}`:"default"}function Qe(){b.clear()}function Je(n){let e=[n.kind,n.path,n.source,n.envVar??"",n.ignoredEnvVar??"",n.ignoredReason??""].join("\0"),t=b.get(e);if(t instanceof h)throw t;if(t===n.path)return t;try{return Te(n.path,{recursive:!0}),fe(n.path,he.W_OK),b.set(e,n.path),n.path}catch(r){let s=new h(n.kind,Ce(r)??n.path,l,r,void 0,{ignoredEnvVar:n.ignoredEnvVar,ignoredReason:n.ignoredReason});throw b.set(e,s),s}}function Ne(n,e,t={}){return[`context-mode ${n} directory is not writable: ${e}`,Oe(t),J()].filter(Boolean).join(`
3
+ `)}function Oe(n){return n.ignoredEnvVar&&n.ignoredReason==="empty"?`Ignored empty ${n.ignoredEnvVar}; using adapter default.`:null}function J(){return`Set ${l} to a writable absolute path.`}function Ce(n){if(!n||typeof n!="object")return null;let e=n.path;return typeof e=="string"&&e.length>0?e:null}var m;function T(n){let e=n.replace(/\\/g,"/");return/^\/+$/.test(e)?"/":/^[A-Za-z]:\/+$/.test(e)?`${e.slice(0,2)}/`:e.replace(/\/+$/,"")}function W(n){let e=n;try{e=Se.native(n)}catch{}let t=T(e);return process.platform==="win32"||process.platform==="darwin"?t.toLowerCase():t}function Z(n,e){return _e("git",["-C",n,...e],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}function Ae(n){let e=Z(n,["rev-parse","--show-toplevel"]);return e.length>0?T(e):null}function we(n){let e=Z(n,["worktree","list","--porcelain"]).split(/\r?\n/).find(t=>t.startsWith("worktree "))?.replace("worktree ","")?.trim();return e?T(e):null}function Ie(n=process.cwd()){let e=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(m&&m.projectDir===n&&m.envSuffix===e)return m.suffix;let t="";if(e!==void 0)t=e?`__${e}`:"";else try{let r=Ae(n),s=we(n);if(r&&s){let a=W(r),i=W(s);a!==i&&(t=`__${f("sha256").update(a).digest("hex").slice(0,8)}`)}}catch{}return m={projectDir:n,envSuffix:e,suffix:t},t}function Ze(){m=void 0}function ee(n){return f("sha256").update(T(n)).digest("hex").slice(0,16)}function te(n){let e=T(n),t=process.platform==="darwin"||process.platform==="win32"?e.toLowerCase():e;return f("sha256").update(t).digest("hex").slice(0,16)}function et(n){let{projectDir:e,contentDir:t}=n,r=te(e),s=g(t,`${r}.db`);if(D(s))return s;let a=ee(e);if(a===r)return s;let i=g(t,`${a}.db`);if(D(i))try{x(i,s);for(let c of["-wal","-shm"])try{x(i+c,s+c)}catch{}}catch{}return s}function tt(n){return xe({...n,ext:".db"})}function xe(n){let{projectDir:e,sessionsDir:t,ext:r}=n,s=n.suffix??Ie(e),a=te(e),i=g(t,`${a}${s}${r}`);if(D(i))return i;let c=ee(e);if(c===a)return i;let d=g(t,`${c}${s}${r}`);if(D(d))try{x(d,i)}catch{}return i}var H=1e3,X=5;function R(n){let e=Number(n);return!Number.isFinite(e)||e<=0?0:Math.floor(e)}var o={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"},Ue=[["project_dir","TEXT NOT NULL DEFAULT ''"],["attribution_source","TEXT NOT NULL DEFAULT 'unknown'"],["attribution_confidence","REAL NOT NULL DEFAULT 0"],["bytes_avoided","INTEGER NOT NULL DEFAULT 0"],["bytes_returned","INTEGER NOT NULL DEFAULT 0"]];function ne(n){let e=n.pragma("table_xinfo(session_events)"),t=new Set(e.map(s=>s.name)),r=!1;for(let[s,a]of Ue)t.has(s)||(n.exec(`ALTER TABLE session_events ADD COLUMN ${s} ${a}`),r=!0);return r&&n.exec("CREATE INDEX IF NOT EXISTS idx_session_events_project ON session_events(session_id, project_dir)"),r}function nt(n,e){let t=null;try{t=new e(n),ne(t)}catch{}finally{try{t?.close()}catch{}}}var $=class extends v{constructor(e){super(e?.dbPath??j("session"))}stmt(e){return this.stmts.get(e)}initSchema(){try{let t=this.db.pragma("table_xinfo(session_events)").find(r=>r.name==="data_hash");t&&t.hidden!==0&&this.db.exec("DROP TABLE session_events")}catch{}this.db.exec(`
4
4
  CREATE TABLE IF NOT EXISTS session_events (
5
5
  id INTEGER PRIMARY KEY AUTOINCREMENT,
6
6
  session_id TEXT NOT NULL,
@@ -118,4 +118,6 @@ import{createRequire as oe}from"node:module";import{existsSync as ie,unlinkSync
118
118
  FROM tool_calls WHERE session_id = ?`),e(o.getToolCallByTool,`SELECT tool, calls, bytes_returned
119
119
  FROM tool_calls WHERE session_id = ? ORDER BY calls DESC`),e(o.getEventBytesSummary,`SELECT COALESCE(SUM(bytes_avoided), 0) AS bytes_avoided,
120
120
  COALESCE(SUM(bytes_returned), 0) AS bytes_returned
121
- FROM session_events WHERE session_id = ?`)}insertEvent(e,t,r="PostToolUse",s,a){let i=f("sha256").update(t.data).digest("hex").slice(0,16).toUpperCase(),c=String(s?.projectDir??t.project_dir??this._getSessionProjectDir(e)).trim(),d=String(s?.source??t.attribution_source??"unknown"),u=Number(s?.confidence??t.attribution_confidence??0),S=Number.isFinite(u)?Math.max(0,Math.min(1,u)):0,y=R(a?.bytesAvoided),L=R(a?.bytesReturned),N=this.db.transaction(()=>{if(this.stmt(o.checkDuplicate).get(e,$,t.type,i))return;this.stmt(o.getEventCount).get(e).cnt>=X&&this.stmt(o.evictLowestPriority).run(e),this.stmt(o.insertEvent).run(e,t.type,t.category,t.priority,t.data,c,d,S,y,L,r,i),this.stmt(o.updateMetaLastEvent).run(e)});this.withRetry(()=>N())}bulkInsertEvents(e,t,r="PostToolUse",s,a){if(!t||t.length===0)return;if(t.length===1){this.insertEvent(e,t[0],r,s?.[0],a?.[0]);return}let i=t.map((d,u)=>{let S=f("sha256").update(d.data).digest("hex").slice(0,16).toUpperCase(),y=s?.[u],L=String(y?.projectDir??d.project_dir??this._getSessionProjectDir(e)??"").trim(),N=String(y?.source??d.attribution_source??"unknown"),O=Number(y?.confidence??d.attribution_confidence??0),U=Number.isFinite(O)?Math.max(0,Math.min(1,O)):0,k=a?.[u],re=R(k?.bytesAvoided),se=R(k?.bytesReturned);return{event:d,dataHash:S,projectDir:L,attributionSource:N,attributionConfidence:U,bytesAvoided:re,bytesReturned:se}}),c=this.db.transaction(()=>{let d=this.stmt(o.getEventCount).get(e).cnt;for(let u of i)this.stmt(o.checkDuplicate).get(e,$,u.event.type,u.dataHash)||(d>=X?this.stmt(o.evictLowestPriority).run(e):d++,this.stmt(o.insertEvent).run(e,u.event.type,u.event.category,u.event.priority,u.event.data,u.projectDir,u.attributionSource,u.attributionConfidence,u.bytesAvoided,u.bytesReturned,r,u.dataHash));this.stmt(o.updateMetaLastEvent).run(e)});this.withRetry(()=>c())}getEvents(e,t){let r=t?.limit??1e3,s=t?.type,a=t?.minPriority;return s&&a!==void 0?this.stmt(o.getEventsByTypeAndPriority).all(e,s,a,r):s?this.stmt(o.getEventsByType).all(e,s,r):a!==void 0?this.stmt(o.getEventsByPriority).all(e,a,r):this.stmt(o.getEvents).all(e,r)}getEventCount(e){return this.stmt(o.getEventCount).get(e).cnt}getEventBytesSummary(e){let t=this.stmt(o.getEventBytesSummary).get(e);return{bytesAvoided:Number(t?.bytes_avoided??0),bytesReturned:Number(t?.bytes_returned??0)}}getLatestAttributedProjectDir(e){return this.stmt(o.getLatestAttributedProject).get(e)?.project_dir||null}_getSessionProjectDir(e){try{return this.db.prepare("SELECT project_dir FROM session_meta WHERE session_id = ?").get(e)?.project_dir||""}catch{return""}}searchEvents(e,t,r,s){try{let a=e.replace(/[%_]/g,c=>"\\"+c),i=s??null;return this.stmt(o.searchEvents).all(r,a,a,i,i,t)}catch{return[]}}ensureSession(e,t){this.stmt(o.ensureSession).run(e,t)}getSessionStats(e){return this.stmt(o.getSessionStats).get(e)??null}incrementCompactCount(e){this.stmt(o.incrementCompactCount).run(e)}upsertResume(e,t,r){this.stmt(o.upsertResume).run(e,t,r??0)}getResume(e){return this.stmt(o.getResume).get(e)??null}markResumeConsumed(e){this.stmt(o.markResumeConsumed).run(e)}claimLatestUnconsumedResume(e){let t=this.stmt(o.claimLatestUnconsumedResume).get(e);return t?{sessionId:t.session_id,snapshot:t.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(e,t,r=0){let s=Number.isFinite(r)&&r>0?Math.round(r):0;try{this.stmt(o.incrementToolCall).run(e,t,s)}catch{}}getToolCallStats(e){try{let t=this.stmt(o.getToolCallTotals).get(e),r=this.stmt(o.getToolCallByTool).all(e),s={};for(let a of r)s[a.tool]={calls:a.calls,bytesReturned:a.bytes_returned};return{totalCalls:t?.calls??0,totalBytesReturned:t?.bytes_returned??0,byTool:s}}catch{return{totalCalls:0,totalBytesReturned:0,byTool:{}}}}deleteSession(e){this.db.transaction(()=>{this.stmt(o.deleteEvents).run(e),this.stmt(o.deleteResume).run(e),this.stmt(o.deleteMeta).run(e)})()}cleanupOldSessions(e=7){let t=`-${e}`,r=this.stmt(o.getOldSessions).all(t);for(let{session_id:s}of r)this.deleteSession(s);return r.length}};export{H as SessionDB,h as StorageDirectoryError,Ze as _resetWorktreeSuffixCacheForTests,ne as applyMissingSessionEventsColumns,Qe as clearStorageDirectoryCheckCacheForTests,ze as describeStorageDirectorySource,nt as ensureSessionEventsSchema,Je as ensureWritableStorageDir,Ke as formatStorageDirectoryError,xe as getWorktreeSuffix,te as hashProjectDirCanonical,ee as hashProjectDirLegacy,v as normalizeWorktreePath,Ye as resolveContentStorageDir,et as resolveContentStorePath,Ge as resolveDefaultSessionDir,tt as resolveSessionDbPath,Ie as resolveSessionPath,Q as resolveSessionStorageDir,qe as resolveStatsStorageDir};
121
+ FROM session_events WHERE session_id = ?`)}insertEvent(e,t,r="PostToolUse",s,a){let i=f("sha256").update(t.data).digest("hex").slice(0,16).toUpperCase(),c=String(s?.projectDir??t.project_dir??this._getSessionProjectDir(e)).trim(),d=String(s?.source??t.attribution_source??"unknown"),u=Number(s?.confidence??t.attribution_confidence??0),S=Number.isFinite(u)?Math.max(0,Math.min(1,u)):0,y=R(a?.bytesAvoided),L=R(a?.bytesReturned),N=this.db.transaction(()=>{if(this.stmt(o.checkDuplicate).get(e,X,t.type,i))return;this.stmt(o.getEventCount).get(e).cnt>=H&&this.stmt(o.evictLowestPriority).run(e),this.stmt(o.insertEvent).run(e,t.type,t.category,t.priority,t.data,c,d,S,y,L,r,i),this.stmt(o.updateMetaLastEvent).run(e)});this.withRetry(()=>N())}bulkInsertEvents(e,t,r="PostToolUse",s,a){if(!t||t.length===0)return;if(t.length===1){this.insertEvent(e,t[0],r,s?.[0],a?.[0]);return}let i=t.map((d,u)=>{let S=f("sha256").update(d.data).digest("hex").slice(0,16).toUpperCase(),y=s?.[u],L=String(y?.projectDir??d.project_dir??this._getSessionProjectDir(e)??"").trim(),N=String(y?.source??d.attribution_source??"unknown"),O=Number(y?.confidence??d.attribution_confidence??0),U=Number.isFinite(O)?Math.max(0,Math.min(1,O)):0,M=a?.[u],re=R(M?.bytesAvoided),se=R(M?.bytesReturned);return{event:d,dataHash:S,projectDir:L,attributionSource:N,attributionConfidence:U,bytesAvoided:re,bytesReturned:se}}),c=this.db.transaction(()=>{let d=this.stmt(o.getEventCount).get(e).cnt;for(let u of i)this.stmt(o.checkDuplicate).get(e,X,u.event.type,u.dataHash)||(d>=H?this.stmt(o.evictLowestPriority).run(e):d++,this.stmt(o.insertEvent).run(e,u.event.type,u.event.category,u.event.priority,u.event.data,u.projectDir,u.attributionSource,u.attributionConfidence,u.bytesAvoided,u.bytesReturned,r,u.dataHash));this.stmt(o.updateMetaLastEvent).run(e)});this.withRetry(()=>c())}getEvents(e,t){let r=t?.limit??1e3,s=t?.type,a=t?.minPriority;return s&&a!==void 0?this.stmt(o.getEventsByTypeAndPriority).all(e,s,a,r):s?this.stmt(o.getEventsByType).all(e,s,r):a!==void 0?this.stmt(o.getEventsByPriority).all(e,a,r):this.stmt(o.getEvents).all(e,r)}getEventCount(e){return this.stmt(o.getEventCount).get(e).cnt}getEventBytesSummary(e){let t=this.stmt(o.getEventBytesSummary).get(e);return{bytesAvoided:Number(t?.bytes_avoided??0),bytesReturned:Number(t?.bytes_returned??0)}}getLatestAttributedProjectDir(e){return this.stmt(o.getLatestAttributedProject).get(e)?.project_dir||null}_getSessionProjectDir(e){try{return this.db.prepare("SELECT project_dir FROM session_meta WHERE session_id = ?").get(e)?.project_dir||""}catch{return""}}searchEvents(e,t,r,s){try{let a=e.replace(/[%_]/g,c=>"\\"+c),i=s??null;return this.stmt(o.searchEvents).all(r,a,a,i,i,t)}catch{return[]}}getSessionIdsForProject(e){try{return this.db.prepare(`SELECT DISTINCT session_id
122
+ FROM session_events
123
+ WHERE project_dir = ?`).all(e).map(r=>r.session_id)}catch{return[]}}ensureSession(e,t){this.stmt(o.ensureSession).run(e,t)}getSessionStats(e){return this.stmt(o.getSessionStats).get(e)??null}incrementCompactCount(e){this.stmt(o.incrementCompactCount).run(e)}upsertResume(e,t,r){this.stmt(o.upsertResume).run(e,t,r??0)}getResume(e){return this.stmt(o.getResume).get(e)??null}markResumeConsumed(e){this.stmt(o.markResumeConsumed).run(e)}claimLatestUnconsumedResume(e){let t=this.stmt(o.claimLatestUnconsumedResume).get(e);return t?{sessionId:t.session_id,snapshot:t.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(e,t,r=0){let s=Number.isFinite(r)&&r>0?Math.round(r):0;try{this.stmt(o.incrementToolCall).run(e,t,s)}catch{}}getToolCallStats(e){try{let t=this.stmt(o.getToolCallTotals).get(e),r=this.stmt(o.getToolCallByTool).all(e),s={};for(let a of r)s[a.tool]={calls:a.calls,bytesReturned:a.bytes_returned};return{totalCalls:t?.calls??0,totalBytesReturned:t?.bytes_returned??0,byTool:s}}catch{return{totalCalls:0,totalBytesReturned:0,byTool:{}}}}deleteSession(e){this.db.transaction(()=>{this.stmt(o.deleteEvents).run(e),this.stmt(o.deleteResume).run(e),this.stmt(o.deleteMeta).run(e)})()}cleanupOldSessions(e=7){let t=`-${e}`,r=this.stmt(o.getOldSessions).all(t);for(let{session_id:s}of r)this.deleteSession(s);return r.length}pruneOrphanedEvents(){let e=this.db.prepare("DELETE FROM session_events WHERE session_id NOT IN (SELECT session_id FROM session_meta)").run();return Number(e.changes??0)}};export{$ as SessionDB,h as StorageDirectoryError,Ze as _resetWorktreeSuffixCacheForTests,ne as applyMissingSessionEventsColumns,Qe as clearStorageDirectoryCheckCacheForTests,ze as describeStorageDirectorySource,nt as ensureSessionEventsSchema,Je as ensureWritableStorageDir,Ke as formatStorageDirectoryError,Ie as getWorktreeSuffix,te as hashProjectDirCanonical,ee as hashProjectDirLegacy,T as normalizeWorktreePath,Ye as resolveContentStorageDir,et as resolveContentStorePath,Ge as resolveDefaultSessionDir,tt as resolveSessionDbPath,xe as resolveSessionPath,Q as resolveSessionStorageDir,qe as resolveStatsStorageDir};
@@ -1,2 +1,2 @@
1
- function i(t){return t==null?"":String(t)}function E(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function d(t){let e=String(t.tool_response??""),n=String(t.tool_input?.command??"");if(e.startsWith("context-mode:")||n.startsWith('echo "context-mode:')||n.startsWith("echo 'context-mode:"))return!1;let r=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)||r}function k(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 n=new Set;return e.filter(r=>{if(!r.path)return!1;let o=`${r.type}:${r.path}`;return n.has(o)?!1:(n.add(o),!0)})}function S(t){return/(?:^|[/\\])\.claude[/\\]plans[/\\]/.test(t)}function A(t){let{tool_name:e,tool_input:n,tool_response:r}=t,o=[];if(e==="Read"){let s=String(n.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(s)||/\/copilot-instructions\.md$/i.test(s)||/\/context-mode\.mdc$/i.test(s)||/\.claude[\\/]/i.test(s)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(s))&&(o.push({type:"rule",category:"rule",data:i(s),priority:1}),r&&r.length>0&&o.push({type:"rule_content",category:"rule",data:i(r),priority:1})),o.push({type:"file_read",category:"file",data:i(s),priority:1}),o}if(e==="Edit"){let s=String(n.file_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="NotebookEdit"){let s=String(n.notebook_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="Write"){let s=String(n.file_path??"");return o.push({type:"file_write",category:"file",data:i(s),priority:1}),o}if(e==="apply_patch"){if(d(t))return[];let s=k(String(n.command??n.patch??""));for(let a of s)o.push({type:a.type,category:"file",data:i(a.path),priority:1});return o}if(e==="Glob"){let s=String(n.pattern??"");return o.push({type:"file_glob",category:"file",data:i(s),priority:3}),o}if(e==="Grep"){let s=String(n.pattern??""),a=String(n.path??"");return o.push({type:"file_search",category:"file",data:i(`${s} in ${a}`),priority:3}),o}return o}function R(t){if(t.tool_name!=="Bash")return[];let n=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!n)return[];let r=n[2]??n[3]??n[4]??"";return[{type:"cwd",category:"cwd",data:i(r),priority:2}]}function x(t){let{tool_response:e}=t,n=String(e??"");return d(t)?[{type:"error_tool",category:"error",data:i(n),priority:2}]:[]}var T=[{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 w(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),n=T.find(r=>r.pattern.test(e));return n?[{type:"git",category:"git",data:i(n.operation),priority:2}]:[]}function I(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 N(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,r=Array.isArray(n)&&n.length>0?`exited plan mode (allowed: ${E(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:i(r),priority:2});let o=String(t.tool_response??"").toLowerCase();return o.includes("approved")||o.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(o.includes("rejected")||o.includes("decline")||o.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(S(e))return[{type:"plan_file_write",category:"plan",data:i(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return t.tool_name==="apply_patch"?d(t)?[]:k(String(t.tool_input.command??t.tool_input.patch??"")).filter(n=>S(n.path)).map(n=>({type:"plan_file_write",category:"plan",data:i(`plan file: ${n.path.split(/[/\\]/).pop()??n.path}`),priority:2})):[]}var C=[/\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 H(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!C.some(o=>o.test(e)))return[];let r=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:i(r),priority:2}]}function L(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 $(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),n=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let r of n){let o=e.match(r);if(o){let s=e.toLowerCase().indexOf(o[0].toLowerCase()),a=e.slice(Math.max(0,s-50),Math.min(e.length,s+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:i(a),priority:2}]}}return[]}function O(t){if(t.tool_name!=="Agent")return[];let e=i(String(t.tool_input.prompt??t.tool_input.description??"")),n=t.tool_response?i(String(t.tool_response)):"",r=n.length>0;return[{type:r?"subagent_completed":"subagent_launched",category:"subagent",data:i(r?`[completed] ${e} \u2192 ${n}`:`[launched] ${e}`),priority:r?2:3}]}function P(t){let{tool_name:e,tool_input:n,tool_response:r}=t;if(!e.startsWith("mcp__"))return[];let o=e.split("__"),s=o[o.length-1]||e,a=Object.values(n).find(g=>typeof g=="string"),u=a?`: ${i(String(a))}`:"",c=r&&r.length>0?`
2
- response: ${i(r)}`:"";return[{type:"mcp",category:"mcp",data:i(`${s}${u}${c}`),priority:3}]}var M=2048;function B(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let n=Buffer.from(t,"utf8"),r=e;for(;r>0&&(n[r]&192)===128;)r--;return{value:n.subarray(0,r).toString("utf8"),truncated:!0}}var W=/(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,j="[REDACTED]";function y(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let n;if(Array.isArray(t))n=t.map(r=>y(r,e));else{let r={};for(let[o,s]of Object.entries(t))W.test(o)?r[o]=j:r[o]=y(s,e);n=r}return e.delete(t),n}function F(t){let{tool_name:e,tool_input:n}=t;if(!e.startsWith("mcp__"))return[];let r=y(n??{}),o;try{o=JSON.stringify(r)}catch{o="{}"}let{value:s,truncated:a}=B(o,M),u=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(s)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${s}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:i(u),priority:4}]}function D(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,n=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",r=String(t.tool_response??""),o="";try{let c=JSON.parse(r)?.answers;if(c&&typeof c=="object"){let g=f=>typeof f=="string"?f:Array.isArray(f)?f.filter(h=>typeof h=="string").join(" | "):"",m=n?g(c[n]):"";m?o=m:o=Object.values(c).map(g).filter(h=>h.length>0).join(" | ")}}catch{}let s=i(o),a=n?`Q: ${i(n)} \u2192 A: ${s}`:`answer: ${s}`;return[{type:"decision_question",category:"decision",data:i(a),priority:2}]}function U(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 K(t){let e=[E(t.tool_input),i(t.tool_response)].join(" ");if(e.length===0)return[];let n=new Set,r=e.match(/https?:\/\/[^\s)]+/g);if(r)for(let c of r)c=c.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(c)||n.add(c);let o=e.match(/(?<!\w)#(\d+)/g);if(o)for(let c of o)n.add(c);if(n.size===0)return[];let s,a=i(t.tool_response).match(/Fetched and indexed[^\(]*\(([\d.]+)\s*KB\)/i);if(a){let c=Number(a[1]);Number.isFinite(c)&&c>0&&(s=Math.round(c*1024))}let u={type:"external_ref",category:"external-ref",data:i(Array.from(n).join(", ")),priority:3};return s!==void 0&&(u.bytes_avoided=s),[u]}function G(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 v=/[,;,;、،]/u,J=15,q=500;function z(t){if(_.test(t)||!b.test(t)||!v.test(t))return!1;let e=[...t].length;return e>=J&&e<=q}function Q(t){let e=t.trim();return z(e)?[{type:"decision",category:"decision",data:i(t),priority:2}]:[]}var V=8,X=120,Y=new RegExp("\\p{L}+\\s+\\p{L}+","u"),Z=new RegExp("\\p{L}{6,}","u");function tt(t){let e=t.split(/[.!\n。!]/u)[0].trim();if(_.test(e)||v.test(e)||!b.test(e))return!1;let n=[...e].length;return n<V||n>X?!1:Y.test(e)||Z.test(e)}function et(t){let e=t.trim();return tt(e)?[{type:"role",category:"role",data:i(t),priority:3}]:[]}var _=/[??؟¿]/u,b=new RegExp("\\p{L}","u"),nt=60;function rt(t){if(_.test(t)||!b.test(t))return!1;let e=[...t].length;return e>0&&e<nt}function ot(t){let e=t.trim();if(!e)return[];let n;return _.test(e)?n="investigate":rt(e)&&(n="implement"),n?[{type:"intent",category:"intent",data:i(n),priority:4}]:[]}var st=/(?:\bError\s*:|\bException\s*:|\bTraceback\b|\bat\s+\S+\s*\([^)]*:\d+:\d+\))/u,it=/[✓✔✅☑🎉]/u,at=/^\s*(?:fixed|resolved)\s*:/iu;function ct(t){let e=[];return it.test(t)||at.test(t)?(e.push({type:"blocker_resolved",category:"blocked-on",data:i(t),priority:2}),e):(st.test(t)&&e.push({type:"blocker",category:"blocked-on",data:i(t),priority:2}),e)}function lt(t){return t.length<=1024?[]:[{type:"data",category:"data",data:i(t),priority:4}]}var l=null;function pt(t){let{tool_name:e,tool_response:n}=t,r=String(n??"");if(d(t))return l={tool:e,error:r.slice(0,200),callsSince:0},[];if(!l)return[];if(l.callsSince++,l.callsSince>10)return l=null,[];if(!!d(t))return[];let s=e===l.tool,a=l.tool==="Read"&&(e==="Edit"||e==="Write"||e==="apply_patch");if(s||a){let u={type:"error_resolved",category:"error-resolution",data:i(`Error in ${l.tool}: ${l.error} \u2192 Fixed`),priority:2};return l=null,[u]}return[]}function _t(){l=null}var p=[];function ut(t){return`${t.length}:${t.slice(0,20)}`}function ft(t){let{tool_name:e,tool_input:n}=t,r=ut(JSON.stringify(n).slice(0,200));if(p.push({tool:e,inputHash:r}),p.length>50&&p.splice(0,p.length-50),p.length<3)return[];let o=0;for(let s=p.length-1;s>=0&&(p[s].tool===e&&p[s].inputHash===r);s--)o++;return o>=3?(p.splice(p.length-o),[{type:"retry_detected",category:"iteration-loop",data:i(`${e} called ${o} times with similar input`),priority:2}]):[]}function ht(){p.length=0}var dt={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 gt(t){let e=dt[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function yt(t){try{let e=gt(t),n=[];return n.push(...A(e)),n.push(...R(e)),n.push(...x(e)),n.push(...w(e)),n.push(...H(e)),n.push(...I(e)),n.push(...N(e)),n.push(...L(e)),n.push(...O(e)),n.push(...P(e)),n.push(...F(e)),n.push(...D(e)),n.push(...$(e)),n.push(...G(e)),n.push(...U(e)),n.push(...K(e)),n.push(...pt(e)),n.push(...ft(e)),n}catch{return[]}}function bt(t){try{let e=[];return e.push(...Q(t)),e.push(...et(t)),e.push(...ot(t)),e.push(...ct(t)),e.push(...lt(t)),e}catch{return[]}}export{yt as extractEvents,bt as extractUserEvents,_t as resetErrorResolutionState,ht as resetIterationLoopState};
1
+ function i(t){return t==null?"":String(t)}function E(t){return t==null?"":typeof t=="string"?t:JSON.stringify(t)}function d(t){let e=String(t.tool_response??""),n=String(t.tool_input?.command??"");if(e.startsWith("context-mode:")||n.startsWith('echo "context-mode:')||n.startsWith("echo 'context-mode:"))return!1;let r=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)||r}function k(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 n=new Set;return e.filter(r=>{if(!r.path)return!1;let o=`${r.type}:${r.path}`;return n.has(o)?!1:(n.add(o),!0)})}function S(t){return/(?:^|[/\\])\.claude[/\\]plans[/\\]/.test(t)}function A(t){let{tool_name:e,tool_input:n,tool_response:r}=t,o=[];if(e==="Read"){let s=String(n.file_path??"");return(/(?:CLAUDE|AGENTS(?:\.override)?|GEMINI|QWEN|KIRO)\.md$/i.test(s)||/\/copilot-instructions\.md$/i.test(s)||/\/context-mode\.mdc$/i.test(s)||/\.claude[\\/]/i.test(s)||/[\\/]memor(?:y|ies)[\\/][^\\/]+\.md$/i.test(s))&&(o.push({type:"rule",category:"rule",data:i(s),priority:1}),r&&r.length>0&&o.push({type:"rule_content",category:"rule",data:i(r),priority:1})),o.push({type:"file_read",category:"file",data:i(s),priority:1}),o}if(e==="Edit"){let s=String(n.file_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="NotebookEdit"){let s=String(n.notebook_path??"");return o.push({type:"file_edit",category:"file",data:i(s),priority:1}),o}if(e==="Write"){let s=String(n.file_path??"");return o.push({type:"file_write",category:"file",data:i(s),priority:1}),o}if(e==="apply_patch"){if(d(t))return[];let s=k(String(n.command??n.patch??""));for(let a of s)o.push({type:a.type,category:"file",data:i(a.path),priority:1});return o}if(e==="Glob"){let s=String(n.pattern??"");return o.push({type:"file_glob",category:"file",data:i(s),priority:3}),o}if(e==="Grep"){let s=String(n.pattern??""),a=String(n.path??"");return o.push({type:"file_search",category:"file",data:i(`${s} in ${a}`),priority:3}),o}return o}function R(t){if(t.tool_name!=="Bash")return[];let n=String(t.tool_input.command??"").match(/\bcd\s+("([^"]+)"|'([^']+)'|(\S+))/);if(!n)return[];let r=n[2]??n[3]??n[4]??"";return[{type:"cwd",category:"cwd",data:i(r),priority:2}]}function T(t){let{tool_response:e}=t,n=String(e??"");return d(t)?[{type:"error_tool",category:"error",data:i(n),priority:2}]:[]}var x=[{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 w(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??""),n=x.find(r=>r.pattern.test(e));return n?[{type:"git",category:"git",data:i(n.operation),priority:2}]:[]}function I(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 N(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,r=Array.isArray(n)&&n.length>0?`exited plan mode (allowed: ${E(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:i(r),priority:2});let o=String(t.tool_response??"").toLowerCase();return o.includes("approved")||o.includes("approve")?e.push({type:"plan_approved",category:"plan",data:"plan approved by user",priority:1}):(o.includes("rejected")||o.includes("decline")||o.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(S(e))return[{type:"plan_file_write",category:"plan",data:i(`plan file: ${e.split(/[/\\]/).pop()??e}`),priority:2}]}return t.tool_name==="apply_patch"?d(t)?[]:k(String(t.tool_input.command??t.tool_input.patch??"")).filter(n=>S(n.path)).map(n=>({type:"plan_file_write",category:"plan",data:i(`plan file: ${n.path.split(/[/\\]/).pop()??n.path}`),priority:2})):[]}var C=[/\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 L(t){if(t.tool_name!=="Bash")return[];let e=String(t.tool_input.command??"");if(!C.some(o=>o.test(e)))return[];let r=e.replace(/\bexport\s+(\w+)=\S*/g,"export $1=***");return[{type:"env",category:"env",data:i(r),priority:2}]}function $(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 H(t){if(!t.tool_response?.includes("Error")&&!t.tool_output?.isError)return[];let e=String(t.tool_response||""),n=[/not supported/i,/cannot/i,/does not support/i,/FAIL/i,/refused/i,/permission denied/i,/incompatible/i];for(let r of n){let o=e.match(r);if(o){let s=e.toLowerCase().indexOf(o[0].toLowerCase()),a=e.slice(Math.max(0,s-50),Math.min(e.length,s+200)).trim();return[{type:"constraint_discovered",category:"constraint",data:i(a),priority:2}]}}return[]}function O(t){if(t.tool_name!=="Agent")return[];let e=i(String(t.tool_input.prompt??t.tool_input.description??"")),n=t.tool_response?i(String(t.tool_response)):"",r=n.length>0;return[{type:r?"subagent_completed":"subagent_launched",category:"subagent",data:i(r?`[completed] ${e} \u2192 ${n}`:`[launched] ${e}`),priority:r?2:3}]}function P(t){let{tool_name:e,tool_input:n,tool_response:r}=t;if(!e.startsWith("mcp__"))return[];let o=e.split("__"),s=o[o.length-1]||e,a=Object.values(n).find(g=>typeof g=="string"),u=a?`: ${i(String(a))}`:"",c=r&&r.length>0?`
2
+ response: ${i(r)}`:"";return[{type:"mcp",category:"mcp",data:i(`${s}${u}${c}`),priority:3}]}var M=2048;function B(t,e){if(Buffer.byteLength(t,"utf8")<=e)return{value:t,truncated:!1};let n=Buffer.from(t,"utf8"),r=e;for(;r>0&&(n[r]&192)===128;)r--;return{value:n.subarray(0,r).toString("utf8"),truncated:!0}}var W=/(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,j="[REDACTED]";function y(t,e=new WeakSet){if(t==null||typeof t!="object")return t;if(e.has(t))return"[CIRCULAR]";e.add(t);let n;if(Array.isArray(t))n=t.map(r=>y(r,e));else{let r={};for(let[o,s]of Object.entries(t))W.test(o)?r[o]=j:r[o]=y(s,e);n=r}return e.delete(t),n}function D(t){let{tool_name:e,tool_input:n}=t;if(!e.startsWith("mcp__"))return[];let r=y(n??{}),o;try{o=JSON.stringify(r)}catch{o="{}"}let{value:s,truncated:a}=B(o,M),u=a?`{"tool_name":${JSON.stringify(e)},"params_raw":${JSON.stringify(s)},"truncated":true}`:`{"tool_name":${JSON.stringify(e)},"params":${s}}`;return[{type:"mcp_tool_call",category:"mcp_tool_call",data:i(u),priority:4}]}function F(t){if(t.tool_name!=="AskUserQuestion")return[];let e=t.tool_input.questions,n=Array.isArray(e)&&e.length>0?String(e[0].question??""):"",r=String(t.tool_response??""),o="";try{let c=JSON.parse(r)?.answers;if(c&&typeof c=="object"){let g=f=>typeof f=="string"?f:Array.isArray(f)?f.filter(h=>typeof h=="string").join(" | "):"",m=n?g(c[n]):"";m?o=m:o=Object.values(c).map(g).filter(h=>h.length>0).join(" | ")}}catch{}let s=i(o),a=n?`Q: ${i(n)} \u2192 A: ${s}`:`answer: ${s}`;return[{type:"decision_question",category:"decision",data:i(a),priority:2}]}function U(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 G(t){let e=[E(t.tool_input),i(t.tool_response)].join(" ");if(e.length===0)return[];let n=new Set,r=e.match(/https?:\/\/[^\s)]+/g);if(r)for(let c of r)c=c.replace(/["'})\],;.]+$/,""),/localhost|127\.0\.0\.1/i.test(c)||n.add(c);let o=e.match(/(?<!\w)#(\d+)/g);if(o)for(let c of o)n.add(c);if(n.size===0)return[];let s,a=i(t.tool_response).match(/Fetched and indexed[^\(]*\(([\d.]+)\s*KB\)/i);if(a){let c=Number(a[1]);Number.isFinite(c)&&c>0&&(s=Math.round(c*1024))}let u={type:"external_ref",category:"external-ref",data:i(Array.from(n).join(", ")),priority:3};return s!==void 0&&(u.bytes_avoided=s),[u]}function K(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 v=/[,;,;、،]/u,J=15,q=500;function z(t){if(_.test(t)||!b.test(t)||!v.test(t))return!1;let e=[...t].length;return e>=J&&e<=q}function Q(t){let e=t.trim();return z(e)?[{type:"decision",category:"decision",data:i(t),priority:2}]:[]}var V=8,X=120,Y=new RegExp("\\p{L}+\\s+\\p{L}+","u"),Z=new RegExp("\\p{L}{6,}","u");function tt(t){let e=t.split(/[.!\n。!]/u)[0].trim();if(_.test(e)||v.test(e)||!b.test(e))return!1;let n=[...e].length;return n<V||n>X?!1:Y.test(e)||Z.test(e)}function et(t){let e=t.trim();return tt(e)?[{type:"role",category:"role",data:i(t),priority:3}]:[]}var _=/[??؟¿]/u,b=new RegExp("\\p{L}","u"),nt=60;function rt(t){if(_.test(t)||!b.test(t))return!1;let e=[...t].length;return e>0&&e<nt}function ot(t){let e=t.trim();if(!e)return[];let n;return _.test(e)?n="investigate":rt(e)&&(n="implement"),n?[{type:"intent",category:"intent",data:i(n),priority:4}]:[]}var st=/^(?:\/goal\s+|(?:goal|objective)\s*:\s*)(.+)$/is;function it(t){let e=t.trim();if(!e)return[];let n=e.match(st);if(!n)return[];let r=n[1].trim();return r?[{type:"goal",category:"goal",data:i(r),priority:4}]:[]}var at=/(?:\bError\s*:|\bException\s*:|\bTraceback\b|\bat\s+\S+\s*\([^)]*:\d+:\d+\))/u,ct=/[✓✔✅☑🎉]/u,lt=/^\s*(?:fixed|resolved)\s*:/iu;function pt(t){let e=[];return ct.test(t)||lt.test(t)?(e.push({type:"blocker_resolved",category:"blocked-on",data:i(t),priority:2}),e):(at.test(t)&&e.push({type:"blocker",category:"blocked-on",data:i(t),priority:2}),e)}function ut(t){return t.length<=1024?[]:[{type:"data",category:"data",data:i(t),priority:4}]}var l=null;function ft(t){let{tool_name:e,tool_response:n}=t,r=String(n??"");if(d(t))return l={tool:e,error:r.slice(0,200),callsSince:0},[];if(!l)return[];if(l.callsSince++,l.callsSince>10)return l=null,[];if(!!d(t))return[];let s=e===l.tool,a=l.tool==="Read"&&(e==="Edit"||e==="Write"||e==="apply_patch");if(s||a){let u={type:"error_resolved",category:"error-resolution",data:i(`Error in ${l.tool}: ${l.error} \u2192 Fixed`),priority:2};return l=null,[u]}return[]}function yt(){l=null}var p=[];function dt(t){return`${t.length}:${t.slice(0,20)}`}function gt(t){let{tool_name:e,tool_input:n}=t,r=dt(JSON.stringify(n).slice(0,200));if(p.push({tool:e,inputHash:r}),p.length>50&&p.splice(0,p.length-50),p.length<3)return[];let o=0;for(let s=p.length-1;s>=0&&(p[s].tool===e&&p[s].inputHash===r);s--)o++;return o>=3?(p.splice(p.length-o),[{type:"retry_detected",category:"iteration-loop",data:i(`${e} called ${o} times with similar input`),priority:2}]):[]}function bt(){p.length=0}var _t={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 ht(t){let e=_t[t.tool_name];return!e||e===t.tool_name?t:{...t,tool_name:e}}function mt(t){try{let e=ht(t),n=[];return n.push(...A(e)),n.push(...R(e)),n.push(...T(e)),n.push(...w(e)),n.push(...L(e)),n.push(...I(e)),n.push(...N(e)),n.push(...$(e)),n.push(...O(e)),n.push(...P(e)),n.push(...D(e)),n.push(...F(e)),n.push(...H(e)),n.push(...K(e)),n.push(...U(e)),n.push(...G(e)),n.push(...ft(e)),n.push(...gt(e)),n}catch{return[]}}function St(t){try{let e=[];return e.push(...Q(t)),e.push(...et(t)),e.push(...ot(t)),e.push(...it(t)),e.push(...pt(t)),e.push(...ut(t)),e}catch{return[]}}export{mt as extractEvents,St as extractUserEvents,yt as resetErrorResolutionState,bt as resetIterationLoopState};
@@ -175,6 +175,25 @@ export const KIRO_OPTS = {
175
175
  sessionIdEnv: undefined, // No session ID env var — uses ppid fallback
176
176
  };
177
177
 
178
+ /** Kimi Code CLI platform options.
179
+ *
180
+ * `KIMI_CODE_HOME` is documented at
181
+ * refs/platforms/kimi-code/docs/zh/configuration/env-vars.md:11-21
182
+ * refs/platforms/kimi-code/docs/en/configuration/env-vars.md:9-21
183
+ * and is read by MoonshotAI's own first-party plugins
184
+ * refs/platforms/kimi-code/plugins/official/kimi-datasource/bin/
185
+ * kimi-datasource.mjs:207-210
186
+ * so context-mode must honour it too — otherwise relocated Kimi installs
187
+ * keep the user's data root at `$KIMI_CODE_HOME` while context-mode keeps
188
+ * its session DB stranded at `~/.kimi-code/context-mode/sessions/`.
189
+ */
190
+ export const KIMI_OPTS = {
191
+ configDir: ".kimi-code",
192
+ configDirEnv: "KIMI_CODE_HOME",
193
+ projectDirEnv: undefined, // Kimi Code passes cwd in hook stdin, no env var
194
+ sessionIdEnv: undefined, // Uses session_id from hook stdin or ppid fallback
195
+ };
196
+
178
197
  /** JetBrains Copilot platform options. */
179
198
  export const JETBRAINS_OPTS = {
180
199
  configDir: ".config/JetBrains",
@@ -212,15 +231,86 @@ export function parseStdin(raw) {
212
231
 
213
232
  /**
214
233
  * Read all of stdin as a string (event-based, cross-platform safe).
234
+ *
235
+ * Idle-timeout semantics (override via env `CONTEXT_MODE_HOOK_STDIN_IDLE_MS`,
236
+ * default 1500 ms):
237
+ * - EOF before any data \u2192 resolve("") \u2014 the original well-behaved path.
238
+ * - EOF after data \u2192 resolve(buffer) with BOM strip (#139 \u2014 Cursor on
239
+ * Windows can emit a leading U+FEFF that crashes
240
+ * downstream JSON.parse).
241
+ * - Idle with 0 bytes \u2192 resolve("") \u2014 covers hosts that hold the pipe open
242
+ * without ever closing it (issue #639 \u2014 Bun re-exec
243
+ * EOF path) so the hook still terminates.
244
+ * - Idle with > 0 bytes \u2192 reject(Error) \u2014 partial data after a stall MUST NOT
245
+ * be silently truncated, otherwise downstream
246
+ * JSON.parse corrupts on large `tool_response`
247
+ * payloads (issue #242 \u2014 Gemini AfterTool >1MB).
248
+ * Visible non-zero exit is correct here; the host
249
+ * surfaces the failure in its hook diagnostics.
215
250
  */
216
251
  export function readStdin() {
217
252
  return new Promise((resolve, reject) => {
218
253
  let data = "";
254
+ const idleMs = Number(process.env.CONTEXT_MODE_HOOK_STDIN_IDLE_MS || 1500);
255
+ let done = false;
256
+ let timer;
257
+
258
+ const cleanup = () => {
259
+ clearTimeout(timer);
260
+ process.stdin.removeListener("data", onData);
261
+ process.stdin.removeListener("end", onEnd);
262
+ process.stdin.removeListener("error", onError);
263
+ try { process.stdin.pause(); } catch {}
264
+ try { process.stdin.destroy?.(); } catch {}
265
+ };
266
+ const resolveBuffer = () => {
267
+ if (done) return;
268
+ done = true;
269
+ cleanup();
270
+ // Preserves #139 BOM strip \u2014 applies on both EOF and idle-empty paths.
271
+ resolve(data.replace(/^\uFEFF/, ""));
272
+ };
273
+ const rejectIdle = () => {
274
+ if (done) return;
275
+ done = true;
276
+ cleanup();
277
+ reject(new Error(
278
+ `stdin idle for ${idleMs}ms with ${data.length} bytes buffered`,
279
+ ));
280
+ };
281
+ const onIdle = () => {
282
+ // Zero-buffer idle = host never wrote anything (issue #639). Resolve
283
+ // empty so the hook can no-op. Non-zero buffer = partial data, which
284
+ // must reject to avoid silent JSON.parse corruption (issue #242).
285
+ if (data.length === 0) {
286
+ resolveBuffer();
287
+ } else {
288
+ rejectIdle();
289
+ }
290
+ };
291
+ const arm = () => {
292
+ clearTimeout(timer);
293
+ timer = setTimeout(onIdle, idleMs);
294
+ timer.unref?.();
295
+ };
296
+ const onData = (chunk) => {
297
+ data += chunk;
298
+ arm();
299
+ };
300
+ const onEnd = () => resolveBuffer();
301
+ const onError = (error) => {
302
+ if (done) return;
303
+ done = true;
304
+ cleanup();
305
+ reject(error);
306
+ };
307
+
219
308
  process.stdin.setEncoding("utf-8");
220
- process.stdin.on("data", (chunk) => { data += chunk; });
221
- process.stdin.on("end", () => resolve(data.replace(/^\uFEFF/, "")));
222
- process.stdin.on("error", reject);
309
+ process.stdin.on("data", onData);
310
+ process.stdin.on("end", onEnd);
311
+ process.stdin.on("error", onError);
223
312
  process.stdin.resume();
313
+ arm();
224
314
  });
225
315
  }
226
316
 
@@ -1,31 +1,32 @@
1
- function a(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}var D=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 e=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 B=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 e=r.map(n=>`"${a(n)}"`).join(", ");return`
2
2
  For full details:
3
3
  ${a(t)}(
4
4
  queries: [${e}],
5
5
  source: "session-events"
6
- )`}function F(t,r){if(t.length===0)return"";let e=new Map;for(let f of t){let S=f.data,p=e.get(S);p||(p={ops:new Map},e.set(S,p));let d;f.type==="file_write"?d="write":f.type==="file_read"?d="read":f.type==="file_edit"?d="edit":d=f.type,p.ops.set(d,(p.ops.get(d)??0)+1)}let o=Array.from(e.entries()).slice(-D),c=[],i=[];for(let[f,{ops:S}]of o){let p=Array.from(S.entries()).map(([b,y])=>`${b}\xD7${y}`).join(", "),d=f.split("/").pop()??f;c.push(` ${a(d)} (${a(p)})`),i.push(`${d} ${Array.from(S.keys()).join(" ")}`)}let s=h(i);return[` <files count="${e.size}">`,...c,m(r,s)," </files>"].join(`
7
- `)}function B(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <errors count="${t.length}">`,...e,m(r,o)," </errors>"].join(`
8
- `)}function J(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <decisions count="${n.length}">`,...n,m(r,c)," </decisions>"].join(`
9
- `)}function X(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),s.type==="rule_content"?n.push(` ${a(s.data)}`):n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <rules count="${n.length}">`,...n,m(r,c)," </rules>"].join(`
10
- `)}function G(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...e,m(r,o)," </git>"].join(`
11
- `)}function z(t){if(t.length===0)return"";let r=[],e={};for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"?r.push(u.subject):typeof u.taskId=="string"&&typeof u.status=="string"&&(e[u.taskId]=u.status)}catch{}if(r.length===0)return"";let n=new Set(["completed","deleted","failed"]),o=Object.keys(e).sort((s,u)=>Number(s)-Number(u)),c=[];for(let s=0;s<r.length;s++){let u=o[s],f=u?e[u]??"pending":"pending";n.has(f)||c.push(r[s])}if(c.length===0)return"";let i=[];for(let s of c)i.push(` [pending] ${a(s)}`);return i.join(`
12
- `)}function P(t,r){let e=z(t);if(!e)return"";let n=[];for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"&&n.push(u.subject)}catch{}let o=h(n);return[` <task_state count="${e.split(`
6
+ )`}function G(t,r){if(t.length===0)return"";let e=new Map;for(let f of t){let S=f.data,p=e.get(S);p||(p={ops:new Map},e.set(S,p));let d;f.type==="file_write"?d="write":f.type==="file_read"?d="read":f.type==="file_edit"?d="edit":d=f.type,p.ops.set(d,(p.ops.get(d)??0)+1)}let o=Array.from(e.entries()).slice(-B),c=[],i=[];for(let[f,{ops:S}]of o){let p=Array.from(S.entries()).map(([b,y])=>`${b}\xD7${y}`).join(", "),d=f.split("/").pop()??f;c.push(` ${a(d)} (${a(p)})`),i.push(`${d} ${Array.from(S.keys()).join(" ")}`)}let s=h(i);return[` <files count="${e.size}">`,...c,m(r,s)," </files>"].join(`
7
+ `)}function J(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <errors count="${t.length}">`,...e,m(r,o)," </errors>"].join(`
8
+ `)}function X(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <decisions count="${n.length}">`,...n,m(r,c)," </decisions>"].join(`
9
+ `)}function z(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),s.type==="rule_content"?n.push(` ${a(s.data)}`):n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <rules count="${n.length}">`,...n,m(r,c)," </rules>"].join(`
10
+ `)}function P(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...e,m(r,o)," </git>"].join(`
11
+ `)}function H(t){if(t.length===0)return"";let r=[],e={};for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"?r.push(u.subject):typeof u.taskId=="string"&&typeof u.status=="string"&&(e[u.taskId]=u.status)}catch{}if(r.length===0)return"";let n=new Set(["completed","deleted","failed"]),o=Object.keys(e).sort((s,u)=>Number(s)-Number(u)),c=[];for(let s=0;s<r.length;s++){let u=o[s],f=u?e[u]??"pending":"pending";n.has(f)||c.push(r[s])}if(c.length===0)return"";let i=[];for(let s of c)i.push(` [pending] ${a(s)}`);return i.join(`
12
+ `)}function K(t,r){let e=H(t);if(!e)return"";let n=[];for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"&&n.push(u.subject)}catch{}let o=h(n);return[` <task_state count="${e.split(`
13
13
  `).length}">`,e,m(r,o)," </task_state>"].join(`
14
- `)}function H(t,r,e){if(t.length===0&&r.length===0)return"";let n=[],o=[];if(t.length>0){let s=t[t.length-1];n.push(` cwd: ${a(s.data)}`),o.push("working directory")}for(let s of r)n.push(` ${a(s.data)}`),o.push(s.data);let c=h(o);return[" <environment>",...n,m(e,c)," </environment>"].join(`
15
- `)}function Q(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t){let s=i.type==="subagent_completed"?"completed":i.type==="subagent_launched"?"launched":"unknown";e.push(` [${s}] ${a(i.data)}`),n.push(`subagent ${i.data}`)}let o=h(n);return[` <subagents count="${t.length}">`,...e,m(r,o)," </subagents>"].join(`
16
- `)}function U(t,r){if(t.length===0)return"";let e=new Map;for(let s of t){let u=s.data.split(":")[0].trim();e.set(u,(e.get(u)??0)+1)}let n=[],o=[];for(let[s,u]of e)n.push(` ${a(s)} (${u}\xD7)`),o.push(`skill ${s} invocation`);let c=h(o);return[` <skills count="${t.length}">`,...n,m(r,c)," </skills>"].join(`
17
- `)}function V(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <roles count="${n.length}">`,...n,m(r,c)," </roles>"].join(`
18
- `)}function K(t){if(t.length===0)return"";let r=t[t.length-1];return` <intent mode="${a(r.data)}"/>`}var W=3,Y=400;function Z(t,r){let e=[...t];return e.length<=r?t:e.slice(0,r).join("")}function tt(t){if(t.length===0)return"";let e=t.slice(-W).map(n=>{let o=Z(n.data??"",Y);return o?` <message>${a(o)}</message>`:""}).filter(Boolean);return e.length===0?"":[` <recent_user_messages count="${e.length}">`,...e," </recent_user_messages>"].join(`
19
- `)}function st(t,r){let e=r?.compactCount??1,n=r?.searchTool??"ctx_search",o=new Date().toISOString(),c=[],i=[],s=[],u=[],f=[],S=[],p=[],d=[],b=[],y=[],$=[],k=[],v=[];for(let g of t)switch(g.category){case"file":c.push(g);break;case"task":i.push(g);break;case"rule":s.push(g);break;case"decision":u.push(g);break;case"cwd":f.push(g);break;case"error":S.push(g);break;case"env":p.push(g);break;case"git":d.push(g);break;case"subagent":b.push(g);break;case"intent":y.push(g);break;case"skill":$.push(g);break;case"role":k.push(g);break;case"user-prompt":v.push(g);break}let l=[];l.push(` <how_to_search>
14
+ `)}function Q(t,r,e){if(t.length===0&&r.length===0)return"";let n=[],o=[];if(t.length>0){let s=t[t.length-1];n.push(` cwd: ${a(s.data)}`),o.push("working directory")}for(let s of r)n.push(` ${a(s.data)}`),o.push(s.data);let c=h(o);return[" <environment>",...n,m(e,c)," </environment>"].join(`
15
+ `)}function U(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t){let s=i.type==="subagent_completed"?"completed":i.type==="subagent_launched"?"launched":"unknown";e.push(` [${s}] ${a(i.data)}`),n.push(`subagent ${i.data}`)}let o=h(n);return[` <subagents count="${t.length}">`,...e,m(r,o)," </subagents>"].join(`
16
+ `)}function V(t,r){if(t.length===0)return"";let e=new Map;for(let s of t){let u=s.data.split(":")[0].trim();e.set(u,(e.get(u)??0)+1)}let n=[],o=[];for(let[s,u]of e)n.push(` ${a(s)} (${u}\xD7)`),o.push(`skill ${s} invocation`);let c=h(o);return[` <skills count="${t.length}">`,...n,m(r,c)," </skills>"].join(`
17
+ `)}function W(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <roles count="${n.length}">`,...n,m(r,c)," </roles>"].join(`
18
+ `)}function Y(t){if(t.length===0)return"";let r=t[t.length-1];return` <intent mode="${a(r.data)}"/>`}function Z(t){if(t.length===0)return"";let r=t[t.length-1];return[" <session_goal>"," The active objective for this session. Keep working toward it until it is met; do not ask the user to restate it.",` ${a(r.data)}`," </session_goal>"].join(`
19
+ `)}var tt=3,nt=400;function et(t,r){let e=[...t];return e.length<=r?t:e.slice(0,r).join("")}function st(t){if(t.length===0)return"";let e=t.slice(-tt).map(n=>{let o=et(n.data??"",nt);return o?` <message>${a(o)}</message>`:""}).filter(Boolean);return e.length===0?"":[` <recent_user_messages count="${e.length}">`,...e," </recent_user_messages>"].join(`
20
+ `)}function it(t,r){let e=r?.compactCount??1,n=r?.searchTool??"ctx_search",o=new Date().toISOString(),c=[],i=[],s=[],u=[],f=[],S=[],p=[],d=[],b=[],y=[],k=[],$=[],v=[],E=[];for(let g of t)switch(g.category){case"file":c.push(g);break;case"task":i.push(g);break;case"rule":s.push(g);break;case"decision":u.push(g);break;case"cwd":f.push(g);break;case"error":S.push(g);break;case"env":p.push(g);break;case"git":d.push(g);break;case"subagent":b.push(g);break;case"intent":y.push(g);break;case"goal":k.push(g);break;case"skill":$.push(g);break;case"role":v.push(g);break;case"user-prompt":E.push(g);break}let l=[];l.push(` <how_to_search>
20
21
  Each section below contains a summary of prior work.
21
22
  For FULL DETAILS, run the exact tool call shown under each section.
22
23
  Do NOT ask the user to re-explain prior work. Search first.
23
24
  Do NOT invent your own queries \u2014 use the ones provided.
24
- </how_to_search>`);let E=F(c,n);E&&l.push(E);let _=B(S,n);_&&l.push(_);let w=J(u,n);w&&l.push(w);let q=X(s,n);q&&l.push(q);let j=G(d,n);j&&l.push(j);let L=P(i,n);L&&l.push(L);let T=H(f,p,n);T&&l.push(T);let M=Q(b,n);M&&l.push(M);let C=U($,n);C&&l.push(C);let A=V(k,n);A&&l.push(A);let I=K(y);I&&l.push(I);let N=tt(v);N&&l.push(N);let O=`<session_resume events="${t.length}" compact_count="${e}" generated_at="${o}">`,R="</session_resume>",x=l.join(`
25
+ </how_to_search>`);let _=Z(k);_&&l.push(_);let w=G(c,n);w&&l.push(w);let j=J(S,n);j&&l.push(j);let q=X(u,n);q&&l.push(q);let T=z(s,n);T&&l.push(T);let L=P(d,n);L&&l.push(L);let M=K(i,n);M&&l.push(M);let C=Q(f,p,n);C&&l.push(C);let A=U(b,n);A&&l.push(A);let I=V($,n);I&&l.push(I);let N=W(v,n);N&&l.push(N);let O=Y(y);O&&l.push(O);let R=st(E);R&&l.push(R);let x=`<session_resume events="${t.length}" compact_count="${e}" generated_at="${o}">`,D="</session_resume>",F=l.join(`
25
26
 
26
- `);return x?`${O}
27
+ `);return F?`${x}
27
28
 
28
- ${x}
29
+ ${F}
29
30
 
30
- ${R}`:`${O}
31
- ${R}`}export{st as buildResumeSnapshot,z as renderTaskState};
31
+ ${D}`:`${x}
32
+ ${D}`}export{it as buildResumeSnapshot,H as renderTaskState};
@@ -51,6 +51,70 @@ await runHook(async () => {
51
51
  const HOOK_DIR = dirname(fileURLToPath(import.meta.url));
52
52
  const { loadSessionDB } = createSessionLoaders(HOOK_DIR);
53
53
 
54
+ // Self-heal a partial plugin cache install before anything else
55
+ // touches the cache dir. The Algo-D4 boot gate and the #604
56
+ // normalize-hooks ratchet both fire from start.mjs, which is one of
57
+ // the files that may be missing in the failure mode; sessionstart.mjs
58
+ // fires from CC's hooks.json wiring regardless of MCP boot status, so
59
+ // it is the reliably-available entry point. See
60
+ // hooks/heal-partial-install.mjs for the full failure-mode description.
61
+ try {
62
+ const { healPartialInstallFromMarketplace } = await import("./heal-partial-install.mjs");
63
+ healPartialInstallFromMarketplace();
64
+ } catch { /* best effort, never block session start */ }
65
+
66
+ // Issue #710 — Layer 2: self-heal Claude Code's per-session shell snapshots.
67
+ //
68
+ // Claude Code `source`s ~/.claude/shell-snapshots/snapshot-*.sh before every
69
+ // Bash tool call (refs/platforms/claude-code/src/utils/bash/ShellSnapshot.ts:269-336,
70
+ // sourced at bashProvider.ts:166). The snapshot bakes an `export PATH='…'`
71
+ // line with the context-mode `bin/` of the version active at session boot.
72
+ // After /ctx-upgrade deletes the old cache dir, the snapshot still points
73
+ // at it — every Bash call fails with "Plugin directory does not exist"
74
+ // until the session restarts.
75
+ //
76
+ // Layer 1 (cli.ts /ctx-upgrade) rewrites the active session's snapshot
77
+ // mid-upgrade so the in-process session never sees the broken state.
78
+ // Layer 2 (this) catches sessions that started after /ctx-upgrade but
79
+ // whose snapshots somehow missed the rewrite (parallel sessions, killed
80
+ // /ctx-upgrade run, manual cache surgery). Resolves currentVersion from
81
+ // the plugin's own manifest — no env-var dependency, immune to PATH bugs.
82
+ // Best-effort, never blocks session start.
83
+ try {
84
+ const { selfHealShellSnapshots } = await import("./cache-heal-utils.mjs");
85
+ const { resolve } = await import("node:path");
86
+ const { resolveConfigDir } = await import("./session-helpers.mjs");
87
+
88
+ // Read the version this MCP boot is running under. PLUGIN_ROOT
89
+ // points at ~/.claude/plugins/cache/context-mode/context-mode/<vX>/.
90
+ let currentVersion = null;
91
+ try {
92
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT
93
+ ?? resolve(HOOK_DIR, "..");
94
+ const manifestPath = resolve(pluginRoot, ".claude-plugin", "plugin.json");
95
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
96
+ if (typeof manifest?.version === "string" && manifest.version) {
97
+ currentVersion = manifest.version;
98
+ }
99
+ } catch { /* missing/malformed manifest — skip self-heal */ }
100
+
101
+ if (currentVersion) {
102
+ const snapshotsDir = resolve(resolveConfigDir(), "shell-snapshots");
103
+ const pluginCacheRoot = resolve(
104
+ resolveConfigDir(),
105
+ "plugins",
106
+ "cache",
107
+ "context-mode",
108
+ "context-mode",
109
+ );
110
+ selfHealShellSnapshots({
111
+ snapshotsDir,
112
+ pluginCacheRoot,
113
+ currentVersion,
114
+ });
115
+ }
116
+ } catch { /* best effort, never block session start */ }
117
+
54
118
  let additionalContext = ROUTING_BLOCK;
55
119
 
56
120
  // ─── #558: surface security init failure as agent-facing context ───
@@ -448,6 +448,10 @@ function apiAnalytics() {
448
448
  safeAll(db, `SELECT data as detail, created_at, session_id FROM session_events
449
449
  WHERE type = 'error_tool' OR type = 'error' ORDER BY created_at DESC LIMIT 20`)
450
450
  );
451
+ const errorCounts = queryAllSessionDBs(db =>
452
+ safeAll(db, `SELECT COUNT(*) as count FROM session_events
453
+ WHERE type = 'error_tool' OR type = 'error'`)
454
+ );
451
455
  const fileActivity = queryAllSessionDBs(db =>
452
456
  safeAll(db, `SELECT data as file, type as op, COUNT(*) as count FROM session_events
453
457
  WHERE type IN ('file_read', 'file_write', 'file') AND data != ''
@@ -563,17 +567,25 @@ function apiAnalytics() {
563
567
  safeAll(db, `SELECT substr(data, 1, 100) as task, created_at FROM session_events
564
568
  WHERE type = 'task' ORDER BY created_at DESC LIMIT 20`)
565
569
  );
570
+ const taskCounts = queryAllSessionDBs(db =>
571
+ safeAll(db, `SELECT COUNT(*) as count FROM session_events WHERE type = 'task'`)
572
+ );
566
573
  const prompts = queryAllSessionDBs(db =>
567
574
  safeAll(db, `SELECT substr(data, 1, 100) as prompt, created_at, session_id FROM session_events
568
575
  WHERE type = 'user_prompt' ORDER BY created_at DESC LIMIT 20`)
569
576
  );
577
+ const promptCounts = queryAllSessionDBs(db =>
578
+ safeAll(db, `SELECT COUNT(*) as count FROM session_events WHERE type = 'user_prompt'`)
579
+ );
570
580
 
571
581
  const rw = readWriteRatio.reduce((a, b) => ({
572
582
  reads: (a.reads || 0) + (b.reads || 0), writes: (a.writes || 0) + (b.writes || 0),
573
583
  total_file_ops: (a.total_file_ops || 0) + (b.total_file_ops || 0),
574
584
  }), { reads: 0, writes: 0, total_file_ops: 0 });
575
585
  const totalEvents = toolUsage.reduce((a, b) => a + b.count, 0);
576
- const totalErrors = errors.length;
586
+ const totalErrors = errorCounts.reduce((a, b) => a + (b.count || 0), 0);
587
+ const totalTasks = taskCounts.reduce((a, b) => a + (b.count || 0), 0);
588
+ const totalPrompts = promptCounts.reduce((a, b) => a + (b.count || 0), 0);
577
589
  const totalCompacts = sessionDurations.reduce((a, b) => a + (b.compact_count || 0), 0);
578
590
  const sessionsWithCompact = sessionDurations.filter(s => s.compact_count > 0).length;
579
591
 
@@ -706,9 +718,9 @@ function apiAnalytics() {
706
718
  reads: rw.reads, writes: rw.writes,
707
719
  readWriteRatio: rw.writes > 0 ? Math.round(10 * rw.reads / rw.writes) / 10 : rw.reads,
708
720
  totalFileOps: rw.total_file_ops, totalSubagents: subagents.total,
709
- totalTasks: tasks.length, totalPrompts: prompts.length,
721
+ totalTasks, totalPrompts,
710
722
  promptsPerSession: sessionDurations.length > 0
711
- ? Math.round(10 * prompts.length / sessionDurations.length) / 10 : 0,
723
+ ? Math.round(10 * totalPrompts / sessionDurations.length) / 10 : 0,
712
724
  uniqueProjects: nonUnknownProjects.length,
713
725
  totalCommits: commitRate.reduce((a, b) => a + (b.commits || 0), 0),
714
726
  commitsPerSession: sessionDurations.length > 0
@@ -3,12 +3,27 @@
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.151",
6
+ "version": "1.0.152",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
10
10
  "system_access": "full"
11
11
  },
12
+ "contracts": {
13
+ "tools": [
14
+ "ctx_execute",
15
+ "ctx_execute_file",
16
+ "ctx_index",
17
+ "ctx_search",
18
+ "ctx_fetch_and_index",
19
+ "ctx_batch_execute",
20
+ "ctx_stats",
21
+ "ctx_doctor",
22
+ "ctx_upgrade",
23
+ "ctx_purge",
24
+ "ctx_insight"
25
+ ]
26
+ },
12
27
  "configSchema": {
13
28
  "type": "object",
14
29
  "properties": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.151",
3
+ "version": "1.0.152",
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",