@devflow-tools/cli 0.16.11 → 0.16.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {getLocalApiKey}from'@devflow-tools/sdk/auth';import {classifyWorkflowFailure}from'@devflow-tools/workflow-engine/failure-classifier';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,renameSync,readdirSync,unlinkSync}from'fs';import {join}from'path';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey as getLocalApiKey$1,getProjectStateDir}from'@devflow-tools/sdk';import {randomUUID,createHash}from'crypto';var S=1e4,j=3e4,h=500;function L(o,t,e){return new Promise(r=>{try{let s=new URL(o),n=request({hostname:s.hostname,port:s.port||80,path:s.pathname+s.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);});});n.on("error",()=>r(null)),n.on("timeout",()=>{n.destroy(),r(null);}),n.write(t),n.end();}catch{r(null);}})}var g=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$1(),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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,s,n=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:t,sessionId:e,skillName:r,startedAt:s,projectRoot:n,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",r=Date.now(),s){let n={executionId:t,status:e,finishedAt:r,metadata:s},i=this.commitOrCache("execution_complete",n);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",n),i}async sendSessionStart(t,e,r){let s={id:t,projectRoot:e,startedAt:r,label:e.split("/").pop()??"unknown"},n=this.commitOrCache("session_start",s);return n&&this.postHttp("/api/telemetry/sessions",s),n}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},s=this.commitOrCache("session_end",r);return s&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),s}async flushCache(){try{let r=this.getDatabase(),s=r.listTelemetryFailures({unresolvedOnly:!0,limit:h}).reverse();for(let n of s)try{this.applyOperation(n.operation,n.payload),r.resolveTelemetryFailure(n.id);}catch{}r.trimTelemetryFailures(h);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(r=>!!r))].filter(r=>existsSync(r)).flatMap(r=>readdirSync(r).filter(s=>s.endsWith(".json")).map(s=>{let n=join(r,s);try{return {cacheFile:n,envelope:$(JSON.parse(readFileSync(n,"utf8")),s)}}catch{return null}})).filter(r=>r!==null).sort((r,s)=>r.envelope.timestamp-s.envelope.timestamp||w(r.envelope.operation)-w(s.envelope.operation));for(let{cacheFile:r,envelope:s}of e)try{let n=this.getDatabase();n.insertTelemetryFailure({id:s.id,operation:s.operation,payload:s.payload,error:s.failure,createdAt:s.timestamp}),this.applyOperation(s.operation,s.payload),n.resolveTelemetryFailure(s.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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),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:R(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(R(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 s=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:s,label:s==="unknown"?void 0:s.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,r){let s=Date.now(),n={id:`failure:${s}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:r instanceof Error?r.message:String(r),timestamp:s};try{let i=this.getDatabase();i.insertTelemetryFailure({id:n.id,operation:t,payload:e,error:n.failure,createdAt:s}),i.trimTelemetryFailures(h),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${s}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(n,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-h)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},j).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){L(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=S?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,S)}...`}}};function w(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function R(o){return `hook-run:${o}`}function $(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 s=e.payload??{},n=Number(s.timestamp??s.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:r,payload:s,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:n}}function J(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function I(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(J(o))}function X(o){return Buffer.from(o,"utf8").toString("base64url")}var f=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 s=Date.now(),n={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:s,lastActivityAt:s};return this.sessions.set(e,n),this.persist(n),n}startExecution(t,e,r){let s=this.registerSession(t);return (!s.executionId||s.skillName!==e)&&(s.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),s.skillName=e,s.requiredMcpTools=[...new Set(r)],s.lastActivityAt=Date.now(),this.persist(s),s}get(t){let e=t.trim();if(!e)return null;let r=this.sessions.get(e);if(r)return r;let s=this.snapshotPath(e);if(!existsSync(s))return null;try{let n=JSON.parse(readFileSync(s,"utf8"));return n.sessionId!==e||n.projectRoot!==this.projectRoot?null:(n.requiredMcpTools=Array.isArray(n.requiredMcpTools)?n.requiredMcpTools:[],this.sessions.set(e,n),n)}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,`${X(t)}.json`)}persist(t){mkdirSync(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 O(o,t){return t?`evt_tool_${createHash("sha256").update(`${o}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var te=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",re=getLocalApiKey(),_=process.env.CLAUDE_PROJECT_DIR||process.cwd();function v(o,t){let e=Number(o);return Number.isInteger(e)&&e>=0?e:t}function se(o,t,e){return new Promise((r,s)=>{let n=JSON.stringify(t),i=new URL(o,te),a=false,c=l=>{a||(a=true,l?s(l):r());},u=request({hostname:i.hostname,port:i.port,path:i.pathname+i.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":re,"Content-Length":Buffer.byteLength(n)},timeout:e},l=>{l.on("error",c),l.on("end",()=>{let d=l.statusCode??0;if(d<200||d>=300){c(new Error(`HTTP ${d}`));return}c();}),l.resume();});u.on("error",c),u.on("timeout",()=>{u.destroy(new Error(`PostToolUseFailure request timed out after ${e}ms`));}),u.write(n),u.end();})}function ne(o){return new Promise(t=>setTimeout(t,o))}async function oe(o,t){let e=t.timeoutMs??v(process.env.DEVFLOW_FAILURE_TIMEOUT_MS,1500),r=t.maxRetries??v(process.env.DEVFLOW_FAILURE_MAX_RETRIES,2),s=t.retryDelayMs??v(process.env.DEVFLOW_FAILURE_RETRY_DELAY_MS,100),n=`/api/memory/session-events?rootPath=${encodeURIComponent(_)}`;for(let i=0;i<=r;i+=1)try{await se(n,o,e);return}catch(a){if(i===r)throw a;await ne(s*2**i);}}async function ie(o,t={}){let e;try{e=JSON.parse(o);}catch{return}let r=e.tool_name||"",s=e.tool_input||{},n=e.error||"",i=e.session_id?.trim();if(!i)return;let a=new f(_).registerSession(i),c=O(i,e.tool_use_id),u=classifyWorkflowFailure({stepId:r,toolName:r,error:new Error(n||`${r||"tool"} failed`),errorStack:n||void 0}),l=typeof s=="object"&&s.command?s.command:r,d={id:`memory:${c}`,sessionId:i,tool:r,command:l,exitCode:-1,stderr:n,durationMs:0,createdAt:Date.now(),kind:r==="Bash"?"bash_error":"tool_use",payload:{command:l,exitCode:-1,stderr:n,failureSource:"PostToolUseFailure",failureCategory:u.category}},P=!t.telemetryClient,y=t.telemetryClient??new g,p=r.startsWith("mcp__"),A={eventId:c,executionId:a.executionId??i,sessionId:i,projectRoot:_,toolUseId:e.tool_use_id,timestamp:d.createdAt,toolName:r,toolType:p?"mcp":"direct",isMcpTool:p,mcpToolName:p?r:void 0,mcpEnforced:p,mcpFallback:false,kind:"error",input:s,duration:0,error:n,blocked:false,failureCategory:u.category};try{await y.sendEvent(A),await y.completeEvent({eventId:c,sessionId:i,error:n,duration:0,completedAt:Date.now()});}finally{P&&y.close();}t.eventDelivery?await t.eventDelivery(d):await oe(d,t);}if(process.argv[1]?.endsWith("post-tool-use-failure")||process.argv[1]?.endsWith("post-tool-use-failure.js")){let o=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{try{await ie(t.trim()||process.argv[2]||""),o(JSON.stringify({status:"ok"}));}catch(e){console.error("[devflow] PostToolUseFailure delivery failed:",e.message),o(JSON.stringify({status:"degraded",reason:"post_tool_failure_delivery_failed",fallback:"durable_retry_on_next_runtime"}));}}),process.stdin.on("error",e=>{console.error("[devflow] PostToolUseFailure input failed:",e.message),o(JSON.stringify({status:"degraded",reason:"post_tool_failure_input_failed",fallback:"host_event_continues"}));});}
2
- export{ie as handlePostToolUseFailure};
1
+ import {request}from'http';import {getLocalApiKey}from'@devflow-tools/sdk/auth';import {classifyWorkflowFailure}from'@devflow-tools/workflow-engine/failure-classifier';import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync}from'fs';import {join}from'path';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey as getLocalApiKey$1,getProjectStateDir}from'@devflow-tools/sdk';import {randomUUID,createHash}from'crypto';var T=1e4,G=3e4,f=500;function Q(s,t,e){return new Promise(n=>{try{let i=new URL(s),r=request({hostname:i.hostname,port:i.port||80,path:i.pathname+i.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},o=>{let a=[];o.on("data",c=>a.push(c)),o.on("end",()=>{let c=Buffer.concat(a).toString();n(o.statusCode!=null&&o.statusCode>=200&&o.statusCode<300?c:null);});});r.on("error",()=>n(null)),r.on("timeout",()=>{r.destroy(),n(null);}),r.write(t),r.end();}catch{n(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$1(),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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,n,i,r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),o=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:i,projectRoot:r,requiredMcpTools:o};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",n=Date.now(),i){let r={executionId:t,status:e,finishedAt:n,metadata:i},o=this.commitOrCache("execution_complete",r);return o&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",r),o}async sendSessionStart(t,e,n){let i={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},r=this.commitOrCache("session_start",i);return r&&this.postHttp("/api/telemetry/sessions",i),r}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 n={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",n);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let n=this.getDatabase(),i=n.listTelemetryFailures({unresolvedOnly:!0,limit:f}).reverse();for(let r of i)try{this.applyOperation(r.operation,r.payload),n.resolveTelemetryFailure(r.id);}catch{}n.trimTelemetryFailures(f);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(i=>i.endsWith(".json")).map(i=>{let r=join(n,i);try{return {cacheFile:r,envelope:ee(JSON.parse(readFileSync(r,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||R(n.envelope.operation)-R(i.envelope.operation));for(let{cacheFile:n,envelope:i}of e)try{let r=this.getDatabase();r.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),r.resolveTelemetryFailure(i.id),unlinkSync(n);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:k(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(!n.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":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(k(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let i=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:n,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let i=Date.now(),r={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:i};try{let o=this.getDatabase();o.insertTelemetryFailure({id:r.id,operation:t,payload:e,error:r.failure,createdAt:i}),o.trimTelemetryFailures(f),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let o=join(this.cacheDir,`${i}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(o,JSON.stringify(r,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-f)))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(t,e){Q(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=T?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,T)}...`}}};function R(s){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(s)}function k(s){return `hook-run:${s}`}function ee(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 n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let i=e.payload??{},r=Number(i.timestamp??i.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:r}}function ne(s){return s??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function C(s){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(ne(s))}function M(s){return Buffer.from(s,"utf8").toString("base64url")}function se(s,t,e){let n=t?.trim();if(n){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${s}:${i}`}return `${s}:legacy-${e}-${randomUUID().slice(0,8)}`}function L(s){return `${s}:legacy-journal`}var y=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(C(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let i=Date.now(),r={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,r),this.persist(r),r}startExecution(t,e,n){let i=this.registerSession(t);return (!i.executionId||i.skillName!==e)&&(i.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),i.skillName=e,i.requiredMcpTools=[...new Set(n)],i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let i=this.snapshotPath(e);if(!existsSync(i))return null;try{let r=JSON.parse(readFileSync(i,"utf8"));return r.sessionId!==e||r.projectRoot!==this.projectRoot?null:(r.requiredMcpTools=Array.isArray(r.requiredMcpTools)?r.requiredMcpTools:[],r.evidenceObligations=$(r.evidenceObligations),r.evidenceDegradations=J(r.evidenceDegradations),r.evidenceOutcomes=j(r.evidenceOutcomes),this.replayEvidenceJournal(r),this.sessions.set(e,r),r)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let n=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}addEvidenceObligation(t,e,n=Date.now(),i){let r=this.registerSession(t),a=(i?void 0:r.evidenceObligations.find(d=>d.contractId===e.id))?.obligationId??se(e.id,i,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:n,contract:e},`add\0${a}`),this.replayEvidenceJournal(r);let c=r.evidenceObligations.find(d=>d.obligationId===a);return c?(r.lastActivityAt=Date.now(),this.persist(r),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,i,r=Date.now()){let o=this.get(t),a=o?.evidenceObligations.find(l=>l.obligationId===e);if(!o||!a)return null;let c=/^[a-f0-9]{64}$/.test(i)?i:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:r,fingerprint:c,violations:n.slice(0,16).map(l=>l.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(o),o.lastActivityAt=r,this.persist(o);let d=o.evidenceObligations.find(l=>l.obligationId===e);return d?structuredClone(d):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let i=n.evidenceObligations.find(o=>o.obligationId===e);if(!i)return false;let r=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:r},`resolve\0${e}`),this.replayEvidenceJournal(n),n.lastActivityAt=r,this.persist(n),true}degradeEvidenceObligation(t,e,n,i=Date.now()){let r=this.get(t),o=r?.evidenceObligations.find(c=>c.obligationId===e);if(!r||!o)return false;let a=n.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:o.contractId,at:i,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(r),r.lastActivityAt=i,this.persist(r),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join(this.sessionsDir,`${M(t)}.json`)}evidenceJournalDir(t){return join(this.sessionsDir,"evidence-journal",M(t))}appendEvidenceEvent(t,e,n){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let r=createHash("sha256").update(n).digest("hex"),o=join(i,`${e.kind}-${r}.json`);if(existsSync(o))return;let a=join(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,o);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=$(t.evidenceObligations),t.evidenceDegradations=J(t.evidenceDegradations),t.evidenceOutcomes=j(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let n;try{n=readdirSync(e).filter(r=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(r)).slice(0,4096);}catch{return}let i=n.flatMap(r=>{try{let o=readFileSync(join(e,r),"utf8");if(Buffer.byteLength(o,"utf8")>64*1024)return [];let a=ae(JSON.parse(o));return a?[a]:[]}catch{return []}}).sort((r,o)=>r.at-o.at||N(r.kind)-N(o.kind));for(let r of i)this.applyEvidenceEvent(t,r);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let n=t.evidenceOutcomes.find(o=>o.obligationId===e.obligationId);if(e.kind==="add"){if(n)return;let o=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);o?(o.contract=e.contract,o.promptedAt=Math.min(o.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let i=t.evidenceObligations.find(o=>o.obligationId===e.obligationId);if(e.kind==="correction"){if(!i||n||i.correctionFingerprint===e.fingerprint)return;i.attempt+=1,i.correctionRequested=true,i.correctionRequestedAt=e.at,i.correctionFingerprint=e.fingerprint,i.violations=e.violations;return}let r=i?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(o=>o.obligationId!==e.obligationId),!n&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:r}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:r,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(n,JSON.stringify(t),{mode:384}),renameSync(n,e);}};function $(s){return Array.isArray(s)?s.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!q(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:L(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,r=e.correctionFingerprint??i;return r!==void 0&&!/^[a-f0-9]{64}$/.test(r)?[]:[{...e,obligationId:n,correctionFingerprint:r}]}).slice(-8):[]}function J(s){return Array.isArray(s)?s.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function j(s){return Array.isArray(s)?s.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function ae(s){if(!s||typeof s!="object")return null;let t=s;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:L(t.contractId);if(t.kind==="add")return q(t.contract)?{...t,obligationId:e}:null;if(t.kind==="correction"){let n=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof n=="string"&&/^[a-f0-9]{64}$/.test(n)&&Array.isArray(t.violations)&&t.violations.every(i=>typeof i=="string"&&i.length<=240)?{...t,obligationId:e,fingerprint:n}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function N(s){return s==="add"?0:s==="correction"?1:2}function q(s){if(!s||typeof s!="object")return false;let t=s,e=t.requiredSections,n=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(n)&&n.length<=16&&n.every(i=>typeof i=="string"&&i.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function H(s,t){return t?`evt_tool_${createHash("sha256").update(`${s}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var pe=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",ge=getLocalApiKey(),O=process.env.CLAUDE_PROJECT_DIR||process.cwd();function D(s,t){let e=Number(s);return Number.isInteger(e)&&e>=0?e:t}function me(s,t,e){return new Promise((n,i)=>{let r=JSON.stringify(t),o=new URL(s,pe),a=false,c=l=>{a||(a=true,l?i(l):n());},d=request({hostname:o.hostname,port:o.port,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":ge,"Content-Length":Buffer.byteLength(r)},timeout:e},l=>{l.on("error",c),l.on("end",()=>{let u=l.statusCode??0;if(u<200||u>=300){c(new Error(`HTTP ${u}`));return}c();}),l.resume();});d.on("error",c),d.on("timeout",()=>{d.destroy(new Error(`PostToolUseFailure request timed out after ${e}ms`));}),d.write(r),d.end();})}function fe(s){return new Promise(t=>setTimeout(t,s))}async function he(s,t){let e=t.timeoutMs??D(process.env.DEVFLOW_FAILURE_TIMEOUT_MS,1500),n=t.maxRetries??D(process.env.DEVFLOW_FAILURE_MAX_RETRIES,2),i=t.retryDelayMs??D(process.env.DEVFLOW_FAILURE_RETRY_DELAY_MS,100),r=`/api/memory/session-events?rootPath=${encodeURIComponent(O)}`;for(let o=0;o<=n;o+=1)try{await me(r,s,e);return}catch(a){if(o===n)throw a;await fe(i*2**o);}}async function ve(s,t={}){let e;try{e=JSON.parse(s);}catch{return}let n=e.tool_name||"",i=e.tool_input||{},r=e.error||"",o=e.session_id?.trim();if(!o)return;let a=new y(O).registerSession(o),c=H(o,e.tool_use_id),d=classifyWorkflowFailure({stepId:n,toolName:n,error:new Error(r||`${n||"tool"} failed`),errorStack:r||void 0}),l=typeof i=="object"&&i.command?i.command:n,u={id:`memory:${c}`,sessionId:o,tool:n,command:l,exitCode:-1,stderr:r,durationMs:0,createdAt:Date.now(),kind:n==="Bash"?"bash_error":"tool_use",payload:{command:l,exitCode:-1,stderr:r,failureSource:"PostToolUseFailure",failureCategory:d.category}},W=!t.telemetryClient,b=t.telemetryClient??new h,m=n.startsWith("mcp__"),V={eventId:c,executionId:a.executionId??o,sessionId:o,projectRoot:O,toolUseId:e.tool_use_id,timestamp:u.createdAt,toolName:n,toolType:m?"mcp":"direct",isMcpTool:m,mcpToolName:m?n:void 0,mcpEnforced:m,mcpFallback:false,kind:"error",input:i,duration:0,error:r,blocked:false,failureCategory:d.category};try{await b.sendEvent(V),await b.completeEvent({eventId:c,sessionId:o,error:r,duration:0,completedAt:Date.now()});}finally{W&&b.close();}t.eventDelivery?await t.eventDelivery(u):await he(u,t);}if(process.argv[1]?.endsWith("post-tool-use-failure")||process.argv[1]?.endsWith("post-tool-use-failure.js")){let s=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{try{await ve(t.trim()||process.argv[2]||""),s(JSON.stringify({status:"ok"}));}catch(e){console.error("[devflow] PostToolUseFailure delivery failed:",e.message),s(JSON.stringify({status:"degraded",reason:"post_tool_failure_delivery_failed",fallback:"durable_retry_on_next_runtime"}));}}),process.stdin.on("error",e=>{console.error("[devflow] PostToolUseFailure input failed:",e.message),s(JSON.stringify({status:"degraded",reason:"post_tool_failure_input_failed",fallback:"host_event_continues"}));});}
2
+ export{ve as handlePostToolUseFailure};
@@ -1,3 +1,6 @@
1
- import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,renameSync,readdirSync,unlinkSync,appendFileSync}from'fs';import {join,dirname}from'path';import {getLogWriter}from'@devflow-tools/telemetry';import {request}from'http';import {homedir}from'os';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {randomUUID,createHash}from'crypto';import {fileURLToPath}from'url';function H(o,t,e){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:o,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{n.close();}}catch{}}var M=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",be=getLocalApiKey(),_e=8,we=6e4,J=new Map;function Se(o){let t=new URL(o,M).pathname,e=J.get(t);return e||(e={failures:0,lastFailure:0,openUntil:0,status:"closed"},J.set(t,e)),e}function F(o,t,e){if(t.status===e)return;let n=t.status;t.status=e,H("http_circuit_transition",{path:new URL(o,M).pathname,previous:n,status:e,failures:t.failures,openUntil:t.openUntil});}function A(o,t){t.failures++,t.lastFailure=Date.now(),t.failures>=_e&&(t.openUntil=Date.now()+we,F(o,t,"open"));}function Re(o,t){let e=t.status!=="closed";t.failures=0,t.openUntil=0,e&&F(o,t,"closed");}var O=join(homedir(),".devflow","errors");function B(o,t){try{existsSync(O)||mkdirSync(O,{recursive:!0});let e=`${new Date().toISOString()} | ${o} | ${t?.message??String(t)}
2
- `;appendFileSync(join(O,"http-errors.log"),e);}catch{}}function K(o,t,e={}){let n=e.timeout??5e3,r=e.maxRetries??2,s=e.circuitBreaker??true,i=Se(o);if(s&&i.openUntil>Date.now())return Promise.resolve();s&&i.status==="open"&&F(o,i,"half_open");let a=c=>new Promise(l=>{let u=JSON.stringify(t),d=new URL(o,M),f=request({hostname:d.hostname,port:d.port,path:d.pathname+d.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":be,"Content-Length":Buffer.byteLength(u)},timeout:n},g=>{if(g.resume(),g.statusCode&&g.statusCode>=400){let y=new Error(`HTTP ${g.statusCode}`);if(B(o,y),c>0){let w=Math.min(1e3*Math.pow(2,r-c),8e3);setTimeout(()=>{a(c-1).then(l);},w);}else A(o,i),l();return}Re(o,i),l();});f.on("error",g=>{if(B(o,g),c>0){let y=Math.min(1e3*Math.pow(2,r-c),8e3);setTimeout(()=>{a(c-1).then(l);},y);}else A(o,i),l();}),f.on("timeout",()=>{f.destroy(),c>0?a(c-1).then(l):(A(o,i),l());}),f.write(u),f.end();});return a(r)}function j(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function h(o){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(j(o))}function R(o){if(!o||typeof o!="object"||Array.isArray(o))return {};let t=o,e={};for(let n of ["lastMcpCall","bypassCount"])if(n in t){let r=t[n];if(r==null)continue;e[n]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return e}function Ee(o,t){return o.lastMcpCall===t.lastMcpCall&&o.bypassCount===t.bypassCount}function ke(o){try{return existsSync(o)?R(JSON.parse(readFileSync(o,"utf-8"))):{}}catch{return {}}}function Ie(o,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${o} skipped: ${e}`);}function z(o){let t=h(o);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join(t,e))&&unlinkSync(join(t,e));}catch{}}function Te(o,t){if(o.getHookReceipt(t)){z(t);return}let e=join(h(t),"receipt.json");if(!existsSync(e))return;let n=ke(e);o.updateHookReceipt(t,()=>n),z(t);}function X(o,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Te(n,o);let r={},s=n.updateHookReceipt(o,a=>(r=R(a),R(t(r)))),i=R(s);return {receipt:i,applied:!0,changed:!Ee(r,i)}}catch(r){return Ie(e,r),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function U(o,t){return X(o,()=>t,"write").applied}function L(o,t){return X(o,t,"update")}var V={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function Ae(o){switch(o){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var D=class{constructor(t,e,n){this.projectRoot=t;this.sessionId=e;this.executionId=n;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}evaluate(t,e){let n=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(n==="context_gathering"&&V[t])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(n==="context_ready")return {permissionDecision:"allow"};let r=V[t];if(!r)return {permissionDecision:"allow"};let s=L(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!s.applied)return {permissionDecision:"allow"};let i=s.receipt.bypassCount??0,a=Ae(t);return i>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${i} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){U(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var ne=1e4,Ue=3e4,C=500;function Le(o,t,e){return new Promise(n=>{try{let r=new URL(o),s=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(t)},timeout:5e3},i=>{let a=[];i.on("data",c=>a.push(c)),i.on("end",()=>{let c=Buffer.concat(a).toString();n(i.statusCode!=null&&i.statusCode>=200&&i.statusCode<300?c:null);});});s.on("error",()=>n(null)),s.on("timeout",()=>{s.destroy(),n(null);}),s.write(t),s.end();}catch{n(null);}})}var x=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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,n,r,s=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:r,projectRoot:s,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",n=Date.now(),r){let s={executionId:t,status:e,finishedAt:n,metadata:r},i=this.commitOrCache("execution_complete",s);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",s),i}async sendSessionStart(t,e,n){let r={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},s=this.commitOrCache("session_start",r);return s&&this.postHttp("/api/telemetry/sessions",r),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 n={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",n);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let n=this.getDatabase(),r=n.listTelemetryFailures({unresolvedOnly:!0,limit:C}).reverse();for(let s of r)try{this.applyOperation(s.operation,s.payload),n.resolveTelemetryFailure(s.id);}catch{}n.trimTelemetryFailures(C);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(r=>r.endsWith(".json")).map(r=>{let s=join(n,r);try{return {cacheFile:s,envelope:$e(JSON.parse(readFileSync(s,"utf8")),r)}}catch{return null}})).filter(n=>n!==null).sort((n,r)=>n.envelope.timestamp-r.envelope.timestamp||re(n.envelope.operation)-re(r.envelope.operation));for(let{cacheFile:n,envelope:r}of e)try{let s=this.getDatabase();s.insertTelemetryFailure({id:r.id,operation:r.operation,payload:r.payload,error:r.failure,createdAt:r.timestamp}),this.applyOperation(r.operation,r.payload),s.resolveTelemetryFailure(r.id),unlinkSync(n);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:oe(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(!n.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":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(oe(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)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";t.ensureSession({id:n,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let r=Date.now(),s={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:r};try{let i=this.getDatabase();i.insertTelemetryFailure({id:s.id,operation:t,payload:e,error:s.failure,createdAt:r}),i.trimTelemetryFailures(C),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${r}_${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-C)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Ue).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){Le(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ne?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ne)}...`}}};function re(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function oe(o){return `hook-run:${o}`}function $e(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 n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},s=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:s}}function ze(o){return Buffer.from(o,"utf8").toString("base64url")}var E=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(h(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let r=Date.now(),s={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,s),this.persist(s),s}startExecution(t,e,n){let r=this.registerSession(t);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(n)],r.lastActivityAt=Date.now(),this.persist(r),r}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return n;let r=this.snapshotPath(e);if(!existsSync(r))return null;try{let s=JSON.parse(readFileSync(r,"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 n={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}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,`${ze(t)}.json`)}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.tmp`;writeFileSync(n,JSON.stringify(t),{mode:384}),renameSync(n,e);}};var Qe=2,et=1;function tt(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join(dirname(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function ie(o=tt()){let t=[join(o,"dist","command-registry.json"),join(o,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let n=JSON.parse(readFileSync(e,"utf8"));if(n.version!==Qe&&n.version!==et||!nt(n.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return n.commands}catch(n){console.error(`[devflow] command registry load failed: ${n.message}`);}return null}function nt(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 $(e.mcpTools)&&$(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||$(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function $(o){return Array.isArray(o)&&o.every(t=>typeof t=="string"&&t.length>0)}function ae(o){let t=ie();return t?t[o]?.mcpTools??[]:[]}function ce(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 le(o,t){return t?`evt_tool_${createHash("sha256").update(`${o}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var ut=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function pt(o,t,e,n){try{let r=join(h(o),"event-map.json");if(!existsSync(r))return null;let s=JSON.parse(readFileSync(r,"utf-8")),i=s.filter(l=>l.toolName===e&&(!l.sessionId||l.sessionId===t));if(i.length===0)return null;let a=n?i.find(l=>l.toolUseId===n):i.sort((l,u)=>l.timestamp-u.timestamp)[0];if(!a)return null;let c=s.findIndex(l=>l.eventId===a.eventId);return c!==-1&&s.splice(c,1),writeFileSync(r,JSON.stringify(s)),{eventId:a.eventId,timestamp:a.timestamp}}catch{return null}}function ue(o){if(!o)return 0;let t=o;if(typeof o=="string")try{t=JSON.parse(o);}catch{return 1}let e=t,n=["files","results","data","result","memories","nodes","chunks","findings","symbols","keySymbols"],r=["reasoning","riskHints","nextActions"],s=Array.isArray(e.data)?e.data:e.structuredContent??e;if(Array.isArray(s))return s.length;if(typeof s=="object"&&s!==null){let i=s,a=0,c=false;for(let u of n)Array.isArray(i[u])&&(c=true,a+=i[u].length);for(let u of r)Array.isArray(i[u])&&(a+=i[u].length);for(let[,u]of Object.entries(i))u&&typeof u=="object"&&!Array.isArray(u)&&(a+=ue(u));let l=!!(i._devflow||i._devflow_unique||i.taskType);return a===0&&l&&!c?1:a>0?a:c?0:Object.keys(i).length>0?1:0}return 0}function dt(o,t){if(!ut.has(t))return null;let e=L(o,r=>({...r,bypassCount:(r.bypassCount??0)+1}));if(!e.applied)return null;let n=e.receipt.bypassCount??0;return n>20&&n%10===0?`MCP \u5DE5\u5177\u4F7F\u7528\u7387\u4F4E\uFF1A${n} \u6B21\u76F4\u63A5\u5DE5\u5177\u8C03\u7528\u3002\u5EFA\u8BAE\u4F7F\u7528 get_project_context \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`:null}async function mt(o){if(!o)return null;let t;try{t=JSON.parse(o);}catch{return null}let e=t.tool_name||"",n=j(),r=t.tool_input||{},s=t.tool_response||{},i=t.session_id?.trim()||null,a=new E(n);if(i&&a.registerSession(i),e==="Skill"){let p=typeof r=="object"&&r.skill?r.skill:"",m=ce(p);i&&m&&(a.startExecution(i,m,ae(m)),U(n,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}e.startsWith("mcp__")&&new D(n).recordMcpCall();let c=i?a.get(i):null,l=i?pt(n,i,e,t.tool_use_id):null,u=i&&t.tool_use_id&&!l?(()=>{try{let p=openGlobalDevFlowDatabase();try{return p.getToolCallEventByToolUseId(i,t.tool_use_id)}finally{p.close();}}catch{return null}})():null,d=l??u,f=typeof s=="object"&&s!==null?s:null,g=JSON.stringify(s),y=Buffer.byteLength(g,"utf8"),w=ue(s);if(c?.executionId!==void 0||e.startsWith("mcp__devflow__")||e==="Skill"){let p=getLogWriter(n),m=c?.executionId??`auto-${i??Date.now()}`;p.toolCall({tool:e,runId:m,stepId:`step-${m}`,input:r,output:s,duration:d?Math.max(0,Date.now()-d.timestamp):0,success:!f?.error,resultCount:w,resultSizeBytes:y,error:f?.error});}if(d&&i){let p=typeof s=="string"?s:JSON.stringify(s),m=p.length>5e3?{_truncated:true,_originalSize:p.length,text:p.slice(0,5e3)}:s;await new x().completeEvent({eventId:d.eventId,sessionId:i,output:m,duration:d?Math.max(0,Date.now()-d.timestamp):0,completedAt:Date.now()});}let k=typeof r=="object"&&r.command?r.command:"",S=f?.exitCode,W=f?.stderr,pe=/^\s*(ls|cat|pwd|cd|echo|head|tail|wc|which|whoami|date|env|printenv|id|hostname|uname)\b/,v,b,I=true;if(e.startsWith("mcp__"))v="mcp_call",b={mcpTool:e.replace(/^mcp__[^_]+__/,""),query:typeof r=="object"&&r.query?r.query:null,resultCount:w,resultSizeBytes:y};else if(e==="Read"||e==="Write"||e==="Edit")v=e==="Read"?"file_read":"file_write",b={filePath:typeof r=="object"&&r.file_path?r.file_path:null,fileContentSize:y};else if(e==="Bash"){let p=pe.test(k),m=S!==void 0&&S!==0;I=!p||m,v=m?"bash_error":"bash_command",b={command:k||e,exitCode:S??null,stderr:W??null};}else e==="Agent"?(v="subagent",b={subagentType:typeof r=="object"&&r.subagent_type?r.subagent_type:null,description:typeof r=="object"&&r.description?String(r.description).slice(0,200):null}):e==="WebSearch"||e==="WebFetch"?(v=e==="WebSearch"?"web_search":"web_fetch",b={query:typeof r=="object"&&r.query?String(r.query).slice(0,200):null}):(I=false,v="tool_use",b={});if(I){let p={id:t.tool_use_id?`memory:${le(i??"",t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:i??"",tool:e,kind:v,payload:b,command:k||void 0,exitCode:S,stderr:W??void 0,durationMs:d?Math.max(0,Date.now()-d.timestamp):0,createdAt:Date.now()};i&&K(`/api/memory/session-events?rootPath=${encodeURIComponent(n)}`,p);}let T=dt(n,e);return T&&console.error("[devflow] Enforcement:",T),T}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let o=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=await mt(t.trim()||process.argv[2]||"");if(e){let n=JSON.stringify(e);o(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:n}}));}else o(JSON.stringify({status:"ok"}));}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}
3
- export{mt as handlePostToolUse};
1
+ import {existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,linkSync,readdirSync,renameSync,unlinkSync,appendFileSync}from'fs';import {join,dirname}from'path';import {getLogWriter}from'@devflow-tools/telemetry';import {request}from'http';import {homedir}from'os';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {randomUUID,createHash}from'crypto';import {fileURLToPath}from'url';function K(r,t,e){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:r,timestamp:Date.now(),duration:e,success:t.success!==!1,metadata:t});}finally{n.close();}}catch{}}var j=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",je=getLocalApiKey(),Ne=8,Le=6e4,Y=new Map;function Ue(r){let t=new URL(r,j).pathname,e=Y.get(t);return e||(e={failures:0,lastFailure:0,openUntil:0,status:"closed"},Y.set(t,e)),e}function N(r,t,e){if(t.status===e)return;let n=t.status;t.status=e,K("http_circuit_transition",{path:new URL(r,j).pathname,previous:n,status:e,failures:t.failures,openUntil:t.openUntil});}function P(r,t){t.failures++,t.lastFailure=Date.now(),t.failures>=Ne&&(t.openUntil=Date.now()+Le,N(r,t,"open"));}function qe(r,t){let e=t.status!=="closed";t.failures=0,t.openUntil=0,e&&N(r,t,"closed");}var F=join(homedir(),".devflow","errors");function Z(r,t){try{existsSync(F)||mkdirSync(F,{recursive:!0});let e=`${new Date().toISOString()} | ${r} | ${t?.message??String(t)}
2
+ `;appendFileSync(join(F,"http-errors.log"),e);}catch{}}function Q(r,t,e={}){let n=e.timeout??5e3,i=e.maxRetries??2,o=e.circuitBreaker??true,s=Ue(r);if(o&&s.openUntil>Date.now())return Promise.resolve();o&&s.status==="open"&&N(r,s,"half_open");let a=c=>new Promise(l=>{let d=JSON.stringify(t),p=new URL(r,j),g=request({hostname:p.hostname,port:p.port,path:p.pathname+p.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":je,"Content-Length":Buffer.byteLength(d)},timeout:n},m=>{if(m.resume(),m.statusCode&&m.statusCode>=400){let y=new Error(`HTTP ${m.statusCode}`);if(Z(r,y),c>0){let R=Math.min(1e3*Math.pow(2,i-c),8e3);setTimeout(()=>{a(c-1).then(l);},R);}else P(r,s),l();return}qe(r,s),l();});g.on("error",m=>{if(Z(r,m),c>0){let y=Math.min(1e3*Math.pow(2,i-c),8e3);setTimeout(()=>{a(c-1).then(l);},y);}else P(r,s),l();}),g.on("timeout",()=>{g.destroy(),c>0?a(c-1).then(l):(P(r,s),l());}),g.write(d),g.end();});return a(i)}function L(r){return r??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function h(r){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(L(r))}function A(r){if(!r||typeof r!="object"||Array.isArray(r))return {};let t=r,e={};for(let n of ["lastMcpCall","bypassCount"])if(n in t){let i=t[n];if(i==null)continue;e[n]=typeof i=="number"&&Number.isFinite(i)&&i>=0?i:0;}return e}function He(r,t){return r.lastMcpCall===t.lastMcpCall&&r.bypassCount===t.bypassCount}function We(r){try{return existsSync(r)?A(JSON.parse(readFileSync(r,"utf-8"))):{}}catch{return {}}}function Ge(r,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${r} skipped: ${e}`);}function ee(r){let t=h(r);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join(t,e))&&unlinkSync(join(t,e));}catch{}}function Ve(r,t){if(r.getHookReceipt(t)){ee(t);return}let e=join(h(t),"receipt.json");if(!existsSync(e))return;let n=We(e);r.updateHookReceipt(t,()=>n),ee(t);}function ie(r,t,e){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Ve(n,r);let i={},o=n.updateHookReceipt(r,a=>(i=A(a),A(t(i)))),s=A(o);return {receipt:s,applied:!0,changed:!He(i,s)}}catch(i){return Ge(e,i),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function J(r,t){return ie(r,()=>t,"write").applied}function z(r,t){return ie(r,t,"update")}var te={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function Ke(r){switch(r){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var O=class{constructor(t,e,n){this.projectRoot=t;this.sessionId=e;this.executionId=n;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}evaluate(t,e){let n=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(n==="context_gathering"&&te[t])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(n==="context_ready")return {permissionDecision:"allow"};let i=te[t];if(!i)return {permissionDecision:"allow"};let o=z(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!o.applied)return {permissionDecision:"allow"};let s=o.receipt.bypassCount??0,a=Ke(t);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${i} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){J(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var ce=1e4,nt=3e4,D=500;function it(r,t,e){return new Promise(n=>{try{let i=new URL(r),o=request({hostname:i.hostname,port:i.port||80,path:i.pathname+i.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},s=>{let a=[];s.on("data",c=>a.push(c)),s.on("end",()=>{let c=Buffer.concat(a).toString();n(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?c:null);});});o.on("error",()=>n(null)),o.on("timeout",()=>{o.destroy(),n(null);}),o.write(t),o.end();}catch{n(null);}})}var k=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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,n,i,o=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:i,projectRoot:o,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",n=Date.now(),i){let o={executionId:t,status:e,finishedAt:n,metadata:i},s=this.commitOrCache("execution_complete",o);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",o),s}async sendSessionStart(t,e,n){let i={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",i);return o&&this.postHttp("/api/telemetry/sessions",i),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 n={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",n);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let n=this.getDatabase(),i=n.listTelemetryFailures({unresolvedOnly:!0,limit:D}).reverse();for(let o of i)try{this.applyOperation(o.operation,o.payload),n.resolveTelemetryFailure(o.id);}catch{}n.trimTelemetryFailures(D);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(i=>i.endsWith(".json")).map(i=>{let o=join(n,i);try{return {cacheFile:o,envelope:rt(JSON.parse(readFileSync(o,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||le(n.envelope.operation)-le(i.envelope.operation));for(let{cacheFile:n,envelope:i}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id),unlinkSync(n);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:de(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(!n.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":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(de(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let i=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:n,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let i=Date.now(),o={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:i}),s.trimTelemetryFailures(D),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join(this.cacheDir,`${i}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,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();},nt).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){it(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=ce?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,ce)}...`}}};function le(r){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(r)}function de(r){return `hook-run:${r}`}function rt(r,t){if(!r||typeof r!="object")throw new Error("Invalid telemetry cache envelope");let e=r;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let i=e.payload??{},o=Number(i.timestamp??i.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}function ge(r){return Buffer.from(r,"utf8").toString("base64url")}function ct(r,t,e){let n=t?.trim();if(n){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${r}:${i}`}return `${r}:legacy-${e}-${randomUUID().slice(0,8)}`}function we(r){return `${r}:legacy-journal`}var E=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(h(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let i=Date.now(),o={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,o),this.persist(o),o}startExecution(t,e,n){let i=this.registerSession(t);return (!i.executionId||i.skillName!==e)&&(i.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),i.skillName=e,i.requiredMcpTools=[...new Set(n)],i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let i=this.snapshotPath(e);if(!existsSync(i))return null;try{let o=JSON.parse(readFileSync(i,"utf8"));return o.sessionId!==e||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],o.evidenceObligations=me(o.evidenceObligations),o.evidenceDegradations=he(o.evidenceDegradations),o.evidenceOutcomes=ye(o.evidenceOutcomes),this.replayEvidenceJournal(o),this.sessions.set(e,o),o)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let n=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}addEvidenceObligation(t,e,n=Date.now(),i){let o=this.registerSession(t),a=(i?void 0:o.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??ct(e.id,i,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:n,contract:e},`add\0${a}`),this.replayEvidenceJournal(o);let c=o.evidenceObligations.find(l=>l.obligationId===a);return c?(o.lastActivityAt=Date.now(),this.persist(o),structuredClone(c)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,i,o=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!a)return null;let c=/^[a-f0-9]{64}$/.test(i)?i:"";if(!c)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:o,fingerprint:c,violations:n.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${c}`),this.replayEvidenceJournal(s),s.lastActivityAt=o,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let i=n.evidenceObligations.find(s=>s.obligationId===e);if(!i)return false;let o=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:o},`resolve\0${e}`),this.replayEvidenceJournal(n),n.lastActivityAt=o,this.persist(n),true}degradeEvidenceObligation(t,e,n,i=Date.now()){let o=this.get(t),s=o?.evidenceObligations.find(c=>c.obligationId===e);if(!o||!s)return false;let a=n.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:i,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join(this.sessionsDir,`${ge(t)}.json`)}evidenceJournalDir(t){return join(this.sessionsDir,"evidence-journal",ge(t))}appendEvidenceEvent(t,e,n){let i=this.evidenceJournalDir(t);mkdirSync(i,{recursive:true,mode:448});let o=createHash("sha256").update(n).digest("hex"),s=join(i,`${e.kind}-${o}.json`);if(existsSync(s))return;let a=join(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(c){if(c.code!=="EEXIST")throw c}finally{rmSync(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=me(t.evidenceObligations),t.evidenceDegradations=he(t.evidenceDegradations),t.evidenceOutcomes=ye(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let n;try{n=readdirSync(e).filter(o=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(o)).slice(0,4096);}catch{return}let i=n.flatMap(o=>{try{let s=readFileSync(join(e,o),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=lt(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((o,s)=>o.at-s.at||be(o.kind)-be(s.kind));for(let o of i)this.applyEvidenceEvent(t,o);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let n=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(n)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let i=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!i||n||i.correctionFingerprint===e.fingerprint)return;i.attempt+=1,i.correctionRequested=true,i.correctionRequestedAt=e.at,i.correctionFingerprint=e.fingerprint,i.violations=e.violations;return}let o=i?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!n&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:o}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:o,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(n,JSON.stringify(t),{mode:384}),renameSync(n,e);}};function me(r){return Array.isArray(r)?r.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!_e(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:we(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,o=e.correctionFingerprint??i;return o!==void 0&&!/^[a-f0-9]{64}$/.test(o)?[]:[{...e,obligationId:n,correctionFingerprint:o}]}).slice(-8):[]}function he(r){return Array.isArray(r)?r.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function ye(r){return Array.isArray(r)?r.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function lt(r){if(!r||typeof r!="object")return null;let t=r;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:we(t.contractId);if(t.kind==="add")return _e(t.contract)?{...t,obligationId:e}:null;if(t.kind==="correction"){let n=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof n=="string"&&/^[a-f0-9]{64}$/.test(n)&&Array.isArray(t.violations)&&t.violations.every(i=>typeof i=="string"&&i.length<=240)?{...t,obligationId:e,fingerprint:n}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function be(r){return r==="add"?0:r==="correction"?1:2}function _e(r){if(!r||typeof r!="object")return false;let t=r,e=t.requiredSections,n=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(n)&&n.length<=16&&n.every(i=>typeof i=="string"&&i.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}var gt=2,mt=1;function ht(){if(process.env.CLAUDE_PLUGIN_ROOT)return process.env.CLAUDE_PLUGIN_ROOT;try{return join(dirname(fileURLToPath(import.meta.url)),"..","..")}catch{return process.cwd()}}function Ee(r=ht()){let t=[join(r,"dist","command-registry.json"),join(r,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let n=JSON.parse(readFileSync(e,"utf8"));if(n.version!==gt&&n.version!==mt||!yt(n.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return n.commands}catch(n){console.error(`[devflow] command registry load failed: ${n.message}`);}return null}function yt(r){return !r||typeof r!="object"||Array.isArray(r)?false:Object.values(r).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return W(e.mcpTools)&&W(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||W(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function W(r){return Array.isArray(r)&&r.every(t=>typeof t=="string"&&t.length>0)}function Se(r){let t=Ee();return t?t[r]?.mcpTools??[]:[]}function Re(r){let t=r.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 Ie(r,t){return t?`evt_tool_${createHash("sha256").update(`${r}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var vt=256*1024,wt=48*1024;var _t=5,x=["\u5DE5\u5177\u53D1\u73B0","\u6A21\u578B\u5047\u8BBE","\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"];function Et(r){return r==="react_audit_performance"||r.endsWith("__react_audit_performance")}function St(r){let t=S(r,0,new Set);return t?It(t.contract,t.canonicalReport):null}function Ae(r){if(!r.sessionId||!Et(r.toolName))return null;let t=St(r.toolResponse);return t?(r.runtimeStore.addEvidenceObligation(r.sessionId,t,Date.now(),r.toolUseId),Rt(t)):null}function Rt(r){return [`DevFlow performance evidence contract ${r.id} is active.`,`The final performance answer MUST contain these three sections exactly: ${r.requiredSections.join(" / ")}.`,r.runtimeProfilingOccurred?"Only claims directly supported by the returned runtime measurements may be stated as measured facts.":"No runtime profiling occurred. Treat every finding as a static candidate: do not assign P0/high-risk severity, claim a confirmed bottleneck/jank/frame drop/CPU hotspot, quantify performance or benefit, or recommend requestAnimationFrame as generic throttling without sampling evidence.",`samplingEvidenceOccurred=${r.samplingEvidenceOccurred}. RAF recommendations are permitted only when this structured contract field is true; answer text cannot self-declare sampling evidence.`,"Use the canonical report below directly or preserve its evidence boundaries. Stop will request one correction for unsupported claims, then fail open with degradation telemetry.",r.canonicalReport].join(`
3
+
4
+ `)}function S(r,t,e){if(t>_t||r===null||r===void 0)return null;if(typeof r=="string"){if(Buffer.byteLength(r,"utf8")>vt)return null;try{return S(JSON.parse(r),t+1,e)}catch{return null}}if(typeof r!="object"||e.has(r))return null;if(e.add(r),Array.isArray(r)){for(let i of r.slice(0,16)){let o=S(i,t+1,e);if(o)return o}return null}let n=r;if("evidenceContract"in n)return {contract:n.evidenceContract,canonicalReport:n.canonicalReport};for(let i of ["structuredContent","data","result"])if(i in n){let o=S(n[i],t+1,e);if(o)return o}if(Array.isArray(n.content))for(let i of n.content.slice(0,16)){let o=i&&typeof i=="object"&&"text"in i?i.text:i,s=S(o,t+1,e);if(s)return s}return null}function It(r,t){if(!r||typeof r!="object"||Array.isArray(r))return null;let e=r;if(e.version!=="1.0"||typeof e.id!="string"||!/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(e.id)||typeof e.runtimeProfilingOccurred!="boolean"||typeof e.samplingEvidenceOccurred!="boolean"||!Array.isArray(e.requiredSections)||e.requiredSections.length!==x.length)return null;let n=e.requiredSections.filter(c=>typeof c=="string");if(n.length!==x.length||x.some((c,l)=>n[l]!==c)||!Array.isArray(e.prohibitedClaims)||e.prohibitedClaims.length>16)return null;let i=e.prohibitedClaims.filter(c=>typeof c=="string"&&c.length<=128);if(i.length!==e.prohibitedClaims.length)return null;let o=e.correctionPolicy;if(!o||typeof o!="object"||Array.isArray(o))return null;let s=o;if(s.maxAttempts!==1||s.repeatedViolation!=="fail_open")return null;let a=typeof e.canonicalReport=="string"?e.canonicalReport:t;return typeof a!="string"||Buffer.byteLength(a,"utf8")>wt||x.some(c=>!a.includes(c))?null:{version:"1.0",id:e.id,runtimeProfilingOccurred:e.runtimeProfilingOccurred,samplingEvidenceOccurred:e.samplingEvidenceOccurred,requiredSections:n,prohibitedClaims:i,correctionPolicy:{maxAttempts:1,repeatedViolation:"fail_open"},canonicalReport:a}}var Tt=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function $t(r,t,e,n){try{let i=join(h(r),"event-map.json");if(!existsSync(i))return null;let o=JSON.parse(readFileSync(i,"utf-8")),s=o.filter(l=>l.toolName===e&&(!l.sessionId||l.sessionId===t));if(s.length===0)return null;let a=n?s.find(l=>l.toolUseId===n):s.sort((l,d)=>l.timestamp-d.timestamp)[0];if(!a)return null;let c=o.findIndex(l=>l.eventId===a.eventId);return c!==-1&&o.splice(c,1),writeFileSync(i,JSON.stringify(o)),{eventId:a.eventId,timestamp:a.timestamp}}catch{return null}}function Oe(r){if(!r)return 0;let t=r;if(typeof r=="string")try{t=JSON.parse(r);}catch{return 1}let e=t,n=["files","results","data","result","memories","nodes","chunks","findings","symbols","keySymbols"],i=["reasoning","riskHints","nextActions"],o=Array.isArray(e.data)?e.data:e.structuredContent??e;if(Array.isArray(o))return o.length;if(typeof o=="object"&&o!==null){let s=o,a=0,c=false;for(let d of n)Array.isArray(s[d])&&(c=true,a+=s[d].length);for(let d of i)Array.isArray(s[d])&&(a+=s[d].length);for(let[,d]of Object.entries(s))d&&typeof d=="object"&&!Array.isArray(d)&&(a+=Oe(d));let l=!!(s._devflow||s._devflow_unique||s.taskType);return a===0&&l&&!c?1:a>0?a:c?0:Object.keys(s).length>0?1:0}return 0}function Mt(r,t){if(!Tt.has(t))return null;let e=z(r,i=>({...i,bypassCount:(i.bypassCount??0)+1}));if(!e.applied)return null;let n=e.receipt.bypassCount??0;return n>20&&n%10===0?`MCP \u5DE5\u5177\u4F7F\u7528\u7387\u4F4E\uFF1A${n} \u6B21\u76F4\u63A5\u5DE5\u5177\u8C03\u7528\u3002\u5EFA\u8BAE\u4F7F\u7528 get_project_context \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`:null}async function Pt(r){if(!r)return null;let t;try{t=JSON.parse(r);}catch{return null}let e=t.tool_name||"",n=L(),i=t.tool_input||{},o=t.tool_response||{},s=t.session_id?.trim()||null,a=new E(n);if(s&&a.registerSession(s),e==="Skill"){let u=typeof i=="object"&&i.skill?i.skill:"",f=Re(u);s&&f&&(a.startExecution(s,f,Se(f)),J(n,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}e.startsWith("mcp__")&&new O(n).recordMcpCall();let c=s?a.get(s):null,l=s?$t(n,s,e,t.tool_use_id):null,d=s&&t.tool_use_id&&!l?(()=>{try{let u=openGlobalDevFlowDatabase();try{return u.getToolCallEventByToolUseId(s,t.tool_use_id)}finally{u.close();}}catch{return null}})():null,p=l??d,g=typeof o=="object"&&o!==null?o:null,m=JSON.stringify(o),y=Buffer.byteLength(m,"utf8"),R=Oe(o);if(c?.executionId!==void 0||e.startsWith("mcp__devflow__")||e==="Skill"){let u=getLogWriter(n),f=c?.executionId??`auto-${s??Date.now()}`;u.toolCall({tool:e,runId:f,stepId:`step-${f}`,input:i,output:o,duration:p?Math.max(0,Date.now()-p.timestamp):0,success:!g?.error,resultCount:R,resultSizeBytes:y,error:g?.error});}if(p&&s){let u=typeof o=="string"?o:JSON.stringify(o),f=u.length>5e3?{_truncated:true,_originalSize:u.length,text:u.slice(0,5e3)}:o;await new k().completeEvent({eventId:p.eventId,sessionId:s,output:f,duration:p?Math.max(0,Date.now()-p.timestamp):0,completedAt:Date.now()});}let T=typeof i=="object"&&i.command?i.command:"",I=g?.exitCode,V=g?.stderr,De=/^\s*(ls|cat|pwd|cd|echo|head|tail|wc|which|whoami|date|env|printenv|id|hostname|uname)\b/,b,v,$=true;if(e.startsWith("mcp__"))b="mcp_call",v={mcpTool:e.replace(/^mcp__[^_]+__/,""),query:typeof i=="object"&&i.query?i.query:null,resultCount:R,resultSizeBytes:y};else if(e==="Read"||e==="Write"||e==="Edit")b=e==="Read"?"file_read":"file_write",v={filePath:typeof i=="object"&&i.file_path?i.file_path:null,fileContentSize:y};else if(e==="Bash"){let u=De.test(T),f=I!==void 0&&I!==0;$=!u||f,b=f?"bash_error":"bash_command",v={command:T||e,exitCode:I??null,stderr:V??null};}else e==="Agent"?(b="subagent",v={subagentType:typeof i=="object"&&i.subagent_type?i.subagent_type:null,description:typeof i=="object"&&i.description?String(i.description).slice(0,200):null}):e==="WebSearch"||e==="WebFetch"?(b=e==="WebSearch"?"web_search":"web_fetch",v={query:typeof i=="object"&&i.query?String(i.query).slice(0,200):null}):($=false,b="tool_use",v={});if($){let u={id:t.tool_use_id?`memory:${Ie(s??"",t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:s??"",tool:e,kind:b,payload:v,command:T||void 0,exitCode:I,stderr:V??void 0,durationMs:p?Math.max(0,Date.now()-p.timestamp):0,createdAt:Date.now()};s&&Q(`/api/memory/session-events?rootPath=${encodeURIComponent(n)}`,u);}let ke=Ae({toolName:e,toolResponse:o,sessionId:s,toolUseId:t.tool_use_id,runtimeStore:a}),M=Mt(n,e);return M&&console.error("[devflow] Enforcement:",M),[ke,M].filter(u=>!!u).join(`
5
+
6
+ `)||null}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let r=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=await Pt(t.trim()||process.argv[2]||"");r(JSON.stringify(e?{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:e}}:{status:"ok"}));}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}export{Pt as handlePostToolUse};
@@ -1,3 +1,3 @@
1
- import {getLocalApiKey}from'@devflow-tools/sdk';import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync}from'fs';import {request}from'http';import {join}from'path';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';function m(s){return s??process.env.CLAUDE_PROJECT_DIR??process.cwd()}var y=1e4,O=3e4,u=500;function M(s,r,e){return new Promise(t=>{try{let o=new URL(s),n=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(r)},timeout:5e3},i=>{let a=[];i.on("data",l=>a.push(l)),i.on("end",()=>{let l=Buffer.concat(a).toString();t(i.statusCode!=null&&i.statusCode>=200&&i.statusCode<300?l:null);});});n.on("error",()=>t(null)),n.on("timeout",()=>{n.destroy(),t(null);}),n.write(r),n.end();}catch{t(null);}})}var d=class{constructor(r){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=r?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=r?.apiKey??getLocalApiKey(),this.cacheDir=r?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=r?.legacyCacheDir??(r?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=r?.database??null,this.ownsDatabase=!r?.database;let e=r?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(r){let e={...r,input:this.truncateInput(r.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),r.eventId):null}async sendExecutionStart(r,e,t,o,n=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:r,sessionId:e,skillName:t,startedAt:o,projectRoot:n,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(r,e="completed",t=Date.now(),o){let n={executionId:r,status:e,finishedAt:t,metadata:o},i=this.commitOrCache("execution_complete",n);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",n),i}async sendSessionStart(r,e,t){let o={id:r,projectRoot:e,startedAt:t,label:e.split("/").pop()??"unknown"},n=this.commitOrCache("session_start",o);return n&&this.postHttp("/api/telemetry/sessions",o),n}async completeEvent(r){let e=this.commitOrCache("complete_event",r);return e&&(this.postHttp("/api/telemetry/tool-call/output",r),this.scheduleMetricAggregation()),e}async endSession(r,e=Date.now()){let t={sessionId:r,finishedAt:e},o=this.commitOrCache("session_end",t);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(r)}/close`,{finishedAt:e})),o}async flushCache(){try{let t=this.getDatabase(),o=t.listTelemetryFailures({unresolvedOnly:!0,limit:u}).reverse();for(let n of o)try{this.applyOperation(n.operation,n.payload),t.resolveTelemetryFailure(n.id);}catch{}t.trimTelemetryFailures(u);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(t=>!!t))].filter(t=>existsSync(t)).flatMap(t=>readdirSync(t).filter(o=>o.endsWith(".json")).map(o=>{let n=join(t,o);try{return {cacheFile:n,envelope:x(JSON.parse(readFileSync(n,"utf8")),o)}}catch{return null}})).filter(t=>t!==null).sort((t,o)=>t.envelope.timestamp-o.envelope.timestamp||v(t.envelope.operation)-v(o.envelope.operation));for(let{cacheFile:t,envelope:o}of e)try{let n=this.getDatabase();n.insertTelemetryFailure({id:o.id,operation:o.operation,payload:o.payload,error:o.failure,createdAt:o.timestamp}),this.applyOperation(o.operation,o.payload),n.resolveTelemetryFailure(o.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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(r,e){try{return this.applyOperation(r,e),!0}catch(t){return this.cacheOperation(r,e,t),false}}applyOperation(r,e){let t=this.getDatabase();switch(r){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:b(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(b(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(r,e){let t=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!t)throw new Error("Canonical session ID is required for telemetry");let o=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";r.ensureSession({id:t,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(r,e,t){let o=Date.now(),n={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:r,payload:e,failure:t instanceof Error?t.message:String(t),timestamp:o};try{let i=this.getDatabase();i.insertTelemetryFailure({id:n.id,operation:r,payload:e,error:n.failure,createdAt:o}),i.trimTelemetryFailures(u),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(n,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let r=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of r.slice(0,Math.max(0,r.length-u)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},O).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(r,e){M(`${this.apiUrl}${r}`,JSON.stringify(e),this.apiKey);}truncateInput(r){let e=JSON.stringify(r);return e===void 0||e.length<=y?r:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,y)}...`}}};function v(s){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(s)}function b(s){return `hook-run:${s}`}function x(s,r){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 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 o=e.payload??{},n=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${r}`,operation:t,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:n}}async function D(s){let r=!s.memory,e=s.memory??new MemoryGate(s.projectRoot),t=0,o=0;try{await e.forceWarmUp(),s.trigger==="session_end"&&(t=await e.releasePendingDistillLeases(s.sessionId)),o=e.getPendingEventCount();}finally{r&&e.close();}let n={pendingEvents:o,releasedLeases:t,trigger:s.trigger,sessionId:s.sessionId};try{let i=openGlobalDevFlowDatabase();try{let a=Date.now(),l=`distill:${a}:${Math.random().toString(36).slice(2,10)}`;i.recordMemoryDistillCheckpoint({id:l,projectRoot:s.projectRoot,sessionId:s.sessionId,trigger:s.trigger,pendingEvents:o,releasedLeases:t,createdAt:a}),i.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...n,projectRoot:s.projectRoot}});}finally{i.close();}}catch{}return n}function _(s){if(s.pendingEvents===0)return "";let r=s.sessionId?`\uFF0CsessionId=${s.sessionId}`:"";return `Memory distill checkpoint: ${s.pendingEvents} \u4E2A\u4E8B\u4EF6\u5F85\u63D0\u70BC${r}\u3002\u4E0A\u4E0B\u6587\u538B\u7F29\u5B8C\u6210\u540E\uFF0C\u8C03\u7528 mcp__devflow__memory_request_distill\uFF1B\u6309\u8FD4\u56DE\u7684 nextPage \u5206\u9875\u8BFB\u53D6\u5168\u90E8\u4E8B\u4EF6\uFF0C\u63D0\u70BC observations\uFF0C\u518D\u8C03\u7528 mcp__devflow__memory_save_distilled \u5E76\u786E\u8BA4\u4FDD\u5B58\u7ED3\u679C\u3002`}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 T(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}async function j(s="",r=m()){let e;try{let i=JSON.parse(s);typeof i.session_id=="string"&&i.session_id.trim()&&(e=i.session_id.trim());}catch{}let t=new d;try{await t.flushAndAggregate();}finally{t.close();}let o=await D({projectRoot:r,sessionId:e,trigger:"pre_compact"}),n=[T()?w:"",_(o)].filter(Boolean).join(`
1
+ import {getLocalApiKey}from'@devflow-tools/sdk';import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync}from'fs';import {request}from'http';import {join}from'path';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {createHash}from'node:crypto';function m(o){return o??process.env.CLAUDE_PROJECT_DIR??process.cwd()}var y=1e4,O=3e4,u=500;function M(o,r,e){return new Promise(t=>{try{let s=new URL(o),n=request({hostname:s.hostname,port:s.port||80,path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(r)},timeout:5e3},i=>{let a=[];i.on("data",l=>a.push(l)),i.on("end",()=>{let l=Buffer.concat(a).toString();t(i.statusCode!=null&&i.statusCode>=200&&i.statusCode<300?l:null);});});n.on("error",()=>t(null)),n.on("timeout",()=>{n.destroy(),t(null);}),n.write(r),n.end();}catch{t(null);}})}var d=class{constructor(r){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=r?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=r?.apiKey??getLocalApiKey(),this.cacheDir=r?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=r?.legacyCacheDir??(r?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=r?.database??null,this.ownsDatabase=!r?.database;let e=r?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}async sendEvent(r){let e={...r,input:this.truncateInput(r.input)};return this.commitOrCache("tool_call",e)?(this.postHttp("/api/telemetry/tool-call",e),r.eventId):null}async sendExecutionStart(r,e,t,s,n=process.env.CLAUDE_PROJECT_DIR??process.cwd(),i=[]){let a={executionId:r,sessionId:e,skillName:t,startedAt:s,projectRoot:n,requiredMcpTools:i};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(r,e="completed",t=Date.now(),s){let n={executionId:r,status:e,finishedAt:t,metadata:s},i=this.commitOrCache("execution_complete",n);return i&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",n),i}async sendSessionStart(r,e,t){let s={id:r,projectRoot:e,startedAt:t,label:e.split("/").pop()??"unknown"},n=this.commitOrCache("session_start",s);return n&&this.postHttp("/api/telemetry/sessions",s),n}async completeEvent(r){let e=this.commitOrCache("complete_event",r);return e&&(this.postHttp("/api/telemetry/tool-call/output",r),this.scheduleMetricAggregation()),e}async endSession(r,e=Date.now()){let t={sessionId:r,finishedAt:e},s=this.commitOrCache("session_end",t);return s&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(r)}/close`,{finishedAt:e})),s}async flushCache(){try{let t=this.getDatabase(),s=t.listTelemetryFailures({unresolvedOnly:!0,limit:u}).reverse();for(let n of s)try{this.applyOperation(n.operation,n.payload),t.resolveTelemetryFailure(n.id);}catch{}t.trimTelemetryFailures(u);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(t=>!!t))].filter(t=>existsSync(t)).flatMap(t=>readdirSync(t).filter(s=>s.endsWith(".json")).map(s=>{let n=join(t,s);try{return {cacheFile:n,envelope:x(JSON.parse(readFileSync(n,"utf8")),s)}}catch{return null}})).filter(t=>t!==null).sort((t,s)=>t.envelope.timestamp-s.envelope.timestamp||v(t.envelope.operation)-v(s.envelope.operation));for(let{cacheFile:t,envelope:s}of e)try{let n=this.getDatabase();n.insertTelemetryFailure({id:s.id,operation:s.operation,payload:s.payload,error:s.failure,createdAt:s.timestamp}),this.applyOperation(s.operation,s.payload),n.resolveTelemetryFailure(s.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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(r,e){try{return this.applyOperation(r,e),!0}catch(t){return this.cacheOperation(r,e,t),false}}applyOperation(r,e){let t=this.getDatabase();switch(r){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:_(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(_(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(r,e){let t=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!t)throw new Error("Canonical session ID is required for telemetry");let s=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";r.ensureSession({id:t,projectRoot:s,label:s==="unknown"?void 0:s.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(r,e,t){let s=Date.now(),n={id:`failure:${s}:${Math.random().toString(36).slice(2,11)}`,operation:r,payload:e,failure:t instanceof Error?t.message:String(t),timestamp:s};try{let i=this.getDatabase();i.insertTelemetryFailure({id:n.id,operation:r,payload:e,error:n.failure,createdAt:s}),i.trimTelemetryFailures(u),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let i=join(this.cacheDir,`${s}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(i,JSON.stringify(n,null,2),{mode:384}),this.trimCompatibilityCache(),this.scheduleRetry();}catch{}}trimCompatibilityCache(){try{let r=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json")).sort();for(let e of r.slice(0,Math.max(0,r.length-u)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},O).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(r,e){M(`${this.apiUrl}${r}`,JSON.stringify(e),this.apiKey);}truncateInput(r){let e=JSON.stringify(r);return e===void 0||e.length<=y?r:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,y)}...`}}};function v(o){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(o)}function _(o){return `hook-run:${o}`}function x(o,r){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 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 s=e.payload??{},n=Number(s.timestamp??s.startedAt??Date.now());return {id:`legacy-cache:${r}`,operation:t,payload:s,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:n}}async function b(o){let r=!o.memory,e=o.memory??new MemoryGate(o.projectRoot),t=0,s=0;try{await e.forceWarmUp(),o.trigger==="session_end"&&(t=await e.releasePendingDistillLeases(o.sessionId)),s=e.getPendingEventCount(o.sessionId,o.trigger!=="session_end");}finally{r&&e.close();}let n={pendingEvents:s,releasedLeases:t,trigger:o.trigger,sessionId:o.sessionId,details:o.details};try{let i=openGlobalDevFlowDatabase();try{let a=Date.now(),l=o.trigger==="session_end"&&o.sessionId?`distill:session_end:${createHash("sha256").update(`${o.projectRoot}\0${o.sessionId}`).digest("hex").slice(0,24)}`:`distill:${a}:${Math.random().toString(36).slice(2,10)}`;i.recordMemoryDistillCheckpoint({id:l,projectRoot:o.projectRoot,sessionId:o.sessionId,trigger:o.trigger,pendingEvents:s,releasedLeases:t,details:o.details,createdAt:a}),i.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...n,projectRoot:o.projectRoot}});}finally{i.close();}}catch(i){if(o.strictPersistence)throw i}return n}function D(o){if(o.pendingEvents===0)return "";let r=o.sessionId?`\uFF0CsessionId=${o.sessionId}`:"";return `Memory distill checkpoint: ${o.pendingEvents} \u4E2A\u4E8B\u4EF6\u5F85\u63D0\u70BC${r}\u3002\u4E0A\u4E0B\u6587\u538B\u7F29\u5B8C\u6210\u540E\uFF0C\u8C03\u7528 mcp__devflow__memory_request_distill\uFF1B\u6309\u8FD4\u56DE\u7684 nextPage \u5206\u9875\u8BFB\u53D6\u5168\u90E8\u4E8B\u4EF6\uFF0C\u63D0\u70BC observations\uFF0C\u518D\u8C03\u7528 mcp__devflow__memory_save_distilled \u5E76\u786E\u8BA4\u4FDD\u5B58\u7ED3\u679C\u3002`}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 T(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}async function F(o="",r=m()){let e;try{let i=JSON.parse(o);typeof i.session_id=="string"&&i.session_id.trim()&&(e=i.session_id.trim());}catch{}let t=new d;try{await t.flushAndAggregate();}finally{t.close();}let s=await b({projectRoot:r,sessionId:e,trigger:"pre_compact"}),n=[T()?w:"",D(s)].filter(Boolean).join(`
2
2
 
3
- `);return {hookSpecificOutput:{hookEventName:"PreCompact",...n?{additionalContext:n}:{}}}}if(process.argv[1]?.endsWith("pre-compact")||process.argv[1]?.endsWith("pre-compact.js")){let s=console.log,r=console.info,e=()=>{console.log=s,console.info=r;};console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",o=>{t+=o;}),process.stdin.on("end",()=>{j(t.trim()||process.argv[2]||"").then(o=>{e(),s(JSON.stringify(o)),process.exit(0);}).catch(()=>{e(),process.exit(0);});}),process.stdin.on("error",()=>{e(),process.exit(0);}),setTimeout(()=>process.exit(0),14e3).unref();}export{j as handlePreCompact};
3
+ `);return {hookSpecificOutput:{hookEventName:"PreCompact",...n?{additionalContext:n}:{}}}}if(process.argv[1]?.endsWith("pre-compact")||process.argv[1]?.endsWith("pre-compact.js")){let o=console.log,r=console.info,e=()=>{console.log=o,console.info=r;};console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{t+=s;}),process.stdin.on("end",()=>{F(t.trim()||process.argv[2]||"").then(s=>{e(),o(JSON.stringify(s)),process.exit(0);}).catch(()=>{e(),process.exit(0);});}),process.stdin.on("error",()=>{e(),process.exit(0);}),setTimeout(()=>process.exit(0),14e3).unref();}export{F as handlePreCompact};
@@ -1,2 +1,2 @@
1
- import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,renameSync}from'fs';import {join,dirname as dirname$1}from'path';import {request}from'http';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {mkdirSync as mkdirSync$1,existsSync as existsSync$1,statSync,appendFileSync,chmodSync,rmSync as rmSync$1,renameSync as renameSync$1}from'node:fs';import {createHash as createHash$1}from'node:crypto';import {homedir as homedir$1}from'node:os';import {resolve,basename,relative,sep,dirname,join as join$1,isAbsolute}from'node:path';import {randomUUID,createHash}from'crypto';var H=1e4,Se=3e4,w=500;function ke(n,t,e){return new Promise(o=>{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(t)},timeout:5e3},s=>{let c=[];s.on("data",l=>c.push(l)),s.on("end",()=>{let l=Buffer.concat(c).toString();o(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?l:null);});});i.on("error",()=>o(null)),i.on("timeout",()=>{i.destroy(),o(null);}),i.write(t),i.end();}catch{o(null);}})}var S=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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,o,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let c={executionId:t,sessionId:e,skillName:o,startedAt:r,projectRoot:i,requiredMcpTools:s};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(t,e="completed",o=Date.now(),r){let i={executionId:t,status:e,finishedAt:o,metadata:r},s=this.commitOrCache("execution_complete",i);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),s}async sendSessionStart(t,e,o){let r={id:t,projectRoot:e,startedAt:o,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}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 o={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",o);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let o=this.getDatabase(),r=o.listTelemetryFailures({unresolvedOnly:!0,limit:w}).reverse();for(let i of r)try{this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id);}catch{}o.trimTelemetryFailures(w);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(o=>!!o))].filter(o=>existsSync(o)).flatMap(o=>readdirSync(o).filter(r=>r.endsWith(".json")).map(r=>{let i=join(o,r);try{return {cacheFile:i,envelope:Ee(JSON.parse(readFileSync(i,"utf8")),r)}}catch{return null}})).filter(o=>o!==null).sort((o,r)=>o.envelope.timestamp-r.envelope.timestamp||W(o.envelope.operation)-W(r.envelope.operation));for(let{cacheFile:o,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(o);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(o){return this.cacheOperation(t,e,o),false}}applyOperation(t,e){let o=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(o,e),o.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(o,e),o.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":o.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":o.ensureSession(e),o.insertRun({id:G(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(!o.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":o.closeSession(e.sessionId,e.finishedAt),o.updateRun(G(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let o=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!o)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";t.ensureSession({id:o,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,o){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:o instanceof Error?o.message:String(o),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:i.id,operation:t,payload:e,error:i.failure,createdAt:r}),s.trimTelemetryFailures(w),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(i,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-w)))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){ke(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=H?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,H)}...`}}};function W(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function G(n){return `hook-run:${n}`}function Ee(n,t){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 o=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!o)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},i=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:o,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}function T(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function d(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(T(n))}var Ae=2,Me=1;function je(){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 B(n=je()){let t=[join(n,"dist","command-registry.json"),join(n,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let o=JSON.parse(readFileSync(e,"utf8"));if(o.version!==Ae&&o.version!==Me||!Ne(o.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return o.commands}catch(o){console.error(`[devflow] command registry load failed: ${o.message}`);}return null}function Ne(n){return !n||typeof n!="object"||Array.isArray(n)?false:Object.values(n).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return O(e.mcpTools)&&O(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||O(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function O(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function J(n){let t=B();return t?t[n]?.mcpTools??[]:[]}function _(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let o of ["lastMcpCall","bypassCount"])if(o in t){let r=t[o];if(r==null)continue;e[o]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return e}function Ue(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function Le(n){try{return existsSync(n)?_(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function z(n,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${n} skipped: ${e}`);}function K(n){let t=d(n);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join(t,e))&&unlinkSync(join(t,e));}catch{}}function Y(n,t){if(n.getHookReceipt(t)){K(t);return}let e=join(d(t),"receipt.json");if(!existsSync(e))return;let o=Le(e);n.updateHookReceipt(t,()=>o),K(t);}function X(n,t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Y(o,n);let r={},i=o.updateHookReceipt(n,c=>(r=_(c),_(t(r)))),s=_(i);return {receipt:s,applied:!0,changed:!Ue(r,s)}}catch(r){return z(e,r),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function Q(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Y(t,n),_(t.getHookReceipt(n))}catch(e){return z("update",e),{}}finally{try{t?.close();}catch{}}}function $e(n,t){return X(n,()=>t,"write").applied}function qe(n,t){return X(n,t,"update")}var V={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function He(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var k=class{constructor(t,e,o){this.projectRoot=t;this.sessionId=e;this.executionId=o;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}evaluate(t,e){let o=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(o==="context_gathering"&&V[t])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(o==="context_ready")return {permissionDecision:"allow"};let r=V[t];if(!r)return {permissionDecision:"allow"};let i=qe(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,c=He(t);return s>=c?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){$e(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var Xe=10*1024*1024,Qe=5;function Ze(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function te(n){return join$1(homedir$1(),".devflow","logs","hook-debug",`${Ze(n)}.jsonl`)}function ne(n,t,e={}){let o=e.maxBytes??Xe,r=e.maxFiles??Qe;mkdirSync$1(dirname(n),{recursive:true,mode:448});let i=Buffer.byteLength(t),s=existsSync$1(n)?statSync(n).size:0;s>0&&s+i>o&&et(n,r),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}function et(n,t){if(t<=1){rmSync$1(n,{force:true});return}rmSync$1(`${n}.${t-1}`,{force:true});for(let e=t-2;e>=1;e-=1){let o=`${n}.${e}`;existsSync$1(o)&&renameSync$1(o,`${n}.${e+1}`);}existsSync$1(n)&&renameSync$1(n,`${n}.1`);}var N="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function oe(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function at(n){return Buffer.from(n,"utf8").toString("base64url")}var E=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(d(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let o=this.get(e);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;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(t,e,o){let r=this.registerSession(t);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(o)],r.lastActivityAt=Date.now(),this.persist(r),r}get(t){let e=t.trim();if(!e)return null;let o=this.sessions.get(e);if(o)return o;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(t){let e=this.get(t);if(!e)return null;let o={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),o}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,`${at(t)}.json`)}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),o=`${e}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384}),renameSync(o,e);}};function ie(n){let t=n.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 se(n,t){return t?`evt_tool_${createHash("sha256").update(`${n}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var pt=new Set(["Write","Edit","NotebookEdit"]),ce="Claude native memory writes are disabled for this project. Use DevFlow explicit memory or mcp__devflow__memory_commit_turn so a canonical receipt is created.";function pe(n){if(!pt.has(n.toolName))return null;let t=mt(n.toolInput);if(!t)return null;let e=gt(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(ae(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return ce;let r=resolve(n.home??homedir$1(),".claude","projects");return ae(e,r)&&relative(r,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?ce:null}function mt(n){for(let t of ["file_path","notebook_path","path"]){let e=n[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function gt(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function ae(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function v(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function me(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function vt(n){let t=d(n);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Dt(n,t,e,o,r,i){let s=join(vt(n),"event-map.json"),c=[];try{existsSync(s)&&(c=JSON.parse(readFileSync(s,"utf-8")));}catch{}c.push({sessionId:t,toolName:e,toolUseId:o,eventId:r,timestamp:i}),writeFileSync(s,JSON.stringify(c));}function Rt(n){switch(n){case "Read":case "Glob":return "file_read";case "Write":case "Edit":case "NotebookEdit":return "file_write";case "Bash":return "bash_command";case "Agent":return "subagent";case "Skill":return "skill_invoke";default:return "tool_use"}}async function bt(n){let t=oe();try{if(!n||n.trim()==="")return v();let e=JSON.parse(n),o=Date.now(),r=T(),i=new S;e.tool_name.startsWith("mcp__devflow__")&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=r);let s=e.session_id?.trim();if(!s)return me(N);let c=new E(r),l=c.get(s)!==null;if(c.registerSession(s),l||await i.sendSessionStart(s,r,Date.now()),e.tool_name==="Skill"){let b=e.tool_input?.skill,m=b?ie(b):null;if(m){let ye=c.get(s)?.executionId,y=c.startExecution(s,m,J(m));y.executionId&&y.executionId!==ye&&await i.sendExecutionStart(y.executionId,s,m,y.lastActivityAt,r,y.requiredMcpTools);}}let p=c.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=p?.executionId??s,e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let u=e.tool_name.startsWith("mcp__"),fe=u?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,F=new k(r,s,p?.executionId),P=F.getPhase(),a,f=pe({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:r}),D=f?{permissionDecision:"deny",reason:f}:F.evaluate(e.tool_name,u);D.permissionDecision==="deny"?a={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:D.reason??"MCP context required"}}:D.additionalContext?a=me(D.additionalContext):a=v(),e.tool_name.startsWith("mcp__devflow__")&&(a.hookSpecificOutput.updatedInput=e.tool_input),t&&a.hookSpecificOutput.permissionDecision==="allow"&&(a.hookSpecificOutput.additionalContext=N);let he=p?.executionId??s,h={eventId:se(s,e.tool_use_id),executionId:he,sessionId:s,projectRoot:r,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:u?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:u,mcpToolName:fe,mcpEnforced:u&&P==="context_gathering",mcpFallback:!u&&P==="context_gathering",kind:Rt(e.tool_name),input:e.tool_input,duration:0,blocked:a.hookSpecificOutput.permissionDecision==="deny",blockReason:a.hookSpecificOutput.permissionDecision==="deny"?f?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0,error:a.hookSpecificOutput.permissionDecision==="deny"?f?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0},R=await i.sendEvent(h);R&&!h.blocked&&Dt(r,s,e.tool_name,e.tool_use_id,R,h.timestamp),R&&h.blocked&&await i.completeEvent({eventId:R,sessionId:s,error:f?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-h.timestamp,completedAt:Date.now()});try{let b=Q(r),m={ts:o,tool:e.tool_name,sessionId:s,skill:p?.skillName??"(none)",requiredTools:p?.requiredMcpTools??[],isMcp:u,enforce:p?.executionId!==void 0,stateless:p?.executionId===void 0&&!u&&e.tool_name!=="Skill",bypassCount:b.bypassCount??0,decision:a.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};ne(te(r),`${JSON.stringify(m)}
2
- `);}catch{}return a}catch{return v()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=await bt(t);n(JSON.stringify(e));}),process.stdin.on("error",()=>{n(JSON.stringify(v())),process.exit(0);}),setTimeout(()=>{n(JSON.stringify(v())),process.exit(0);},4e3).unref();}export{bt as handlePreToolUse};
1
+ import {existsSync,readdirSync,readFileSync,unlinkSync,mkdirSync,writeFileSync,rmSync,linkSync,renameSync}from'fs';import {join,dirname as dirname$1}from'path';import {request}from'http';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {fileURLToPath}from'url';import {mkdirSync as mkdirSync$1,existsSync as existsSync$1,statSync,appendFileSync,chmodSync,rmSync as rmSync$1,renameSync as renameSync$1}from'node:fs';import {createHash as createHash$1}from'node:crypto';import {homedir as homedir$1}from'node:os';import {resolve,basename,relative,sep,dirname,join as join$1,isAbsolute}from'node:path';import {randomUUID,createHash}from'crypto';var B=1e4,Pe=3e4,w=500;function Le(n,t,e){return new Promise(o=>{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(t)},timeout:5e3},s=>{let c=[];s.on("data",a=>c.push(a)),s.on("end",()=>{let a=Buffer.concat(c).toString();o(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?a:null);});});i.on("error",()=>o(null)),i.on("timeout",()=>{i.destroy(),o(null);}),i.write(t),i.end();}catch{o(null);}})}var I=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;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,o,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let c={executionId:t,sessionId:e,skillName:o,startedAt:r,projectRoot:i,requiredMcpTools:s};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(t,e="completed",o=Date.now(),r){let i={executionId:t,status:e,finishedAt:o,metadata:r},s=this.commitOrCache("execution_complete",i);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),s}async sendSessionStart(t,e,o){let r={id:t,projectRoot:e,startedAt:o,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}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 o={sessionId:t,finishedAt:e},r=this.commitOrCache("session_end",o);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),r}async flushCache(){try{let o=this.getDatabase(),r=o.listTelemetryFailures({unresolvedOnly:!0,limit:w}).reverse();for(let i of r)try{this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id);}catch{}o.trimTelemetryFailures(w);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(o=>!!o))].filter(o=>existsSync(o)).flatMap(o=>readdirSync(o).filter(r=>r.endsWith(".json")).map(r=>{let i=join(o,r);try{return {cacheFile:i,envelope:Ue(JSON.parse(readFileSync(i,"utf8")),r)}}catch{return null}})).filter(o=>o!==null).sort((o,r)=>o.envelope.timestamp-r.envelope.timestamp||z(o.envelope.operation)-z(r.envelope.operation));for(let{cacheFile:o,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(o);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(o){return this.cacheOperation(t,e,o),false}}applyOperation(t,e){let o=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(o,e),o.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(o,e),o.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":o.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":o.ensureSession(e),o.insertRun({id:V(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(!o.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":o.closeSession(e.sessionId,e.finishedAt),o.updateRun(V(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let o=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!o)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";t.ensureSession({id:o,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,o){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:o instanceof Error?o.message:String(o),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:i.id,operation:t,payload:e,error:i.failure,createdAt:r}),s.trimTelemetryFailures(w),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join(this.cacheDir,`${r}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(s,JSON.stringify(i,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-w)))unlinkSync(join(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},Pe).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){Le(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=B?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,B)}...`}}};function z(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function V(n){return `hook-run:${n}`}function Ue(n,t){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 o=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!o)throw new Error("Unknown legacy telemetry cache operation");let r=e.payload??{},i=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:o,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}function A(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function p(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(A(n))}var Be=2,ze=1;function Ve(){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 K(n=Ve()){let t=[join(n,"dist","command-registry.json"),join(n,"command-registry.json")];for(let e of t)try{if(!existsSync(e))continue;let o=JSON.parse(readFileSync(e,"utf8"));if(o.version!==Be&&o.version!==ze||!Ke(o.commands)){console.error(`[devflow] command registry contract mismatch: ${e}`);continue}return o.commands}catch(o){console.error(`[devflow] command registry load failed: ${o.message}`);}return null}function Ke(n){return !n||typeof n!="object"||Array.isArray(n)?false:Object.values(n).every(t=>{if(!t||typeof t!="object"||Array.isArray(t))return false;let e=t;return C(e.mcpTools)&&C(e.blockedNative)&&(e.source===void 0||e.source==="core"||e.source==="plugin")&&(e.requiresContext===void 0||typeof e.requiresContext=="boolean")&&(e.runtimePackages===void 0||C(e.runtimePackages))&&(e.evidenceMode===void 0||["static","runtime","mixed"].includes(e.evidenceMode))})}function C(n){return Array.isArray(n)&&n.every(t=>typeof t=="string"&&t.length>0)}function Y(n){let t=K();return t?t[n]?.mcpTools??[]:[]}function b(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let t=n,e={};for(let o of ["lastMcpCall","bypassCount"])if(o in t){let r=t[o];if(r==null)continue;e[o]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return e}function Qe(n,t){return n.lastMcpCall===t.lastMcpCall&&n.bypassCount===t.bypassCount}function Ze(n){try{return existsSync(n)?b(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function Z(n,t){let e=t instanceof Error?t.message:String(t);console.error(`[devflow] Receipt ${n} skipped: ${e}`);}function X(n){let t=p(n);for(let e of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join(t,e))&&unlinkSync(join(t,e));}catch{}}function ee(n,t){if(n.getHookReceipt(t)){X(t);return}let e=join(p(t),"receipt.json");if(!existsSync(e))return;let o=Ze(e);n.updateHookReceipt(t,()=>o),X(t);}function te(n,t,e){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ee(o,n);let r={},i=o.updateHookReceipt(n,c=>(r=b(c),b(t(r)))),s=b(i);return {receipt:s,applied:!0,changed:!Qe(r,s)}}catch(r){return Z(e,r),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function ne(n){let t;try{return t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),ee(t,n),b(t.getHookReceipt(n))}catch(e){return Z("update",e),{}}finally{try{t?.close();}catch{}}}function et(n,t){return te(n,()=>t,"write").applied}function tt(n,t){return te(n,t,"update")}var Q={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function nt(n){switch(n){case "WebSearch":case "WebFetch":return 1;case "Agent":return 3;case "Grep":case "Glob":return 3;case "Bash":return 5;default:return 2}}var k=class{constructor(t,e,o){this.projectRoot=t;this.sessionId=e;this.executionId=o;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let t;try{t=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let e=t.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(e&&e.expiresAt>Date.now())return "context_ready";e&&t.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{t?.close();}catch{}}return "context_gathering"}evaluate(t,e){let o=this.getPhase();if(e||t==="Skill")return {permissionDecision:"allow"};if(o==="context_gathering"&&Q[t])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${t}.`};if(o==="context_ready")return {permissionDecision:"allow"};let r=Q[t];if(!r)return {permissionDecision:"allow"};let i=tt(this.projectRoot,a=>({...a,bypassCount:(a.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,c=nt(t);return s>=c?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${t}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){et(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var ut=10*1024*1024,pt=5;function gt(n){return createHash$1("sha256").update(n).digest("hex").slice(0,16)}function ie(n){return join$1(homedir$1(),".devflow","logs","hook-debug",`${gt(n)}.jsonl`)}function se(n,t,e={}){let o=e.maxBytes??ut,r=e.maxFiles??pt;mkdirSync$1(dirname(n),{recursive:true,mode:448});let i=Buffer.byteLength(t),s=existsSync$1(n)?statSync(n).size:0;s>0&&s+i>o&&mt(n,r),appendFileSync(n,t,{mode:384}),chmodSync(n,384);}function mt(n,t){if(t<=1){rmSync$1(n,{force:true});return}rmSync$1(`${n}.${t-1}`,{force:true});for(let e=t-2;e>=1;e-=1){let o=`${n}.${e}`;existsSync$1(o)&&renameSync$1(o,`${n}.${e+1}`);}existsSync$1(n)&&renameSync$1(n,`${n}.1`);}var $="WARNING: DevFlow is in degraded mode (daemon unreachable): 4-Gate enforcement and memory prefetch cache are unavailable. Run `devflow doctor` for details.";function ce(){return process.env.DEVFLOW_HOOK_DEGRADED==="1"}function ue(n){return Buffer.from(n,"utf8").toString("base64url")}function vt(n,t,e){let o=t?.trim();if(o){let r=/^[a-zA-Z0-9:._-]{1,192}$/.test(o)?o:`tool-${createHash("sha256").update(o.slice(0,1024)).digest("hex").slice(0,32)}`;return `${n}:${r}`}return `${n}:legacy-${e}-${randomUUID().slice(0,8)}`}function ye(n){return `${n}:legacy-journal`}var S=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join(p(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let o=this.get(e);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let r=Date.now(),i={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:r,lastActivityAt:r};return this.sessions.set(e,i),this.persist(i),i}startExecution(t,e,o){let r=this.registerSession(t);return (!r.executionId||r.skillName!==e)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=e,r.requiredMcpTools=[...new Set(o)],r.lastActivityAt=Date.now(),this.persist(r),r}get(t){let e=t.trim();if(!e)return null;let o=this.sessions.get(e);if(o)return this.replayEvidenceJournal(o),o;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:[],i.evidenceObligations=pe(i.evidenceObligations),i.evidenceDegradations=ge(i.evidenceDegradations),i.evidenceOutcomes=me(i.evidenceOutcomes),this.replayEvidenceJournal(i),this.sessions.set(e,i),i)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let o=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),o}addEvidenceObligation(t,e,o=Date.now(),r){let i=this.registerSession(t),c=(r?void 0:i.evidenceObligations.find(l=>l.contractId===e.id))?.obligationId??vt(e.id,r,o);this.appendEvidenceEvent(t,{kind:"add",obligationId:c,contractId:e.id,at:o,contract:e},`add\0${c}`),this.replayEvidenceJournal(i);let a=i.evidenceObligations.find(l=>l.obligationId===c);return a?(i.lastActivityAt=Date.now(),this.persist(i),structuredClone(a)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,o,r,i=Date.now()){let s=this.get(t),c=s?.evidenceObligations.find(d=>d.obligationId===e);if(!s||!c)return null;let a=/^[a-f0-9]{64}$/.test(r)?r:"";if(!a)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:c.contractId,at:i,fingerprint:a,violations:o.slice(0,16).map(d=>d.slice(0,240))},`correction\0${e}\0${a}`),this.replayEvidenceJournal(s),s.lastActivityAt=i,this.persist(s);let l=s.evidenceObligations.find(d=>d.obligationId===e);return l?structuredClone(l):null}resolveEvidenceObligation(t,e){let o=this.get(t);if(!o)return false;let r=o.evidenceObligations.find(s=>s.obligationId===e);if(!r)return false;let i=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:r.contractId,at:i},`resolve\0${e}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}degradeEvidenceObligation(t,e,o,r=Date.now()){let i=this.get(t),s=i?.evidenceObligations.find(a=>a.obligationId===e);if(!i||!s)return false;let c=o.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:r,reason:c},`degrade\0${e}\0${c}`),this.replayEvidenceJournal(i),i.lastActivityAt=r,this.persist(i),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync(this.snapshotPath(e),{force:true}),rmSync(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join(this.sessionsDir,`${ue(t)}.json`)}evidenceJournalDir(t){return join(this.sessionsDir,"evidence-journal",ue(t))}appendEvidenceEvent(t,e,o){let r=this.evidenceJournalDir(t);mkdirSync(r,{recursive:true,mode:448});let i=createHash("sha256").update(o).digest("hex"),s=join(r,`${e.kind}-${i}.json`);if(existsSync(s))return;let c=join(r,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync(c,JSON.stringify(e),{mode:384});try{linkSync(c,s);}catch(a){if(a.code!=="EEXIST")throw a}finally{rmSync(c,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=pe(t.evidenceObligations),t.evidenceDegradations=ge(t.evidenceDegradations),t.evidenceOutcomes=me(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync(e))return;let o;try{o=readdirSync(e).filter(i=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(i)).slice(0,4096);}catch{return}let r=o.flatMap(i=>{try{let s=readFileSync(join(e,i),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let c=bt(JSON.parse(s));return c?[c]:[]}catch{return []}}).sort((i,s)=>i.at-s.at||fe(i.kind)-fe(s.kind));for(let i of r)this.applyEvidenceEvent(t,i);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let o=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(o)return;let s=t.evidenceObligations.find(c=>c.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let r=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!r||o||r.correctionFingerprint===e.fingerprint)return;r.attempt+=1,r.correctionRequested=true,r.correctionRequestedAt=e.at,r.correctionFingerprint=e.fingerprint,r.violations=e.violations;return}let i=r?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!o&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:i}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:i,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),o=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384}),renameSync(o,e);}};function pe(n){return Array.isArray(n)?n.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!ve(e.contract))return [];let o=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:ye(e.contractId),r=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,i=e.correctionFingerprint??r;return i!==void 0&&!/^[a-f0-9]{64}$/.test(i)?[]:[{...e,obligationId:o,correctionFingerprint:i}]}).slice(-8):[]}function ge(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function me(n){return Array.isArray(n)?n.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function bt(n){if(!n||typeof n!="object")return null;let t=n;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:ye(t.contractId);if(t.kind==="add")return ve(t.contract)?{...t,obligationId:e}:null;if(t.kind==="correction"){let o=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof o=="string"&&/^[a-f0-9]{64}$/.test(o)&&Array.isArray(t.violations)&&t.violations.every(r=>typeof r=="string"&&r.length<=240)?{...t,obligationId:e,fingerprint:o}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function fe(n){return n==="add"?0:n==="correction"?1:2}function ve(n){if(!n||typeof n!="object")return false;let t=n,e=t.requiredSections,o=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(o)&&o.length<=16&&o.every(r=>typeof r=="string"&&r.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function be(n){let t=n.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 _e(n,t){return t?`evt_tool_${createHash("sha256").update(`${n}\0${t}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Rt=new Set(["Write","Edit","NotebookEdit"]),Ee="Claude native memory writes are disabled for this project. Use DevFlow explicit memory or mcp__devflow__memory_commit_turn so a canonical receipt is created.";function ke(n){if(!Rt.has(n.toolName))return null;let t=wt(n.toolInput);if(!t)return null;let e=It(t,n.projectRoot),o=resolve(n.projectRoot,".claude");if(De(e,o)&&basename(e).toLocaleUpperCase("en-US")==="MEMORY.MD")return Ee;let r=resolve(n.home??homedir$1(),".claude","projects");return De(e,r)&&relative(r,e).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?Ee:null}function wt(n){for(let t of ["file_path","notebook_path","path"]){let e=n[t];if(typeof e=="string"&&e.trim())return e.trim()}return null}function It(n,t){return resolve(isAbsolute(n)?n:resolve(t,n))}function De(n,t){let e=relative(t,n);return e===""||!e.startsWith(`..${sep}`)&&e!==".."&&!isAbsolute(e)}function _(){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}function Oe(n){return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:n}}}function At(n){let t=p(n);return existsSync(t)||mkdirSync(t,{recursive:true}),t}function Ct(n,t,e,o,r,i){let s=join(At(n),"event-map.json"),c=[];try{existsSync(s)&&(c=JSON.parse(readFileSync(s,"utf-8")));}catch{}c.push({sessionId:t,toolName:e,toolUseId:o,eventId:r,timestamp:i}),writeFileSync(s,JSON.stringify(c));}function Tt(n){switch(n){case "Read":case "Glob":return "file_read";case "Write":case "Edit":case "NotebookEdit":return "file_write";case "Bash":return "bash_command";case "Agent":return "subagent";case "Skill":return "skill_invoke";default:return "tool_use"}}async function Mt(n){let t=ce();try{if(!n||n.trim()==="")return _();let e=JSON.parse(n),o=Date.now(),r=A(),i=new I;e.tool_name.startsWith("mcp__devflow__")&&(typeof e.tool_input.projectRoot!="string"||!e.tool_input.projectRoot.trim())&&(e.tool_input.projectRoot=r);let s=e.session_id?.trim();if(!s)return Oe($);let c=new S(r),a=c.get(s)!==null;if(c.registerSession(s),a||await i.sendSessionStart(s,r,Date.now()),e.tool_name==="Skill"){let R=e.tool_input?.skill,g=R?be(R):null;if(g){let Ce=c.get(s)?.executionId,v=c.startExecution(s,g,Y(g));v.executionId&&v.executionId!==Ce&&await i.sendExecutionStart(v.executionId,s,g,v.lastActivityAt,r,v.requiredMcpTools);}}let l=c.get(s);e.tool_name.startsWith("mcp__devflow__")&&(e.tool_input._devflow_session_id=s,e.tool_input._devflow_execution_id=l?.executionId??s,e.tool_use_id&&(e.tool_input._devflow_tool_use_id=e.tool_use_id));let d=e.tool_name.startsWith("mcp__"),xe=d?e.tool_name.replace(/^mcp__[^_]+__/,""):void 0,U=new k(r,s,l?.executionId),J=U.getPhase(),u,h=ke({toolName:e.tool_name,toolInput:e.tool_input,projectRoot:r}),E=h?{permissionDecision:"deny",reason:h}:U.evaluate(e.tool_name,d);E.permissionDecision==="deny"?u={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:E.reason??"MCP context required"}}:E.additionalContext?u=Oe(E.additionalContext):u=_(),e.tool_name.startsWith("mcp__devflow__")&&(u.hookSpecificOutput.updatedInput=e.tool_input),t&&u.hookSpecificOutput.permissionDecision==="allow"&&(u.hookSpecificOutput.additionalContext=$);let Ae=l?.executionId??s,y={eventId:_e(s,e.tool_use_id),executionId:Ae,sessionId:s,projectRoot:r,toolUseId:e.tool_use_id,timestamp:Date.now(),toolName:e.tool_name,toolType:d?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:d,mcpToolName:xe,mcpEnforced:d&&J==="context_gathering",mcpFallback:!d&&J==="context_gathering",kind:Tt(e.tool_name),input:e.tool_input,duration:0,blocked:u.hookSpecificOutput.permissionDecision==="deny",blockReason:u.hookSpecificOutput.permissionDecision==="deny"?h?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0,error:u.hookSpecificOutput.permissionDecision==="deny"?h?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0},D=await i.sendEvent(y);D&&!y.blocked&&Ct(r,s,e.tool_name,e.tool_use_id,D,y.timestamp),D&&y.blocked&&await i.completeEvent({eventId:D,sessionId:s,error:h?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-y.timestamp,completedAt:Date.now()});try{let R=ne(r),g={ts:o,tool:e.tool_name,sessionId:s,skill:l?.skillName??"(none)",requiredTools:l?.requiredMcpTools??[],isMcp:d,enforce:l?.executionId!==void 0,stateless:l?.executionId===void 0&&!d&&e.tool_name!=="Skill",bypassCount:R.bypassCount??0,decision:u.hookSpecificOutput.permissionDecision,env_CLAUDE_PLUGIN_ROOT:process.env.CLAUDE_PLUGIN_ROOT??"(unset)",cwd:process.cwd()};se(ie(r),`${JSON.stringify(g)}
2
+ `);}catch{}return u}catch{return _()}}if(process.argv[1]?.endsWith("pre-tool-use")||process.argv[1]?.endsWith("pre-tool-use.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=await Mt(t);n(JSON.stringify(e));}),process.stdin.on("error",()=>{n(JSON.stringify(_())),process.exit(0);}),setTimeout(()=>{n(JSON.stringify(_())),process.exit(0);},4e3).unref();}export{Mt as handlePreToolUse};
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,renameSync as renameSync$1,readdirSync,unlinkSync as unlinkSync$1}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 {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,rmSync}from'node:fs';import {join}from'node:path';function S(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function g(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(S(n))}var R=1e4,K=3e4,v=500;function B(n,t,e){return new Promise(s=>{try{let o=new URL(n),i=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},r=>{let c=[];r.on("data",u=>c.push(u)),r.on("end",()=>{let u=Buffer.concat(c).toString();s(r.statusCode!=null&&r.statusCode>=200&&r.statusCode<300?u:null);});});i.on("error",()=>s(null)),i.on("timeout",()=>{i.destroy(),s(null);}),i.write(t),i.end();}catch{s(null);}})}var b=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$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,s,o,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),r=[]){let c={executionId:t,sessionId:e,skillName:s,startedAt:o,projectRoot:i,requiredMcpTools:r};this.commitOrCache("execution_start",c)&&this.postHttp("/api/telemetry/skill-execution/start",c);}async sendExecutionComplete(t,e="completed",s=Date.now(),o){let i={executionId:t,status:e,finishedAt:s,metadata:o},r=this.commitOrCache("execution_complete",i);return r&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),r}async sendSessionStart(t,e,s){let o={id:t,projectRoot:e,startedAt:s,label:e.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",o);return i&&this.postHttp("/api/telemetry/sessions",o),i}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 s={sessionId:t,finishedAt:e},o=this.commitOrCache("session_end",s);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),o}async flushCache(){try{let s=this.getDatabase(),o=s.listTelemetryFailures({unresolvedOnly:!0,limit:v}).reverse();for(let i of o)try{this.applyOperation(i.operation,i.payload),s.resolveTelemetryFailure(i.id);}catch{}s.trimTelemetryFailures(v);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(s=>!!s))].filter(s=>existsSync$1(s)).flatMap(s=>readdirSync(s).filter(o=>o.endsWith(".json")).map(o=>{let i=join$1(s,o);try{return {cacheFile:i,envelope:G(JSON.parse(readFileSync(i,"utf8")),o)}}catch{return null}})).filter(s=>s!==null).sort((s,o)=>s.envelope.timestamp-o.envelope.timestamp||k(s.envelope.operation)-k(o.envelope.operation));for(let{cacheFile:s,envelope:o}of e)try{let i=this.getDatabase();i.insertTelemetryFailure({id:o.id,operation:o.operation,payload:o.payload,error:o.failure,createdAt:o.timestamp}),this.applyOperation(o.operation,o.payload),i.resolveTelemetryFailure(o.id),unlinkSync$1(s);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(s){return this.cacheOperation(t,e,s),false}}applyOperation(t,e){let s=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(s,e),s.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(s,e),s.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":s.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":s.ensureSession(e),s.insertRun({id:x(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(!s.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":s.closeSession(e.sessionId,e.finishedAt),s.updateRun(x(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let s=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!s)throw new Error("Canonical session ID is required for telemetry");let o=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:s,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,s){let o=Date.now(),i={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:s instanceof Error?s.message:String(s),timestamp:o};try{let r=this.getDatabase();r.insertTelemetryFailure({id:i.id,operation:t,payload:e,error:i.failure,createdAt:o}),r.trimTelemetryFailures(v),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let r=join$1(this.cacheDir,`${o}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(r,JSON.stringify(i,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-v)))unlinkSync$1(join$1(this.cacheDir,e));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},K).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){B(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=R?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,R)}...`}}};function k(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function x(n){return `hook-run:${n}`}function G(n,t){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 s=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!s)throw new Error("Unknown legacy telemetry cache operation");let o=e.payload??{},i=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:s,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}async function E(n){let t=!n.memory,e=n.memory??new MemoryGate(n.projectRoot),s=0,o=0;try{await e.forceWarmUp(),n.trigger==="session_end"&&(s=await e.releasePendingDistillLeases(n.sessionId)),o=e.getPendingEventCount();}finally{t&&e.close();}let i={pendingEvents:o,releasedLeases:s,trigger:n.trigger,sessionId:n.sessionId};try{let r=openGlobalDevFlowDatabase();try{let c=Date.now(),u=`distill:${c}:${Math.random().toString(36).slice(2,10)}`;r.recordMemoryDistillCheckpoint({id:u,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:o,releasedLeases:s,createdAt:c}),r.insertEvent({kind:"memory_distill_requested",timestamp:c,success:!0,metadata:{...i,projectRoot:n.projectRoot}});}finally{r.close();}}catch{}return i}function ie(n){return Buffer.from(n,"utf8").toString("base64url")}var D=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(g(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let s=this.get(e);if(s)return s.lastActivityAt=Date.now(),this.persist(s),s;let o=Date.now(),i={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:o,lastActivityAt:o};return this.sessions.set(e,i),this.persist(i),i}startExecution(t,e,s){let o=this.registerSession(t);return (!o.executionId||o.skillName!==e)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=e,o.requiredMcpTools=[...new Set(s)],o.lastActivityAt=Date.now(),this.persist(o),o}get(t){let e=t.trim();if(!e)return null;let s=this.sessions.get(e);if(s)return s;let o=this.snapshotPath(e);if(!existsSync$1(o))return null;try{let i=JSON.parse(readFileSync(o,"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(t){let e=this.get(t);if(!e)return null;let s={...e,requiredMcpTools:[...e.requiredMcpTools]};return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),s}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${ie(t)}.json`)}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),s=`${e}.${process.pid}.tmp`;writeFileSync$1(s,JSON.stringify(t),{mode:384}),renameSync$1(s,e);}};function F(n,t){let e=le(n);mkdirSync(e,{recursive:true,mode:448});let s=join(e,`${t.receiptId}.json`);if(existsSync(s))return t.receiptId;let o=`${s}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(t),{mode:384});try{renameSync(o,s);}catch(i){try{unlinkSync(o);}catch{}if(!existsSync(s))throw i}return t.receiptId}function le(n){return join(g(n),"session-finalize-pending")}var ge=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",he=getLocalApiKey();function ye(n,t=S(),e=true,s,o=true){let i;try{i=JSON.parse(n);}catch{return null}let r=i.session_id?.trim();if(!r)return null;let c=`session-close:${createHash("sha256").update(`${t}\0${r}`).digest("hex").slice(0,24)}`,u={inputJson:n,sessionId:r,cleanupSharedState:e,executionId:s},m;try{m=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let l=m.requestSessionClosure({receiptId:c,projectRoot:t,sessionId:r,payload:u}),d=m.getWorkByIdempotencyKey(c);return {status:l.state==="closed"||l.state==="closed_with_pending_work"?"completed":"accepted",receiptId:c,workState:d?.state??"pending",closureState:l.state,pendingWorkCount:l.pendingWorkCount}}catch(l){if(!o)throw l;return F(t,{receiptId:c,...u}),{status:"accepted",receiptId:c,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{m?.close();}}function O(n,t){return new Promise(e=>{let s=JSON.stringify(t),o=new URL(n,ge),i=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":he,"Content-Length":Buffer.byteLength(s)},timeout:5e3},()=>e());i.on("error",()=>e()),i.write(s),i.end();})}async function et(n,t=S(),e=true,s){let o;try{o=JSON.parse(n);}catch{return}let i=o.session_id?.trim();if(!i)return;let r=new D(t),c=r.get(i),u=s?.telemetry??new b,m=!s?.telemetry;try{try{await u.flushAndAggregate();}catch{}let l;try{l=openGlobalDevFlowDatabase();let d=c?.executionId;if(d){let a=Date.now(),y=l.listMemoryTurns(t,i,100);try{l.reconcileSkillExecution(d,"completed",a,{memoryReceiptIds:y.flatMap(f=>f.receiptId?[f.receiptId]:[]),missingMemoryDecisionCount:y.filter(f=>f.status==="pending").length});let p=l.getSkillExecution(d);await O("/api/telemetry/skill-execution/complete",{executionId:d,finishedAt:a,status:"completed",summary:{totalToolCalls:p?.totalToolCalls??0,mcpToolCalls:p?.mcpToolCalls??0,directToolCalls:p?.directToolCalls??0,subagentCount:p?.subagentCount??0,totalDuration:p?.totalDuration??0,mcpComplianceRate:p?.mcpComplianceRate??0,missedTools:p?.missedMcpTools??[],actualFailureCount:p?.failedToolCalls??0,fallbackCount:p?.fallbackCount??0,fallbackReasons:p?.fallbackReasons??[]}});}catch{}}let w=l.listMemoryTurns(t,i,100),N=l.reconcileRunningSkillExecutionsForSession(i,Date.now(),{memoryReceiptIds:w.flatMap(a=>a.receiptId?[a.receiptId]:[]),missingMemoryDecisionCount:w.filter(a=>a.status==="pending").length,closureReason:"session_finalize"});for(let a of N)await O("/api/telemetry/skill-execution/complete",{executionId:a.executionId,finishedAt:a.finishedAt,status:a.status,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??[]}});if(e){l.deleteHookReceipt(t);let a=g(t),y=createHash("sha256").update(t).digest("hex").slice(0,12);for(let p of [`session-id-${y}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(a,p),{force:!0});}l.deleteContextReceipt(t,i);}catch{}finally{l?.close();}try{if(await E({projectRoot:t,sessionId:i,trigger:"session_end",memory:s?.memory}),s?.memory)await s.memory.closeSession(i);else {let d=new(await import('@devflow-tools/memory-engine')).MemoryGate(t);try{await d.closeSession(i);}finally{d.close();}}}catch{}try{await u.endSession(i),await u.flushAndAggregate();}catch{}}finally{m&&u.close(),r.removeSession(i);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let n=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=ye(t.trim()||process.argv[2]||"");e&&n(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}
2
- export{ye as enqueueSessionEndFinalization,et as handleSessionEnd};
1
+ import {request}from'http';import {getLocalApiKey,getProjectStateDir}from'@devflow-tools/sdk';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {MemoryGate}from'@devflow-tools/memory-engine';import {existsSync as existsSync$1,readFileSync,rmSync as rmSync$1,mkdirSync as mkdirSync$1,writeFileSync as writeFileSync$1,linkSync,readdirSync,renameSync as renameSync$1,unlinkSync as unlinkSync$1}from'fs';import {join as join$1}from'path';import {homedir}from'os';import {createHash}from'node:crypto';import {randomUUID,createHash as createHash$1}from'crypto';import {mkdirSync,existsSync,writeFileSync,renameSync,unlinkSync,rmSync}from'node:fs';import {join}from'node:path';function C(r){return r??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function v(r){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(C(r))}var W=1e4,Se=3e4,O=500;function Ee(r,t,e){return new Promise(n=>{try{let i=new URL(r),o=request({hostname:i.hostname,port:i.port||80,path:i.pathname+i.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},s=>{let a=[];s.on("data",l=>a.push(l)),s.on("end",()=>{let l=Buffer.concat(a).toString();n(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?l:null);});});o.on("error",()=>n(null)),o.on("timeout",()=>{o.destroy(),n(null);}),o.write(t),o.end();}catch{n(null);}})}var R=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$1(process.env.DEVFLOW_STATE_DIR??join$1(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=t?.legacyCacheDir??(t?.cacheDir?null:join$1(homedir(),".devflow","telemetry-cache")),this.database=t?.database??null,this.ownsDatabase=!t?.database;let e=t?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(e)&&e>=0?e:100;}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,n,i,o=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:t,sessionId:e,skillName:n,startedAt:i,projectRoot:o,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(t,e="completed",n=Date.now(),i){let o={executionId:t,status:e,finishedAt:n,metadata:i},s=this.commitOrCache("execution_complete",o);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",o),s}async sendSessionStart(t,e,n){let i={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},o=this.commitOrCache("session_start",i);return o&&this.postHttp("/api/telemetry/sessions",i),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 n={sessionId:t,finishedAt:e},i=this.commitOrCache("session_end",n);return i&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(t)}/close`,{finishedAt:e})),i}async flushCache(){try{let n=this.getDatabase(),i=n.listTelemetryFailures({unresolvedOnly:!0,limit:O}).reverse();for(let o of i)try{this.applyOperation(o.operation,o.payload),n.resolveTelemetryFailure(o.id);}catch{}n.trimTelemetryFailures(O);}catch{}let e=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync$1(n)).flatMap(n=>readdirSync(n).filter(i=>i.endsWith(".json")).map(i=>{let o=join$1(n,i);try{return {cacheFile:o,envelope:Ie(JSON.parse(readFileSync(o,"utf8")),i)}}catch{return null}})).filter(n=>n!==null).sort((n,i)=>n.envelope.timestamp-i.envelope.timestamp||B(n.envelope.operation)-B(i.envelope.operation));for(let{cacheFile:n,envelope:i}of e)try{let o=this.getDatabase();o.insertTelemetryFailure({id:i.id,operation:i.operation,payload:i.payload,error:i.failure,createdAt:i.timestamp}),this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id),unlinkSync$1(n);}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(void 0,{busyTimeoutMs:this.busyTimeoutMs}),this.database}commitOrCache(t,e){try{return this.applyOperation(t,e),!0}catch(n){return this.cacheOperation(t,e,n),false}}applyOperation(t,e){let n=this.getDatabase();switch(t){case "tool_call":this.ensureParentSession(n,e),n.insertToolCallEvent(e);return;case "execution_start":this.ensureParentSession(n,e),n.insertSkillExecution({executionId:e.executionId,sessionId:e.sessionId,skillName:e.skillName,startedAt:e.startedAt,status:"running",requiredMcpTools:e.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(e.executionId,e.status,e.finishedAt,e.metadata);return;case "session_start":n.ensureSession(e),n.insertRun({id:G(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(!n.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":n.closeSession(e.sessionId,e.finishedAt),n.updateRun(G(e.sessionId),{status:"completed",finishedAt:e.finishedAt});return}}ensureParentSession(t,e){let n=typeof e.sessionId=="string"?e.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let i=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:n,projectRoot:i,label:i==="unknown"?void 0:i.split("/").pop(),startedAt:Number(e.startedAt??e.timestamp??Date.now())});}cacheOperation(t,e,n){let i=Date.now(),o={id:`failure:${i}:${Math.random().toString(36).slice(2,11)}`,operation:t,payload:e,failure:n instanceof Error?n.message:String(n),timestamp:i};try{let s=this.getDatabase();s.insertTelemetryFailure({id:o.id,operation:t,payload:e,error:o.failure,createdAt:i}),s.trimTelemetryFailures(O),this.scheduleRetry();return}catch{}try{existsSync$1(this.cacheDir)||mkdirSync$1(this.cacheDir,{recursive:!0});let s=join$1(this.cacheDir,`${i}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync$1(s,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-O)))unlinkSync$1(join$1(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){Ee(`${this.apiUrl}${t}`,JSON.stringify(e),this.apiKey);}truncateInput(t){let e=JSON.stringify(t);return e===void 0||e.length<=W?t:{_truncated:true,_original_size:e.length,_preview:`${e.substring(0,W)}...`}}};function B(r){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(r)}function G(r){return `hook-run:${r}`}function Ie(r,t){if(!r||typeof r!="object")throw new Error("Invalid telemetry cache envelope");let e=r;if(typeof e.operation=="string"&&e.payload!==void 0)return e;let n=e.type==="tool_call"?"tool_call":e.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let i=e.payload??{},o=Number(i.timestamp??i.startedAt??Date.now());return {id:`legacy-cache:${t}`,operation:n,payload:i,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:o}}async function K(r){let t=!r.memory,e=r.memory??new MemoryGate(r.projectRoot),n=0,i=0;try{await e.forceWarmUp(),r.trigger==="session_end"&&(n=await e.releasePendingDistillLeases(r.sessionId)),i=e.getPendingEventCount(r.sessionId,r.trigger!=="session_end");}finally{t&&e.close();}let o={pendingEvents:i,releasedLeases:n,trigger:r.trigger,sessionId:r.sessionId,details:r.details};try{let s=openGlobalDevFlowDatabase();try{let a=Date.now(),l=r.trigger==="session_end"&&r.sessionId?`distill:session_end:${createHash("sha256").update(`${r.projectRoot}\0${r.sessionId}`).digest("hex").slice(0,24)}`:`distill:${a}:${Math.random().toString(36).slice(2,10)}`;s.recordMemoryDistillCheckpoint({id:l,projectRoot:r.projectRoot,sessionId:r.sessionId,trigger:r.trigger,pendingEvents:i,releasedLeases:n,details:r.details,createdAt:a}),s.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...o,projectRoot:r.projectRoot}});}finally{s.close();}}catch(s){throw s}return o}function Z(r){return Buffer.from(r,"utf8").toString("base64url")}function Re(r,t,e){let n=t?.trim();if(n){let i=/^[a-zA-Z0-9:._-]{1,192}$/.test(n)?n:`tool-${createHash$1("sha256").update(n.slice(0,1024)).digest("hex").slice(0,32)}`;return `${r}:${i}`}return `${r}:legacy-${e}-${randomUUID().slice(0,8)}`}function oe(r){return `${r}:legacy-journal`}var x=class{constructor(t){this.projectRoot=t;this.sessions=new Map;this.sessionsDir=join$1(v(t),"hook-sessions");}registerSession(t){let e=t.trim();if(!e)throw new Error("session_id_required");let n=this.get(e);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let i=Date.now(),o={sessionId:e,projectRoot:this.projectRoot,requiredMcpTools:[],evidenceObligations:[],evidenceDegradations:[],evidenceOutcomes:[],startedAt:i,lastActivityAt:i};return this.sessions.set(e,o),this.persist(o),o}startExecution(t,e,n){let i=this.registerSession(t);return (!i.executionId||i.skillName!==e)&&(i.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),i.skillName=e,i.requiredMcpTools=[...new Set(n)],i.lastActivityAt=Date.now(),this.persist(i),i}get(t){let e=t.trim();if(!e)return null;let n=this.sessions.get(e);if(n)return this.replayEvidenceJournal(n),n;let i=this.snapshotPath(e);if(!existsSync$1(i))return null;try{let o=JSON.parse(readFileSync(i,"utf8"));return o.sessionId!==e||o.projectRoot!==this.projectRoot?null:(o.requiredMcpTools=Array.isArray(o.requiredMcpTools)?o.requiredMcpTools:[],o.evidenceObligations=Q(o.evidenceObligations),o.evidenceDegradations=ee(o.evidenceDegradations),o.evidenceOutcomes=te(o.evidenceOutcomes),this.replayEvidenceJournal(o),this.sessions.set(e,o),o)}catch{return null}}completeExecution(t){let e=this.get(t);if(!e)return null;let n=structuredClone(e);return delete e.executionId,delete e.skillName,e.requiredMcpTools=[],e.lastActivityAt=Date.now(),this.persist(e),n}addEvidenceObligation(t,e,n=Date.now(),i){let o=this.registerSession(t),a=(i?void 0:o.evidenceObligations.find(u=>u.contractId===e.id))?.obligationId??Re(e.id,i,n);this.appendEvidenceEvent(t,{kind:"add",obligationId:a,contractId:e.id,at:n,contract:e},`add\0${a}`),this.replayEvidenceJournal(o);let l=o.evidenceObligations.find(u=>u.obligationId===a);return l?(o.lastActivityAt=Date.now(),this.persist(o),structuredClone(l)):null}listEvidenceObligations(t){return (this.get(t)?.evidenceObligations??[]).map(e=>structuredClone(e))}markEvidenceCorrection(t,e,n,i,o=Date.now()){let s=this.get(t),a=s?.evidenceObligations.find(g=>g.obligationId===e);if(!s||!a)return null;let l=/^[a-f0-9]{64}$/.test(i)?i:"";if(!l)return null;this.appendEvidenceEvent(t,{kind:"correction",obligationId:e,contractId:a.contractId,at:o,fingerprint:l,violations:n.slice(0,16).map(g=>g.slice(0,240))},`correction\0${e}\0${l}`),this.replayEvidenceJournal(s),s.lastActivityAt=o,this.persist(s);let u=s.evidenceObligations.find(g=>g.obligationId===e);return u?structuredClone(u):null}resolveEvidenceObligation(t,e){let n=this.get(t);if(!n)return false;let i=n.evidenceObligations.find(s=>s.obligationId===e);if(!i)return false;let o=Date.now();return this.appendEvidenceEvent(t,{kind:"resolve",obligationId:e,contractId:i.contractId,at:o},`resolve\0${e}`),this.replayEvidenceJournal(n),n.lastActivityAt=o,this.persist(n),true}degradeEvidenceObligation(t,e,n,i=Date.now()){let o=this.get(t),s=o?.evidenceObligations.find(l=>l.obligationId===e);if(!o||!s)return false;let a=n.slice(0,240);return this.appendEvidenceEvent(t,{kind:"degrade",obligationId:e,contractId:s.contractId,at:i,reason:a},`degrade\0${e}\0${a}`),this.replayEvidenceJournal(o),o.lastActivityAt=i,this.persist(o),true}removeSession(t){let e=t.trim();e&&(this.sessions.delete(e),rmSync$1(this.snapshotPath(e),{force:true}),rmSync$1(this.evidenceJournalDir(e),{recursive:true,force:true}));}list(){return [...this.sessions.values()]}snapshotPath(t){return join$1(this.sessionsDir,`${Z(t)}.json`)}evidenceJournalDir(t){return join$1(this.sessionsDir,"evidence-journal",Z(t))}appendEvidenceEvent(t,e,n){let i=this.evidenceJournalDir(t);mkdirSync$1(i,{recursive:true,mode:448});let o=createHash$1("sha256").update(n).digest("hex"),s=join$1(i,`${e.kind}-${o}.json`);if(existsSync$1(s))return;let a=join$1(i,`.${process.pid}.${randomUUID()}.tmp`);writeFileSync$1(a,JSON.stringify(e),{mode:384});try{linkSync(a,s);}catch(l){if(l.code!=="EEXIST")throw l}finally{rmSync$1(a,{force:true});}}replayEvidenceJournal(t){t.evidenceObligations=Q(t.evidenceObligations),t.evidenceDegradations=ee(t.evidenceDegradations),t.evidenceOutcomes=te(t.evidenceOutcomes);let e=this.evidenceJournalDir(t.sessionId);if(!existsSync$1(e))return;let n;try{n=readdirSync(e).filter(o=>/^(?:add|correction|resolve|degrade)-[a-f0-9]{64}\.json$/.test(o)).slice(0,4096);}catch{return}let i=n.flatMap(o=>{try{let s=readFileSync(join$1(e,o),"utf8");if(Buffer.byteLength(s,"utf8")>64*1024)return [];let a=Te(JSON.parse(s));return a?[a]:[]}catch{return []}}).sort((o,s)=>o.at-s.at||ne(o.kind)-ne(s.kind));for(let o of i)this.applyEvidenceEvent(t,o);t.evidenceObligations=t.evidenceObligations.slice(-8),t.evidenceDegradations=t.evidenceDegradations.slice(-20),t.evidenceOutcomes=t.evidenceOutcomes.slice(-20);}applyEvidenceEvent(t,e){let n=t.evidenceOutcomes.find(s=>s.obligationId===e.obligationId);if(e.kind==="add"){if(n)return;let s=t.evidenceObligations.find(a=>a.obligationId===e.obligationId);s?(s.contract=e.contract,s.promptedAt=Math.min(s.promptedAt,e.at)):t.evidenceObligations.push({obligationId:e.obligationId,contractId:e.contractId,contract:e.contract,promptedAt:e.at,attempt:0,correctionRequested:false,violations:[]});return}let i=t.evidenceObligations.find(s=>s.obligationId===e.obligationId);if(e.kind==="correction"){if(!i||n||i.correctionFingerprint===e.fingerprint)return;i.attempt+=1,i.correctionRequested=true,i.correctionRequestedAt=e.at,i.correctionFingerprint=e.fingerprint,i.violations=e.violations;return}let o=i?.attempt??0;t.evidenceObligations=t.evidenceObligations.filter(s=>s.obligationId!==e.obligationId),!n&&(e.kind==="degrade"&&t.evidenceDegradations.push({obligationId:e.obligationId,contractId:e.contractId,reason:e.reason,degradedAt:e.at,attempt:o}),t.evidenceOutcomes.push({obligationId:e.obligationId,contractId:e.contractId,status:e.kind==="resolve"?"resolved":"degraded",completedAt:e.at,attempt:o,...e.kind==="degrade"?{reason:e.reason}:{}}));}persist(t){mkdirSync$1(this.sessionsDir,{recursive:true,mode:448});let e=this.snapshotPath(t.sessionId),n=`${e}.${process.pid}.${randomUUID()}.tmp`;writeFileSync$1(n,JSON.stringify(t),{mode:384}),renameSync$1(n,e);}};function Q(r){return Array.isArray(r)?r.flatMap(t=>{if(!t||typeof t!="object")return [];let e=t;if(typeof e.contractId!="string"||e.contractId.length===0||e.contractId.length>128||typeof e.promptedAt!="number"||typeof e.attempt!="number"||typeof e.correctionRequested!="boolean"||!Array.isArray(e.violations)||!re(e.contract))return [];let n=typeof e.obligationId=="string"&&e.obligationId.length>0&&e.obligationId.length<=384?e.obligationId:oe(e.contractId),i=typeof e.correctionTranscriptHash=="string"?e.correctionTranscriptHash:void 0,o=e.correctionFingerprint??i;return o!==void 0&&!/^[a-f0-9]{64}$/.test(o)?[]:[{...e,obligationId:n,correctionFingerprint:o}]}).slice(-8):[]}function ee(r){return Array.isArray(r)?r.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&typeof e.reason=="string"&&typeof e.degradedAt=="number"&&typeof e.attempt=="number"}).slice(-20):[]}function te(r){return Array.isArray(r)?r.filter(t=>{if(!t||typeof t!="object")return false;let e=t;return typeof e.obligationId=="string"&&typeof e.contractId=="string"&&(e.status==="resolved"||e.status==="degraded")&&typeof e.completedAt=="number"&&typeof e.attempt=="number"&&(e.reason===void 0||typeof e.reason=="string")}).slice(-20):[]}function Te(r){if(!r||typeof r!="object")return null;let t=r;if(!["add","correction","resolve","degrade"].includes(t.kind??"")||typeof t.contractId!="string"||t.contractId.length>128||typeof t.at!="number")return null;let e=typeof t.obligationId=="string"&&t.obligationId.length>0&&t.obligationId.length<=384?t.obligationId:oe(t.contractId);if(t.kind==="add")return re(t.contract)?{...t,obligationId:e}:null;if(t.kind==="correction"){let n=typeof t.fingerprint=="string"?t.fingerprint:t.transcriptHash;return typeof n=="string"&&/^[a-f0-9]{64}$/.test(n)&&Array.isArray(t.violations)&&t.violations.every(i=>typeof i=="string"&&i.length<=240)?{...t,obligationId:e,fingerprint:n}:null}return t.kind==="resolve"?{...t,obligationId:e}:typeof t.reason=="string"&&t.reason.length<=240?{...t,obligationId:e}:null}function ne(r){return r==="add"?0:r==="correction"?1:2}function re(r){if(!r||typeof r!="object")return false;let t=r,e=t.requiredSections,n=t.prohibitedClaims;return t.version==="1.0"&&typeof t.id=="string"&&/^[a-zA-Z0-9][a-zA-Z0-9:._-]{0,127}$/.test(t.id)&&typeof t.runtimeProfilingOccurred=="boolean"&&typeof t.samplingEvidenceOccurred=="boolean"&&Array.isArray(e)&&e.length===3&&e[0]==="\u5DE5\u5177\u53D1\u73B0"&&e[1]==="\u6A21\u578B\u5047\u8BBE"&&e[2]==="\u9700\u8981\u8FD0\u884C\u65F6\u9A8C\u8BC1"&&Array.isArray(n)&&n.length<=16&&n.every(i=>typeof i=="string"&&i.length<=128)&&typeof t.canonicalReport=="string"&&Buffer.byteLength(t.canonicalReport,"utf8")<=48*1024&&!!t.correctionPolicy&&t.correctionPolicy.maxAttempts===1&&t.correctionPolicy.repeatedViolation==="fail_open"}function ce(r,t){let e=Fe(r);mkdirSync(e,{recursive:true,mode:448});let n=join(e,`${t.receiptId}.json`);if(existsSync(n))return t.receiptId;let i=`${n}.${process.pid}.tmp`;writeFileSync(i,JSON.stringify(t),{mode:384});try{renameSync(i,n);}catch(o){try{unlinkSync(i);}catch{}if(!existsSync(n))throw o}return t.receiptId}function Fe(r){return join(v(r),"session-finalize-pending")}var Ne=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",qe=getLocalApiKey();function Ue(r){let t={committed:0,skipped:0,pending:0},e=[];for(let n of r)t[n.status]+=1,n.receiptId&&e.push(n.receiptId);return {memoryReceiptIds:[...new Set(e)],missingMemoryDecisionCount:t.pending,memoryTurnOutcomes:t}}function A(r){return (r instanceof Error?r.message:String(r)).trim().slice(0,240)||"memory_lifecycle_unavailable"}var E=class extends Error{constructor(t,e){super(`session_finalize_${t}:${e}`),this.name="SessionFinalizationRetryableError",this.category=`session_finalize_${t}`;}};function P(r){let t;try{t=openGlobalDevFlowDatabase();let e=(r.executionId?t.getSkillExecution(r.executionId):null)??t.getLatestSkillExecutionForSession(r.sessionId),n={stage:r.stage,reason:r.reason,degradedAt:Date.now()};e&&t.mergeSkillExecutionMetadata(e.executionId,{...r.metadata,sessionFinalizationDegradations:[n]}),t.insertEvent({kind:"session_finalize_degraded",timestamp:n.degradedAt,success:!1,metadata:{projectRoot:r.projectRoot,sessionId:r.sessionId,executionId:e?.executionId,...n}});}catch{}finally{t?.close();}}function He(r,t=C(),e=true,n,i=true){let o;try{o=JSON.parse(r);}catch{return null}let s=o.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${t}\0${s}`).digest("hex").slice(0,24)}`,l={inputJson:r,sessionId:s,cleanupSharedState:e,executionId:n},u;try{u=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let g=u.requestSessionClosure({receiptId:a,projectRoot:t,sessionId:s,payload:l}),w=u.getWorkByIdempotencyKey(a);return {status:g.state==="closed"||g.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:w?.state??"pending",closureState:g.state,pendingWorkCount:g.pendingWorkCount}}catch(g){if(!i)throw g;return ce(t,{receiptId:a,...l}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{u?.close();}}function le(r,t){return new Promise(e=>{let n=JSON.stringify(t),i=new URL(r,Ne),o=request({hostname:i.hostname,port:i.port,path:i.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":qe,"Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>e());o.on("error",()=>e()),o.write(n),o.end();})}async function Tt(r,t=C(),e=true,n){let i;try{i=JSON.parse(r);}catch{return}let o=i.session_id?.trim();if(!o)return;let s=new x(t),a=s.get(o),l={evidenceDegradations:a?.evidenceDegradations??[],evidenceContractOutcomes:a?.evidenceOutcomes??[],pendingEvidenceContractIds:a?.evidenceObligations.map(y=>y.contractId)??[]},u=n?.telemetry??new R,g=!n?.telemetry,w=false,h;try{try{await u.flushAndAggregate();}catch{}let y=Date.now(),I=n?.executionId??a?.executionId,F;try{let p=openGlobalDevFlowDatabase();try{F=p.listSessionMemoryTurnsForReconciliation(t,o);}finally{p.close();}}catch(p){let d=A(p),m={...l,memoryEventReconciliation:{status:"degraded",stage:"turn_load",reason:d,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw P({projectRoot:t,sessionId:o,executionId:I,stage:"turn_load",reason:d,metadata:m}),new E("turn_load",d)}let k=Ue(F),$=n?.memory??(h=new MemoryGate(t)),_;try{_=await $.reconcileDecidedTurnEventWindows(o,F,y);}catch(p){let d=A(p),m={...k,...l,memoryEventReconciliation:{status:"degraded",stage:"event_reconciliation",reason:d,committedProcessed:0,skippedDiscarded:0,remainingUndecided:null,checkpointPending:null}};throw P({projectRoot:t,sessionId:o,executionId:I,stage:"event_reconciliation",reason:d,metadata:m}),new E("event_reconciliation",d)}let j;try{j=await K({projectRoot:t,sessionId:o,trigger:"session_end",memory:$,details:{eventReconciliation:_},strictPersistence:!0});}catch(p){let d=A(p),m={...k,...l,memoryEventReconciliation:{status:"completed",..._,checkpointPending:null},memoryCheckpointDegradation:d};throw P({projectRoot:t,sessionId:o,executionId:I,stage:"checkpoint",reason:d,metadata:m}),new E("checkpoint",d)}let L={memoryEventReconciliation:{status:"completed",..._,checkpointPending:j.pendingEvents},memoryDistillCheckpoint:j};try{await $.closeSession(o),h&&(h.close(),h=void 0);}catch(p){let d=A(p),m={...k,...l,...L,memorySessionCloseDegradation:d};throw P({projectRoot:t,sessionId:o,executionId:I,stage:"memory_close",reason:d,metadata:m}),new E("memory_close",d)}let D={...k,...l,...L};w=!0;let f;try{f=openGlobalDevFlowDatabase();let p=I;if(p)try{f.reconcileSkillExecution(p,"completed",y,D);let c=f.getSkillExecution(p);await le("/api/telemetry/skill-execution/complete",{executionId:p,finishedAt:y,status:"completed",summary:{totalToolCalls:c?.totalToolCalls??0,mcpToolCalls:c?.mcpToolCalls??0,directToolCalls:c?.directToolCalls??0,subagentCount:c?.subagentCount??0,totalDuration:c?.totalDuration??0,mcpComplianceRate:c?.mcpComplianceRate??0,missedTools:c?.missedMcpTools??[],actualFailureCount:c?.failedToolCalls??0,fallbackCount:c?.fallbackCount??0,fallbackReasons:c?.fallbackReasons??[]},metadata:D});}catch{}let d=f.reconcileRunningSkillExecutionsForSession(o,y,{closureReason:"session_finalize",...D});for(let c of d)await le("/api/telemetry/skill-execution/complete",{executionId:c.executionId,finishedAt:c.finishedAt,status:c.status,summary:{totalToolCalls:c.totalToolCalls??0,mcpToolCalls:c.mcpToolCalls??0,directToolCalls:c.directToolCalls??0,subagentCount:c.subagentCount??0,totalDuration:c.totalDuration??0,mcpComplianceRate:c.mcpComplianceRate??0,missedTools:c.missedMcpTools??[],actualFailureCount:c.failedToolCalls??0,fallbackCount:c.fallbackCount??0,fallbackReasons:c.fallbackReasons??[]},metadata:D});let m=f.getLatestSkillExecutionForSession(o);if(m&&!d.some(c=>c.executionId===m.executionId)&&f.mergeSkillExecutionMetadata(m.executionId,D),e){f.deleteHookReceipt(t);let c=v(t),ue=createHash("sha256").update(t).digest("hex").slice(0,12);for(let pe of [`session-id-${ue}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join(c,pe),{force:!0});}f.deleteContextReceipt(t,o);}catch{}finally{f?.close();}try{await u.endSession(o),await u.flushAndAggregate();}catch{}}finally{if(h)try{h.close();}catch{}g&&u.close(),w&&s.removeSession(o);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let r=console.log.bind(console);console.log=console.error.bind(console),console.info=console.error.bind(console);let t="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{t+=e;}),process.stdin.on("end",async()=>{let e=He(t.trim()||process.argv[2]||"");e&&r(JSON.stringify(e)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}
2
+ export{Ue as buildMemoryTurnOutcomeMetadata,He as enqueueSessionEndFinalization,Tt as handleSessionEnd};