@devflow-tools/devflow 0.16.8 → 0.16.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.
Files changed (59) hide show
  1. package/dist/cli.js +59 -58
  2. package/dist/dashboard/404.html +1 -1
  3. package/dist/dashboard/accuracy.html +1 -1
  4. package/dist/dashboard/accuracy.txt +1 -1
  5. package/dist/dashboard/benchmark.html +1 -1
  6. package/dist/dashboard/benchmark.txt +1 -1
  7. package/dist/dashboard/context.html +1 -1
  8. package/dist/dashboard/context.txt +1 -1
  9. package/dist/dashboard/doctor.html +1 -1
  10. package/dist/dashboard/doctor.txt +1 -1
  11. package/dist/dashboard/executions.html +1 -1
  12. package/dist/dashboard/executions.txt +1 -1
  13. package/dist/dashboard/graph.html +1 -1
  14. package/dist/dashboard/graph.txt +1 -1
  15. package/dist/dashboard/index.html +1 -1
  16. package/dist/dashboard/index.txt +1 -1
  17. package/dist/dashboard/knowledge.html +1 -1
  18. package/dist/dashboard/knowledge.txt +1 -1
  19. package/dist/dashboard/memory.html +1 -1
  20. package/dist/dashboard/memory.txt +1 -1
  21. package/dist/dashboard/replay.html +1 -1
  22. package/dist/dashboard/replay.txt +1 -1
  23. package/dist/dashboard/runs/_.html +1 -1
  24. package/dist/dashboard/runs/_.txt +1 -1
  25. package/dist/dashboard/runs.html +1 -1
  26. package/dist/dashboard/runs.txt +1 -1
  27. package/dist/dashboard/settings.html +1 -1
  28. package/dist/dashboard/settings.txt +1 -1
  29. package/dist/dashboard/timeline.html +1 -1
  30. package/dist/dashboard/timeline.txt +1 -1
  31. package/dist/dashboard/tool-metrics.html +1 -1
  32. package/dist/dashboard/tool-metrics.txt +1 -1
  33. package/dist/dashboard/workflows.html +1 -1
  34. package/dist/dashboard/workflows.txt +1 -1
  35. package/dist/hooks/hook-client.js +6 -6
  36. package/dist/hooks/hook-daemon.js +14 -13
  37. package/dist/hooks/post-tool-use.js +3 -3
  38. package/dist/hooks/pre-compact.js +1 -1
  39. package/dist/hooks/pre-tool-use.js +2 -2
  40. package/dist/hooks/session-end.js +2 -2
  41. package/dist/hooks/stop.js +2 -2
  42. package/dist/hooks/user-prompt-submit.js +5 -3
  43. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  44. package/dist/plugin/dist/command-registry.json +116 -20
  45. package/dist/plugin/dist/hooks/hook-client.js +6 -6
  46. package/dist/plugin/dist/hooks/hook-daemon.js +14 -13
  47. package/dist/plugin/dist/hooks/post-tool-use.js +3 -3
  48. package/dist/plugin/dist/hooks/pre-compact.js +1 -1
  49. package/dist/plugin/dist/hooks/pre-tool-use.js +2 -2
  50. package/dist/plugin/dist/hooks/session-end.js +2 -2
  51. package/dist/plugin/dist/hooks/stop.js +2 -2
  52. package/dist/plugin/dist/hooks/user-prompt-submit.js +5 -3
  53. package/dist/plugin/hooks/stop +6 -4
  54. package/dist/plugin/package.json +7 -7
  55. package/dist/scripts/audit-session-data.js +13 -5
  56. package/package.json +13 -13
  57. package/plugin-registry.json +29 -29
  58. /package/dist/dashboard/_next/static/{KgbYRVRx1rrkTqJx51q3j → E8qR8p8oP4qQpCa0xXyqj}/_buildManifest.js +0 -0
  59. /package/dist/dashboard/_next/static/{KgbYRVRx1rrkTqJx51q3j → E8qR8p8oP4qQpCa0xXyqj}/_ssgManifest.js +0 -0
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,renameSync,readdirSync,unlinkSync}from'fs';import {join}from'path';import {homedir}from'os';import {MemoryGate}from'@devflow-tools/memory-engine';import {randomUUID}from'crypto';function w(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function E(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(w(n))}var M=1e4,G=3e4,h=500;function W(n,s,e){return new Promise(t=>{try{let r=new URL(n),i=request({hostname:r.hostname,port:r.port||80,path:r.pathname+r.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(s)},timeout:5e3},o=>{let a=[];o.on("data",c=>a.push(c)),o.on("end",()=>{let c=Buffer.concat(a).toString();t(o.statusCode!=null&&o.statusCode>=200&&o.statusCode<300?c:null);});});i.on("error",()=>t(null)),i.on("timeout",()=>{i.destroy(),t(null);}),i.write(s),i.end();}catch{t(null);}})}var g=class{constructor(s){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=s?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=s?.apiKey??getLocalApiKey(),this.cacheDir=s?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=s?.legacyCacheDir??(s?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=s?.database??null,this.ownsDatabase=!s?.database;}async sendEvent(s){let e={...s,input:this.truncateInput(s.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),s.eventId):null}async sendExecutionStart(s,e,t,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),o=[]){let a={executionId:s,sessionId:e,skillName:t,startedAt:r,projectRoot:i,requiredMcpTools:o};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(s,e="completed",t=Date.now(),r){let i={executionId:s,status:e,finishedAt:t,metadata:r},o=this.commitOrCache("execution_complete",i);return o&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),o}async sendSessionStart(s,e,t){let r={id:s,projectRoot:e,startedAt:t,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}async completeEvent(s){let e=this.commitOrCache("complete_event",s);return e&&(this.postHttp("/api/telemetry/tool-call/output",s),this.scheduleMetricAggregation()),e}async endSession(s,e=Date.now()){let t={sessionId:s,finishedAt:e},r=this.commitOrCache("session_end",t);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(s)}/close`,{finishedAt:e})),r}async flushCache(){try{let t=this.getDatabase(),r=t.listTelemetryFailures({unresolvedOnly:!0,limit:h}).reverse();for(let i of r)try{this.applyOperation(i.operation,i.payload),t.resolveTelemetryFailure(i.id);}catch{}t.trimTelemetryFailures(h);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(t=>!!t))].filter(t=>existsSync(t)).flatMap(t=>readdirSync(t).filter(r=>r.endsWith(".json")).map(r=>{let i=join(t,r);try{return {cacheFile:i,envelope:B(JSON.parse(readFileSync(i,"utf8")),r)}}catch{return null}})).filter(t=>t!==null).sort((t,r)=>t.envelope.timestamp-r.envelope.timestamp||P(t.envelope.operation)-P(r.envelope.operation));for(let{cacheFile:t,envelope:r}of e)try{let i=this.getDatabase();i.insertTelemetryFailure({id:r.id,operation:r.operation,payload:r.payload,error:r.failure,createdAt:r.timestamp}),this.applyOperation(r.operation,r.payload),i.resolveTelemetryFailure(r.id),unlinkSync(t);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(),this.database}commitOrCache(s,e){try{return this.applyOperation(s,e),!0}catch(t){return this.cacheOperation(s,e,t),false}}applyOperation(s,e){let t=this.getDatabase();switch(s){case "tool_call":this.ensureParentSession(t,e),t.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(t,e),t.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":t.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":t.ensureSession(e),t.insertRun({id:O(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!t.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":t.closeSession(e.sessionId,e.finishedAt),t.updateRun(O(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(s,e){let t=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!t)throw new Error("Canonical session ID is required for telemetry");let r=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";s.ensureSession({id:t,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(s,e,t){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:s,payload:e,failure:t instanceof Error?t.message:String(t),timestamp:r};try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:s,payload:e,error:i.failure,createdAt:r}),o.trimTelemetryFailures(h),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let o=join(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(o,JSON.stringify(i,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let s=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of s.slice(0,Math.max(0,s.length-h)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},G).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(s,e){W(`${this.apiUrl}${s}`,JSON.stringify(e),this.apiKey);}truncateInput(s){let e=JSON.stringify(s);return e===void 0||e.length<=M?s:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,M)}...`}}};function P(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function O(n){return `hook-run:${n}`}function B(n,s){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let e=n;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let t=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!t)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},i=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${s}`,operation:t,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}async function j(n){let s=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),t=0,r=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(t=await e.releasePendingDistillLeases(n.sessionId)),r=e.getPendingEventCount();}finally{s&&e.close();}let i={pendingEvents:r,releasedLeases:t,trigger:n.trigger,sessionId:n.sessionId};try{let o=openGlobalDevFlowDatabase();try{let a=Date.now(),c=`distill:${a}:${Math.random().toString(36).slice(2,10)}`;o.recordMemoryDistillCheckpoint({id:c,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:r,releasedLeases:t,createdAt:a}),o.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...i,projectRoot:n.projectRoot}});}finally{o.close();}}catch{}return i}function re(n){return Buffer.from(n,"utf8").toString("base64url")}var y=class{constructor(s){this.projectRoot=s;this.sessions=new Map;this.sessionsDir=join(E(s),"hook-sessions");}registerSession(s){let e=s.trim();if(!e)throw new Error("session_id_required");let t=this.get(e);if(t)return t.lastActivityAt=Date.now(),this.persist(t),t;let r=Date.now(),i={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,i),this.persist(i),i}startExecution(s,e,t){let r=this.registerSession(s);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(t)],r.lastActivityAt=Date.now(),this.persist(r),r}get(s){let e=s.trim();if(!e)return null;let t=this.sessions.get(e);if(t)return t;let r=this.snapshotPath(e);if(!existsSync(r))return null;try{let i=JSON.parse(readFileSync(r,"utf8"));return i.sessionId!==e||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],this.sessions.set(e,i),i)}catch{return null}}completeExecution(s){let e=this.get(s);if(!e)return null;let t={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),t}removeSession(s){let e=s.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(s){return join(this.sessionsDir,`${re(s)}.json`)}persist(s){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(s.sessionId),t=`${e}.${process.pid}.tmp`;writeFileSync(t,JSON.stringify(s),{mode:384}),renameSync(t,e);}};var ae=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",ce=getLocalApiKey();function le(n,s){return new Promise(e=>{let t=JSON.stringify(s),r=new URL(n,ae),i=request({hostname:r.hostname,port:r.port,path:r.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":ce,"Content-Length":Buffer.byteLength(t)},timeout:5e3},()=>e());i.on("error",()=>e()),i.write(t),i.end();})}async function ue(n,s=w(),e=true,t){let r;try{r=JSON.parse(n);}catch{return}let i=r.session_id?.trim();if(!i)return;let o=new y(s),a=o.get(i),c=t?.telemetry??new g,L=!t?.telemetry;try{try{await c.flushAndAggregate();}catch{}let l;try{l=openGlobalDevFlowDatabase();let d=l.listToolCallEventsBySession(i),u=a?.executionId;if(u){let f=d.filter(p=>p.executionId===u),v=f.length,D=f.filter(p=>p.isMcpTool).length,S=v-D,_=f.filter(p=>p.toolType==="subagent").length,b=Date.now(),T=l.getSkillExecution(u),C=T?.startedAt!=null?Math.max(0,b-T.startedAt):0,R=l.getExecutionObligationCompliance(u);try{l.updateSkillExecution(u,{status:"completed",finishedAt:b,totalToolCalls:v,mcpToolCalls:D,directToolCalls:S,subagentCount:_,totalDuration:C,mcpComplianceRate:R.rate}),await le("/api/telemetry/skill-execution/complete",{executionId:u,finishedAt:b,status:"completed",summary:{totalToolCalls:v,mcpToolCalls:D,directToolCalls:S,subagentCount:_,totalDuration:C,mcpComplianceRate:R.rate}});}catch{}}e&&l.deleteHookReceipt(s),l.deleteContextReceipt(s,i);}catch{}finally{l?.close();}try{if(await j({projectRoot:s,sessionId:i,trigger:"session_end",memory:t?.memory}),t?.memory)await t.memory.closeSession(i);else {let d=new(await import('@devflow-tools/memory-engine')).MemoryGate(s);try{await d.closeSession(i);}finally{d.close();}}}catch{}try{await c.endSession(i),await c.flushAndAggregate();}catch{}}finally{L&&c.close(),o.removeSession(i);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{n+=s;}),process.stdin.on("end",async()=>{await ue(n.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}
2
- export{ue as handleSessionEnd};
1
+ import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {existsSync,readFileSync,rmSync as rmSync$1,mkdirSync,writeFileSync,renameSync,readdirSync,unlinkSync}from'fs';import {join as join$1}from'path';import {homedir}from'os';import {MemoryGate}from'@devflow-tools/memory-engine';import {randomUUID}from'crypto';import {createHash}from'node:crypto';import {rmSync}from'node:fs';import {join}from'node:path';function b(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function y(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(b(n))}var T=1e4,U=3e4,f=500;function $(n,s,e){return new Promise(t=>{try{let r=new URL(n),i=request({hostname:r.hostname,port:r.port||80,path:r.pathname+r.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(s)},timeout:5e3},o=>{let c=[];o.on("data",l=>c.push(l)),o.on("end",()=>{let l=Buffer.concat(c).toString();t(o.statusCode!=null&&o.statusCode>=200&&o.statusCode<300?l:null);});});i.on("error",()=>t(null)),i.on("timeout",()=>{i.destroy(),t(null);}),i.write(s),i.end();}catch{t(null);}})}var v=class{constructor(s){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=s?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=s?.apiKey??getLocalApiKey(),this.cacheDir=s?.cacheDir??join$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=s?.legacyCacheDir??(s?.cacheDir?null:join$1(homedir(),".devflow","telemetry-cache")),this.database=s?.database??null,this.ownsDatabase=!s?.database;}async sendEvent(s){let e={...s,input:this.truncateInput(s.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),s.eventId):null}async sendExecutionStart(s,e,t,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),o=[]){let c={executionId:s,sessionId:e,skillName:t,startedAt:r,projectRoot:i,requiredMcpTools:o};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(s,e="completed",t=Date.now(),r){let i={executionId:s,status:e,finishedAt:t,metadata:r},o=this.commitOrCache("execution_complete",i);return o&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),o}async sendSessionStart(s,e,t){let r={id:s,projectRoot:e,startedAt:t,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}async completeEvent(s){let e=this.commitOrCache("complete_event",s);return e&&(this.postHttp("/api/telemetry/tool-call/output",s),this.scheduleMetricAggregation()),e}async endSession(s,e=Date.now()){let t={sessionId:s,finishedAt:e},r=this.commitOrCache("session_end",t);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(s)}/close`,{finishedAt:e})),r}async flushCache(){try{let t=this.getDatabase(),r=t.listTelemetryFailures({unresolvedOnly:!0,limit:f}).reverse();for(let i of r)try{this.applyOperation(i.operation,i.payload),t.resolveTelemetryFailure(i.id);}catch{}t.trimTelemetryFailures(f);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(t=>!!t))].filter(t=>existsSync(t)).flatMap(t=>readdirSync(t).filter(r=>r.endsWith(".json")).map(r=>{let i=join$1(t,r);try{return {cacheFile:i,envelope:N(JSON.parse(readFileSync(i,"utf8")),r)}}catch{return null}})).filter(t=>t!==null).sort((t,r)=>t.envelope.timestamp-r.envelope.timestamp||R(t.envelope.operation)-R(r.envelope.operation));for(let{cacheFile:t,envelope:r}of e)try{let i=this.getDatabase();i.insertTelemetryFailure({id:r.id,operation:r.operation,payload:r.payload,error:r.failure,createdAt:r.timestamp}),this.applyOperation(r.operation,r.payload),i.resolveTelemetryFailure(r.id),unlinkSync(t);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(),this.database}commitOrCache(s,e){try{return this.applyOperation(s,e),!0}catch(t){return this.cacheOperation(s,e,t),false}}applyOperation(s,e){let t=this.getDatabase();switch(s){case "tool_call":this.ensureParentSession(t,e),t.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(t,e),t.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":t.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":t.ensureSession(e),t.insertRun({id:I(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!t.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":t.closeSession(e.sessionId,e.finishedAt),t.updateRun(I(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(s,e){let t=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!t)throw new Error("Canonical session ID is required for telemetry");let r=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";s.ensureSession({id:t,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(s,e,t){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:s,payload:e,failure:t instanceof Error?t.message:String(t),timestamp:r};try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:s,payload:e,error:i.failure,createdAt:r}),o.trimTelemetryFailures(f),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let o=join$1(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(o,JSON.stringify(i,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let s=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of s.slice(0,Math.max(0,s.length-f)))unlinkSync(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},U).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(s,e){$(`${this.apiUrl}${s}`,JSON.stringify(e),this.apiKey);}truncateInput(s){let e=JSON.stringify(s);return e===void 0||e.length<=T?s:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,T)}...`}}};function R(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function I(n){return `hook-run:${n}`}function N(n,s){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let e=n;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let t=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!t)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},i=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${s}`,operation:t,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}async function E(n){let s=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),t=0,r=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(t=await e.releasePendingDistillLeases(n.sessionId)),r=e.getPendingEventCount();}finally{s&&e.close();}let i={pendingEvents:r,releasedLeases:t,trigger:n.trigger,sessionId:n.sessionId};try{let o=openGlobalDevFlowDatabase();try{let c=Date.now(),l=`distill:${c}:${Math.random().toString(36).slice(2,10)}`;o.recordMemoryDistillCheckpoint({id:l,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:r,releasedLeases:t,createdAt:c}),o.insertEvent({kind:"memory_distill_requested",timestamp:c,success:!0,metadata:{...i,projectRoot:n.projectRoot}});}finally{o.close();}}catch{}return i}function X(n){return Buffer.from(n,"utf8").toString("base64url")}var D=class{constructor(s){this.projectRoot=s;this.sessions=new Map;this.sessionsDir=join$1(y(s),"hook-sessions");}registerSession(s){let e=s.trim();if(!e)throw new Error("session_id_required");let t=this.get(e);if(t)return t.lastActivityAt=Date.now(),this.persist(t),t;let r=Date.now(),i={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,i),this.persist(i),i}startExecution(s,e,t){let r=this.registerSession(s);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(t)],r.lastActivityAt=Date.now(),this.persist(r),r}get(s){let e=s.trim();if(!e)return null;let t=this.sessions.get(e);if(t)return t;let r=this.snapshotPath(e);if(!existsSync(r))return null;try{let i=JSON.parse(readFileSync(r,"utf8"));return i.sessionId!==e||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],this.sessions.set(e,i),i)}catch{return null}}completeExecution(s){let e=this.get(s);if(!e)return null;let t={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),t}removeSession(s){let e=s.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(s){return join$1(this.sessionsDir,`${X(s)}.json`)}persist(s){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(s.sessionId),t=`${e}.${process.pid}.tmp`;writeFileSync(t,JSON.stringify(s),{mode:384}),renameSync(t,e);}};var re=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",ie=getLocalApiKey();function ne(n,s){return new Promise(e=>{let t=JSON.stringify(s),r=new URL(n,re),i=request({hostname:r.hostname,port:r.port,path:r.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":ie,"Content-Length":Buffer.byteLength(t)},timeout:5e3},()=>e());i.on("error",()=>e()),i.write(t),i.end();})}async function oe(n,s=b(),e=true,t){let r;try{r=JSON.parse(n);}catch{return}let i=r.session_id?.trim();if(!i)return;let o=new D(s),c=o.get(i),l=t?.telemetry??new v,x=!t?.telemetry;try{try{await l.flushAndAggregate();}catch{}let m;try{m=openGlobalDevFlowDatabase();let u=c?.executionId;if(u){let d=Date.now(),h=m.listMemoryTurns(s,i,100);try{m.reconcileSkillExecution(u,"completed",d,{memoryReceiptIds:h.flatMap(g=>g.receiptId?[g.receiptId]:[]),missingMemoryDecisionCount:h.filter(g=>g.status==="pending").length});let a=m.getSkillExecution(u);await ne("/api/telemetry/skill-execution/complete",{executionId:u,finishedAt:d,status:"completed",summary:{totalToolCalls:a?.totalToolCalls??0,mcpToolCalls:a?.mcpToolCalls??0,directToolCalls:a?.directToolCalls??0,subagentCount:a?.subagentCount??0,totalDuration:a?.totalDuration??0,mcpComplianceRate:a?.mcpComplianceRate??0,missedTools:a?.missedMcpTools??[],actualFailureCount:a?.failedToolCalls??0,fallbackCount:a?.fallbackCount??0,fallbackReasons:a?.fallbackReasons??[]}});}catch{}}if(e){m.deleteHookReceipt(s);let d=y(s),h=createHash("sha256").update(s).digest("hex").slice(0,12);for(let a of [`session-id-${h}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(d,a),{force:!0});}m.deleteContextReceipt(s,i);}catch{}finally{m?.close();}try{if(await E({projectRoot:s,sessionId:i,trigger:"session_end",memory:t?.memory}),t?.memory)await t.memory.closeSession(i);else {let u=new(await import('@devflow-tools/memory-engine')).MemoryGate(s);try{await u.closeSession(i);}finally{u.close();}}}catch{}try{await l.endSession(i),await l.flushAndAggregate();}catch{}}finally{x&&l.close(),o.removeSession(i);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{n+=s;}),process.stdin.on("end",async()=>{await oe(n.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}
2
+ export{oe as handleSessionEnd};
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,renameSync}from'fs';import {join}from'path';import {randomUUID}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';function c(i){return i??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function a(i){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(c(i))}function y(i){return Buffer.from(i,"utf8").toString("base64url")}var r=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join(a(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let s=this.get(t);if(s)return s.lastActivityAt=Date.now(),this.persist(s),s;let o=Date.now(),n={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:o,lastActivityAt:o};return this.sessions.set(t,n),this.persist(n),n}startExecution(e,t,s){let o=this.registerSession(e);return (!o.executionId||o.skillName!==t)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=t,o.requiredMcpTools=[...new Set(s)],o.lastActivityAt=Date.now(),this.persist(o),o}get(e){let t=e.trim();if(!t)return null;let s=this.sessions.get(t);if(s)return s;let o=this.snapshotPath(t);if(!existsSync(o))return null;try{let n=JSON.parse(readFileSync(o,"utf8"));return n.sessionId!==t||n.projectRoot!==this.projectRoot?null:(n.requiredMcpTools=Array.isArray(n.requiredMcpTools)?n.requiredMcpTools:[],this.sessions.set(t,n),n)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let s={...t,requiredMcpTools:[...t.requiredMcpTools]};return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),s}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join(this.sessionsDir,`${y(e)}.json`)}persist(e){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),s=`${t}.${process.pid}.tmp`;writeFileSync(s,JSON.stringify(e),{mode:384}),renameSync(s,t);}};var D=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",I=getLocalApiKey();function w(i,e){return new Promise(t=>{let s=JSON.stringify(e),o=new URL(i,D),n=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":I,"Content-Length":Buffer.byteLength(s)},timeout:5e3},()=>t());n.on("error",()=>t()),n.write(s),n.end();})}async function _(i,e=c()){let t;try{t=JSON.parse(i);}catch{return null}if(t.stop_hook_active)return null;let s=t.session_id?.trim();if(!s)return null;let o=new r(e).completeExecution(s);if(o?.executionId){let n=openGlobalDevFlowDatabase();try{n.reconcileSkillExecution(o.executionId,"completed"),n.deleteContextReceipt(e,s,o.executionId);}finally{n.close();}}return w(`/api/telemetry/sessions/${encodeURIComponent(s)}/tick`,{timestamp:Date.now()}).catch(()=>{}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let i="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{i+=e;}),process.stdin.on("end",async()=>{await _(i.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}
2
- export{_ as handleStop};
1
+ import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,renameSync}from'fs';import {join}from'path';import {randomUUID}from'crypto';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';function a(s){return s??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function m(s){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(a(s))}function x(s){return Buffer.from(s,"utf8").toString("base64url")}var i=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join(m(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let n=this.get(t);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let r=Date.now(),o={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:r,lastActivityAt:r};return this.sessions.set(t,o),this.persist(o),o}startExecution(e,t,n){let r=this.registerSession(e);return (!r.executionId||r.skillName!==t)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=t,r.requiredMcpTools=[...new Set(n)],r.lastActivityAt=Date.now(),this.persist(r),r}get(e){let t=e.trim();if(!t)return null;let n=this.sessions.get(t);if(n)return n;let r=this.snapshotPath(t);if(!existsSync(r))return null;try{let o=JSON.parse(readFileSync(r,"utf8"));return o.sessionId!==t||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],this.sessions.set(t,o),o)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let n={...t,requiredMcpTools:[...t.requiredMcpTools]};return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),n}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join(this.sessionsDir,`${x(e)}.json`)}persist(e){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),n=`${t}.${process.pid}.tmp`;writeFileSync(n,JSON.stringify(e),{mode:384}),renameSync(n,t);}};function M(s){return `DevFlow memory decision required for ${s.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt.`}function p(s,e,t){if(t)return null;let n=openGlobalDevFlowDatabase();try{let r=n.getPendingMemoryTurn(s,e);return !r||!n.markMemoryTurnStopPrompted(r.turnId)?null:{decision:"block",reason:M(r)}}finally{n.close();}}var T=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",k=getLocalApiKey();function D(s,e){return new Promise(t=>{let n=JSON.stringify(e),r=new URL(s,T),o=request({hostname:r.hostname,port:r.port,path:r.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":k,"Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>t());o.on("error",()=>t()),o.write(n),o.end();})}async function b(s,e=a()){let t;try{t=JSON.parse(s);}catch{return null}let n=t.session_id?.trim();if(!n)return null;let r=p(e,n,t.stop_hook_active===true);if(r)return r;if(t.stop_hook_active)return null;let o=new i(e).completeExecution(n);if(o?.executionId){let c=openGlobalDevFlowDatabase();try{c.reconcileSkillExecution(o.executionId,"completed"),c.deleteContextReceipt(e,n,o.executionId);}finally{c.close();}}return D(`/api/telemetry/sessions/${encodeURIComponent(n)}/tick`,{timestamp:Date.now()}).catch(()=>{}),null}if(process.argv[1]?.endsWith("stop")||process.argv[1]?.endsWith("stop.js")){let s="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{s+=e;}),process.stdin.on("end",async()=>{let e=await b(s.trim()||process.argv[2]||"");e&&console.log(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),4e3).unref();}
2
+ export{b as handleStop};
@@ -1,3 +1,5 @@
1
- import {createHash}from'node:crypto';import {mkdirSync,appendFileSync}from'node:fs';import {homedir as homedir$1}from'node:os';import {dirname,join as join$1}from'node:path';import {MemoryGate}from'@devflow-tools/memory-engine';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {existsSync,readFileSync,rmSync,mkdirSync as mkdirSync$1,writeFileSync,renameSync,readdirSync,unlinkSync}from'fs';import {join,dirname as dirname$1}from'path';import {randomUUID}from'crypto';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {request}from'http';import {homedir}from'os';var L=/(?:^|[.!?。!?]\s*)(?:(?:please\s+)?(?:remember|memorize)\b|(?:请记|(?:请)?记住))/iu,J=/\b(?:(?:do\s+not|don't|dont|never|not)(?:\s+need\s+to)?|no\s+need\s+to)\s+(?:please\s+)?(?:remember|memorize)\b|(?:不要|别|不用|无需|不必|不需要)(?:再)?(?:记住|记|记忆)/iu;function S(s){let t=s.trim();return t&&L.test(t)&&!J.test(t)?t:null}function H(s){let t=createHash("sha256").update(s).digest("hex").slice(0,16),e=process.env.DEVFLOW_STATE_DIR||join$1(homedir$1(),".devflow","state",t);return join$1(e,"memory-intents.jsonl")}function D(s,t){let e=H(s);mkdirSync(dirname(e),{recursive:true}),appendFileSync(e,`${JSON.stringify(t)}
2
- `,{mode:384});}var w="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function b(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function W(s){return s??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function f(s){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(W(s))}function Q(s){return Buffer.from(s,"utf8").toString("base64url")}var p=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(f(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let r=this.get(e);if(r)return r.lastActivityAt=Date.now(),this.persist(r),r;let n=Date.now(),o={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:n,lastActivityAt:n};return this.sessions.set(e,o),this.persist(o),o}startExecution(t,e,r){let n=this.registerSession(t);return (!n.executionId||n.skillName!==e)&&(n.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),n.skillName=e,n.requiredMcpTools=[...new Set(r)],n.lastActivityAt=Date.now(),this.persist(n),n}get(t){let e=t.trim();if(!e)return null;let r=this.sessions.get(e);if(r)return r;let n=this.snapshotPath(e);if(!existsSync(n))return null;try{let o=JSON.parse(readFileSync(n,"utf8"));return o.sessionId!==e||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],this.sessions.set(e,o),o)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let r={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),r}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join(this.sessionsDir,`${Q(t)}.json`)}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),r=`${e}.${process.pid}.tmp`;writeFileSync(r,JSON.stringify(t),{mode:384}),renameSync(r,e);}};function ee(s){let t=s.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function R(s){let t=s.trimStart().match(/^\/(devflow:[a-z0-9][a-z0-9-]*)\b/i);if(!t)return null;let e=ee(t[1]);return e?{rawName:t[1],skillName:e}:null}var se=1;function ie(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join(dirname$1(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function x(s=ie()){let t=[join(s,"dist","command-registry.json"),join(s,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let r=JSON.parse(readFileSync(e,"utf8"));if(r.version!==se||!ae(r.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return r.commands}catch(r){console.error(`[devflow] command registry load failed: ${r.message}`);}return null}function ae(s){return !s||typeof s!="object"||Array.isArray(s)?false:Object.values(s).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return I(e.mcpTools)&&I(e.blockedNative)})}function I(s){return Array.isArray(s)&&s.every(t=>typeof t=="string"&&t.length>0)}function E(s){let t=x();return t?t[s]?.mcpTools??[]:[]}var C=1e4,he=3e4,d=500;function ge(s,t,e){return new Promise(r=>{try{let n=new URL(s),o=request({hostname:n.hostname,port:n.port||80,path:n.pathname+n.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},i=>{let a=[];i.on("data",c=>a.push(c)),i.on("end",()=>{let c=Buffer.concat(a).toString();r(i.statusCode!=null&&i.statusCode>=200&&i.statusCode<300?c:null);});});o.on("error",()=>r(null)),o.on("timeout",()=>{o.destroy(),r(null);}),o.write(t),o.end();}catch{r(null);}})}var h=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??getLocalApiKey(),this.cacheDir=t?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,r,n,o=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:t,sessionId:e,skillName:r,startedAt:n,projectRoot:o,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",r=Date.now(),n){let o={executionId:t,status:e,finishedAt:r,metadata:n},i=this.commitOrCache("execution_complete",o);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",o),i}async sendSessionStart(t,e,r){let n={id:t,projectRoot:e,startedAt:r,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",n);return o&&this.postHttp("/api/telemetry/sessions",n),o}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let r={sessionId:t,finishedAt:e},n=this.commitOrCache("session_end",r);return n&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),n}async flushCache(){try{let r=this.getDatabase(),n=r.listTelemetryFailures({unresolvedOnly:!0,limit:d}).reverse();for(let o of n)try{this.applyOperation(o.operation,o.payload),r.resolveTelemetryFailure(o.id);}catch{}r.trimTelemetryFailures(d);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(r=>!!r))].filter(r=>existsSync(r)).flatMap(r=>readdirSync(r).filter(n=>n.endsWith(".json")).map(n=>{let o=join(r,n);try{return {cacheFile:o,envelope:fe(JSON.parse(readFileSync(o,"utf8")),n)}}catch{return null}})).filter(r=>r!==null).sort((r,n)=>r.envelope.timestamp-n.envelope.timestamp||M(r.envelope.operation)-M(n.envelope.operation));for(let{cacheFile:r,envelope:n}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:n.id,operation:n.operation,payload:n.payload,error:n.failure,createdAt:n.timestamp}),this.applyOperation(n.operation,n.payload),o.resolveTelemetryFailure(n.id),unlinkSync(r);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(r){return this.cacheOperation(t,e,r),false}}applyOperation(t,e){let r=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(r,e),r.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(r,e),r.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":r.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":r.ensureSession(e),r.insertRun({id:N(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!r.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":r.closeSession(e.sessionId,e.finishedAt),r.updateRun(N(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let r=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!r)throw new Error("Canonical session ID is required for telemetry");let n=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:r,projectRoot:n,label:n==="unknown"?void 0:n.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,r){let n=Date.now(),o={id:`failure:${n}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:r instanceof Error?r.message:String(r),timestamp:n};try{let i=this.getDatabase();i.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:n}),i.trimTelemetryFailures(d),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${n}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(o,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-d)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},he).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){ge(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=C?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,C)}...`}}};function M(s){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(s)}function N(s){return `hook-run:${s}`}function fe(s,t){if(!s||typeof s!="object")throw new Error("Invalid telemetry cache envelope");let e=s;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let r=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!r)throw new Error("Unknown legacy telemetry cache operation");let n=e.payload??{},o=Number(n.timestamp??n.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:r,payload:n,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}var m=process.env.CLAUDE_PROJECT_DIR||process.cwd();async function ve(s){let t=b()?{additionalContext:w}:{},e;try{e=JSON.parse(s);}catch{return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}}}let r=e.prompt||"";if(!r.trim())return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}};let n=S(r);if(n)try{D(m,{content:n,sessionId:e.session_id,createdAt:Date.now()});}catch{}let o=e.session_id?.trim(),i=R(r);if(o&&i){let c=new p(m),P=c.get(o)?.executionId,l=c.startExecution(o,i.skillName,E(i.skillName));if(l.executionId&&l.executionId!==P){let g=new h;try{await g.sendSessionStart(o,m,l.startedAt),await g.sendExecutionStart(l.executionId,o,i.skillName,l.lastActivityAt,m,l.requiredMcpTools);}finally{g.close();}}}let a=new MemoryGate(m);try{await a.forceWarmUp(),o&&await a.recordUserMessage(r.slice(0,2e3),o,r.slice(0,200));}catch{}finally{a.close();}return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t}}}if(process.argv[1]?.endsWith("user-prompt-submit")||process.argv[1]?.endsWith("user-prompt-submit.js")){let s="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{s+=t;}),process.stdin.on("end",async()=>{let t=await ve(s.trim()||process.argv[2]||"");console.log(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);},3e4).unref();}
3
- export{ve as handleUserPromptSubmit};
1
+ import {createHash}from'node:crypto';import {mkdirSync,appendFileSync}from'node:fs';import {homedir as homedir$1}from'node:os';import {dirname,join as join$1}from'node:path';import {MemoryGate}from'@devflow-tools/memory-engine';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {existsSync,readFileSync,rmSync,mkdirSync as mkdirSync$1,writeFileSync,renameSync,readdirSync,unlinkSync}from'fs';import {join,dirname as dirname$1}from'path';import {randomUUID}from'crypto';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {request}from'http';import {homedir}from'os';var G=/^\/(?:devflow:)?[\w-]+\b\s*/iu,W=/\b(?:(?:do\s+not|don't|dont|never|not)(?:\s+need\s+to)?|no\s+need\s+to)\s+(?:please\s+)?(?:remember|memorize)\b|(?:不要|别|不用|无需|不必|不需要)(?:再)?(?:记住|记|记忆)/iu,z=/(?:^|[.!?]\s*)(?:(?:please|kindly)\s+)?(?:remember|memorize|save\s+this|store\s+this|note\s+that)(?:\s+(?:that|to))?[\s:,-]*(.+)$/iu,K=/(?:^|[。!?;,,]\s*)(?:(?:请|麻烦|务必|一定要|帮我|帮忙|需要)\s*)?(?:记住|记一下|记下来|记|记录一下|记录下来|保存一下|保存下来)(?:这(?:件事|一点|个信息|些内容))?[\s::,,]*(.+)$/iu;function p(o){let t=o.trim().replace(G,"").trim();return !t||W.test(t)?null:(K.exec(t)??z.exec(t))?.[1]?.trim().replace(/^[::,,\s]+/u,"")||null}function V(o){let t=createHash("sha256").update(o).digest("hex").slice(0,16),e=process.env.DEVFLOW_STATE_DIR||join$1(homedir$1(),".devflow","state",t);return join$1(e,"memory-intents.jsonl")}function w(o,t){let e=V(o);mkdirSync(dirname(e),{recursive:true}),appendFileSync(e,`${JSON.stringify(t)}
2
+ `,{mode:384});}var _="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function b(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function Y(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function I(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(Y(o))}function oe(o){return Buffer.from(o,"utf8").toString("base64url")}var h=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(I(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let r=this.get(e);if(r)return r.lastActivityAt=Date.now(),this.persist(r),r;let n=Date.now(),s={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:n,lastActivityAt:n};return this.sessions.set(e,s),this.persist(s),s}startExecution(t,e,r){let n=this.registerSession(t);return (!n.executionId||n.skillName!==e)&&(n.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),n.skillName=e,n.requiredMcpTools=[...new Set(r)],n.lastActivityAt=Date.now(),this.persist(n),n}get(t){let e=t.trim();if(!e)return null;let r=this.sessions.get(e);if(r)return r;let n=this.snapshotPath(e);if(!existsSync(n))return null;try{let s=JSON.parse(readFileSync(n,"utf8"));return s.sessionId!==e||s.projectRoot!==this.projectRoot?null:(s.requiredMcpTools=Array.isArray(s.requiredMcpTools)?s.requiredMcpTools:[],this.sessions.set(e,s),s)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let r={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),r}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join(this.sessionsDir,`${oe(t)}.json`)}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),r=`${e}.${process.pid}.tmp`;writeFileSync(r,JSON.stringify(t),{mode:384}),renameSync(r,e);}};function se(o){let t=o.trim().replace(/^\//,"");if(!t.startsWith("devflow:"))return null;let e=t.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(e)?`devflow:${e.toLowerCase()}`:null}function R(o){let t=o.trimStart().match(/^\/(devflow:[a-z0-9][a-z0-9-]*)\b/i);if(!t)return null;let e=se(t[1]);return e?{rawName:t[1],skillName:e}:null}var ue=2,me=1;function de(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join(dirname$1(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function T(o=de()){let t=[join(o,"dist","command-registry.json"),join(o,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let r=JSON.parse(readFileSync(e,"utf8"));if(r.version!==ue&&r.version!==me||!pe(r.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return r.commands}catch(r){console.error(`[devflow] command registry load failed: ${r.message}`);}return null}function pe(o){return !o||typeof o!="object"||Array.isArray(o)?false:Object.values(o).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return k(e.mcpTools)&&k(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function k(o){return Array.isArray(o)&&o.every(t=>typeof t=="string"&&t.length>0)}function M(o){let t=T();return t?t[o]?.mcpTools??[]:[]}var N=1e4,Se=3e4,g=500;function De(o,t,e){return new Promise(r=>{try{let n=new URL(o),s=request({hostname:n.hostname,port:n.port||80,path:n.pathname+n.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},i=>{let c=[];i.on("data",a=>c.push(a)),i.on("end",()=>{let a=Buffer.concat(c).toString();r(i.statusCode!=null&&i.statusCode>=200&&i.statusCode<300?a:null);});});s.on("error",()=>r(null)),s.on("timeout",()=>{s.destroy(),r(null);}),s.write(t),s.end();}catch{r(null);}})}var f=class{constructor(t){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??getLocalApiKey(),this.cacheDir=t?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;}async sendEvent(t){let e={...t,input:this.truncateInput(t.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),t.eventId):null}async sendExecutionStart(t,e,r,n,s=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let c={executionId:t,sessionId:e,skillName:r,startedAt:n,projectRoot:s,requiredMcpTools:i};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(t,e="completed",r=Date.now(),n){let s={executionId:t,status:e,finishedAt:r,metadata:n},i=this.commitOrCache("execution_complete",s);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",s),i}async sendSessionStart(t,e,r){let n={id:t,projectRoot:e,startedAt:r,label:e.split("/").pop()??"unknown"},s=this.commitOrCache("session_start",n);return s&&this.postHttp("/api/telemetry/sessions",n),s}async completeEvent(t){let e=this.commitOrCache("complete_event",t);return e&&(this.postHttp("/api/telemetry/tool-call/output",t),this.scheduleMetricAggregation()),e}async endSession(t,e=Date.now()){let r={sessionId:t,finishedAt:e},n=this.commitOrCache("session_end",r);return n&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),n}async flushCache(){try{let r=this.getDatabase(),n=r.listTelemetryFailures({unresolvedOnly:!0,limit:g}).reverse();for(let s of n)try{this.applyOperation(s.operation,s.payload),r.resolveTelemetryFailure(s.id);}catch{}r.trimTelemetryFailures(g);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(r=>!!r))].filter(r=>existsSync(r)).flatMap(r=>readdirSync(r).filter(n=>n.endsWith(".json")).map(n=>{let s=join(r,n);try{return {cacheFile:s,envelope:we(JSON.parse(readFileSync(s,"utf8")),n)}}catch{return null}})).filter(r=>r!==null).sort((r,n)=>r.envelope.timestamp-n.envelope.timestamp||P(r.envelope.operation)-P(n.envelope.operation));for(let{cacheFile:r,envelope:n}of e)try{let s=this.getDatabase();s.insertTelemetryFailure({id:n.id,operation:n.operation,payload:n.payload,error:n.failure,createdAt:n.timestamp}),this.applyOperation(n.operation,n.payload),s.resolveTelemetryFailure(n.id),unlinkSync(r);}catch{}this.database?.aggregatePendingToolMetrics();}aggregateMetrics(){return this.getDatabase().aggregatePendingToolMetrics()}async flushAndAggregate(){await this.flushCache(),this.aggregateMetrics();}close(){this.ownsDatabase&&this.database?.close(),this.database=null;}getDatabase(){return this.database??=openGlobalDevFlowDatabase(),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(r){return this.cacheOperation(t,e,r),false}}applyOperation(t,e){let r=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(r,e),r.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(r,e),r.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":r.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":r.ensureSession(e),r.insertRun({id:j(e.id),source:"hook",tool:"session",input:{projectRoot:e.projectRoot},status:"active",startedAt:e.startedAt,tokenUsed:0,metadata:{sessionId:e.id,projectRoot:e.projectRoot}});return;case "complete_event":if(!r.updateToolCallEvent(e.eventId,{output:e.output===void 0?void 0:JSON.stringify(e.output),error:e.error,duration:e.duration}))throw new Error(`Tool call event ${e.eventId} is not available for completion`);return;case "session_end":r.closeSession(e.sessionId,e.finishedAt),r.updateRun(j(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let r=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!r)throw new Error("Canonical session ID is required for telemetry");let n=typeof e.projectRoot=="string"&&e.projectRoot.trim()?e.projectRoot:typeof e.input?.projectRoot=="string"&&e.input.projectRoot.trim()?e.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";t.ensureSession({id:r,projectRoot:n,label:n==="unknown"?void 0:n.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,r){let n=Date.now(),s={id:`failure:${n}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:r instanceof Error?r.message:String(r),timestamp:n};try{let i=this.getDatabase();i.insertTelemetryFailure({id:s.id,operation:t,payload:e,error:s.failure,createdAt:n}),i.trimTelemetryFailures(g),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${n}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(s,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of t.slice(0,Math.max(0,t.length-g)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Se).unref());}scheduleMetricAggregation(){if(this.metricAggregationScheduled||process.env.DEVFLOW_HOOK_DEGRADED==="1")return;this.metricAggregationScheduled=true,setTimeout(()=>{this.metricAggregationScheduled=false;try{this.getDatabase().aggregatePendingToolMetrics(50)===50&&this.scheduleMetricAggregation();}catch{}},25).unref();}postHttp(t,e){De(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=N?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,N)}...`}}};function P(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function j(o){return `hook-run:${o}`}function we(o,t){if(!o||typeof o!="object")throw new Error("Invalid telemetry cache envelope");let e=o;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let r=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!r)throw new Error("Unknown legacy telemetry cache operation");let n=e.payload??{},s=Number(n.timestamp??n.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:r,payload:n,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:s}}var be=/^(?:ok(?:ay)?|yes|no|thanks?|thank you|continue|好的?|可以|行|是|否|谢谢|继续|收到|明白了?)[.!。!\s]*$/iu;function xe(o){let t=o.trim();return t.length>0&&!be.test(t)}function Re(o,t,e=Date.now()){let r=createHash("sha256").update(t.trim()).digest("hex"),n=createHash("sha256").update(`${o}\0${e}\0${r}`).digest("hex").slice(0,24);return {turnId:`turn:${n}`,eventId:`memory-turn:${n}`,promptHash:r,createdAt:e}}function ke(o,t,e=[]){return `memory-receipt:${createHash("sha256").update(`${o}\0${t}\0${[...e].sort().join("\0")}`).digest("hex").slice(0,24)}`}function Te(o){return `DevFlow memory decision required for ${o.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt.`}function F(o){let t=o.memoryIds.length>0?o.memoryIds.join(","):"none";return `DevFlow canonical memory receipt: status=${o.status}; receiptId=${o.receiptId??"missing"}; turnId=${o.turnId}; memoryIds=${t}; source=${o.source??"unknown"}.`}async function $(o){if(!xe(o.prompt))return null;let t=openGlobalDevFlowDatabase();try{let e=createHash("sha256").update(o.prompt.trim()).digest("hex"),r=t.listMemoryTurns(o.projectRoot,o.sessionId,5).find(u=>u.promptHash===e&&Date.now()-u.createdAt<1e4),n=r?{turnId:r.turnId,eventId:r.eventId,promptHash:r.promptHash,createdAt:r.createdAt}:Re(o.sessionId,o.prompt),s=r??t.beginMemoryTurn({...n,projectRoot:o.projectRoot,sessionId:o.sessionId});if(s.status!=="pending")return {turn:s,additionalContext:F(s),skipSkillRouting:s.source==="explicit_intent"};await o.memory.recordUserMessage(o.prompt.slice(0,4e3),o.sessionId,o.prompt.slice(0,200)),await o.memory.recordEvent({id:n.eventId,sessionId:o.sessionId,tool:"UserPromptSubmit",kind:"user_message",payload:{prompt:o.prompt.slice(0,4e3),turnId:n.turnId},createdAt:n.createdAt});let i=p(o.prompt);if(!i)return {turn:s,additionalContext:Te(s),skipSkillRouting:!1};let c=await o.memory.saveExplicitMemoryIntent(i,o.sessionId,n.eventId),a=ke(s.turnId,"committed",[c.id]);return s=t.commitMemoryTurn({turnId:s.turnId,receiptId:a,memoryIds:[c.id],source:"explicit_intent",reason:"explicit_user_request"}),{turn:s,explicitContent:i,additionalContext:F(s),skipSkillRouting:!0}}finally{t.close();}}var m=process.env.CLAUDE_PROJECT_DIR||process.cwd();async function Ce(o){let t=b()?[_]:[],e;try{e=JSON.parse(o);}catch{return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t.length?{additionalContext:t.join(`
3
+ `)}:{}}}}let r=e.prompt||"";if(!r.trim())return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t.length?{additionalContext:t.join(`
4
+ `)}:{}}};let n=e.session_id?.trim(),s=R(r),i=new MemoryGate(m),c=false;try{if(await i.forceWarmUp(),n){let a=await $({projectRoot:m,sessionId:n,prompt:r,memory:i});a&&(t.push(a.additionalContext),c=a.skipSkillRouting);}}catch{let a=p(r);if(a){try{let u=openGlobalDevFlowDatabase();try{let l=n?u.getPendingMemoryTurn(m,n):null;w(m,{content:a,sessionId:n,turnId:l?.turnId,eventId:l?.eventId,createdAt:Date.now()});}finally{u.close();}}catch{}t.push("DevFlow explicit memory save failed; no canonical receipt was created. Do not claim that the content was remembered."),c=true;}}finally{i.close();}if(n&&s&&!c){let a=new h(m),u=a.get(n)?.executionId,l=a.startExecution(n,s.skillName,M(s.skillName));if(l.executionId&&l.executionId!==u){let v=new f;try{await v.sendSessionStart(n,m,l.startedAt),await v.sendExecutionStart(l.executionId,n,s.skillName,l.lastActivityAt,m,l.requiredMcpTools);}finally{v.close();}}}return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t.length?{additionalContext:t.join(`
5
+ `)}:{}}}}if(process.argv[1]?.endsWith("user-prompt-submit")||process.argv[1]?.endsWith("user-prompt-submit.js")){let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{o+=t;}),process.stdin.on("end",async()=>{let t=await Ce(o.trim()||process.argv[2]||"");console.log(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);}),setTimeout(()=>{console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow"}})),process.exit(0);},3e4).unref();}export{Ce as handleUserPromptSubmit};
@@ -5,17 +5,19 @@ set -euo pipefail
5
5
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
6
  PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$SCRIPT_DIR/..}"
7
7
 
8
- # 1. Tell daemon to stop via hook-client
8
+ # 1. Use the daemon as the authoritative Stop handler.
9
9
  CLIENT_JS="$PLUGIN_ROOT/dist/hooks/hook-client.js"
10
10
  INPUT="$(cat)"
11
11
  if [ -f "$CLIENT_JS" ]; then
12
- node "$CLIENT_JS" stop "$INPUT" </dev/null 2>/dev/null || true
12
+ if node "$CLIENT_JS" stop "$INPUT" </dev/null 2>/dev/null; then
13
+ exit 0
14
+ fi
13
15
  fi
14
16
 
15
- # 2. Run existing stop.js cleanup (session close, memory extraction)
17
+ # 2. Run standalone fallback only when daemon delivery failed.
16
18
  STOP_JS="$PLUGIN_ROOT/dist/hooks/stop.js"
17
19
  if [ -f "$STOP_JS" ]; then
18
- printf '%s' "$INPUT" | node "$STOP_JS" 2>/dev/null || true
20
+ printf '%s' "$INPUT" | DEVFLOW_HOOK_DEGRADED=1 node "$STOP_JS" 2>/dev/null || true
19
21
  fi
20
22
 
21
23
  # 3. Clean up stale receipt files for this project
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/claude-code-plugin",
3
- "version": "0.16.8",
3
+ "version": "0.16.10",
4
4
  "description": "DevFlow — Developer Intelligence Platform for Claude Code",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -8,18 +8,18 @@
8
8
  "deploy": "npx tsx scripts/inject-gates.ts --deploy"
9
9
  },
10
10
  "dependencies": {
11
- "@devflow-tools/database": "0.16.8",
12
- "@devflow-tools/memory-engine": "0.16.8",
13
- "@devflow-tools/sdk": "0.16.8",
14
- "@devflow-tools/telemetry": "0.16.8",
15
- "@devflow-tools/workflow-engine": "0.16.8"
11
+ "@devflow-tools/database": "0.16.10",
12
+ "@devflow-tools/memory-engine": "0.16.10",
13
+ "@devflow-tools/sdk": "0.16.10",
14
+ "@devflow-tools/telemetry": "0.16.10",
15
+ "@devflow-tools/workflow-engine": "0.16.10"
16
16
  },
17
17
  "allowScripts": {
18
18
  "better-sqlite3@12.11.1": true,
19
19
  "sharp@0.32.6": true
20
20
  },
21
21
  "devDependencies": {
22
- "@devflow-tools/mcp-server": "0.16.8"
22
+ "@devflow-tools/mcp-server": "0.16.10"
23
23
  },
24
24
  "keywords": [
25
25
  "pi-package",
@@ -1,6 +1,14 @@
1
- import {execFileSync}from'node:child_process';import {createRequire}from'node:module';import {existsSync,readdirSync,readFileSync}from'node:fs';import {homedir}from'node:os';import {join}from'node:path';var L=6e4,R;function P(){if(R)return R;let e=createRequire(import.meta.url)("node:sqlite");if(typeof e.DatabaseSync!="function")throw new Error("audit-session-data requires Node.js with node:sqlite (Node.js >=22.13.0)");return R=e.DatabaseSync,R}function V(e){let t,n,o=false;for(let i=0;i<e.length;i+=1){let l=e[i];if(l==="--json")o=true;else if(l==="--project")t=e[++i];else if(l==="--session")n=e[++i];else throw new Error(`Unknown argument: ${l}`)}if(!t)throw new Error("--project is required");if(!n)throw new Error("--session is required");return {project:t,session:n,json:o}}function u(e){return typeof e=="string"&&e.length>0?e:null}function j(e){return typeof e=="number"&&Number.isFinite(e)?e:null}function h(e){return e===true||e===1}function d(e,t){return !!e.prepare("SELECT 1 FROM sqlite_master WHERE type IN ('table', 'view') AND name = ?").get(t)}function E(e,t,n){return d(e,t)?e.prepare(`PRAGMA table_info(${t})`).all().some(o=>o.name===n):false}function k(e,t,n=[]){let o=e.prepare(t).get(...n);return Number(o?.count??0)}function A(e){if(typeof e!="string"||e.length===0)return e??null;try{return JSON.parse(e)}catch{return e}}function w(e){return e===null||typeof e!="object"?JSON.stringify(e)??String(e):Array.isArray(e)?`[${e.map(w).join(",")}]`:`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${w(n)}`).join(",")}}`}function F(e){return w({tool:e.tool,command:e.command,kind:e.kind,input:e.input})}function _(e){let t=new Map;for(let n of e){if(n.toolUseId){let l=`tool_use_id:${n.toolUseId}`,a=t.get(l)??{reason:"canonical_tool_use_id",events:[]};a.events.push(n),t.set(l,a);continue}let o=`payload:${F(n)}`,i=t.get(o)??{reason:"normalized_payload",events:[]};i.events.push(n),t.set(o,i);}return [...t.entries()].map(([n,o])=>{let i=o.events.map(a=>a.timestamp).filter(a=>a!==null),l=i.length>1?Math.max(...i)-Math.min(...i):null;return {key:n,reason:o.reason,count:o.events.length,eventIds:o.events.map(a=>a.id),timeSpanMs:l,tool:o.events[0]?.tool??null}}).filter(n=>n.count>1&&(n.reason==="canonical_tool_use_id"||n.timeSpanMs===null||n.timeSpanMs<=L)).sort((n,o)=>o.count-n.count||n.key.localeCompare(o.key))}function O(e){return existsSync(e)?new(P())(e,{readOnly:true,timeout:1e3}):null}function I(e,t){if(!existsSync(e))return {path:e,exists:false,sessions:[],executions:[],events:[],duplicateCandidates:[]};let n=null;try{if(n=O(e),!n)return {path:e,exists:!1,sessions:[],executions:[],events:[],duplicateCandidates:[]};let o=d(n,"sessions")?n.prepare("SELECT * FROM sessions WHERE id = ?").all(t):[],i=E(n,"skill_executions","session_id"),l=d(n,"skill_executions")?n.prepare(i?"SELECT * FROM skill_executions WHERE session_id = ? OR execution_id = ? ORDER BY started_at":"SELECT * FROM skill_executions WHERE execution_id = ? ORDER BY started_at").all(...i?[t,t]:[t]):[],a=l.map(s=>u(s.execution_id)).filter(s=>s!==null),m=E(n,"tool_call_events","tool_use_id"),c=E(n,"tool_call_events","session_id"),b=E(n,"tool_call_events","kind"),C=a.length>0?`execution_id IN (${a.map(()=>"?").join(",")})`:"execution_id = ?",y=a.length>0?a:[t],r=(d(n,"tool_call_events")?n.prepare(`SELECT * FROM tool_call_events WHERE ${c?"session_id = ? OR ":""}${C} ORDER BY timestamp`).all(...c?[t,...y]:y):[]).map(s=>({id:u(s.event_id)??"unknown",sessionId:u(s.session_id),executionId:u(s.execution_id),timestamp:j(s.timestamp),tool:u(s.tool_name),toolType:u(s.tool_type),toolUseId:m?u(s.tool_use_id):null,input:A(s.input),command:null,kind:b?u(s.kind):null,fallback:h(s.mcp_fallback),blocked:h(s.blocked),processed:!1}));return {path:e,exists:!0,sessions:o,executions:l,events:r,duplicateCandidates:_(r)}}catch(o){return {path:e,exists:true,sessions:[],executions:[],events:[],duplicateCandidates:[],error:o instanceof Error?o.message:String(o)}}finally{n?.close();}}function N(e,t){let n=join(e,".devflow","memory","memories.db"),o={databasePath:n,session:null,eventCount:0,processedEventCount:0,pendingEventCount:0,eventsByTool:[],duplicateCandidates:[],projectObservationCount:0,sessionObservationCount:0,sessionObservationVectorCount:0,projectObservationVectorCount:0,projectObservationVectorRowCount:0,pendingLeaseCount:0,activeSessionCount:0};if(!existsSync(n))return o;let i=null;try{if(i=O(n),!i)return o;let a=(d(i,"session_events")?i.prepare("SELECT * FROM session_events WHERE session_id = ? ORDER BY created_at").all(t):[]).map(r=>({id:u(r.id)??"unknown",sessionId:u(r.session_id),executionId:null,timestamp:j(r.created_at),tool:u(r.tool),toolType:null,toolUseId:null,input:A(r.payload),command:u(r.command),kind:u(r.kind),fallback:!1,blocked:!1,processed:h(r.processed)})),m=d(i,"observations")?i.prepare("SELECT id, session_id, embedding FROM observations").all():[],c=d(i,"sessions")?i.prepare("SELECT * FROM sessions WHERE id = ?").get(t)??null:null,b=new Map;for(let r of a){let s=`${r.tool??""}\0${r.kind??""}`,f=b.get(s)??{tool:r.tool,kind:r.kind,count:0};f.count+=1,b.set(s,f);}let C=d(i,"memories_vec_rowids")?new Set(i.prepare("SELECT id FROM memories_vec_rowids").all().map(r=>u(r.id)).filter(r=>r!==null)):new Set,y=m.filter(r=>r.session_id===t),v=r=>r.embedding!==null&&r.embedding!==void 0;return {databasePath:n,session:c,eventCount:a.length,processedEventCount:a.filter(r=>r.processed).length,pendingEventCount:a.filter(r=>!r.processed).length,eventsByTool:[...b.values()].sort((r,s)=>s.count-r.count),duplicateCandidates:_(a),projectObservationCount:m.length,sessionObservationCount:y.length,sessionObservationVectorCount:y.filter(v).length,projectObservationVectorCount:m.filter(v).length,projectObservationVectorRowCount:m.filter(r=>C.has(String(r.id))).length,pendingLeaseCount:d(i,"distill_leases")?k(i,"SELECT COUNT(*) AS count FROM distill_leases WHERE status = 'pending'"):0,activeSessionCount:d(i,"sessions")?k(i,"SELECT COUNT(*) AS count FROM sessions WHERE status = 'active'"):0}}catch(l){return {...o,error:l instanceof Error?l.message:String(l)}}finally{i?.close();}}function U(e){let t=join(e,".devflow","knowledge","knowledge.db"),n={databasePath:t,documentCount:0,chunkCount:0,emptyTitleCount:0,vectorRowCount:0,sourceCounts:[]};if(!existsSync(t))return n;let o=null;try{if(o=O(t),!o)return n;let i=d(o,"knowledge_docs")?k(o,"SELECT COUNT(*) AS count FROM knowledge_docs"):0,l=d(o,"knowledge_chunks")?k(o,"SELECT COUNT(*) AS count FROM knowledge_chunks"):0,a=d(o,"knowledge_docs")?k(o,"SELECT COUNT(*) AS count FROM knowledge_docs WHERE TRIM(COALESCE(title, '')) = ''"):0,m=d(o,"knowledge_docs")?o.prepare("SELECT source, COUNT(*) AS count FROM knowledge_docs GROUP BY source ORDER BY count DESC").all().map(c=>({source:u(c.source),count:Number(c.count??0)})):[];return {databasePath:t,documentCount:i,chunkCount:l,emptyTitleCount:a,vectorRowCount:d(o,"knowledge_vec_rowids")?k(o,"SELECT COUNT(*) AS count FROM knowledge_vec_rowids"):0,sourceCounts:m}}catch(i){return {...n,error:i instanceof Error?i.message:String(i)}}finally{o?.close();}}function W(){let e=join(homedir(),".claude","plugins","cache","devflow-local","devflow");if(!existsSync(e))return null;let t=readdirSync(e,{withFileTypes:true}).filter(n=>n.isDirectory()).map(n=>n.name).sort();return t.length>0?join(e,t[t.length-1]):null}function x(e){if(!e)return null;try{let t=JSON.parse(readFileSync(join(e,".claude-plugin","plugin.json"),"utf8"));return u(t.version)}catch{return null}}function q(e,t){try{return execFileSync(e,t,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}function B(e,t,n){let o=join(e,".devflow","logs","traces");if(!existsSync(o))return null;let i=[];for(let l of readdirSync(o,{withFileTypes:true})){if(!l.isDirectory())continue;for(let m of t){let c=join(o,l.name,`${m}.jsonl`);existsSync(c)&&i.push(c);}let a=join(o,l.name,`${n}.jsonl`);existsSync(a)&&i.push(a);}return i[0]??null}function H(e){if(!e)return null;try{return readFileSync(e,"utf8").split(`
2
- `).filter(t=>t.trim().length>0).length}catch{return null}}function Y(e){try{return execFileSync("git",["-C",e,"status","--short","--branch"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return "unavailable"}}function J(e,t){let n=process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),o=[join(n,"devflow.db"),join(e,".devflow","devflow.db")],i=o.filter((s,f)=>o.indexOf(s)===f).map(s=>I(s,t)),l=i.flatMap(s=>s.events),a=[...new Set(i.flatMap(s=>s.executions).map(s=>u(s.execution_id)).filter(s=>s!==null))],m=new Map;for(let s of l)m.set(s.tool,(m.get(s.tool)??0)+1);let c=W(),b=B(e,a,t),C=N(e,t),y=U(e),v=join(homedir(),".claude","skills","devflow:react","SKILL.md"),r=i.find(s=>s.executions.length>0)??i.find(s=>s.sessions.length>0);return {schemaVersion:1,readOnly:true,generatedAt:new Date().toISOString(),project:{root:e,gitStatus:Y(e)},query:{sessionId:t,executionIds:a},runtime:{nodeVersion:process.version,claudeVersion:q("claude",["--version"]),devflowVersion:x(c),activePluginPath:c,activePluginVersion:x(c),activeReactSkillPath:c?join(c,"skills","react","SKILL.md"):null,activeReactSkillExists:c?existsSync(join(c,"skills","react","SKILL.md")):false,legacyReactSkillPath:v,legacyReactSkillExists:existsSync(v),tracePath:b,traceEventCount:H(b)},telemetry:{databases:i,eventCount:l.length,mcpEventCount:l.filter(s=>s.toolType==="mcp").length,fallbackCount:l.filter(s=>s.fallback).length,blockedCount:l.filter(s=>s.blocked).length,duplicateCandidates:_(l),byTool:[...m.entries()].map(([s,f])=>({tool:s,count:f})).sort((s,f)=>f.count-s.count||String(s.tool).localeCompare(String(f.tool)))},memory:C,knowledge:y,lifecycle:{telemetrySession:r?.sessions[0]??null,telemetryExecution:r?.executions[0]??null,memorySession:C.session}}}function K(e){let t=e.telemetry,n=e.memory,o=e.lifecycle;return [`Session audit: ${e.query.sessionId}`,`Project: ${e.project.root}`,`Git: ${e.project.gitStatus||"(clean)"}`,`Telemetry: ${t.eventCount} events (${t.mcpEventCount} MCP, ${t.fallbackCount} fallback, ${t.blockedCount} blocked)`,`Memory events: ${n.eventCount} (${n.processedEventCount} processed, ${n.pendingEventCount} pending)`,`Observations: ${n.sessionObservationCount} for session / ${n.projectObservationCount} for project; vectors ${n.sessionObservationVectorCount}/${n.sessionObservationCount} for session, ${n.projectObservationVectorCount}/${n.projectObservationCount} by blob, ${n.projectObservationVectorRowCount} indexed`,`Duplicates: ${t.duplicateCandidates.length} telemetry candidate groups, ${n.duplicateCandidates.length} Memory candidate groups`,`Lifecycle: telemetry ${u(o.telemetrySession?.status)??"missing"}, execution ${u(o.telemetryExecution?.status)??"missing"}, memory ${u(o.memorySession?.status)??"missing"}`,`Knowledge: ${e.knowledge.documentCount} docs, ${e.knowledge.chunkCount} chunks, ${e.knowledge.vectorRowCount} vectors, ${e.knowledge.emptyTitleCount} empty titles`,`Runtime: Claude ${e.runtime.claudeVersion??"unknown"}, DevFlow ${e.runtime.devflowVersion??"unknown"}, trace events ${e.runtime.traceEventCount??"unknown"}`].join(`
3
- `)}function z(){try{let e=V(process.argv.slice(2)),t=J(e.project,e.session);process.stdout.write(e.json?`${JSON.stringify(t,null,2)}
4
- `:`${K(t)}
1
+ import {execFileSync}from'node:child_process';import {createRequire}from'node:module';import {existsSync,readdirSync,readFileSync}from'node:fs';import {homedir}from'node:os';import {join}from'node:path';var I=6e4,E;function N(){if(E)return E;let e=createRequire(import.meta.url)("node:sqlite");if(typeof e.DatabaseSync!="function")throw new Error("audit-session-data requires Node.js with node:sqlite (Node.js >=22.13.0)");return E=e.DatabaseSync,E}function V(e){let t,n,o=false;for(let i=0;i<e.length;i+=1){let l=e[i];if(l==="--json")o=true;else if(l==="--project")t=e[++i];else if(l==="--session")n=e[++i];else throw new Error(`Unknown argument: ${l}`)}if(!t)throw new Error("--project is required");if(!n)throw new Error("--session is required");return {project:t,session:n,json:o}}function a(e){return typeof e=="string"&&e.length>0?e:null}function j(e){return typeof e=="number"&&Number.isFinite(e)?e:null}function S(e){return e===true||e===1}function c(e,t){return !!e.prepare("SELECT 1 FROM sqlite_master WHERE type IN ('table', 'view') AND name = ?").get(t)}function h(e,t,n){return c(e,t)?e.prepare(`PRAGMA table_info(${t})`).all().some(o=>o.name===n):false}function R(e,t,n=[]){let o=e.prepare(t).get(...n);return Number(o?.count??0)}function T(e){if(typeof e!="string"||e.length===0)return e??null;try{return JSON.parse(e)}catch{return e}}function L(e){let t=T(e);return Array.isArray(t)?t.filter(n=>typeof n=="string"):[]}function w(e){return e===null||typeof e!="object"?JSON.stringify(e)??String(e):Array.isArray(e)?`[${e.map(w).join(",")}]`:`{${Object.entries(e).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>`${JSON.stringify(t)}:${w(n)}`).join(",")}}`}function q(e){return w({tool:e.tool,command:e.command,kind:e.kind,input:e.input})}function $(e){let t=new Map;for(let n of e){if(n.toolUseId){let l=`tool_use_id:${n.toolUseId}`,u=t.get(l)??{reason:"canonical_tool_use_id",events:[]};u.events.push(n),t.set(l,u);continue}let o=`payload:${q(n)}`,i=t.get(o)??{reason:"normalized_payload",events:[]};i.events.push(n),t.set(o,i);}return [...t.entries()].map(([n,o])=>{let i=o.events.map(u=>u.timestamp).filter(u=>u!==null),l=i.length>1?Math.max(...i)-Math.min(...i):null;return {key:n,reason:o.reason,count:o.events.length,eventIds:o.events.map(u=>u.id),timeSpanMs:l,tool:o.events[0]?.tool??null}}).filter(n=>n.count>1&&(n.reason==="canonical_tool_use_id"||n.timeSpanMs===null||n.timeSpanMs<=I)).sort((n,o)=>o.count-n.count||n.key.localeCompare(o.key))}function x(e){return existsSync(e)?new(N())(e,{readOnly:true,timeout:1e3}):null}function U(e,t){if(!existsSync(e))return {path:e,exists:false,sessions:[],executions:[],events:[],duplicateCandidates:[],hookFallbacks:[],memoryTurns:[]};let n=null;try{if(n=x(e),!n)return {path:e,exists:!1,sessions:[],executions:[],events:[],duplicateCandidates:[],hookFallbacks:[],memoryTurns:[]};let o=c(n,"sessions")?n.prepare("SELECT * FROM sessions WHERE id = ?").all(t):[],i=h(n,"skill_executions","session_id"),l=c(n,"skill_executions")?n.prepare(i?"SELECT * FROM skill_executions WHERE session_id = ? OR execution_id = ? ORDER BY started_at":"SELECT * FROM skill_executions WHERE execution_id = ? ORDER BY started_at").all(...i?[t,t]:[t]):[],u=l.map(s=>a(s.execution_id)).filter(s=>s!==null),p=h(n,"tool_call_events","tool_use_id"),m=h(n,"tool_call_events","session_id"),y=h(n,"tool_call_events","kind"),g=u.length>0?`execution_id IN (${u.map(()=>"?").join(",")})`:"execution_id = ?",C=u.length>0?u:[t],k=(c(n,"tool_call_events")?n.prepare(`SELECT * FROM tool_call_events WHERE ${m?"session_id = ? OR ":""}${g} ORDER BY timestamp`).all(...m?[t,...C]:C):[]).map(s=>({id:a(s.event_id)??"unknown",sessionId:a(s.session_id),executionId:a(s.execution_id),timestamp:j(s.timestamp),tool:a(s.tool_name),toolType:a(s.tool_type),toolUseId:p?a(s.tool_use_id):null,input:T(s.input),command:null,kind:y?a(s.kind):null,fallback:S(s.mcp_fallback),failed:a(s.error)!==null&&!S(s.blocked),blocked:S(s.blocked),processed:!1})),r=c(n,"devflow_hook_fallbacks")?n.prepare("SELECT * FROM devflow_hook_fallbacks WHERE session_id = ? ORDER BY created_at").all(t):[],f=c(n,"devflow_memory_turns")?n.prepare("SELECT * FROM devflow_memory_turns WHERE session_id = ? ORDER BY created_at").all(t):[];return {path:e,exists:!0,sessions:o,executions:l,events:k,duplicateCandidates:$(k),hookFallbacks:r,memoryTurns:f}}catch(o){return {path:e,exists:true,sessions:[],executions:[],events:[],duplicateCandidates:[],hookFallbacks:[],memoryTurns:[],error:o instanceof Error?o.message:String(o)}}finally{n?.close();}}function W(e,t){let n=join(e,".devflow","memory","memories.db"),o={databasePath:n,session:null,eventCount:0,processedEventCount:0,pendingEventCount:0,eventsByTool:[],duplicateCandidates:[],projectObservationCount:0,quarantinedObservationCount:0,supersededObservationCount:0,sessionObservationCount:0,sessionObservationVectorCount:0,projectObservationVectorCount:0,pendingLeaseCount:0,distillReceiptIds:[],activeSessionCount:0};if(!existsSync(n))return o;let i=null;try{if(i=x(n),!i)return o;let u=(c(i,"session_events")?i.prepare("SELECT * FROM session_events WHERE session_id = ? ORDER BY created_at").all(t):[]).map(r=>({id:a(r.id)??"unknown",sessionId:a(r.session_id),executionId:null,timestamp:j(r.created_at),tool:a(r.tool),toolType:null,toolUseId:null,input:T(r.payload),command:a(r.command),kind:a(r.kind),fallback:!1,failed:!1,blocked:!1,processed:S(r.processed)})),p=c(i,"observations")?i.prepare(`
2
+ SELECT session_id, embedding, quality_status, resolution_state
3
+ FROM observations
4
+ `).all():[],m=c(i,"sessions")?i.prepare("SELECT * FROM sessions WHERE id = ?").get(t)??null:null,y=new Map;for(let r of u){let f=`${r.tool??""}\0${r.kind??""}`,s=y.get(f)??{tool:r.tool,kind:r.kind,count:0};s.count+=1,y.set(f,s);}let g=p.filter(r=>a(r.quality_status)!=="quarantined"&&a(r.resolution_state)!=="superseded"),C=g.filter(r=>r.session_id===t),_=c(i,"distill_receipts")&&c(i,"distill_leases")?i.prepare(`
5
+ SELECT r.receipt_id, l.session_ids
6
+ FROM distill_receipts r
7
+ JOIN distill_leases l ON l.batch_id = r.batch_id
8
+ ORDER BY r.created_at
9
+ `).all().filter(r=>L(r.session_ids).includes(t)).map(r=>a(r.receipt_id)).filter(r=>r!==null):[],k=r=>r.embedding!==null&&r.embedding!==void 0;return {databasePath:n,session:m,eventCount:u.length,processedEventCount:u.filter(r=>r.processed).length,pendingEventCount:u.filter(r=>!r.processed).length,eventsByTool:[...y.values()].sort((r,f)=>f.count-r.count),duplicateCandidates:$(u),projectObservationCount:g.length,quarantinedObservationCount:p.filter(r=>a(r.quality_status)==="quarantined").length,supersededObservationCount:p.filter(r=>a(r.resolution_state)==="superseded").length,sessionObservationCount:C.length,sessionObservationVectorCount:C.filter(k).length,projectObservationVectorCount:g.filter(k).length,pendingLeaseCount:c(i,"distill_leases")?R(i,"SELECT COUNT(*) AS count FROM distill_leases WHERE status = 'pending'"):0,distillReceiptIds:_,activeSessionCount:c(i,"sessions")?R(i,"SELECT COUNT(*) AS count FROM sessions WHERE status = 'active'"):0}}catch(l){return {...o,error:l instanceof Error?l.message:String(l)}}finally{i?.close();}}function B(e){let t=join(e,".devflow","knowledge","knowledge.db"),n={databasePath:t,documentCount:0,chunkCount:0,emptyTitleCount:0,vectorRowCount:0,sourceCounts:[]};if(!existsSync(t))return n;let o=null;try{if(o=x(t),!o)return n;let i=c(o,"knowledge_docs")?R(o,"SELECT COUNT(*) AS count FROM knowledge_docs"):0,l=c(o,"knowledge_chunks")?R(o,"SELECT COUNT(*) AS count FROM knowledge_chunks"):0,u=c(o,"knowledge_docs")?R(o,"SELECT COUNT(*) AS count FROM knowledge_docs WHERE TRIM(COALESCE(title, '')) = ''"):0,p=c(o,"knowledge_docs")?o.prepare("SELECT source, COUNT(*) AS count FROM knowledge_docs GROUP BY source ORDER BY count DESC").all().map(m=>({source:a(m.source),count:Number(m.count??0)})):[];return {databasePath:t,documentCount:i,chunkCount:l,emptyTitleCount:u,vectorRowCount:c(o,"knowledge_vec_rowids")?R(o,"SELECT COUNT(*) AS count FROM knowledge_vec_rowids"):0,sourceCounts:p}}catch(i){return {...n,error:i instanceof Error?i.message:String(i)}}finally{o?.close();}}function H(){let e=join(homedir(),".claude","plugins","cache","devflow-local","devflow");if(!existsSync(e))return null;let t=readdirSync(e,{withFileTypes:true}).filter(n=>n.isDirectory()).map(n=>n.name).sort();return t.length>0?join(e,t[t.length-1]):null}function D(e){if(!e)return null;try{let t=JSON.parse(readFileSync(join(e,".claude-plugin","plugin.json"),"utf8"));return a(t.version)}catch{return null}}function Y(e,t){try{return execFileSync(e,t,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}function J(e,t,n){let o=join(e,".devflow","logs","traces");if(!existsSync(o))return null;let i=[];for(let l of readdirSync(o,{withFileTypes:true})){if(!l.isDirectory())continue;for(let p of t){let m=join(o,l.name,`${p}.jsonl`);existsSync(m)&&i.push(m);}let u=join(o,l.name,`${n}.jsonl`);existsSync(u)&&i.push(u);}return i[0]??null}function K(e){if(!e)return null;try{return readFileSync(e,"utf8").split(`
10
+ `).filter(t=>t.trim().length>0).length}catch{return null}}function z(e){try{return execFileSync("git",["-C",e,"status","--short","--branch"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return "unavailable"}}function G(e,t){let n=process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),o=[join(n,"devflow.db"),join(e,".devflow","devflow.db")],i=o.filter((s,v)=>o.indexOf(s)===v).map(s=>U(s,t)),l=i.flatMap(s=>s.events),u=i.flatMap(s=>s.hookFallbacks),p=i.flatMap(s=>s.memoryTurns),m=[...new Set(i.flatMap(s=>s.executions).map(s=>a(s.execution_id)).filter(s=>s!==null))],y=new Map;for(let s of l)y.set(s.tool,(y.get(s.tool)??0)+1);let g=H(),C=J(e,m,t),_=W(e,t),k=B(e),r=join(homedir(),".claude","skills","devflow:react","SKILL.md"),f=i.find(s=>s.executions.length>0)??i.find(s=>s.sessions.length>0);return {schemaVersion:1,readOnly:true,generatedAt:new Date().toISOString(),project:{root:e,gitStatus:z(e)},query:{sessionId:t,executionIds:m},runtime:{nodeVersion:process.version,claudeVersion:Y("claude",["--version"]),devflowVersion:D(g),activePluginPath:g,activePluginVersion:D(g),activeReactSkillPath:g?join(g,"skills","react","SKILL.md"):null,activeReactSkillExists:g?existsSync(join(g,"skills","react","SKILL.md")):false,legacyReactSkillPath:r,legacyReactSkillExists:existsSync(r),tracePath:C,traceEventCount:K(C)},telemetry:{databases:i,eventCount:l.length,mcpEventCount:l.filter(s=>s.toolType==="mcp").length,fallbackCount:l.filter(s=>s.fallback).length+u.length,fallbackReasons:[...new Set([...l.filter(s=>s.fallback).map(()=>"direct_tool_during_context"),...u.map(s=>`daemon_${a(s.reason)??"unknown"}`)])],actualFailureCount:l.filter(s=>s.failed).length,missedTools:L(f?.executions[0]?.missed_mcp_tools),memoryReceiptIds:[...new Set(p.map(s=>a(s.receipt_id)).filter(s=>s!==null))],missingMemoryDecisionCount:p.filter(s=>a(s.status)==="pending").length,blockedCount:l.filter(s=>s.blocked).length,duplicateCandidates:$(l),byTool:[...y.entries()].map(([s,v])=>({tool:s,count:v})).sort((s,v)=>v.count-s.count||String(s.tool).localeCompare(String(v.tool)))},memory:_,knowledge:k,lifecycle:{telemetrySession:f?.sessions[0]??null,telemetryExecution:f?.executions[0]??null,memorySession:_.session}}}function Q(e){let t=e.telemetry,n=e.memory,o=e.lifecycle;return [`Session audit: ${e.query.sessionId}`,`Project: ${e.project.root}`,`Git: ${e.project.gitStatus||"(clean)"}`,`Telemetry: ${t.eventCount} events (${t.mcpEventCount} MCP, ${t.fallbackCount} fallback, ${t.actualFailureCount} failed, ${t.blockedCount} blocked)`,`Compliance: missed tools ${t.missedTools.join(", ")||"none"}; fallback reasons ${t.fallbackReasons.join(", ")||"none"}`,`Memory decisions: ${t.memoryReceiptIds.length} receipts, ${t.missingMemoryDecisionCount} pending; distill receipts ${e.memory.distillReceiptIds.length}`,`Memory events: ${n.eventCount} (${n.processedEventCount} processed, ${n.pendingEventCount} pending)`,`Observations: ${n.sessionObservationCount} eligible for session / ${n.projectObservationCount} eligible for project; embedding coverage ${n.sessionObservationVectorCount}/${n.sessionObservationCount} for session, ${n.projectObservationVectorCount}/${n.projectObservationCount} for project`,`Observation exclusions: ${n.quarantinedObservationCount} quarantined, ${n.supersededObservationCount} superseded`,`Duplicates: ${t.duplicateCandidates.length} telemetry candidate groups, ${n.duplicateCandidates.length} Memory candidate groups`,`Lifecycle: telemetry ${a(o.telemetrySession?.status)??"missing"}, execution ${a(o.telemetryExecution?.status)??"missing"}, memory ${a(o.memorySession?.status)??"missing"}`,`Knowledge: ${e.knowledge.documentCount} docs, ${e.knowledge.chunkCount} chunks, ${e.knowledge.vectorRowCount} vectors, ${e.knowledge.emptyTitleCount} empty titles`,`Runtime: Claude ${e.runtime.claudeVersion??"unknown"}, DevFlow ${e.runtime.devflowVersion??"unknown"}, trace events ${e.runtime.traceEventCount??"unknown"}`].join(`
11
+ `)}function X(){try{let e=V(process.argv.slice(2)),t=G(e.project,e.session);process.stdout.write(e.json?`${JSON.stringify(t,null,2)}
12
+ `:`${Q(t)}
5
13
  `);}catch(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}
6
- `),process.exitCode=1;}}z();
14
+ `),process.exitCode=1;}}X();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/devflow",
3
- "version": "0.16.8",
3
+ "version": "0.16.10",
4
4
  "type": "module",
5
5
  "description": "DevFlow - Developer Intelligence Platform (Distribution Package)",
6
6
  "bin": {
@@ -16,17 +16,17 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@colbymchenry/codegraph": "^1.1.1",
19
- "@devflow-tools/adapters": "0.16.8",
20
- "@devflow-tools/benchmark": "0.16.8",
21
- "@devflow-tools/context-engine": "0.16.8",
22
- "@devflow-tools/database": "0.16.8",
23
- "@devflow-tools/knowledge-engine": "0.16.8",
24
- "@devflow-tools/mcp-server": "0.16.8",
25
- "@devflow-tools/memory-engine": "0.16.8",
26
- "@devflow-tools/sdk": "0.16.8",
27
- "@devflow-tools/server": "0.16.8",
28
- "@devflow-tools/telemetry": "0.16.8",
29
- "@devflow-tools/workflow-engine": "0.16.8",
19
+ "@devflow-tools/adapters": "0.16.10",
20
+ "@devflow-tools/benchmark": "0.16.10",
21
+ "@devflow-tools/context-engine": "0.16.10",
22
+ "@devflow-tools/database": "0.16.10",
23
+ "@devflow-tools/knowledge-engine": "0.16.10",
24
+ "@devflow-tools/mcp-server": "0.16.10",
25
+ "@devflow-tools/memory-engine": "0.16.10",
26
+ "@devflow-tools/sdk": "0.16.10",
27
+ "@devflow-tools/server": "0.16.10",
28
+ "@devflow-tools/telemetry": "0.16.10",
29
+ "@devflow-tools/workflow-engine": "0.16.10",
30
30
  "@inquirer/prompts": "^7.10.1",
31
31
  "@modelcontextprotocol/sdk": "^1.0.0",
32
32
  "@nestjs/common": "^10.4.0",
@@ -54,5 +54,5 @@
54
54
  "plugin-registry.json",
55
55
  "scripts/postinstall.js"
56
56
  ],
57
- "gitHead": "38b7ea6653ad6e0d3edb7eae260367032f0bb854"
57
+ "gitHead": "964af33767bf232606e63d973b3a29d7d53c8119"
58
58
  }
@@ -1,172 +1,172 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "lastUpdated": "2026-07-23T05:39:06.572Z",
3
+ "lastUpdated": "2026-07-24T01:37:36.437Z",
4
4
  "plugins": [
5
5
  {
6
6
  "name": "@devflow-tools/plugin-animation",
7
- "version": "0.16.8",
7
+ "version": "0.16.10",
8
8
  "description": "",
9
9
  "tags": [],
10
10
  "compatibleStacks": [
11
11
  "animation"
12
12
  ],
13
- "size": "121615 B",
13
+ "size": "122425 B",
14
14
  "author": "DevFlow Team",
15
15
  "homepage": ""
16
16
  },
17
17
  {
18
18
  "name": "@devflow-tools/plugin-css",
19
- "version": "0.16.8",
19
+ "version": "0.16.10",
20
20
  "description": "",
21
21
  "tags": [],
22
22
  "compatibleStacks": [
23
23
  "css"
24
24
  ],
25
- "size": "109094 B",
25
+ "size": "109892 B",
26
26
  "author": "DevFlow Team",
27
27
  "homepage": ""
28
28
  },
29
29
  {
30
30
  "name": "@devflow-tools/plugin-docker",
31
- "version": "0.16.8",
31
+ "version": "0.16.10",
32
32
  "description": "",
33
33
  "tags": [],
34
34
  "compatibleStacks": [
35
35
  "docker"
36
36
  ],
37
- "size": "137912 B",
37
+ "size": "138716 B",
38
38
  "author": "DevFlow Team",
39
39
  "homepage": ""
40
40
  },
41
41
  {
42
42
  "name": "@devflow-tools/plugin-electron",
43
- "version": "0.16.8",
43
+ "version": "0.16.10",
44
44
  "description": "",
45
45
  "tags": [],
46
46
  "compatibleStacks": [
47
47
  "electron"
48
48
  ],
49
- "size": "153595 B",
49
+ "size": "154403 B",
50
50
  "author": "DevFlow Team",
51
51
  "homepage": ""
52
52
  },
53
53
  {
54
54
  "name": "@devflow-tools/plugin-git",
55
- "version": "0.16.8",
55
+ "version": "0.16.10",
56
56
  "description": "",
57
57
  "tags": [],
58
58
  "compatibleStacks": [
59
59
  "git"
60
60
  ],
61
- "size": "119442 B",
61
+ "size": "120240 B",
62
62
  "author": "DevFlow Team",
63
63
  "homepage": ""
64
64
  },
65
65
  {
66
66
  "name": "@devflow-tools/plugin-graphql",
67
- "version": "0.16.8",
67
+ "version": "0.16.10",
68
68
  "description": "",
69
69
  "tags": [],
70
70
  "compatibleStacks": [
71
71
  "graphql"
72
72
  ],
73
- "size": "121599 B",
73
+ "size": "122405 B",
74
74
  "author": "DevFlow Team",
75
75
  "homepage": ""
76
76
  },
77
77
  {
78
78
  "name": "@devflow-tools/plugin-nest",
79
- "version": "0.16.8",
79
+ "version": "0.16.10",
80
80
  "description": "",
81
81
  "tags": [],
82
82
  "compatibleStacks": [
83
83
  "nest"
84
84
  ],
85
- "size": "158686 B",
85
+ "size": "159486 B",
86
86
  "author": "DevFlow Team",
87
87
  "homepage": ""
88
88
  },
89
89
  {
90
90
  "name": "@devflow-tools/plugin-nextjs",
91
- "version": "0.16.8",
91
+ "version": "0.16.10",
92
92
  "description": "",
93
93
  "tags": [],
94
94
  "compatibleStacks": [
95
95
  "nextjs"
96
96
  ],
97
- "size": "120245 B",
97
+ "size": "121049 B",
98
98
  "author": "DevFlow Team",
99
99
  "homepage": ""
100
100
  },
101
101
  {
102
102
  "name": "@devflow-tools/plugin-performance",
103
- "version": "0.16.8",
103
+ "version": "0.16.10",
104
104
  "description": "",
105
105
  "tags": [],
106
106
  "compatibleStacks": [
107
107
  "performance"
108
108
  ],
109
- "size": "170101 B",
109
+ "size": "170915 B",
110
110
  "author": "DevFlow Team",
111
111
  "homepage": ""
112
112
  },
113
113
  {
114
114
  "name": "@devflow-tools/plugin-react",
115
- "version": "0.16.8",
115
+ "version": "0.16.10",
116
116
  "description": "",
117
117
  "tags": [],
118
118
  "compatibleStacks": [
119
119
  "react"
120
120
  ],
121
- "size": "281624 B",
121
+ "size": "281966 B",
122
122
  "author": "DevFlow Team",
123
123
  "homepage": ""
124
124
  },
125
125
  {
126
126
  "name": "@devflow-tools/plugin-tailwind",
127
- "version": "0.16.8",
127
+ "version": "0.16.10",
128
128
  "description": "",
129
129
  "tags": [],
130
130
  "compatibleStacks": [
131
131
  "tailwind"
132
132
  ],
133
- "size": "126262 B",
133
+ "size": "127070 B",
134
134
  "author": "DevFlow Team",
135
135
  "homepage": ""
136
136
  },
137
137
  {
138
138
  "name": "@devflow-tools/plugin-taro",
139
- "version": "0.16.8",
139
+ "version": "0.16.10",
140
140
  "description": "",
141
141
  "tags": [],
142
142
  "compatibleStacks": [
143
143
  "taro"
144
144
  ],
145
- "size": "129873 B",
145
+ "size": "130673 B",
146
146
  "author": "DevFlow Team",
147
147
  "homepage": ""
148
148
  },
149
149
  {
150
150
  "name": "@devflow-tools/plugin-ui-layout",
151
- "version": "0.16.8",
151
+ "version": "0.16.10",
152
152
  "description": "",
153
153
  "tags": [],
154
154
  "compatibleStacks": [
155
155
  "ui-layout"
156
156
  ],
157
- "size": "106984 B",
157
+ "size": "107794 B",
158
158
  "author": "DevFlow Team",
159
159
  "homepage": ""
160
160
  },
161
161
  {
162
162
  "name": "@devflow-tools/plugin-vue",
163
- "version": "0.16.8",
163
+ "version": "0.16.10",
164
164
  "description": "",
165
165
  "tags": [],
166
166
  "compatibleStacks": [
167
167
  "vue"
168
168
  ],
169
- "size": "138518 B",
169
+ "size": "139316 B",
170
170
  "author": "DevFlow Team",
171
171
  "homepage": ""
172
172
  }