@devflow-tools/claude-code-plugin 0.13.1 → 0.13.2

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.
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';import {join,dirname}from'path';import {homedir}from'os';import {createHash}from'crypto';import {fileURLToPath}from'url';import {getLogWriter}from'@devflow-tools/telemetry';var W=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",$=process.env.DEVFLOW_API_KEY||"dev-key-000000",y=process.env.CLAUDE_PROJECT_DIR||process.cwd(),k=join(homedir(),".devflow","session-id"),S=join(homedir(),".devflow","event-map.json"),F=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function R(e,n){return new Promise(t=>{let r=JSON.stringify(n),o=new URL(e,W),s=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":$,"Content-Length":Buffer.byteLength(r)},timeout:5e3},()=>t());s.on("error",()=>t()),s.write(r),s.end();})}function q(){try{if(existsSync(k))return readFileSync(k,"utf-8").trim()}catch{}return null}function B(e,n){try{if(!existsSync(S))return null;let t=JSON.parse(readFileSync(S,"utf-8")),r=t.filter(i=>i.toolName===e);if(r.length===0)return null;let o=n??Date.now();r.sort((i,g)=>Math.abs(i.timestamp-o)-Math.abs(g.timestamp-o));let s=r[0],u=t.findIndex(i=>i.eventId===s.eventId);return u!==-1&&t.splice(u,1),writeFileSync(S,JSON.stringify(t)),{eventId:s.eventId,timestamp:s.timestamp}}catch{return null}}function E(e){if(!e)return 0;let n=e;if(typeof e=="string")try{n=JSON.parse(e);}catch{return 1}let t=n,r=["files","results","data","result","memories","nodes","chunks","findings","symbols"],o=t.data??t.structuredContent??t;if(Array.isArray(o))return o.length;if(typeof o=="object"&&o!==null){let s=o,u=0;for(let i of r)Array.isArray(s[i])&&(u+=s[i].length);for(let[,i]of Object.entries(s))i&&typeof i=="object"&&!Array.isArray(i)&&(u+=E(i));return u>0?u:Object.keys(s).length>0?1:0}return 0}var m=join(homedir(),".devflow");function K(){existsSync(m)||mkdirSync(m,{recursive:true});}function V(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{let e=fileURLToPath(import.meta.url);return join(dirname(e),"..","..")}catch{return process.cwd()}}function G(){let e=V(),n=[join(e,"dist","command-registry.json"),join(e,"command-registry.json")];for(let t of n)try{if(existsSync(t)){let r=JSON.parse(readFileSync(t,"utf8")).commands;if(r)return r}}catch{}return null}function Y(e){let n=G();return n?n[e]?.mcpTools??[]:[]}function z(e){K();let n=join(m,"current-execution-id");if(existsSync(n))return;let t=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;writeFileSync(n,t),writeFileSync(join(m,"current-skill.json"),JSON.stringify({name:e,required_mcp_tools:Y(e),registeredAt:Date.now()}));}function N(){let e=createHash("sha256").update(y).digest("hex").slice(0,16);return join(process.env.TMPDIR||"/tmp",".devflow-receipts",`${e}.json`)}function H(){try{let e=N();return existsSync(e)?JSON.parse(readFileSync(e,"utf-8")):{}}catch{return {}}}function I(e){try{let n=N(),t=join(process.env.TMPDIR||"/tmp",".devflow-receipts");existsSync(t)||mkdirSync(t,{recursive:!0}),writeFileSync(n,JSON.stringify(e));}catch{}}function X(e){if(!F.has(e))return null;let n=H(),t=(n.bypassCount??0)+1;return I({...n,bypassCount:t}),t>20&&t%10===0?`MCP \u5DE5\u5177\u4F7F\u7528\u7387\u4F4E\uFF1A${t} \u6B21\u76F4\u63A5\u5DE5\u5177\u8C03\u7528\u3002\u5EFA\u8BAE\u4F7F\u7528 get_project_context \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`:null}async function Q(e){if(!e)return null;let n;try{n=JSON.parse(e);}catch{return null}let t=n.tool_name||"",r=n.tool_input||{},o=n.tool_response||{},s=q();if(t==="Skill"){let c=typeof r=="object"&&r.skill?r.skill:"";c&&c.startsWith("devflow:")&&(z(c),I({lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}t.startsWith("mcp__")&&I({lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});let u=getLogWriter(y),i=join(m,"current-execution-id"),g=existsSync(i)?readFileSync(i,"utf-8").trim():`auto-${Date.now()}`,l=B(t,Date.now()),p=typeof o=="object"&&o!==null?o:null,C=JSON.stringify(o),O=Buffer.byteLength(C,"utf8"),w=E(o);if(u.toolCall({tool:t,runId:g,stepId:`step-${g}`,input:r,output:o,duration:l?Date.now()-l.timestamp:0,success:!p?.error,resultCount:w,resultSizeBytes:O,error:p?.error}),l&&s){let c=typeof o=="string"?o:JSON.stringify(o),j=c.length>5e3?{_truncated:true,_originalSize:c.length,text:c.slice(0,5e3)}:o,x=Date.now()-l.timestamp;R("/api/telemetry/tool-call/output",{eventId:l.eventId,sessionId:s,output:j,duration:x,completedAt:Date.now()}).catch(()=>{});}if(t.startsWith("mcp__devflow__")){let c=t.replace("mcp__devflow__","");R("/api/telemetry/tool-metrics",{id:`metric:${Date.now()}:${Math.random().toString(36).slice(2,11)}`,toolCallEventId:l?.eventId??`unknown:${Date.now()}`,sessionId:s??"",toolName:c,query:typeof r=="object"&&r.query?r.query:void 0,status:p?.error?"error":w===0?"empty":"success",resultCount:w,resultSizeBytes:O,latencyMs:l?Date.now()-l.timestamp:0,engine:c.startsWith("get_project_context")||c==="search_symbol"||c==="get_dependency_graph"?"codegraph":c==="get_knowledge"?"knowledge":c==="get_memory"?"memory":void 0}).catch(()=>{});}let P=typeof r=="object"&&r.command?r.command:"",_=p?.exitCode,T=p?.stderr;if(t==="Bash"&&_!==void 0&&_!==0){let c={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:s??`session:${y.split("/").pop()||"default"}`,tool:t,command:P||t,exitCode:_,stderr:T??null,durationMs:0,createdAt:Date.now()};R(`/api/memory/events?rootPath=${encodeURIComponent(y)}`,c).catch(()=>{});}let v=X(t);return v&&console.error("[devflow] Enforcement:",v),v}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n;}),process.stdin.on("end",async()=>{let n=await Q(e.trim()||process.argv[2]||"");if(n){let t=JSON.stringify(n);console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:t}}));}}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}
2
- export{Q as handlePostToolUse};
1
+ import {request}from'http';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';import {join,dirname}from'path';import {homedir}from'os';import {createHash}from'crypto';import {fileURLToPath}from'url';import {getLogWriter}from'@devflow-tools/telemetry';var J=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",W=process.env.DEVFLOW_API_KEY||"dev-key-000000",g=process.env.CLAUDE_PROJECT_DIR||process.cwd(),O=join(homedir(),".devflow","session-id"),v=join(homedir(),".devflow","event-map.json"),F=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function S(e,n){return new Promise(t=>{let r=JSON.stringify(n),o=new URL(e,J),c=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":W,"Content-Length":Buffer.byteLength(r)},timeout:5e3},()=>t());c.on("error",()=>t()),c.write(r),c.end();})}function U(){try{if(existsSync(O))return readFileSync(O,"utf-8").trim()}catch{}return null}function $(e,n){try{if(!existsSync(v))return null;let t=JSON.parse(readFileSync(v,"utf-8")),r=t.filter(s=>s.toolName===e);if(r.length===0)return null;let o=n??Date.now();r.sort((s,d)=>Math.abs(s.timestamp-o)-Math.abs(d.timestamp-o));let c=r[0],a=t.findIndex(s=>s.eventId===c.eventId);return a!==-1&&t.splice(a,1),writeFileSync(v,JSON.stringify(t)),{eventId:c.eventId,timestamp:c.timestamp}}catch{return null}}function D(e){if(!e)return 0;let n=e;if(typeof e=="string")try{n=JSON.parse(e);}catch{return 1}let t=n,r=["files","results","data","result","memories","nodes","chunks","findings","symbols"],o=t.data??t.structuredContent??t;if(Array.isArray(o))return o.length;if(typeof o=="object"&&o!==null){let c=o,a=0;for(let s of r)Array.isArray(c[s])&&(a+=c[s].length);for(let[,s]of Object.entries(c))s&&typeof s=="object"&&!Array.isArray(s)&&(a+=D(s));return a>0?a:Object.keys(c).length>0?1:0}return 0}var p=join(homedir(),".devflow");function q(){existsSync(p)||mkdirSync(p,{recursive:true});}function B(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{let e=fileURLToPath(import.meta.url);return join(dirname(e),"..","..")}catch{return process.cwd()}}function K(){let e=B(),n=[join(e,"dist","command-registry.json"),join(e,"command-registry.json")];for(let t of n)try{if(existsSync(t)){let r=JSON.parse(readFileSync(t,"utf8")).commands;if(r)return r}}catch{}return null}function V(e){let n=K();return n?n[e]?.mcpTools??[]:[]}function G(e){q();let n=join(p,"current-execution-id");if(existsSync(n))return;let t=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;writeFileSync(n,t),writeFileSync(join(p,"current-skill.json"),JSON.stringify({name:e,required_mcp_tools:V(e),registeredAt:Date.now()}));}function E(){let e=createHash("sha256").update(g).digest("hex").slice(0,16);return join(process.env.TMPDIR||"/tmp",".devflow-receipts",`${e}.json`)}function Y(){try{let e=E();return existsSync(e)?JSON.parse(readFileSync(e,"utf-8")):{}}catch{return {}}}function R(e){try{let n=E(),t=join(process.env.TMPDIR||"/tmp",".devflow-receipts");existsSync(t)||mkdirSync(t,{recursive:!0}),writeFileSync(n,JSON.stringify(e));}catch{}}function z(e){if(!F.has(e))return null;let n=Y(),t=(n.bypassCount??0)+1;return R({...n,bypassCount:t}),t>20&&t%10===0?`MCP \u5DE5\u5177\u4F7F\u7528\u7387\u4F4E\uFF1A${t} \u6B21\u76F4\u63A5\u5DE5\u5177\u8C03\u7528\u3002\u5EFA\u8BAE\u4F7F\u7528 get_project_context \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`:null}async function H(e){if(!e)return null;let n;try{n=JSON.parse(e);}catch{return null}let t=n.tool_name||"",r=n.tool_input||{},o=n.tool_response||{},c=U();if(t==="Skill"){let i=typeof r=="object"&&r.skill?r.skill:"";i&&i.startsWith("devflow:")&&(G(i),R({lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}t.startsWith("mcp__")&&R({lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});let a=join(p,"current-execution-id"),s=$(t,Date.now()),d=typeof o=="object"&&o!==null?o:null,N=JSON.stringify(o),b=Buffer.byteLength(N,"utf8"),h=D(o);if(existsSync(a)||t.startsWith("mcp__devflow__")||t==="Skill"){let i=getLogWriter(g),f=existsSync(a)?readFileSync(a,"utf-8").trim():`auto-${Date.now()}`;i.toolCall({tool:t,runId:f,stepId:`step-${f}`,input:r,output:o,duration:s?Date.now()-s.timestamp:0,success:!d?.error,resultCount:h,resultSizeBytes:b,error:d?.error});}if(s&&c){let i=typeof o=="string"?o:JSON.stringify(o),f=i.length>5e3?{_truncated:true,_originalSize:i.length,text:i.slice(0,5e3)}:o,T=Date.now()-s.timestamp;S("/api/telemetry/tool-call/output",{eventId:s.eventId,sessionId:c,output:f,duration:T,completedAt:Date.now()}).catch(()=>{});}if(t.startsWith("mcp__devflow__")){let i=t.replace("mcp__devflow__","");S("/api/telemetry/tool-metrics",{id:`metric:${Date.now()}:${Math.random().toString(36).slice(2,11)}`,toolCallEventId:s?.eventId??`unknown:${Date.now()}`,sessionId:c??"",toolName:i,query:typeof r=="object"&&r.query?r.query:void 0,status:d?.error?"error":h===0?"empty":"success",resultCount:h,resultSizeBytes:b,latencyMs:s?Date.now()-s.timestamp:0,engine:i.startsWith("get_project_context")||i==="search_symbol"||i==="get_dependency_graph"?"codegraph":i==="get_knowledge"?"knowledge":i==="get_memory"?"memory":void 0}).catch(()=>{});}let C=typeof r=="object"&&r.command?r.command:"",w=d?.exitCode,P=d?.stderr;if(t==="Bash"&&w!==void 0&&w!==0){let i={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:c??`session:${g.split("/").pop()||"default"}`,tool:t,command:C||t,exitCode:w,stderr:P??null,durationMs:0,createdAt:Date.now()};S(`/api/memory/events?rootPath=${encodeURIComponent(g)}`,i).catch(()=>{});}let _=z(t);return _&&console.error("[devflow] Enforcement:",_),_}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n;}),process.stdin.on("end",async()=>{let n=await H(e.trim()||process.argv[2]||"");if(n){let t=JSON.stringify(n);console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:t}}));}}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}
2
+ export{H as handlePostToolUse};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/claude-code-plugin",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "description": "DevFlow — Developer Intelligence Platform for Claude Code",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -28,5 +28,5 @@
28
28
  "hooks.json",
29
29
  "skills"
30
30
  ],
31
- "gitHead": "28618c4d84bea33bdd4f433bfc740c1ce2591d51"
31
+ "gitHead": "5faddeb8fb94ca2720ff5574daf6fb3d7cdb7546"
32
32
  }