@devflow-tools/claude-code-plugin 0.8.9 → 0.8.10

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 {existsSync,readFileSync,mkdirSync,writeFileSync,unlinkSync,readdirSync}from'fs';import {request}from'http';import {join}from'path';import {homedir}from'os';var k=1e4,M=300*1e3;function g(r,t,e){return new Promise(n=>{try{let o=new URL(r),i=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},s=>{s.resume(),n(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300);});i.on("error",()=>n(!1)),i.on("timeout",()=>{i.destroy(),n(!1);}),i.write(t),i.end();}catch{n(false);}})}var l=class{constructor(t){this.retryScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??process.env.DEVFLOW_API_KEY??"dev-key-000000",this.cacheDir=t?.cacheDir??join(homedir(),".devflow","telemetry-cache");}async sendEvent(t){let e=this.truncateInput(t.input),n={...t,input:e},o=`${this.apiUrl}/api/telemetry/tool-call`;await g(o,JSON.stringify(n),this.apiKey)||this.cacheEvent({type:"tool_call",payload:n});}async sendExecutionStart(t,e,n){let o={executionId:t,skillName:e,startedAt:n},i=`${this.apiUrl}/api/telemetry/skill-execution/start`;await g(i,JSON.stringify(o),this.apiKey)||this.cacheEvent({type:"execution_start",payload:o});}async flushCache(){if(!existsSync(this.cacheDir))return;let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json"));for(let e of t)try{let n=join(this.cacheDir,e),o=readFileSync(n,"utf8"),i=JSON.parse(o),s=i.type==="execution_start"?"/api/telemetry/skill-execution/start":"/api/telemetry/tool-call",a=`${this.apiUrl}${s}`;await g(a,JSON.stringify(i.payload),this.apiKey)&&unlinkSync(n);}catch{}}cacheEvent(t){try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let e=join(this.cacheDir,`${Date.now()}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(e,JSON.stringify(t,null,2)),this.scheduleRetry();}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache().catch(()=>{});},M).unref());}truncateInput(t){let e=JSON.stringify(t);return e.length<=k?t:{_truncated:true,_original_size:e.length,_preview:e.substring(0,k)+"..."}}};var $=1800*1e3;function J(){return process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow")}var h=class{constructor(t){this.stateDir=J();}detect(){let t=join(this.stateDir,"current-skill.json");if(!existsSync(t))return null;try{let e=readFileSync(t,"utf8"),n=JSON.parse(e);return !n.registeredAt||Date.now()-n.registeredAt>$?(this.endExecution(),null):n}catch{return null}}startExecution(t,e){existsSync(this.stateDir)||mkdirSync(this.stateDir,{recursive:true});let n=this.getCurrentExecutionId();if(n)return n;let o=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return writeFileSync(join(this.stateDir,"current-execution-id"),o),writeFileSync(join(this.stateDir,"current-skill.json"),JSON.stringify({name:t,required_mcp_tools:e?.required_mcp_tools??[],registeredAt:Date.now()})),o}getCurrentExecutionId(){let t=join(this.stateDir,"current-execution-id");if(!existsSync(t))return null;try{return readFileSync(t,"utf8").trim()}catch{return null}}endExecution(){let t=join(this.stateDir,"current-skill.json"),e=join(this.stateDir,"current-execution-id");try{existsSync(t)&&unlinkSync(t);}catch{}try{existsSync(e)&&unlinkSync(e);}catch{}}};function p(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function j(r){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:r}}}async function A(r){try{if(!r||r.trim()==="")return p();let t=JSON.parse(r),e=new h;if(t.tool_name==="Skill"){let d=t.tool_input?.skill;if(d&&d.startsWith("devflow:")){let I=e.startExecution(d);new l().sendExecutionStart(I,d,Date.now()).catch(()=>{});}}let n=e.detect(),o=t.tool_name.startsWith("mcp__devflow__"),i=o?t.tool_name.replace("mcp__devflow__",""):void 0,s=n?.required_mcp_tools??[],a=s.length>0,y=a&&!o,m;y?m=j(`Skill "${n?.name||"unknown"}" requires MCP tools. Use one of: ${s.join(", ")}`):m=p();let D=e.getCurrentExecutionId()??`exec_orphan_${Date.now()}`,w=new l,E={eventId:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,executionId:D,timestamp:Date.now(),toolName:t.tool_name,toolType:o?"mcp":t.tool_name==="Agent"?"subagent":"direct",isMcpTool:o,mcpToolName:i,mcpEnforced:o&&a,mcpFallback:!o&&a,input:t.tool_input,tokensUsed:0,duration:0,blocked:!1};return w.sendEvent(E).then(()=>{try{let f=require('fs'),p=require('path'),o=require('os'),d=p.join(o.homedir(),'.devflow');f.existsSync(d)||f.mkdirSync(d,{recursive:!0});f.writeFileSync(p.join(d,'last-event-id'),E.eventId)}catch{}}).catch(()=>{}),m}catch{return p()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let r="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{r+=t;}),process.stdin.on("end",async()=>{let t=await A(r);console.log(JSON.stringify(t));}),process.stdin.on("error",()=>{console.log(JSON.stringify(p())),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify(p())),process.exit(0);},4e3).unref();}
1
+ import {existsSync,readFileSync,mkdirSync,writeFileSync,unlinkSync,readdirSync}from'fs';import {request}from'http';import {join}from'path';import {homedir}from'os';var k=1e4,M=300*1e3;function g(r,t,e){return new Promise(n=>{try{let o=new URL(r),i=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},s=>{s.resume(),n(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300);});i.on("error",()=>n(!1)),i.on("timeout",()=>{i.destroy(),n(!1);}),i.write(t),i.end();}catch{n(false);}})}var l=class{constructor(t){this.retryScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??process.env.DEVFLOW_API_KEY??"dev-key-000000",this.cacheDir=t?.cacheDir??join(homedir(),".devflow","telemetry-cache");}async sendEvent(t){let e=this.truncateInput(t.input),n={...t,input:e},o=`${this.apiUrl}/api/telemetry/tool-call`;await g(o,JSON.stringify(n),this.apiKey)||this.cacheEvent({type:"tool_call",payload:n});}async sendExecutionStart(t,e,n){let o={executionId:t,skillName:e,startedAt:n},i=`${this.apiUrl}/api/telemetry/skill-execution/start`;await g(i,JSON.stringify(o),this.apiKey)||this.cacheEvent({type:"execution_start",payload:o});}async flushCache(){if(!existsSync(this.cacheDir))return;let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json"));for(let e of t)try{let n=join(this.cacheDir,e),o=readFileSync(n,"utf8"),i=JSON.parse(o),s=i.type==="execution_start"?"/api/telemetry/skill-execution/start":"/api/telemetry/tool-call",a=`${this.apiUrl}${s}`;await g(a,JSON.stringify(i.payload),this.apiKey)&&unlinkSync(n);}catch{}}cacheEvent(t){try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let e=join(this.cacheDir,`${Date.now()}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(e,JSON.stringify(t,null,2)),this.scheduleRetry();}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache().catch(()=>{});},M).unref());}truncateInput(t){let e=JSON.stringify(t);return e.length<=k?t:{_truncated:true,_original_size:e.length,_preview:e.substring(0,k)+"..."}}};var $=1800*1e3;function J(){return process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow")}var h=class{constructor(t){this.stateDir=J();}detect(){let t=join(this.stateDir,"current-skill.json");if(!existsSync(t))return null;try{let e=readFileSync(t,"utf8"),n=JSON.parse(e);return !n.registeredAt||Date.now()-n.registeredAt>$?(this.endExecution(),null):n}catch{return null}}startExecution(t,e){existsSync(this.stateDir)||mkdirSync(this.stateDir,{recursive:true});let n=this.getCurrentExecutionId();if(n)return n;let o=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return writeFileSync(join(this.stateDir,"current-execution-id"),o),writeFileSync(join(this.stateDir,"current-skill.json"),JSON.stringify({name:t,required_mcp_tools:e?.required_mcp_tools??[],registeredAt:Date.now()})),o}getCurrentExecutionId(){let t=join(this.stateDir,"current-execution-id");if(!existsSync(t))return null;try{return readFileSync(t,"utf8").trim()}catch{return null}}endExecution(){let t=join(this.stateDir,"current-skill.json"),e=join(this.stateDir,"current-execution-id");try{existsSync(t)&&unlinkSync(t);}catch{}try{existsSync(e)&&unlinkSync(e);}catch{}}};function p(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function j(r){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:r}}}async function A(r){try{if(!r||r.trim()==="")return p();let t=JSON.parse(r),e=new h;if(t.tool_name==="Skill"){let d=t.tool_input?.skill;if(d&&d.startsWith("devflow:")){let I=e.startExecution(d);new l().sendExecutionStart(I,d,Date.now()).catch(()=>{});}}let n=e.detect(),o=t.tool_name.startsWith("mcp__devflow__"),i=o?t.tool_name.replace("mcp__devflow__",""):void 0,s=n?.required_mcp_tools??[],a=s.length>0,y=a&&!o,m;y?m=j(`Skill "${n?.name||"unknown"}" requires MCP tools. Use one of: ${s.join(", ")}`):m=p();let D=e.getCurrentExecutionId()??`exec_orphan_${Date.now()}`,w=new l,E={eventId:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,executionId:D,timestamp:Date.now(),toolName:t.tool_name,toolType:o?"mcp":t.tool_name==="Agent"?"subagent":"direct",isMcpTool:o,mcpToolName:i,mcpEnforced:o&&a,mcpFallback:!o&&a,input:t.tool_input,tokensUsed:0,duration:0,blocked:!1};return w.sendEvent(E).catch(()=>{}),m}catch{return p()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let r="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{r+=t;}),process.stdin.on("end",async()=>{let t=await A(r);console.log(JSON.stringify(t));}),process.stdin.on("error",()=>{console.log(JSON.stringify(p())),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify(p())),process.exit(0);},4e3).unref();}
2
2
  export{A as handlePreToolUse};
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@devflow-tools/claude-code-plugin",
3
- "version": "0.8.9",
4
- "description": "DevFlow \u2014 Developer Intelligence Platform for Claude Code",
3
+ "version": "0.8.10",
4
+ "description": "DevFlow — Developer Intelligence Platform for Claude Code",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "npx tsx scripts/inject-gates.ts",
8
8
  "deploy": "npx tsx scripts/inject-gates.ts --deploy"
9
9
  },
10
10
  "devDependencies": {
11
- "@devflow-tools/mcp-server": "^0.8.9"
11
+ "@devflow-tools/mcp-server": "^0.8.10"
12
12
  },
13
13
  "keywords": [
14
14
  "pi-package",
@@ -27,5 +27,6 @@
27
27
  "hooks",
28
28
  "hooks.json",
29
29
  "skills"
30
- ]
30
+ ],
31
+ "gitHead": "ac4f93d6a52fa40b4126b514e899eee581f8f46e"
31
32
  }