Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a5e86ad4ab | |||
| d93bde059e | |||
| d60ae14a9b |
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.5.0",
|
||||
"version": "10.5.1",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
+35
-18
@@ -2,6 +2,41 @@
|
||||
|
||||
All notable changes to claude-mem.
|
||||
|
||||
## [v10.5.0] - 2026-02-26
|
||||
|
||||
## Smart Explore: AST-Powered Code Navigation
|
||||
|
||||
This release introduces **Smart Explore**, a token-optimized structural code search system built on tree-sitter AST parsing. It applies the same progressive disclosure pattern used in human-readable code outlines — but programmatically, for AI agents.
|
||||
|
||||
### Why This Matters
|
||||
|
||||
The standard exploration cycle (Glob → Grep → Read) forces agents to consume entire files to understand code structure. A typical 800-line file costs ~12,000 tokens to read. Smart Explore replaces this with a 3-layer progressive disclosure workflow that delivers the same understanding at **6-12x lower token cost**.
|
||||
|
||||
### 3 New MCP Tools
|
||||
|
||||
- **`smart_search`** — Walks directories, parses all code files via tree-sitter, and returns ranked symbols with signatures and line numbers. Replaces the Glob → Grep discovery cycle in a single call (~2-6k tokens).
|
||||
- **`smart_outline`** — Returns the complete structural skeleton of a file: all functions, classes, methods, properties, imports (~1-2k tokens vs ~12k for a full Read).
|
||||
- **`smart_unfold`** — Expands a single symbol to its full source code including JSDoc, decorators, and implementation (~1-7k tokens).
|
||||
|
||||
### Token Economics
|
||||
|
||||
| Approach | Tokens | Savings |
|
||||
|----------|--------|---------|
|
||||
| smart_outline + smart_unfold | ~3,100 | 8x vs Read |
|
||||
| smart_search (cross-file) | ~2,000-6,000 | 6-12x vs Explore agent |
|
||||
| Read (full file) | ~12,000+ | baseline |
|
||||
| Explore agent | ~20,000-40,000 | baseline |
|
||||
|
||||
### Language Support
|
||||
|
||||
10 languages via tree-sitter grammars: TypeScript, JavaScript, Python, Rust, Go, Java, C, C++, Ruby, PHP.
|
||||
|
||||
### Other Changes
|
||||
|
||||
- Simplified hooks configuration
|
||||
- Removed legacy setup.sh script
|
||||
- Security fix: replaced `execSync` with `execFileSync` to prevent command injection in file path handling
|
||||
|
||||
## [v10.4.4] - 2026-02-26
|
||||
|
||||
## Fix
|
||||
@@ -1197,21 +1232,3 @@ Comprehensive test suite in a new PR, targeting **v8.6.0**
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
## [v8.5.5] - 2026-01-03
|
||||
|
||||
## Improved Error Handling and Logging
|
||||
|
||||
This patch release enhances error handling and logging across all worker services for better debugging and reliability.
|
||||
|
||||
### Changes
|
||||
- **Enhanced Error Logging**: Improved error context across SessionStore, SearchManager, SDKAgent, GeminiAgent, and OpenRouterAgent
|
||||
- **SearchManager**: Restored error handling for Chroma calls with improved logging
|
||||
- **SessionStore**: Enhanced error logging throughout database operations
|
||||
- **Bug Fix**: Fixed critical bug where `memory_session_id` could incorrectly equal `content_session_id`
|
||||
- **Hooks**: Streamlined error handling and loading states for better maintainability
|
||||
|
||||
### Investigation Reports
|
||||
- Added detailed analysis documents for generator failures and observation duplication regressions
|
||||
|
||||
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v8.5.4...v8.5.5
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.5.0",
|
||||
"version": "10.5.1",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.5.0",
|
||||
"version": "10.5.1",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
+30
-7
@@ -1,18 +1,40 @@
|
||||
{
|
||||
"description": "Claude-mem memory system hooks",
|
||||
"hooks": {
|
||||
"Setup": [
|
||||
{
|
||||
"matcher": "*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; \"$_R/scripts/setup.sh\"",
|
||||
"timeout": 300
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/smart-install.js\"",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/smart-install.js\"",
|
||||
"timeout": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "startup|clear|compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" start",
|
||||
"timeout": 60
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code context",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code context",
|
||||
"timeout": 60
|
||||
}
|
||||
]
|
||||
@@ -23,7 +45,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-init",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-init",
|
||||
"timeout": 60
|
||||
}
|
||||
]
|
||||
@@ -31,10 +53,11 @@
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code observation",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code observation",
|
||||
"timeout": 120
|
||||
}
|
||||
]
|
||||
@@ -45,13 +68,13 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code summarize",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code summarize",
|
||||
"timeout": 120
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/thedotmack/plugin}\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-complete",
|
||||
"timeout": 120
|
||||
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-complete",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem-plugin",
|
||||
"version": "10.5.0",
|
||||
"version": "10.5.1",
|
||||
"private": true,
|
||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||
"type": "module",
|
||||
|
||||
@@ -114,7 +114,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
||||
${c}`}var _P=new Set([".js",".jsx",".ts",".tsx",".mjs",".cjs",".py",".pyw",".go",".rs",".rb",".java",".cs",".cpp",".c",".h",".hpp",".swift",".kt",".php",".vue",".svelte"]),yP=new Set(["node_modules",".git","dist","build",".next","__pycache__",".venv","venv","env",".env","target","vendor",".cache",".turbo","coverage",".nyc_output",".claude",".smart-file-read"]),$P=512*1024;async function*a$(e,t,r=20){if(r<=0)return;let n;try{n=await(0,Sn.readdir)(e,{withFileTypes:!0})}catch{return}for(let o of n){if(o.name.startsWith(".")&&o.name!=="."||yP.has(o.name))continue;let i=(0,pi.join)(e,o.name);if(o.isDirectory())yield*a$(i,t,r-1);else if(o.isFile()){let a=o.name.slice(o.name.lastIndexOf("."));_P.has(a)&&(yield i)}}}async function bP(e){try{let t=await(0,Sn.stat)(e);if(t.size>$P||t.size===0)return null;let r=await(0,Sn.readFile)(e,"utf-8");return r.slice(0,1e3).includes("\0")?null:r}catch{return null}}async function s$(e,t,r={}){let n=r.maxResults||20,o=t.toLowerCase(),i=o.split(/[\s_\-./]+/).filter(h=>h.length>0),a=[];for await(let h of a$(e,e)){if(r.filePattern&&!(0,pi.relative)(e,h).toLowerCase().includes(r.filePattern.toLowerCase()))continue;let _=await bP(h);_&&a.push({absolutePath:h,relativePath:(0,pi.relative)(e,h),content:_})}let s=n$(a),c=[],u=[],l=0;for(let[h,_]of s){l+=xP(_);let E=Os(h.toLowerCase(),i)>0,I=[],A=(j,Le)=>{for(let de of j){let Kt=0,Qe="",Ht=Os(de.name.toLowerCase(),i);Ht>0&&(Kt+=Ht*3,Qe="name match"),de.signature.toLowerCase().includes(o)&&(Kt+=2,Qe=Qe?`${Qe} + signature`:"signature match"),de.jsdoc&&de.jsdoc.toLowerCase().includes(o)&&(Kt+=1,Qe=Qe?`${Qe} + jsdoc`:"jsdoc match"),Kt>0&&(E=!0,I.push({filePath:h,symbolName:Le?`${Le}.${de.name}`:de.name,kind:de.kind,signature:de.signature,jsdoc:de.jsdoc,lineStart:de.lineStart,lineEnd:de.lineEnd,matchReason:Qe})),de.children&&A(de.children,de.name)}};A(_.symbols),E&&(c.push(_),u.push(...I))}u.sort((h,_)=>{let b=Os(h.symbolName.toLowerCase(),i);return Os(_.symbolName.toLowerCase(),i)-b});let d=u.slice(0,n),m=new Set(d.map(h=>h.filePath)),p=c.filter(h=>m.has(h.filePath)).slice(0,n),g=p.reduce((h,_)=>h+_.foldedTokenEstimate,0);return{foldedFiles:p,matchingSymbols:d,totalFilesScanned:a.length,totalSymbolsFound:l,tokenEstimate:g}}function Os(e,t){let r=0;for(let n of t)if(e===n)r+=10;else if(e.includes(n))r+=5;else{let o=0,i=0;for(let a of n){let s=e.indexOf(a,o);s!==-1&&(i++,o=s+1)}i===n.length&&(r+=1)}return r}function xP(e){let t=e.symbols.length;for(let r of e.symbols)r.children&&(t+=r.children.length);return t}function c$(e,t){let r=[];if(r.push(`\u{1F50D} Smart Search: "${t}"`),r.push(` Scanned ${e.totalFilesScanned} files, found ${e.totalSymbolsFound} symbols`),r.push(` ${e.matchingSymbols.length} matches across ${e.foldedFiles.length} files (~${e.tokenEstimate} tokens for folded view)`),r.push(""),e.matchingSymbols.length===0)return r.push(" No matching symbols found."),r.join(`
|
||||
`);r.push("\u2500\u2500 Matching Symbols \u2500\u2500"),r.push("");for(let n of e.matchingSymbols){if(r.push(` ${n.kind} ${n.symbolName} (${n.filePath}:${n.lineStart+1})`),r.push(` ${n.signature}`),n.jsdoc){let o=n.jsdoc.split(`
|
||||
`).find(i=>i.replace(/^[\s*/]+/,"").trim().length>0);o&&r.push(` \u{1F4AC} ${o.replace(/^[\s*/]+/,"").trim()}`)}r.push("")}r.push("\u2500\u2500 Folded File Views \u2500\u2500"),r.push("");for(let n of e.foldedFiles)r.push(kn(n)),r.push("");return r.push("\u2500\u2500 Actions \u2500\u2500"),r.push(" To see full implementation: use smart_unfold with file path and symbol name"),r.join(`
|
||||
`)}var Tf=require("node:fs/promises"),js=require("node:path"),kP="10.5.0";console.log=(...e)=>{ve.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:e})};var SP=Wy(),wP=Ky(),mi=`http://${wP}:${SP}`,u$={search:"/api/search",timeline:"/api/timeline"};async function l$(e,t){ve.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:e,params:t});try{let r=new URLSearchParams;for(let[a,s]of Object.entries(t))s!=null&&r.append(a,String(s));let n=`${mi}${e}?${r}`,o=await fetch(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return ve.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:e}),i}catch(r){return ve.error("SYSTEM","\u2190 Worker API error",{endpoint:e},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function zP(e,t){ve.debug("HTTP","Worker API request (POST)",void 0,{endpoint:e});try{let r=`${mi}${e}`,n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let i=await n.text();throw new Error(`Worker API error (${n.status}): ${i}`)}let o=await n.json();return ve.debug("HTTP","Worker API success (POST)",void 0,{endpoint:e}),{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(r){return ve.error("HTTP","Worker API error (POST)",{endpoint:e},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function IP(){try{return(await fetch(`${mi}/api/health`)).ok}catch(e){return ve.debug("SYSTEM","Worker health check failed",{},e),!1}}var d$=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
|
||||
`)}var Tf=require("node:fs/promises"),js=require("node:path"),kP="10.5.1";console.log=(...e)=>{ve.error("CONSOLE","Intercepted console output (MCP protocol protection)",void 0,{args:e})};var SP=Wy(),wP=Ky(),mi=`http://${wP}:${SP}`,u$={search:"/api/search",timeline:"/api/timeline"};async function l$(e,t){ve.debug("SYSTEM","\u2192 Worker API",void 0,{endpoint:e,params:t});try{let r=new URLSearchParams;for(let[a,s]of Object.entries(t))s!=null&&r.append(a,String(s));let n=`${mi}${e}?${r}`,o=await fetch(n);if(!o.ok){let a=await o.text();throw new Error(`Worker API error (${o.status}): ${a}`)}let i=await o.json();return ve.debug("SYSTEM","\u2190 Worker API success",void 0,{endpoint:e}),i}catch(r){return ve.error("SYSTEM","\u2190 Worker API error",{endpoint:e},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function zP(e,t){ve.debug("HTTP","Worker API request (POST)",void 0,{endpoint:e});try{let r=`${mi}${e}`,n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){let i=await n.text();throw new Error(`Worker API error (${n.status}): ${i}`)}let o=await n.json();return ve.debug("HTTP","Worker API success (POST)",void 0,{endpoint:e}),{content:[{type:"text",text:JSON.stringify(o,null,2)}]}}catch(r){return ve.error("HTTP","Worker API error (POST)",{endpoint:e},r),{content:[{type:"text",text:`Error calling Worker API: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async function IP(){try{return(await fetch(`${mi}/api/health`)).ok}catch(e){return ve.debug("SYSTEM","Worker health check failed",{},e),!1}}var d$=[{name:"__IMPORTANT",description:`3-LAYER WORKFLOW (ALWAYS FOLLOW):
|
||||
1. search(query) \u2192 Get index with IDs (~50-100 tokens/result)
|
||||
2. timeline(anchor=ID) \u2192 Get context around interesting results
|
||||
3. get_observations([IDs]) \u2192 Fetch full details ONLY for filtered IDs
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user