@devflow-tools/claude-code-plugin 0.16.10 → 0.16.11
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.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/command-registry.json +39 -13
- package/dist/hooks/hook-client.js +5 -5
- package/dist/hooks/hook-daemon.js +13 -13
- package/dist/hooks/post-tool-use-failure.js +1 -1
- package/dist/hooks/post-tool-use.js +2 -2
- package/dist/hooks/pre-compact.js +1 -1
- package/dist/hooks/pre-tool-use.js +2 -2
- package/dist/hooks/session-end.js +2 -2
- package/dist/hooks/stop.js +2 -2
- package/dist/hooks/user-prompt-submit.js +3 -4
- package/hooks/hooks.json +3 -2
- package/hooks/session-start +54 -67
- package/package.json +8 -8
- package/skills/devflow:animation/SKILL.md +3 -1
- package/skills/devflow:css/SKILL.md +3 -1
- package/skills/devflow:docker/SKILL.md +3 -1
- package/skills/devflow:doctor/SKILL.md +1 -1
- package/skills/devflow:electron/SKILL.md +3 -1
- package/skills/devflow:git/SKILL.md +3 -1
- package/skills/devflow:graphql/SKILL.md +3 -1
- package/skills/devflow:nest/SKILL.md +3 -1
- package/skills/devflow:nextjs/SKILL.md +3 -1
- package/skills/devflow:performance/SKILL.md +3 -1
- package/skills/devflow:react/SKILL.md +6 -4
- package/skills/devflow:tailwind/SKILL.md +3 -1
- package/skills/devflow:taro/SKILL.md +3 -1
- package/skills/devflow:ui-layout/SKILL.md +3 -1
- package/skills/devflow:vue/SKILL.md +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devflow",
|
|
3
3
|
"description": "DevFlow — Developer Intelligence Platform: project context, code graph, knowledge base, memory engine, and workflow automation with 14 domain plugins",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.11",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DevFlow"
|
|
7
7
|
},
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"WebFetch"
|
|
20
20
|
],
|
|
21
21
|
"source": "core",
|
|
22
|
-
"sourceVersion": "0.16.
|
|
22
|
+
"sourceVersion": "0.16.11",
|
|
23
23
|
"requiresContext": true,
|
|
24
24
|
"evidenceMode": "mixed",
|
|
25
25
|
"skillPath": "skills/devflow:context/SKILL.md"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"Explore"
|
|
39
39
|
],
|
|
40
40
|
"source": "core",
|
|
41
|
-
"sourceVersion": "0.16.
|
|
41
|
+
"sourceVersion": "0.16.11",
|
|
42
42
|
"requiresContext": true,
|
|
43
43
|
"evidenceMode": "mixed",
|
|
44
44
|
"skillPath": "skills/devflow:graph/SKILL.md"
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"WebFetch"
|
|
53
53
|
],
|
|
54
54
|
"source": "core",
|
|
55
|
-
"sourceVersion": "0.16.
|
|
55
|
+
"sourceVersion": "0.16.11",
|
|
56
56
|
"requiresContext": true,
|
|
57
57
|
"evidenceMode": "mixed",
|
|
58
58
|
"skillPath": "skills/devflow:knowledge/SKILL.md"
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"Explore"
|
|
72
72
|
],
|
|
73
73
|
"source": "core",
|
|
74
|
-
"sourceVersion": "0.16.
|
|
74
|
+
"sourceVersion": "0.16.11",
|
|
75
75
|
"requiresContext": true,
|
|
76
76
|
"evidenceMode": "mixed",
|
|
77
77
|
"skillPath": "skills/devflow:memory/SKILL.md"
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
],
|
|
83
83
|
"blockedNative": [],
|
|
84
84
|
"source": "core",
|
|
85
|
-
"sourceVersion": "0.16.
|
|
85
|
+
"sourceVersion": "0.16.11",
|
|
86
86
|
"requiresContext": true,
|
|
87
87
|
"evidenceMode": "mixed",
|
|
88
88
|
"skillPath": "skills/devflow:workflow/SKILL.md"
|
|
@@ -169,7 +169,10 @@
|
|
|
169
169
|
"sourceVersion": "0.1.0",
|
|
170
170
|
"requiresContext": true,
|
|
171
171
|
"evidenceMode": "mixed",
|
|
172
|
-
"skillPath": "skills/devflow:electron/SKILL.md"
|
|
172
|
+
"skillPath": "skills/devflow:electron/SKILL.md",
|
|
173
|
+
"runtimePackages": [
|
|
174
|
+
"electron"
|
|
175
|
+
]
|
|
173
176
|
},
|
|
174
177
|
"devflow:git": {
|
|
175
178
|
"mcpTools": [
|
|
@@ -211,7 +214,10 @@
|
|
|
211
214
|
"sourceVersion": "0.1.0",
|
|
212
215
|
"requiresContext": true,
|
|
213
216
|
"evidenceMode": "mixed",
|
|
214
|
-
"skillPath": "skills/devflow:graphql/SKILL.md"
|
|
217
|
+
"skillPath": "skills/devflow:graphql/SKILL.md",
|
|
218
|
+
"runtimePackages": [
|
|
219
|
+
"graphql"
|
|
220
|
+
]
|
|
215
221
|
},
|
|
216
222
|
"devflow:nest": {
|
|
217
223
|
"mcpTools": [
|
|
@@ -233,7 +239,10 @@
|
|
|
233
239
|
"sourceVersion": "0.1.0",
|
|
234
240
|
"requiresContext": true,
|
|
235
241
|
"evidenceMode": "mixed",
|
|
236
|
-
"skillPath": "skills/devflow:nest/SKILL.md"
|
|
242
|
+
"skillPath": "skills/devflow:nest/SKILL.md",
|
|
243
|
+
"runtimePackages": [
|
|
244
|
+
"@nestjs/core"
|
|
245
|
+
]
|
|
237
246
|
},
|
|
238
247
|
"devflow:nextjs": {
|
|
239
248
|
"mcpTools": [
|
|
@@ -255,7 +264,11 @@
|
|
|
255
264
|
"sourceVersion": "0.1.0",
|
|
256
265
|
"requiresContext": true,
|
|
257
266
|
"evidenceMode": "mixed",
|
|
258
|
-
"skillPath": "skills/devflow:nextjs/SKILL.md"
|
|
267
|
+
"skillPath": "skills/devflow:nextjs/SKILL.md",
|
|
268
|
+
"runtimePackages": [
|
|
269
|
+
"next",
|
|
270
|
+
"react"
|
|
271
|
+
]
|
|
259
272
|
},
|
|
260
273
|
"devflow:performance": {
|
|
261
274
|
"mcpTools": [
|
|
@@ -301,7 +314,11 @@
|
|
|
301
314
|
"sourceVersion": "0.1.0",
|
|
302
315
|
"requiresContext": true,
|
|
303
316
|
"evidenceMode": "mixed",
|
|
304
|
-
"skillPath": "skills/devflow:react/SKILL.md"
|
|
317
|
+
"skillPath": "skills/devflow:react/SKILL.md",
|
|
318
|
+
"runtimePackages": [
|
|
319
|
+
"react",
|
|
320
|
+
"react-dom"
|
|
321
|
+
]
|
|
305
322
|
},
|
|
306
323
|
"devflow:tailwind": {
|
|
307
324
|
"mcpTools": [
|
|
@@ -323,7 +340,10 @@
|
|
|
323
340
|
"sourceVersion": "0.1.0",
|
|
324
341
|
"requiresContext": true,
|
|
325
342
|
"evidenceMode": "mixed",
|
|
326
|
-
"skillPath": "skills/devflow:tailwind/SKILL.md"
|
|
343
|
+
"skillPath": "skills/devflow:tailwind/SKILL.md",
|
|
344
|
+
"runtimePackages": [
|
|
345
|
+
"tailwindcss"
|
|
346
|
+
]
|
|
327
347
|
},
|
|
328
348
|
"devflow:taro": {
|
|
329
349
|
"mcpTools": [
|
|
@@ -344,7 +364,10 @@
|
|
|
344
364
|
"sourceVersion": "0.1.0",
|
|
345
365
|
"requiresContext": true,
|
|
346
366
|
"evidenceMode": "mixed",
|
|
347
|
-
"skillPath": "skills/devflow:taro/SKILL.md"
|
|
367
|
+
"skillPath": "skills/devflow:taro/SKILL.md",
|
|
368
|
+
"runtimePackages": [
|
|
369
|
+
"@tarojs/taro"
|
|
370
|
+
]
|
|
348
371
|
},
|
|
349
372
|
"devflow:ui-layout": {
|
|
350
373
|
"mcpTools": [
|
|
@@ -387,7 +410,10 @@
|
|
|
387
410
|
"sourceVersion": "0.1.0",
|
|
388
411
|
"requiresContext": true,
|
|
389
412
|
"evidenceMode": "mixed",
|
|
390
|
-
"skillPath": "skills/devflow:vue/SKILL.md"
|
|
413
|
+
"skillPath": "skills/devflow:vue/SKILL.md",
|
|
414
|
+
"runtimePackages": [
|
|
415
|
+
"vue"
|
|
416
|
+
]
|
|
391
417
|
}
|
|
392
418
|
}
|
|
393
419
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {createConnection}from'node:net';import {getDaemonSocketPath}from'@devflow-tools/sdk';import {mkdirSync,appendFileSync}from'node:fs';import {homedir}from'node:os';import {join,dirname}from'node:path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {createHash}from'node:crypto';function b(e,t,n){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:e,timestamp:Date.now(),duration:n,success:t.success!==!1,metadata:t});}finally{o.close();}}catch{}}var S=["4-Gate enforcement","memory prefetch cache","daemon-shared hook state"];function m(e){let t=
|
|
2
|
-
`,{mode:384});}catch{}}function v(e){try{let t=JSON.parse(e);return {sessionId:typeof t.session_id=="string"?t.session_id:void 0,toolUseId:typeof t.tool_use_id=="string"?t.tool_use_id:void 0}}catch{return {}}}function
|
|
3
|
-
`),0
|
|
1
|
+
import {createConnection}from'node:net';import {getDaemonSocketPath}from'@devflow-tools/sdk';import {mkdirSync,appendFileSync}from'node:fs';import {homedir}from'node:os';import {join,dirname}from'node:path';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {createHash}from'node:crypto';function b(e,t,n){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:e,timestamp:Date.now(),duration:n,success:t.success!==!1,metadata:t});}finally{o.close();}}catch{}}var S=["4-Gate enforcement","memory prefetch cache","daemon-shared hook state"];function m(e){let t=N(e.input)??e.requestType;if(b("hook_daemon_request",{success:e.success,projectRoot:e.projectRoot,requestType:e.requestType,tool:t,attempts:e.attempts},e.durationMs),e.success)return;let n=Date.now(),o=v(e.input);try{let r=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});try{r.insertHookFallback({id:`hook-fallback:${createHash("sha256").update(`${e.projectRoot}\0${o.sessionId??""}\0${o.toolUseId??""}\0${e.requestType}\0${n}`).digest("hex").slice(0,24)}`,projectRoot:e.projectRoot,sessionId:o.sessionId,toolUseId:o.toolUseId,requestType:e.requestType,tool:t,reason:e.reason??"unknown",durationMs:e.durationMs,attempts:e.attempts,createdAt:n});}finally{r.close();}}catch{}try{let r=join(homedir(),".devflow","logs","hook-fallback",`${new Date(n).toISOString().slice(0,10)}.log`);mkdirSync(dirname(r),{recursive:!0,mode:448}),appendFileSync(r,`${JSON.stringify({ts:n,tool:t,requestType:e.requestType,projectRoot:e.projectRoot,reason:`daemon-${e.reason??"unknown"}`,durationMs:e.durationMs,attempts:e.attempts,bypassCountLost:!0,disabledFeatures:S})}
|
|
2
|
+
`,{mode:384});}catch{}}function v(e){try{let t=JSON.parse(e);return {sessionId:typeof t.session_id=="string"?t.session_id:void 0,toolUseId:typeof t.tool_use_id=="string"?t.tool_use_id:void 0}}catch{return {}}}function N(e){try{let t=JSON.parse(e);return typeof t.tool_name=="string"&&t.tool_name?t.tool_name:null}catch{return null}}var d=process.env.CLAUDE_PROJECT_DIR||process.cwd(),q=getDaemonSocketPath(d),u=process.argv[2],h=process.argv[3],p=Number(process.env.DEVFLOW_HOOK_CLIENT_TIMEOUT_MS),F=Number.isFinite(p)&&p>0?p:1e3,f=Number(process.env.DEVFLOW_HOOK_CLIENT_RETRY_DELAY_MS),P=Number.isFinite(f)&&f>=0?f:100,g=2*1024*1024,y=u==="memory-snapshot"?2:1;async function L(){let e=h!==void 0?H(h):u==="memory-snapshot"?{input:"",truncated:false}:await j(),{input:t,truncated:n}=e,o=Date.now(),r="unknown";for(let a=0;a<y;a+=1){let s=await B(t,n);if(s.response!==null){if(x(s.response)){r="protocol";break}return m({projectRoot:d,requestType:u,input:t,durationMs:Date.now()-o,success:true,attempts:a+1}),process.stdout.write(`${s.response}
|
|
3
|
+
`),0}r=s.reason??"unknown",a<y-1&&await G(P);}return process.env.DEVFLOW_HOOK_CLIENT_SUPPRESS_FALLBACK_LOG!=="1"&&m({projectRoot:d,requestType:u,input:t,durationMs:Date.now()-o,success:false,attempts:y,reason:r}),1}function x(e){try{let t=JSON.parse(e);return !!(t&&typeof t=="object"&&!Array.isArray(t)&&typeof t.error=="string")}catch{return true}}function B(e,t){return new Promise(n=>{let o=createConnection(q),r=false,a="",s=(c,l)=>{r||(r=true,clearTimeout(i),o.destroy(),n({response:c,reason:l}));},i=setTimeout(()=>s(null,"timeout"),F);o.setEncoding("utf8"),o.on("connect",()=>{o.write(`${JSON.stringify({type:"hello",rootPath:d})}
|
|
4
4
|
`);let c=$(e,t);if(!c){s(null,"protocol");return}o.write(`${JSON.stringify(c)}
|
|
5
|
-
`);}),o.on("data",c=>{
|
|
6
|
-
`);if(l<0)return;let _=
|
|
5
|
+
`);}),o.on("data",c=>{a+=c;let l=a.indexOf(`
|
|
6
|
+
`);if(l<0)return;let _=a.slice(0,l).trim();s(_||null);}),o.on("error",()=>s(null,"unreachable")),o.on("close",()=>s(null,"unreachable"));})}function $(e,t){let n=t?{truncated:true}:{};return u==="stop"?{type:"stop",input:e,...n}:u==="memory-snapshot"?{type:"memory-snapshot"}:["session-start","session-end","post-tool-use","post-tool-use-failure","pre-tool-use","user-prompt-submit","pre-compact"].includes(u)?{type:u,input:e,...n}:null}function j(){return new Promise(e=>{let t=[],n=0,o=false;process.stdin.on("data",r=>{let a=Buffer.isBuffer(r)?r:Buffer.from(r),s=g-n;if(s>0){let i=a.subarray(0,s);t.push(i),n+=i.length;}a.length>s&&(o=true);}),process.stdin.on("end",()=>e({input:Buffer.concat(t).toString("utf8"),truncated:o})),process.stdin.on("error",()=>e({input:"",truncated:false}));})}function H(e){let t=Buffer.from(e);return t.length<=g?{input:e,truncated:false}:{input:t.subarray(0,g).toString("utf8"),truncated:true}}function G(e){return new Promise(t=>setTimeout(t,e))}L().then(e=>process.exit(e)).catch(()=>process.exit(1));
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {createServer,createConnection}from'net';import {join,dirname}from'path';import {mkdirSync,lstatSync,openSync,writeFileSync,fstatSync,closeSync,readFileSync,unlinkSync,existsSync,rmSync as rmSync$1,renameSync,readdirSync,appendFileSync as appendFileSync$1}from'fs';import {getLocalApiKey,getDaemonSocketPath,getDaemonPidPath,loadConfig,getProjectStateDir,getDaemonRegistryPath,getProjectHash}from'@devflow-tools/sdk';import {request}from'http';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {fileURLToPath}from'url';import {spawn}from'child_process';import {rmSync,mkdirSync as mkdirSync$1,appendFileSync,readdirSync as readdirSync$1,renameSync as renameSync$1,unlinkSync as unlinkSync$1,writeFileSync as writeFileSync$1,readFileSync as readFileSync$1,openSync as openSync$1,closeSync as closeSync$1,statSync,existsSync as existsSync$1}from'node:fs';import {join as join$1,resolve,basename,relative,sep,dirname as dirname$1,isAbsolute}from'node:path';import {MemoryGate}from'@devflow-tools/memory-engine';import {randomUUID,createHash as createHash$1}from'crypto';import {createHash}from'node:crypto';import {homedir as homedir$1}from'node:os';var pe=1e4,ft=3e4,k=500;function yt(r,e,t){return new Promise(n=>{try{let o=new URL(r),i=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t,"Content-Length":Buffer.byteLength(e)},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);});});i.on("error",()=>n(null)),i.on("timeout",()=>{i.destroy(),n(null);}),i.write(e),i.end();}catch{n(null);}})}var I=class{constructor(e){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=e?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=e?.apiKey??getLocalApiKey(),this.cacheDir=e?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=e?.legacyCacheDir??(e?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=e?.database??null,this.ownsDatabase=!e?.database;}async sendEvent(e){let t={...e,input:this.truncateInput(e.input)};return this.commitOrCache("tool_call",t)?(this.postHttp("/api/telemetry/tool-call",t),e.eventId):null}async sendExecutionStart(e,t,n,o,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:e,sessionId:t,skillName:n,startedAt:o,projectRoot:i,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(e,t="completed",n=Date.now(),o){let i={executionId:e,status:t,finishedAt:n,metadata:o},s=this.commitOrCache("execution_complete",i);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),s}async sendSessionStart(e,t,n){let o={id:e,projectRoot:t,startedAt:n,label:t.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",o);return i&&this.postHttp("/api/telemetry/sessions",o),i}async completeEvent(e){let t=this.commitOrCache("complete_event",e);return t&&(this.postHttp("/api/telemetry/tool-call/output",e),this.scheduleMetricAggregation()),t}async endSession(e,t=Date.now()){let n={sessionId:e,finishedAt:t},o=this.commitOrCache("session_end",n);return o&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(e)}/close`,{finishedAt:t})),o}async flushCache(){try{let n=this.getDatabase(),o=n.listTelemetryFailures({unresolvedOnly:!0,limit:k}).reverse();for(let i of o)try{this.applyOperation(i.operation,i.payload),n.resolveTelemetryFailure(i.id);}catch{}n.trimTelemetryFailures(k);}catch{}let t=[...new Set([this.cacheDir,this.legacyCacheDir].filter(n=>!!n))].filter(n=>existsSync(n)).flatMap(n=>readdirSync(n).filter(o=>o.endsWith(".json")).map(o=>{let i=join(n,o);try{return {cacheFile:i,envelope:gt(JSON.parse(readFileSync(i,"utf8")),o)}}catch{return null}})).filter(n=>n!==null).sort((n,o)=>n.envelope.timestamp-o.envelope.timestamp||he(n.envelope.operation)-he(o.envelope.operation));for(let{cacheFile:n,envelope:o}of t)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(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(),this.database}commitOrCache(e,t){try{return this.applyOperation(e,t),!0}catch(n){return this.cacheOperation(e,t,n),false}}applyOperation(e,t){let n=this.getDatabase();switch(e){case "tool_call":this.ensureParentSession(n,t),n.insertToolCallEvent(t);return;case "execution_start":this.ensureParentSession(n,t),n.insertSkillExecution({executionId:t.executionId,sessionId:t.sessionId,skillName:t.skillName,startedAt:t.startedAt,status:"running",requiredMcpTools:t.requiredMcpTools});return;case "execution_complete":n.reconcileSkillExecution(t.executionId,t.status,t.finishedAt,t.metadata);return;case "session_start":n.ensureSession(t),n.insertRun({id:fe(t.id),source:"hook",tool:"session",input:{projectRoot:t.projectRoot},status:"active",startedAt:t.startedAt,tokenUsed:0,metadata:{sessionId:t.id,projectRoot:t.projectRoot}});return;case "complete_event":if(!n.updateToolCallEvent(t.eventId,{output:t.output===void 0?void 0:JSON.stringify(t.output),error:t.error,duration:t.duration}))throw new Error(`Tool call event ${t.eventId} is not available for completion`);return;case "session_end":n.closeSession(t.sessionId,t.finishedAt),n.updateRun(fe(t.sessionId),{status:"completed",finishedAt:t.finishedAt});return}}ensureParentSession(e,t){let n=typeof t.sessionId=="string"?t.sessionId.trim():"";if(!n)throw new Error("Canonical session ID is required for telemetry");let o=typeof t.projectRoot=="string"&&t.projectRoot.trim()?t.projectRoot:typeof t.input?.projectRoot=="string"&&t.input.projectRoot.trim()?t.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";e.ensureSession({id:n,projectRoot:o,label:o==="unknown"?void 0:o.split("/").pop(),startedAt:Number(t.startedAt??t.timestamp??Date.now())});}cacheOperation(e,t,n){let o=Date.now(),i={id:`failure:${o}:${Math.random().toString(36).slice(2,11)}`,operation:e,payload:t,failure:n instanceof Error?n.message:String(n),timestamp:o};try{let s=this.getDatabase();s.insertTelemetryFailure({id:i.id,operation:e,payload:t,error:i.failure,createdAt:o}),s.trimTelemetryFailures(k),this.scheduleRetry();return}catch{}try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let s=join(this.cacheDir,`${o}_${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 e=readdirSync(this.cacheDir).filter(t=>t.endsWith(".json")).sort();for(let t of e.slice(0,Math.max(0,e.length-k)))unlinkSync(join(this.cacheDir,t));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},ft).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(e,t){yt(`${this.apiUrl}${e}`,JSON.stringify(t),this.apiKey);}truncateInput(e){let t=JSON.stringify(e);return t===void 0||t.length<=pe?e:{_truncated:true,_original_size:t.length,_preview:`${t.substring(0,pe)}...`}}};function he(r){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(r)}function fe(r){return `hook-run:${r}`}function gt(r,e){if(!r||typeof r!="object")throw new Error("Invalid telemetry cache envelope");let t=r;if(typeof t.operation=="string"&&t.payload!==void 0)return t;let n=t.type==="tool_call"?"tool_call":t.type==="execution_start"?"execution_start":null;if(!n)throw new Error("Unknown legacy telemetry cache operation");let o=t.payload??{},i=Number(o.timestamp??o.startedAt??Date.now());return {id:`legacy-cache:${e}`,operation:n,payload:o,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}function H(r){return r??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function _(r){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(H(r))}var It=2,Et=1;function bt(){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 ge(r=bt()){let e=[join(r,"dist","command-registry.json"),join(r,"command-registry.json")];for(let t of e)try{if(!existsSync(t))continue;let n=JSON.parse(readFileSync(t,"utf8"));if(n.version!==It&&n.version!==Et||!Tt(n.commands)){console.error(`[devflow] command registry contract mismatch: ${t}`);continue}return n.commands}catch(n){console.error(`[devflow] command registry load failed: ${n.message}`);}return null}function Tt(r){return !r||typeof r!="object"||Array.isArray(r)?false:Object.values(r).every(e=>{if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return ye(t.mcpTools)&&ye(t.blockedNative)&&(t.source===void 0||t.source==="core"||t.source==="plugin")&&(t.requiresContext===void 0||typeof t.requiresContext=="boolean")&&(t.evidenceMode===void 0||["static","runtime","mixed"].includes(t.evidenceMode))})}function ye(r){return Array.isArray(r)&&r.every(e=>typeof e=="string"&&e.length>0)}function ve(r){let e=ge();return e?e[r]?.mcpTools??[]:[]}var J=join(homedir(),".devflow"),B=join(J,"server-refs.json"),Ot="http://127.0.0.1:13337/api/health",At=600*1e3,jt=500;function Nt(){existsSync(J)||mkdirSync(J,{recursive:true});}function D(){try{if(existsSync(B))return JSON.parse(readFileSync(B,"utf-8"))}catch{}return {sessions:[],lastActivity:0}}function _e(r){Nt(),writeFileSync(B,JSON.stringify(r));}var M=class{constructor(e){this.process=null;this.idleTimer=null;this.onShutdown=null;this.projectRoot=e;}setOnShutdown(e){this.onShutdown=e;}addRef(e){let t=D();t.sessions.includes(e)||t.sessions.push(e),t.lastActivity=Date.now(),_e(t),this.resetIdleTimer();}removeRef(e){let t=D();t.sessions=t.sessions.filter(n=>n!==e),t.lastActivity=Date.now(),_e(t),t.sessions.length===0&&this.resetIdleTimer();}get activeSessions(){return D().sessions.length}async ensureRunning(){return await this.healthCheck()?true:(await this.startServer(),this.waitForReady())}get isRunning(){return this.process!==null&&!this.process.killed}async stop(){this.idleTimer&&clearTimeout(this.idleTimer),this.process&&(this.process.kill("SIGTERM"),await new Promise(e=>{let t=setTimeout(()=>{this.process&&!this.process.killed&&this.process.kill("SIGKILL"),e();},5e3);this.process?this.process.on("exit",()=>{clearTimeout(t),e();}):(clearTimeout(t),e());}),this.process=null);}async startServer(){let e=join(this.projectRoot,"apps","server","dist","main.js"),t=join(this.projectRoot,"node_modules","@devflow-tools","server","dist","main.js"),n=existsSync(e)?e:t;this.process=spawn("node",[n],{cwd:this.projectRoot,env:{...process.env,NODE_ENV:process.env.NODE_ENV||"development"},stdio:["ignore","pipe","pipe"]}),this.process.stdout?.on("data",o=>{}),this.process.stderr?.on("data",o=>{}),this.process.on("exit",o=>{this.process=null,this.onShutdown&&this.onShutdown();}),this.process.on("error",()=>{this.process=null;});}async waitForReady(){let e=Date.now()+3e4;for(;Date.now()<e;){if(await this.healthCheck())return true;await new Promise(t=>setTimeout(t,jt));}return false}healthCheck(){return new Promise(e=>{let t=new URL(Ot),n=request({hostname:t.hostname,port:t.port,path:t.pathname,method:"GET",timeout:2e3},o=>{e(o.statusCode===200);});n.on("error",()=>e(false)),n.on("timeout",()=>{n.destroy(),e(false);}),n.end();})}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),!(D().sessions.length>0)&&(this.idleTimer=setTimeout(()=>{this.stop();},At).unref());}};function we(r,e,t){try{let n=openGlobalDevFlowDatabase();try{n.insertEvent({kind:r,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{n.close();}}catch{}}var Y=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",Wt=getLocalApiKey(),Jt=8,Bt=6e4,Se=new Map;function Vt(r){let e=new URL(r,Y).pathname,t=Se.get(e);return t||(t={failures:0,lastFailure:0,openUntil:0,status:"closed"},Se.set(e,t)),t}function X(r,e,t){if(e.status===t)return;let n=e.status;e.status=t,we("http_circuit_transition",{path:new URL(r,Y).pathname,previous:n,status:t,failures:e.failures,openUntil:e.openUntil});}function z(r,e){e.failures++,e.lastFailure=Date.now(),e.failures>=Jt&&(e.openUntil=Date.now()+Bt,X(r,e,"open"));}function zt(r,e){let t=e.status!=="closed";e.failures=0,e.openUntil=0,t&&X(r,e,"closed");}var K=join(homedir(),".devflow","errors");function Re(r,e){try{existsSync(K)||mkdirSync(K,{recursive:!0});let t=`${new Date().toISOString()} | ${r} | ${e?.message??String(e)}
|
|
2
|
-
`;appendFileSync$1(join(K,"http-errors.log"),t);}catch{}}function Ee(r,e,t={}){let n=t.timeout??5e3,o=t.maxRetries??2,i=t.circuitBreaker??true,s=Vt(r);if(i&&s.openUntil>Date.now())return Promise.resolve();i&&s.status==="open"&&X(r,s,"half_open");let a=l=>new Promise(c=>{let u=JSON.stringify(e),d=new URL(r,Y),h=request({hostname:d.hostname,port:d.port,path:d.pathname+d.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Wt,"Content-Length":Buffer.byteLength(u)},timeout:n},f=>{if(f.resume(),f.statusCode&&f.statusCode>=400){let m=new Error(`HTTP ${f.statusCode}`);if(Re(r,m),l>0){let p=Math.min(1e3*Math.pow(2,o-l),8e3);setTimeout(()=>{a(l-1).then(c);},p);}else z(r,s),c();return}zt(r,s),c();});h.on("error",f=>{if(Re(r,f),l>0){let m=Math.min(1e3*Math.pow(2,o-l),8e3);setTimeout(()=>{a(l-1).then(c);},m);}else z(r,s),c();}),h.on("timeout",()=>{h.destroy(),l>0?a(l-1).then(c):(z(r,s),c());}),h.write(u),h.end();});return a(o)}function C(r){if(!r||typeof r!="object"||Array.isArray(r))return {};let e=r,t={};for(let n of ["lastMcpCall","bypassCount"])if(n in e){let o=e[n];if(o==null)continue;t[n]=typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0;}return t}function Xt(r,e){return r.lastMcpCall===e.lastMcpCall&&r.bypassCount===e.bypassCount}function Qt(r){try{return existsSync(r)?C(JSON.parse(readFileSync(r,"utf-8"))):{}}catch{return {}}}function Zt(r,e){let t=e instanceof Error?e.message:String(e);console.error(`[devflow] Receipt ${r} skipped: ${t}`);}function be(r){let e=_(r);for(let t of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync(join(e,t))&&unlinkSync(join(e,t));}catch{}}function en(r,e){if(r.getHookReceipt(e)){be(e);return}let t=join(_(e),"receipt.json");if(!existsSync(t))return;let n=Qt(t);r.updateHookReceipt(e,()=>n),be(e);}function De(r,e,t){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),en(n,r);let o={},i=n.updateHookReceipt(r,a=>(o=C(a),C(e(o)))),s=C(i);return {receipt:s,applied:!0,changed:!Xt(o,s)}}catch(o){return Zt(t,o),{receipt:{},applied:false,changed:false}}finally{try{n?.close();}catch{}}}function P(r,e){return De(r,()=>e,"write").applied}function ee(r,e){return De(r,e,"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 tn(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 b=class{constructor(e,t,n){this.projectRoot=e;this.sessionId=t;this.executionId=n;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let e;try{e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let t=e.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(t&&t.expiresAt>Date.now())return "context_ready";t&&e.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{e?.close();}catch{}}return "context_gathering"}evaluate(e,t){let n=this.getPhase();if(t||e==="Skill")return {permissionDecision:"allow"};if(n==="context_gathering"&&Te[e])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${e}.`};if(n==="context_ready")return {permissionDecision:"allow"};let o=Te[e];if(!o)return {permissionDecision:"allow"};let i=ee(this.projectRoot,l=>({...l,bypassCount:(l.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,a=tn(e);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${e}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${o} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){P(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var cn=10,ln=5e3,un=3e4,dn=new Int32Array(new SharedArrayBuffer(4)),Ae=0;function mn(r){if(typeof r!="object"||r===null)return false;let e=r;return typeof e.rootPath=="string"&&e.rootPath.length>0&&typeof e.projectHash=="string"&&e.projectHash.length>0&&typeof e.pid=="number"&&Number.isInteger(e.pid)&&e.pid>0&&typeof e.startedAt=="number"&&Number.isFinite(e.startedAt)&&e.startedAt>=0}function je(r){if(!existsSync$1(r))return {entries:[],needsRepair:false};try{let e=JSON.parse(readFileSync$1(r,"utf8"));if(!Array.isArray(e))return {entries:[],needsRepair:!0};let t=e.filter(mn);return {entries:t,needsRepair:t.length!==e.length}}catch{return {entries:[],needsRepair:true}}}function Ne(r,e){mkdirSync$1(dirname$1(r),{recursive:true});let t=`${r}.${process.pid}.${Date.now()}.${Ae++}.tmp`,n;try{n=openSync$1(t,"wx"),writeFileSync$1(n,JSON.stringify(e,null,2)),closeSync$1(n),n=void 0,renameSync$1(t,r);}finally{try{n!==void 0&&closeSync$1(n);}finally{rmSync(t,{force:true});}}}function Fe(r){try{return process.kill(r,0),!0}catch(e){return e.code!=="ESRCH"}}function Le(r){if(typeof r!="object"||r===null)return false;let e=r;return typeof e.pid=="number"&&Number.isInteger(e.pid)&&e.pid>0&&typeof e.createdAt=="number"&&Number.isFinite(e.createdAt)&&typeof e.token=="string"&&e.token.length>0}function xe(r,e){try{return readFileSync$1(r,"utf8")!==e?!1:(rmSync(r),!0)}catch(t){return t.code==="ENOENT"}}function pn(r){try{let e=readFileSync$1(r,"utf8"),t;try{let o=JSON.parse(e);Le(o)&&(t=o);}catch{}return t?Fe(t.pid)?!1:xe(r,e):Date.now()-statSync(r).mtimeMs>un&&xe(r,e)}catch(e){return e.code==="ENOENT"}}function hn(r){mkdirSync$1(dirname$1(r),{recursive:true});let e=`${r}.lock`,t=Date.now()+ln;for(;;){let n=`${process.pid}:${Date.now()}:${Ae++}`,o;try{return o=openSync$1(e,"wx"),writeFileSync$1(o,JSON.stringify({pid:process.pid,createdAt:Date.now(),token:n})),closeSync$1(o),o=void 0,{path:e,token:n}}catch(i){if(o!==void 0)try{closeSync$1(o);}finally{rmSync(e,{force:true});}if(i.code!=="EEXIST")throw i}if(!pn(e)){if(Date.now()>=t)throw new Error(`Timed out acquiring daemon registry lock: ${e}`);Atomics.wait(dn,0,0,cn);}}}function fn(r){try{let e=readFileSync$1(r.path,"utf8"),t=JSON.parse(e);Le(t)&&t.token===r.token&&rmSync(r.path);}catch(e){if(e.code!=="ENOENT")throw e}}function Ue(r){let e=getDaemonRegistryPath(),t=hn(e);try{return r(e)}finally{fn(t);}}function $e(r,e){Ue(t=>{let n=je(t).entries.filter(o=>o.rootPath!==r&&Fe(o.pid));n.push({rootPath:r,projectHash:getProjectHash(r),pid:e,startedAt:Date.now()}),Ne(t,n);});}function qe(r,e){Ue(t=>{let n=je(t).entries.filter(o=>o.rootPath!==r||e!==void 0&&o.pid!==e);Ne(t,n);});}async function N(r){let e=!r.memory,t=r.memory??new MemoryGate(r.projectRoot),n=0,o=0;try{await t.forceWarmUp(),r.trigger==="session_end"&&(n=await t.releasePendingDistillLeases(r.sessionId)),o=t.getPendingEventCount();}finally{e&&t.close();}let i={pendingEvents:o,releasedLeases:n,trigger:r.trigger,sessionId:r.sessionId};try{let s=openGlobalDevFlowDatabase();try{let a=Date.now(),l=`distill:${a}:${Math.random().toString(36).slice(2,10)}`;s.recordMemoryDistillCheckpoint({id:l,projectRoot:r.projectRoot,sessionId:r.sessionId,trigger:r.trigger,pendingEvents:o,releasedLeases:n,createdAt:a}),s.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...i,projectRoot:r.projectRoot}});}finally{s.close();}}catch{}return i}function te(r){if(r.pendingEvents===0)return "";let e=r.sessionId?`\uFF0CsessionId=${r.sessionId}`:"";return `Memory distill checkpoint: ${r.pendingEvents} \u4E2A\u4E8B\u4EF6\u5F85\u63D0\u70BC${e}\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`}function bn(r){return Buffer.from(r,"utf8").toString("base64url")}var E=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join(_(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let n=this.get(t);if(n)return n.lastActivityAt=Date.now(),this.persist(n),n;let o=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:o,lastActivityAt:o};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,n){let o=this.registerSession(e);return (!o.executionId||o.skillName!==t)&&(o.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),o.skillName=t,o.requiredMcpTools=[...new Set(n)],o.lastActivityAt=Date.now(),this.persist(o),o}get(e){let t=e.trim();if(!t)return null;let n=this.sessions.get(t);if(n)return n;let o=this.snapshotPath(t);if(!existsSync(o))return null;try{let i=JSON.parse(readFileSync(o,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let n={...t,requiredMcpTools:[...t.requiredMcpTools]};return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),n}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync$1(this.snapshotPath(t),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join(this.sessionsDir,`${bn(e)}.json`)}persist(e){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),n=`${t}.${process.pid}.tmp`;writeFileSync(n,JSON.stringify(e),{mode:384}),renameSync(n,t);}};var Pn=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",On=getLocalApiKey();function An(r,e){return new Promise(t=>{let n=JSON.stringify(e),o=new URL(r,Pn),i=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":On,"Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>t());i.on("error",()=>t()),i.write(n),i.end();})}async function ne(r,e=H(),t=true,n){let o;try{o=JSON.parse(r);}catch{return}let i=o.session_id?.trim();if(!i)return;let s=new E(e),a=s.get(i),l=n?.telemetry??new I,c=!n?.telemetry;try{try{await l.flushAndAggregate();}catch{}let u;try{u=openGlobalDevFlowDatabase();let d=a?.executionId;if(d){let h=Date.now(),f=u.listMemoryTurns(e,i,100);try{u.reconcileSkillExecution(d,"completed",h,{memoryReceiptIds:f.flatMap(p=>p.receiptId?[p.receiptId]:[]),missingMemoryDecisionCount:f.filter(p=>p.status==="pending").length});let m=u.getSkillExecution(d);await An("/api/telemetry/skill-execution/complete",{executionId:d,finishedAt:h,status:"completed",summary:{totalToolCalls:m?.totalToolCalls??0,mcpToolCalls:m?.mcpToolCalls??0,directToolCalls:m?.directToolCalls??0,subagentCount:m?.subagentCount??0,totalDuration:m?.totalDuration??0,mcpComplianceRate:m?.mcpComplianceRate??0,missedTools:m?.missedMcpTools??[],actualFailureCount:m?.failedToolCalls??0,fallbackCount:m?.fallbackCount??0,fallbackReasons:m?.fallbackReasons??[]}});}catch{}}if(t){u.deleteHookReceipt(e);let h=_(e),f=createHash("sha256").update(e).digest("hex").slice(0,12);for(let m of [`session-id-${f}`,"current-execution-id","current-skill.json","event-map.json"])rmSync(join$1(h,m),{force:!0});}u.deleteContextReceipt(e,i);}catch{}finally{u?.close();}try{if(await N({projectRoot:e,sessionId:i,trigger:"session_end",memory:n?.memory}),n?.memory)await n.memory.closeSession(i);else {let d=new(await import('@devflow-tools/memory-engine')).MemoryGate(e);try{await d.closeSession(i);}finally{d.close();}}}catch{}try{await l.endSession(i),await l.flushAndAggregate();}catch{}}finally{c&&l.close(),s.removeSession(i);}}if(process.argv[1]?.endsWith("session-end")||process.argv[1]?.endsWith("session-end.js")){let r="";process.stdin.setEncoding("utf8"),process.stdin.on("data",e=>{r+=e;}),process.stdin.on("end",async()=>{await ne(r.trim()||process.argv[2]||""),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var Hn=/^\/(?:devflow:)?[\w-]+\b\s*/iu,Wn=/\b(?:(?:do\s+not|don't|dont|never|not)(?:\s+need\s+to)?|no\s+need\s+to)\s+(?:please\s+)?(?:remember|memorize)\b|(?:不要|别|不用|无需|不必|不需要)(?:再)?(?:记住|记|记忆)/iu,Jn=/(?:^|[.!?]\s*)(?:(?:please|kindly)\s+)?(?:remember|memorize|save\s+this|store\s+this|note\s+that)(?:\s+(?:that|to))?[\s:,-]*(.+)$/iu,Bn=/(?:^|[。!?;,,]\s*)(?:(?:请|麻烦|务必|一定要|帮我|帮忙|需要)\s*)?(?:记住|记一下|记下来|记|记录一下|记录下来|保存一下|保存下来)(?:这(?:件事|一点|个信息|些内容))?[\s::,,]*(.+)$/iu;function F(r){let e=r.trim().replace(Hn,"").trim();return !e||Wn.test(e)?null:(Bn.exec(e)??Jn.exec(e))?.[1]?.trim().replace(/^[::,,\s]+/u,"")||null}function Je(r){let e=createHash("sha256").update(r).digest("hex").slice(0,16),t=process.env.DEVFLOW_STATE_DIR||join$1(homedir$1(),".devflow","state",e);return join$1(t,"memory-intents.jsonl")}function Vn(r){try{return readFileSync$1(r,"utf8").split(`
|
|
3
|
-
`).filter(Boolean).flatMap(e=>{try{let t=JSON.parse(e);return typeof t.content=="string"&&typeof t.createdAt=="number"?[t]:[]}catch{return []}})}catch{return []}}function
|
|
4
|
-
`,{mode:384});}function Ve(r){let e=Je(r),t=`${e}.claim-`,n=`${basename(e)}.claim-`,o=(()=>{try{return readdirSync$1(dirname$1(e)).filter(a=>a.startsWith(n)&&!a.includes(".tmp-")).sort()[0]}catch{return}})(),i=o?join$1(dirname$1(e),o):`${t}${Date.now()}-${process.pid}`;if(!o)try{renameSync$1(e,i);}catch{return null}let s=Vn(i);if(s.length===0){try{unlinkSync$1(i);}catch{}return null}return {path:i,intents:s}}function ze(r){if(r.intents.shift(),r.intents.length===0){try{unlinkSync$1(r.path);}catch{}return}let e=`${r.path}.tmp-${process.pid}`;writeFileSync$1(e,r.intents.map(t=>JSON.stringify(t)).join(`
|
|
1
|
+
import {createServer,createConnection}from'net';import {createHash,randomUUID as randomUUID$1}from'node:crypto';import {join,dirname}from'path';import {mkdirSync,lstatSync,openSync,writeFileSync,fstatSync,closeSync,readFileSync,unlinkSync,existsSync as existsSync$1,readdirSync,rmSync,renameSync as renameSync$1,appendFileSync}from'fs';import {getLocalApiKey,getDaemonSocketPath,getDaemonPidPath,formatSkillRuntimeOverlay,createSkillRuntimeOverlay,loadConfig,selectHostAdapter,getProjectStateDir,getDaemonRegistryPath,getProjectHash}from'@devflow-tools/sdk';import {request}from'http';import {homedir}from'os';import {openGlobalDevFlowDatabase}from'@devflow-tools/database';import {fileURLToPath}from'url';import {spawn}from'child_process';import {mkdirSync as mkdirSync$1,existsSync,writeFileSync as writeFileSync$1,renameSync,unlinkSync as unlinkSync$1,readdirSync as readdirSync$1,readFileSync as readFileSync$1,rmSync as rmSync$1,openSync as openSync$1,closeSync as closeSync$1,statSync}from'node:fs';import {join as join$1,basename,resolve,relative,sep,dirname as dirname$1,isAbsolute}from'node:path';import {MemoryGate}from'@devflow-tools/memory-engine';import {randomUUID,createHash as createHash$1}from'crypto';import {homedir as homedir$1}from'node:os';var Ce=1e4,to=3e4,M=500;function oo(n,e,t){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":t,"Content-Length":Buffer.byteLength(e)},timeout:5e3},s=>{let a=[];s.on("data",c=>a.push(c)),s.on("end",()=>{let c=Buffer.concat(a).toString();o(s.statusCode!=null&&s.statusCode>=200&&s.statusCode<300?c:null);});});i.on("error",()=>o(null)),i.on("timeout",()=>{i.destroy(),o(null);}),i.write(e),i.end();}catch{o(null);}})}var b=class{constructor(e){this.retryScheduled=false;this.metricAggregationScheduled=false;this.apiUrl=e?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=e?.apiKey??getLocalApiKey(),this.cacheDir=e?.cacheDir??join(process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global"),"telemetry-cache"),this.legacyCacheDir=e?.legacyCacheDir??(e?.cacheDir?null:join(homedir(),".devflow","telemetry-cache")),this.database=e?.database??null,this.ownsDatabase=!e?.database;let t=e?.busyTimeoutMs??Number(process.env.DEVFLOW_TELEMETRY_DB_BUSY_TIMEOUT_MS);this.busyTimeoutMs=Number.isSafeInteger(t)&&t>=0?t:100;}async sendEvent(e){let t={...e,input:this.truncateInput(e.input)};return this.commitOrCache("tool_call",t)?(this.postHttp("/api/telemetry/tool-call",t),e.eventId):null}async sendExecutionStart(e,t,o,r,i=process.env.CLAUDE_PROJECT_DIR??process.cwd(),s=[]){let a={executionId:e,sessionId:t,skillName:o,startedAt:r,projectRoot:i,requiredMcpTools:s};this.commitOrCache("execution_start",a)&&this.postHttp("/api/telemetry/skill-execution/start",a);}async sendExecutionComplete(e,t="completed",o=Date.now(),r){let i={executionId:e,status:t,finishedAt:o,metadata:r},s=this.commitOrCache("execution_complete",i);return s&&this.postHttp("/api/telemetry/skill-execution/complete-reconciled",i),s}async sendSessionStart(e,t,o){let r={id:e,projectRoot:t,startedAt:o,label:t.split("/").pop()??"unknown"},i=this.commitOrCache("session_start",r);return i&&this.postHttp("/api/telemetry/sessions",r),i}async completeEvent(e){let t=this.commitOrCache("complete_event",e);return t&&(this.postHttp("/api/telemetry/tool-call/output",e),this.scheduleMetricAggregation()),t}async endSession(e,t=Date.now()){let o={sessionId:e,finishedAt:t},r=this.commitOrCache("session_end",o);return r&&(this.getDatabase().aggregatePendingToolMetrics(),this.postHttp(`/api/telemetry/sessions/${encodeURIComponent(e)}/close`,{finishedAt:t})),r}async flushCache(){try{let o=this.getDatabase(),r=o.listTelemetryFailures({unresolvedOnly:!0,limit:M}).reverse();for(let i of r)try{this.applyOperation(i.operation,i.payload),o.resolveTelemetryFailure(i.id);}catch{}o.trimTelemetryFailures(M);}catch{}let t=[...new Set([this.cacheDir,this.legacyCacheDir].filter(o=>!!o))].filter(o=>existsSync$1(o)).flatMap(o=>readdirSync(o).filter(r=>r.endsWith(".json")).map(r=>{let i=join(o,r);try{return {cacheFile:i,envelope:no(JSON.parse(readFileSync(i,"utf8")),r)}}catch{return null}})).filter(o=>o!==null).sort((o,r)=>o.envelope.timestamp-r.envelope.timestamp||Pe(o.envelope.operation)-Pe(r.envelope.operation));for(let{cacheFile:o,envelope:r}of t)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(e,t){try{return this.applyOperation(e,t),!0}catch(o){return this.cacheOperation(e,t,o),false}}applyOperation(e,t){let o=this.getDatabase();switch(e){case "tool_call":this.ensureParentSession(o,t),o.insertToolCallEvent(t);return;case "execution_start":this.ensureParentSession(o,t),o.insertSkillExecution({executionId:t.executionId,sessionId:t.sessionId,skillName:t.skillName,startedAt:t.startedAt,status:"running",requiredMcpTools:t.requiredMcpTools});return;case "execution_complete":o.reconcileSkillExecution(t.executionId,t.status,t.finishedAt,t.metadata);return;case "session_start":o.ensureSession(t),o.insertRun({id:Oe(t.id),source:"hook",tool:"session",input:{projectRoot:t.projectRoot},status:"active",startedAt:t.startedAt,tokenUsed:0,metadata:{sessionId:t.id,projectRoot:t.projectRoot}});return;case "complete_event":if(!o.updateToolCallEvent(t.eventId,{output:t.output===void 0?void 0:JSON.stringify(t.output),error:t.error,duration:t.duration}))throw new Error(`Tool call event ${t.eventId} is not available for completion`);return;case "session_end":o.closeSession(t.sessionId,t.finishedAt),o.updateRun(Oe(t.sessionId),{status:"completed",finishedAt:t.finishedAt});return}}ensureParentSession(e,t){let o=typeof t.sessionId=="string"?t.sessionId.trim():"";if(!o)throw new Error("Canonical session ID is required for telemetry");let r=typeof t.projectRoot=="string"&&t.projectRoot.trim()?t.projectRoot:typeof t.input?.projectRoot=="string"&&t.input.projectRoot.trim()?t.input.projectRoot:process.env.CLAUDE_PROJECT_DIR??"unknown";e.ensureSession({id:o,projectRoot:r,label:r==="unknown"?void 0:r.split("/").pop(),startedAt:Number(t.startedAt??t.timestamp??Date.now())});}cacheOperation(e,t,o){let r=Date.now(),i={id:`failure:${r}:${Math.random().toString(36).slice(2,11)}`,operation:e,payload:t,failure:o instanceof Error?o.message:String(o),timestamp:r};try{let s=this.getDatabase();s.insertTelemetryFailure({id:i.id,operation:e,payload:t,error:i.failure,createdAt:r}),s.trimTelemetryFailures(M),this.scheduleRetry();return}catch{}try{existsSync$1(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 e=readdirSync(this.cacheDir).filter(t=>t.endsWith(".json")).sort();for(let t of e.slice(0,Math.max(0,e.length-M)))unlinkSync(join(this.cacheDir,t));}catch{}}scheduleRetry(){this.retryScheduled||(this.retryScheduled=true,setTimeout(()=>{this.retryScheduled=false,this.flushCache();},to).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(e,t){oo(`${this.apiUrl}${e}`,JSON.stringify(t),this.apiKey);}truncateInput(e){let t=JSON.stringify(e);return t===void 0||t.length<=Ce?e:{_truncated:true,_original_size:t.length,_preview:`${t.substring(0,Ce)}...`}}};function Pe(n){return ["session_start","execution_start","tool_call","complete_event","execution_complete","session_end"].indexOf(n)}function Oe(n){return `hook-run:${n}`}function no(n,e){if(!n||typeof n!="object")throw new Error("Invalid telemetry cache envelope");let t=n;if(typeof t.operation=="string"&&t.payload!==void 0)return t;let o=t.type==="tool_call"?"tool_call":t.type==="execution_start"?"execution_start":null;if(!o)throw new Error("Unknown legacy telemetry cache operation");let r=t.payload??{},i=Number(r.timestamp??r.startedAt??Date.now());return {id:`legacy-cache:${e}`,operation:o,payload:r,failure:"Replayed legacy HTTP-first telemetry cache entry",timestamp:i}}function C(n){return n??process.env.CLAUDE_PROJECT_DIR??process.cwd()}function _(n){return process.env.DEVFLOW_STATE_DIR??getProjectStateDir(C(n))}var lo=2,uo=1;function po(){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 Ae(n=po()){let e=[join(n,"dist","command-registry.json"),join(n,"command-registry.json")];for(let t of e)try{if(!existsSync$1(t))continue;let o=JSON.parse(readFileSync(t,"utf8"));if(o.version!==lo&&o.version!==uo||!mo(o.commands)){console.error(`[devflow] command registry contract mismatch: ${t}`);continue}return o.commands}catch(o){console.error(`[devflow] command registry load failed: ${o.message}`);}return null}function mo(n){return !n||typeof n!="object"||Array.isArray(n)?false:Object.values(n).every(e=>{if(!e||typeof e!="object"||Array.isArray(e))return false;let t=e;return V(t.mcpTools)&&V(t.blockedNative)&&(t.source===void 0||t.source==="core"||t.source==="plugin")&&(t.requiresContext===void 0||typeof t.requiresContext=="boolean")&&(t.runtimePackages===void 0||V(t.runtimePackages))&&(t.evidenceMode===void 0||["static","runtime","mixed"].includes(t.evidenceMode))})}function V(n){return Array.isArray(n)&&n.every(e=>typeof e=="string"&&e.length>0)}function je(n){let e=Ae();return e?e[n]?.mcpTools??[]:[]}var X=join(homedir(),".devflow"),Q=join(X,"server-refs.json"),vo="http://127.0.0.1:13337/api/health",wo=600*1e3,ko=500;function Ro(){existsSync$1(X)||mkdirSync(X,{recursive:true});}function P(){try{if(existsSync$1(Q))return JSON.parse(readFileSync(Q,"utf-8"))}catch{}return {sessions:[],lastActivity:0}}function Fe(n){Ro(),writeFileSync(Q,JSON.stringify(n));}var A=class{constructor(e){this.process=null;this.idleTimer=null;this.onShutdown=null;this.projectRoot=e;}setOnShutdown(e){this.onShutdown=e;}addRef(e){let t=P();t.sessions.includes(e)||t.sessions.push(e),t.lastActivity=Date.now(),Fe(t),this.resetIdleTimer();}removeRef(e){let t=P();t.sessions=t.sessions.filter(o=>o!==e),t.lastActivity=Date.now(),Fe(t),t.sessions.length===0&&this.resetIdleTimer();}get activeSessions(){return P().sessions.length}async ensureRunning(){return await this.healthCheck()?true:(await this.startServer(),this.waitForReady())}get isRunning(){return this.process!==null&&!this.process.killed}async stop(){this.idleTimer&&clearTimeout(this.idleTimer),this.process&&(this.process.kill("SIGTERM"),await new Promise(e=>{let t=setTimeout(()=>{this.process&&!this.process.killed&&this.process.kill("SIGKILL"),e();},5e3);this.process?this.process.on("exit",()=>{clearTimeout(t),e();}):(clearTimeout(t),e());}),this.process=null);}async startServer(){let e=join(this.projectRoot,"apps","server","dist","main.js"),t=join(this.projectRoot,"node_modules","@devflow-tools","server","dist","main.js"),o=existsSync$1(e)?e:t;this.process=spawn("node",[o],{cwd:this.projectRoot,env:{...process.env,NODE_ENV:process.env.NODE_ENV||"development"},stdio:["ignore","pipe","pipe"]}),this.process.stdout?.on("data",r=>{}),this.process.stderr?.on("data",r=>{}),this.process.on("exit",r=>{this.process=null,this.onShutdown&&this.onShutdown();}),this.process.on("error",()=>{this.process=null;});}async waitForReady(){let e=Date.now()+3e4;for(;Date.now()<e;){if(await this.healthCheck())return true;await new Promise(t=>setTimeout(t,ko));}return false}healthCheck(){return new Promise(e=>{let t=new URL(vo),o=request({hostname:t.hostname,port:t.port,path:t.pathname,method:"GET",timeout:2e3},r=>{e(r.statusCode===200);});o.on("error",()=>e(false)),o.on("timeout",()=>{o.destroy(),e(false);}),o.end();})}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),!(P().sessions.length>0)&&(this.idleTimer=setTimeout(()=>{this.stop();},wo).unref());}};function Ne(n,e,t){try{let o=openGlobalDevFlowDatabase();try{o.insertEvent({kind:n,timestamp:Date.now(),duration:t,success:e.success!==!1,metadata:e});}finally{o.close();}}catch{}}var oe=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",Co=getLocalApiKey(),Po=8,Oo=6e4,$e=new Map;function Ao(n){let e=new URL(n,oe).pathname,t=$e.get(e);return t||(t={failures:0,lastFailure:0,openUntil:0,status:"closed"},$e.set(e,t)),t}function ne(n,e,t){if(e.status===t)return;let o=e.status;e.status=t,Ne("http_circuit_transition",{path:new URL(n,oe).pathname,previous:o,status:t,failures:e.failures,openUntil:e.openUntil});}function ee(n,e){e.failures++,e.lastFailure=Date.now(),e.failures>=Po&&(e.openUntil=Date.now()+Oo,ne(n,e,"open"));}function jo(n,e){let t=e.status!=="closed";e.failures=0,e.openUntil=0,t&&ne(n,e,"closed");}var te=join(homedir(),".devflow","errors");function Le(n,e){try{existsSync$1(te)||mkdirSync(te,{recursive:!0});let t=`${new Date().toISOString()} | ${n} | ${e?.message??String(e)}
|
|
2
|
+
`;appendFileSync(join(te,"http-errors.log"),t);}catch{}}function He(n,e,t={}){let o=t.timeout??5e3,r=t.maxRetries??2,i=t.circuitBreaker??true,s=Ao(n);if(i&&s.openUntil>Date.now())return Promise.resolve();i&&s.status==="open"&&ne(n,s,"half_open");let a=c=>new Promise(l=>{let u=JSON.stringify(e),p=new URL(n,oe),m=request({hostname:p.hostname,port:p.port,path:p.pathname+p.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":Co,"Content-Length":Buffer.byteLength(u)},timeout:o},f=>{if(f.resume(),f.statusCode&&f.statusCode>=400){let d=new Error(`HTTP ${f.statusCode}`);if(Le(n,d),c>0){let y=Math.min(1e3*Math.pow(2,r-c),8e3);setTimeout(()=>{a(c-1).then(l);},y);}else ee(n,s),l();return}jo(n,s),l();});m.on("error",f=>{if(Le(n,f),c>0){let d=Math.min(1e3*Math.pow(2,r-c),8e3);setTimeout(()=>{a(c-1).then(l);},d);}else ee(n,s),l();}),m.on("timeout",()=>{m.destroy(),c>0?a(c-1).then(l):(ee(n,s),l());}),m.write(u),m.end();});return a(r)}function j(n){if(!n||typeof n!="object"||Array.isArray(n))return {};let e=n,t={};for(let o of ["lastMcpCall","bypassCount"])if(o in e){let r=e[o];if(r==null)continue;t[o]=typeof r=="number"&&Number.isFinite(r)&&r>=0?r:0;}return t}function $o(n,e){return n.lastMcpCall===e.lastMcpCall&&n.bypassCount===e.bypassCount}function Lo(n){try{return existsSync$1(n)?j(JSON.parse(readFileSync(n,"utf-8"))):{}}catch{return {}}}function Uo(n,e){let t=e instanceof Error?e.message:String(e);console.error(`[devflow] Receipt ${n} skipped: ${t}`);}function We(n){let e=_(n);for(let t of ["receipt.json","receipt-lock.sqlite","receipt-lock.sqlite-shm","receipt-lock.sqlite-wal"])try{existsSync$1(join(e,t))&&unlinkSync(join(e,t));}catch{}}function Ho(n,e){if(n.getHookReceipt(e)){We(e);return}let t=join(_(e),"receipt.json");if(!existsSync$1(t))return;let o=Lo(t);n.updateHookReceipt(e,()=>o),We(e);}function Je(n,e,t){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),Ho(o,n);let r={},i=o.updateHookReceipt(n,a=>(r=j(a),j(e(r)))),s=j(i);return {receipt:s,applied:!0,changed:!$o(r,s)}}catch(r){return Uo(t,r),{receipt:{},applied:false,changed:false}}finally{try{o?.close();}catch{}}}function F(n,e){return Je(n,()=>e,"write").applied}function se(n,e){return Je(n,e,"update")}var qe={Grep:"get_project_context",Glob:"get_project_context",Agent:"get_project_context",Bash:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function Wo(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 E=class{constructor(e,t,o){this.projectRoot=e;this.sessionId=t;this.executionId=o;}getPhase(){if(!this.sessionId||!this.executionId)return "idle";let e;try{e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250});let t=e.getContextReceipt(this.projectRoot,this.sessionId,this.executionId);if(t&&t.expiresAt>Date.now())return "context_ready";t&&e.deleteContextReceipt(this.projectRoot,this.sessionId,this.executionId);}catch{}finally{try{e?.close();}catch{}}return "context_gathering"}evaluate(e,t){let o=this.getPhase();if(t||e==="Skill")return {permissionDecision:"allow"};if(o==="context_gathering"&&qe[e])return {permissionDecision:"deny",reason:`DevFlow context required. Call mcp__devflow__get_project_context, then retry ${e}.`};if(o==="context_ready")return {permissionDecision:"allow"};let r=qe[e];if(!r)return {permissionDecision:"allow"};let i=se(this.projectRoot,c=>({...c,bypassCount:(c.bypassCount??0)+1}));if(!i.applied)return {permissionDecision:"allow"};let s=i.receipt.bypassCount??0,a=Wo(e);return s>=a?{permissionDecision:"allow",additionalContext:`\u5DF2 ${s} \u6B21\u76F4\u63A5\u4F7F\u7528 ${e}\uFF0C\u5EFA\u8BAE\u7528 mcp__devflow__${r} \u83B7\u53D6\u66F4\u7CBE\u786E\u7684\u4E0A\u4E0B\u6587\u3002`}:{permissionDecision:"allow"}}recordMcpCall(){F(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0});}};var Ko=10,Vo=5e3,Yo=3e4,Xo=new Int32Array(new SharedArrayBuffer(4)),Xe=0;function Qo(n){if(typeof n!="object"||n===null)return false;let e=n;return typeof e.rootPath=="string"&&e.rootPath.length>0&&typeof e.projectHash=="string"&&e.projectHash.length>0&&typeof e.pid=="number"&&Number.isInteger(e.pid)&&e.pid>0&&typeof e.startedAt=="number"&&Number.isFinite(e.startedAt)&&e.startedAt>=0}function Qe(n){if(!existsSync(n))return {entries:[],needsRepair:false};try{let e=JSON.parse(readFileSync$1(n,"utf8"));if(!Array.isArray(e))return {entries:[],needsRepair:!0};let t=e.filter(Qo);return {entries:t,needsRepair:t.length!==e.length}}catch{return {entries:[],needsRepair:true}}}function Ze(n,e){mkdirSync$1(dirname$1(n),{recursive:true});let t=`${n}.${process.pid}.${Date.now()}.${Xe++}.tmp`,o;try{o=openSync$1(t,"wx"),writeFileSync$1(o,JSON.stringify(e,null,2)),closeSync$1(o),o=void 0,renameSync(t,n);}finally{try{o!==void 0&&closeSync$1(o);}finally{rmSync$1(t,{force:true});}}}function et(n){try{return process.kill(n,0),!0}catch(e){return e.code!=="ESRCH"}}function tt(n){if(typeof n!="object"||n===null)return false;let e=n;return typeof e.pid=="number"&&Number.isInteger(e.pid)&&e.pid>0&&typeof e.createdAt=="number"&&Number.isFinite(e.createdAt)&&typeof e.token=="string"&&e.token.length>0}function Ge(n,e){try{return readFileSync$1(n,"utf8")!==e?!1:(rmSync$1(n),!0)}catch(t){return t.code==="ENOENT"}}function Zo(n){try{let e=readFileSync$1(n,"utf8"),t;try{let r=JSON.parse(e);tt(r)&&(t=r);}catch{}return t?et(t.pid)?!1:Ge(n,e):Date.now()-statSync(n).mtimeMs>Yo&&Ge(n,e)}catch(e){return e.code==="ENOENT"}}function en(n){mkdirSync$1(dirname$1(n),{recursive:true});let e=`${n}.lock`,t=Date.now()+Vo;for(;;){let o=`${process.pid}:${Date.now()}:${Xe++}`,r;try{return r=openSync$1(e,"wx"),writeFileSync$1(r,JSON.stringify({pid:process.pid,createdAt:Date.now(),token:o})),closeSync$1(r),r=void 0,{path:e,token:o}}catch(i){if(r!==void 0)try{closeSync$1(r);}finally{rmSync$1(e,{force:true});}if(i.code!=="EEXIST")throw i}if(!Zo(e)){if(Date.now()>=t)throw new Error(`Timed out acquiring daemon registry lock: ${e}`);Atomics.wait(Xo,0,0,Ko);}}}function tn(n){try{let e=readFileSync$1(n.path,"utf8"),t=JSON.parse(e);tt(t)&&t.token===n.token&&rmSync$1(n.path);}catch(e){if(e.code!=="ENOENT")throw e}}function ot(n){let e=getDaemonRegistryPath(),t=en(e);try{return n(e)}finally{tn(t);}}function nt(n,e){ot(t=>{let o=Qe(t).entries.filter(r=>r.rootPath!==n&&et(r.pid));o.push({rootPath:n,projectHash:getProjectHash(n),pid:e,startedAt:Date.now()}),Ze(t,o);});}function rt(n,e){ot(t=>{let o=Qe(t).entries.filter(r=>r.rootPath!==n||e!==void 0&&r.pid!==e);Ze(t,o);});}async function x(n){let e=!n.memory,t=n.memory??new MemoryGate(n.projectRoot),o=0,r=0;try{await t.forceWarmUp(),n.trigger==="session_end"&&(o=await t.releasePendingDistillLeases(n.sessionId)),r=t.getPendingEventCount();}finally{e&&t.close();}let i={pendingEvents:r,releasedLeases:o,trigger:n.trigger,sessionId:n.sessionId};try{let s=openGlobalDevFlowDatabase();try{let a=Date.now(),c=`distill:${a}:${Math.random().toString(36).slice(2,10)}`;s.recordMemoryDistillCheckpoint({id:c,projectRoot:n.projectRoot,sessionId:n.sessionId,trigger:n.trigger,pendingEvents:r,releasedLeases:o,createdAt:a}),s.insertEvent({kind:"memory_distill_requested",timestamp:a,success:!0,metadata:{...i,projectRoot:n.projectRoot}});}finally{s.close();}}catch{}return i}function it(n){if(n.pendingEvents===0)return "";let e=n.sessionId?`\uFF0CsessionId=${n.sessionId}`:"";return `Memory distill checkpoint: ${n.pendingEvents} \u4E2A\u4E8B\u4EF6\u5F85\u63D0\u70BC${e}\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`}function pn(n){return Buffer.from(n,"utf8").toString("base64url")}var I=class{constructor(e){this.projectRoot=e;this.sessions=new Map;this.sessionsDir=join(_(e),"hook-sessions");}registerSession(e){let t=e.trim();if(!t)throw new Error("session_id_required");let o=this.get(t);if(o)return o.lastActivityAt=Date.now(),this.persist(o),o;let r=Date.now(),i={sessionId:t,projectRoot:this.projectRoot,requiredMcpTools:[],startedAt:r,lastActivityAt:r};return this.sessions.set(t,i),this.persist(i),i}startExecution(e,t,o){let r=this.registerSession(e);return (!r.executionId||r.skillName!==t)&&(r.executionId=`exec_${Date.now()}_${randomUUID().slice(0,8)}`),r.skillName=t,r.requiredMcpTools=[...new Set(o)],r.lastActivityAt=Date.now(),this.persist(r),r}get(e){let t=e.trim();if(!t)return null;let o=this.sessions.get(t);if(o)return o;let r=this.snapshotPath(t);if(!existsSync$1(r))return null;try{let i=JSON.parse(readFileSync(r,"utf8"));return i.sessionId!==t||i.projectRoot!==this.projectRoot?null:(i.requiredMcpTools=Array.isArray(i.requiredMcpTools)?i.requiredMcpTools:[],this.sessions.set(t,i),i)}catch{return null}}completeExecution(e){let t=this.get(e);if(!t)return null;let o={...t,requiredMcpTools:[...t.requiredMcpTools]};return delete t.executionId,delete t.skillName,t.requiredMcpTools=[],t.lastActivityAt=Date.now(),this.persist(t),o}removeSession(e){let t=e.trim();t&&(this.sessions.delete(t),rmSync(this.snapshotPath(t),{force:true}));}list(){return [...this.sessions.values()]}snapshotPath(e){return join(this.sessionsDir,`${pn(e)}.json`)}persist(e){mkdirSync(this.sessionsDir,{recursive:true,mode:448});let t=this.snapshotPath(e.sessionId),o=`${t}.${process.pid}.tmp`;writeFileSync(o,JSON.stringify(e),{mode:384}),renameSync$1(o,t);}};function lt(n,e){let t=mt(n);mkdirSync$1(t,{recursive:true,mode:448});let o=join$1(t,`${e.receiptId}.json`);if(existsSync(o))return e.receiptId;let r=`${o}.${process.pid}.tmp`;writeFileSync$1(r,JSON.stringify(e),{mode:384});try{renameSync(r,o);}catch(i){try{unlinkSync$1(r);}catch{}if(!existsSync(o))throw i}return e.receiptId}function ut(n){let e=mt(n);mkdirSync$1(e,{recursive:true,mode:448});let t=readdirSync$1(e).filter(s=>s.endsWith(".json")||/\.json\.claim-\d+$/u.test(s)).sort()[0];if(!t)return null;let o=join$1(e,t),r=/\.json\.claim-\d+$/u.test(t),i=r?o:`${o}.claim-${process.pid}`;if(!r)try{renameSync(o,i);}catch{return null}try{let s=JSON.parse(readFileSync$1(i,"utf8"));if(typeof s.receiptId!="string"||typeof s.inputJson!="string"||typeof s.sessionId!="string"||typeof s.cleanupSharedState!="boolean")throw unlinkSync$1(i),new Error("session_finalize_spool_payload_invalid");return {receiptId:basename(t).replace(/\.json(?:\.claim-\d+)?$/u,""),payload:s,path:i}}catch(s){try{unlinkSync$1(i);}catch{}throw s}}function dt(n){unlinkSync$1(n.path);}function pt(n){try{renameSync(n.path,n.path.replace(/\.claim-\d+$/u,""));}catch{}}function mt(n){return join$1(_(n),"session-finalize-pending")}var wn=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",kn=getLocalApiKey();function H(n,e=C(),t=true,o,r=true){let i;try{i=JSON.parse(n);}catch{return null}let s=i.session_id?.trim();if(!s)return null;let a=`session-close:${createHash("sha256").update(`${e}\0${s}`).digest("hex").slice(0,24)}`,c={inputJson:n,sessionId:s,cleanupSharedState:t,executionId:o},l;try{l=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});let u=l.requestSessionClosure({receiptId:a,projectRoot:e,sessionId:s,payload:c}),p=l.getWorkByIdempotencyKey(a);return {status:u.state==="closed"||u.state==="closed_with_pending_work"?"completed":"accepted",receiptId:a,workState:p?.state??"pending",closureState:u.state,pendingWorkCount:u.pendingWorkCount}}catch(u){if(!r)throw u;return lt(e,{receiptId:a,...c}),{status:"accepted",receiptId:a,workState:"spooled",closureState:"closing",pendingWorkCount:1}}finally{l?.close();}}function ht(n,e){return new Promise(t=>{let o=JSON.stringify(e),r=new URL(n,wn),i=request({hostname:r.hostname,port:r.port,path:r.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":kn,"Content-Length":Buffer.byteLength(o)},timeout:5e3},()=>t());i.on("error",()=>t()),i.write(o),i.end();})}async function gt(n,e=C(),t=true,o){let r;try{r=JSON.parse(n);}catch{return}let i=r.session_id?.trim();if(!i)return;let s=new I(e),a=s.get(i),c=o?.telemetry??new b,l=!o?.telemetry;try{try{await c.flushAndAggregate();}catch{}let u;try{u=openGlobalDevFlowDatabase();let p=a?.executionId;if(p){let d=Date.now(),y=u.listMemoryTurns(e,i,100);try{u.reconcileSkillExecution(p,"completed",d,{memoryReceiptIds:y.flatMap(g=>g.receiptId?[g.receiptId]:[]),missingMemoryDecisionCount:y.filter(g=>g.status==="pending").length});let h=u.getSkillExecution(p);await ht("/api/telemetry/skill-execution/complete",{executionId:p,finishedAt:d,status:"completed",summary:{totalToolCalls:h?.totalToolCalls??0,mcpToolCalls:h?.mcpToolCalls??0,directToolCalls:h?.directToolCalls??0,subagentCount:h?.subagentCount??0,totalDuration:h?.totalDuration??0,mcpComplianceRate:h?.mcpComplianceRate??0,missedTools:h?.missedMcpTools??[],actualFailureCount:h?.failedToolCalls??0,fallbackCount:h?.fallbackCount??0,fallbackReasons:h?.fallbackReasons??[]}});}catch{}}let m=u.listMemoryTurns(e,i,100),f=u.reconcileRunningSkillExecutionsForSession(i,Date.now(),{memoryReceiptIds:m.flatMap(d=>d.receiptId?[d.receiptId]:[]),missingMemoryDecisionCount:m.filter(d=>d.status==="pending").length,closureReason:"session_finalize"});for(let d of f)await ht("/api/telemetry/skill-execution/complete",{executionId:d.executionId,finishedAt:d.finishedAt,status:d.status,summary:{totalToolCalls:d.totalToolCalls??0,mcpToolCalls:d.mcpToolCalls??0,directToolCalls:d.directToolCalls??0,subagentCount:d.subagentCount??0,totalDuration:d.totalDuration??0,mcpComplianceRate:d.mcpComplianceRate??0,missedTools:d.missedMcpTools??[],actualFailureCount:d.failedToolCalls??0,fallbackCount:d.fallbackCount??0,fallbackReasons:d.fallbackReasons??[]}});if(t){u.deleteHookReceipt(e);let d=_(e),y=createHash("sha256").update(e).digest("hex").slice(0,12);for(let h of [`session-id-${y}`,"current-execution-id","current-skill.json","event-map.json"])rmSync$1(join$1(d,h),{force:!0});}u.deleteContextReceipt(e,i);}catch{}finally{u?.close();}try{if(await x({projectRoot:e,sessionId:i,trigger:"session_end",memory:o?.memory}),o?.memory)await o.memory.closeSession(i);else {let p=new(await import('@devflow-tools/memory-engine')).MemoryGate(e);try{await p.closeSession(i);}finally{p.close();}}}catch{}try{await c.endSession(i),await c.flushAndAggregate();}catch{}}finally{l&&c.close(),s.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 e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>{e+=t;}),process.stdin.on("end",async()=>{let t=H(e.trim()||process.argv[2]||"");t&&n(JSON.stringify(t)),process.exit(0);}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),1e4).unref();}var Dn=/^\/(?:devflow:)?[\w-]+\b\s*/iu,Mn=/\b(?:(?:do\s+not|don't|dont|never|not)(?:\s+need\s+to)?|no\s+need\s+to)\s+(?:please\s+)?(?:remember|memorize)\b|(?:不要|别|不用|无需|不必|不需要)(?:再)?(?:记住|记|记忆)/iu,Cn=/(?:^|[.!?]\s*)(?:(?:please|kindly)\s+)?(?:remember|memorize|save\s+this|store\s+this|note\s+that)(?:\s+(?:that|to))?[\s:,-]*(.+)$/iu,Pn=/(?:^|[。!?;,,]\s*)(?:(?:请|麻烦|务必|一定要|帮我|帮忙|需要)\s*)?(?:记住|记一下|记下来|记|记录一下|记录下来|保存一下|保存下来)(?:这(?:件事|一点|个信息|些内容))?[\s::,,]*(.+)$/iu;function W(n){let e=n.trim().replace(Dn,"").trim();return !e||Mn.test(e)?null:(Pn.exec(e)??Cn.exec(e))?.[1]?.trim().replace(/^[::,,\s]+/u,"")||null}function On(n){let e=createHash("sha256").update(n).digest("hex").slice(0,16),t=process.env.DEVFLOW_STATE_DIR||join$1(homedir$1(),".devflow","state",e);return join$1(t,"memory-intents.jsonl")}function An(n){try{return readFileSync$1(n,"utf8").split(`
|
|
3
|
+
`).filter(Boolean).flatMap(e=>{try{let t=JSON.parse(e);return typeof t.content=="string"&&typeof t.createdAt=="number"?[t]:[]}catch{return []}})}catch{return []}}function wt(n){let e=On(n),t=`${e}.claim-`,o=`${basename(e)}.claim-`,r=(()=>{try{return readdirSync$1(dirname$1(e)).filter(a=>a.startsWith(o)&&!a.includes(".tmp-")).sort()[0]}catch{return}})(),i=r?join$1(dirname$1(e),r):`${t}${Date.now()}-${process.pid}`;if(!r)try{renameSync(e,i);}catch{return null}let s=An(i);if(s.length===0){try{unlinkSync$1(i);}catch{}return null}return {path:i,intents:s}}function ue(n){if(n.intents.shift(),n.intents.length===0){try{unlinkSync$1(n.path);}catch{}return}let e=`${n.path}.tmp-${process.pid}`;writeFileSync$1(e,n.intents.map(t=>JSON.stringify(t)).join(`
|
|
5
4
|
`)+`
|
|
6
|
-
`,{mode:384}),renameSync$1(e,r.path);}function L(r){let e=r.trim().replace(/^\//,"");if(!e.startsWith("devflow:"))return null;let t=e.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(t)?`devflow:${t.toLowerCase()}`:null}function Ke(r){let e=r.trimStart().match(/^\/(devflow:[a-z0-9][a-z0-9-]*)\b/i);if(!e)return null;let t=L(e[1]);return t?{rawName:e[1],skillName:t}:null}function T(r,e){return e?`evt_tool_${createHash$1("sha256").update(`${r}\0${e}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Kn=/^(?:ok(?:ay)?|yes|no|thanks?|thank you|continue|好的?|可以|行|是|否|谢谢|继续|收到|明白了?)[.!。!\s]*$/iu;function Yn(r){let e=r.trim();return e.length>0&&!Kn.test(e)}function Xn(r,e,t=Date.now()){let n=createHash("sha256").update(e.trim()).digest("hex"),o=createHash("sha256").update(`${r}\0${t}\0${n}`).digest("hex").slice(0,24);return {turnId:`turn:${o}`,eventId:`memory-turn:${o}`,promptHash:n,createdAt:t}}function ie(r,e,t=[]){return `memory-receipt:${createHash("sha256").update(`${r}\0${e}\0${[...t].sort().join("\0")}`).digest("hex").slice(0,24)}`}function Qe(r){return `DevFlow memory decision required for ${r.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt.`}function Ye(r){let e=r.memoryIds.length>0?r.memoryIds.join(","):"none";return `DevFlow canonical memory receipt: status=${r.status}; receiptId=${r.receiptId??"missing"}; turnId=${r.turnId}; memoryIds=${e}; source=${r.source??"unknown"}.`}function Ze(r,e,t){if(t)return null;let n=openGlobalDevFlowDatabase();try{let o=n.getPendingMemoryTurn(r,e);return !o||!n.markMemoryTurnStopPrompted(o.turnId)?null:{decision:"block",reason:Qe(o)}}finally{n.close();}}async function et(r){if(!Yn(r.prompt))return null;let e=openGlobalDevFlowDatabase();try{let t=createHash("sha256").update(r.prompt.trim()).digest("hex"),n=e.listMemoryTurns(r.projectRoot,r.sessionId,5).find(c=>c.promptHash===t&&Date.now()-c.createdAt<1e4),o=n?{turnId:n.turnId,eventId:n.eventId,promptHash:n.promptHash,createdAt:n.createdAt}:Xn(r.sessionId,r.prompt),i=n??e.beginMemoryTurn({...o,projectRoot:r.projectRoot,sessionId:r.sessionId});if(i.status!=="pending")return {turn:i,additionalContext:Ye(i),skipSkillRouting:i.source==="explicit_intent"};await r.memory.recordUserMessage(r.prompt.slice(0,4e3),r.sessionId,r.prompt.slice(0,200)),await r.memory.recordEvent({id:o.eventId,sessionId:r.sessionId,tool:"UserPromptSubmit",kind:"user_message",payload:{prompt:r.prompt.slice(0,4e3),turnId:o.turnId},createdAt:o.createdAt});let s=F(r.prompt);if(!s)return {turn:i,additionalContext:Qe(i),skipSkillRouting:!1};let a=await r.memory.saveExplicitMemoryIntent(s,r.sessionId,o.eventId),l=ie(i.turnId,"committed",[a.id]);return i=e.commitMemoryTurn({turnId:i.turnId,receiptId:l,memoryIds:[a.id],source:"explicit_intent",reason:"explicit_user_request"}),{turn:i,explicitContent:s,additionalContext:Ye(i),skipSkillRouting:!0}}finally{e.close();}}var eo=new Set(["Write","Edit","NotebookEdit"]),tt="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 st(r){if(!eo.has(r.toolName))return null;let e=to(r.toolInput);if(!e)return null;let t=no(e,r.projectRoot),n=resolve(r.projectRoot,".claude");if(nt(t,n)&&basename(t).toLocaleUpperCase("en-US")==="MEMORY.MD")return tt;let o=resolve(r.home??homedir$1(),".claude","projects");return nt(t,o)&&relative(o,t).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?tt:null}function to(r){for(let e of ["file_path","notebook_path","path"]){let t=r[e];if(typeof t=="string"&&t.trim())return t.trim()}return null}function no(r,e){return resolve(isAbsolute(r)?r:resolve(e,r))}function nt(r,e){let t=relative(e,r);return t===""||!t.startsWith(`..${sep}`)&&t!==".."&&!isAbsolute(t)}var vo=600*1e3,_o=2e3,wo=250,So=2e3,Ro=1e3,at=1024*1024,Io=2*1024*1024,Eo=6e4,bo=100,To={Agent:"get_project_context",Bash:"get_project_context",Glob:"get_project_context",Grep:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function ko(r){switch(r){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"}}function ae(r){return typeof r=="string"&&r.trim().length>0}function Do(r,e,t=process.env,n){if(!r.startsWith("mcp__devflow__"))return e;let o=e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{};if(ae(o.projectRoot))return o;let i=ae(t.CLAUDE_PROJECT_DIR)?t.CLAUDE_PROJECT_DIR:n;return ae(i)&&(o.projectRoot=i),o}var ce=class{constructor(e,t){this.socketIdentity=null;this.pidIdentity=null;this.server=null;this.activeSessionIds=new Set;this.eventMap=[];this.idleTimer=null;this.telemetryFlushTimer=null;this.successfulTelemetryOperations=0;this.shutdownPromise=null;this.explicitMemoryGate=null;this.memoryWarmup=null;this.explicitIntentFlush=null;this.projectRoot=e,this.socketPath=getDaemonSocketPath(e),this.pidPath=getDaemonPidPath(e),this.telemetry=new I,this.runtimeStore=new E(this.projectRoot),this.serverManager=new M(e),t&&this.handleSessionStart(t);}async start(){mkdirSync(dirname(this.socketPath),{recursive:true,mode:448}),await this.cleanStaleStartupResources(),this.server=createServer(e=>this.handleConnection(e));try{await this.listen(),this.writePidFile(),$e(this.projectRoot,process.pid);}catch(e){throw await this.closeServer(),this.cleanupOwnedResources(),e}this.server.on("error",e=>{console.error("[devflow-daemon] Server error:",e.message);}),console.error("[devflow-daemon] Listening on",this.socketPath),await this.telemetry.flushAndAggregate(),this.telemetryFlushTimer=setInterval(()=>{this.flushTelemetry();},Eo),this.telemetryFlushTimer.unref(),this.resetIdleTimer();}handleConnection(e){let t="",n=false,o=false,i=0,s=Promise.resolve();e.setEncoding("utf8");let a=()=>{o||(o=true,clearTimeout(l),e.destroy());},l=setTimeout(()=>{a();},_o).unref(),c=async u=>{if(!o){o=true,clearTimeout(l);try{await this.writeFrame(e,u);}catch{}finally{e.destroy();}}};e.on("data",u=>{if(o)return;t+=u;let d=t.split(`
|
|
7
|
-
`);if(t=
|
|
8
|
-
`,
|
|
9
|
-
`);let t=fstatSync(e);this.pidIdentity={dev:t.dev,ino:t.ino};}finally{closeSync(e);}}removePathIfOwned(e,t,n,o){try{return !this.pathMatchesIdentity(e,t)||o!==void 0&&readFileSync(e,"utf8")!==o||!this.pathMatchesIdentity(e,t)?!1:(unlinkSync(e),!0)}catch(i){return i.code!=="ENOENT"&&console.error(`[devflow-daemon] Failed to remove ${n}:`,i.message),false}}isSocketAcceptingConnections(){return new Promise((e,t)=>{let n=createConnection(this.socketPath),o=setTimeout(()=>{n.destroy(),t(new Error(`Timed out probing daemon socket ${this.socketPath}`));},wo),i=s=>{clearTimeout(o),n.destroy(),e(s);};n.once("connect",()=>i(true)),n.once("error",s=>{let a=s.code;a==="ENOENT"||a==="ECONNREFUSED"?i(false):(clearTimeout(o),t(s));});})}listen(){return new Promise((e,t)=>{let n=this.server;if(!n){t(new Error("Daemon server is not initialized"));return}let o=s=>{n.off("listening",i),t(s);},i=()=>{n.off("error",o);try{let s=this.getPathIdentity(this.socketPath);if(!s)throw new Error(`Daemon socket missing after listen: ${this.socketPath}`);this.socketIdentity=s,e();}catch(s){t(s);}};n.once("error",o),n.once("listening",i),n.listen(this.socketPath);})}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=null,!(this.activeSessionIds.size>0)&&(this.idleTimer=setTimeout(()=>{console.error("[devflow-daemon] Idle timeout, exiting"),this.shutdown();},vo).unref());}async handleRequest(e){switch(e.type){case "pre-tool-use":return this.handlePreToolUse(e.input);case "post-tool-use":return await this.handlePostToolUse(e.input)??{status:"ok"};case "post-tool-use-failure":return await this.handlePostToolUseFailure(e.input)??{status:"ok"};case "stop":return await this.handleStop(e.input??"")??{status:"ok"};case "memory-snapshot":return this.handleMemorySnapshot();case "session-start":return this.handleSessionStart(e.input??"");case "session-end":return await this.handleSessionEnd(e.input??""),{status:"ok"};case "user-prompt-submit":return this.handleUserPromptSubmit(e.input);case "pre-compact":return this.handlePreCompact(e.input);default:return {error:"unknown request type"}}}async handlePreToolUse(e){try{if(!e||e.trim()==="")return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};let t=JSON.parse(e);t.tool_input=Do(t.tool_name,t.tool_input,process.env,this.projectRoot);let n=this.trackSession(t.session_id);if(t.tool_name==="Skill"){let g=t.tool_input?.skill,S=g?L(g):null;S&&this.startSkillExecution(n,S);}let o=this.runtimeStore.get(n);t.tool_name.startsWith("mcp__devflow__")&&(t.tool_input._devflow_session_id=n,t.tool_input._devflow_execution_id=o?.executionId??n,t.tool_use_id&&(t.tool_input._devflow_tool_use_id=t.tool_use_id));let i=t.tool_name.startsWith("mcp__"),s=i?t.tool_name.replace(/^mcp__[^_]+__/,""):void 0,a=new b(this.projectRoot,n,o?.executionId),l=a.getPhase(),c=st({toolName:t.tool_name,toolInput:t.tool_input,projectRoot:this.projectRoot}),u=c?{permissionDecision:"deny",reason:c}:a.evaluate(t.tool_name,i),d;u.permissionDecision==="deny"?d={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:u.reason??"MCP context required"}}:u.additionalContext?d={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:u.additionalContext}}:d={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}},t.tool_name.startsWith("mcp__devflow__")&&(d.hookSpecificOutput.updatedInput=t.tool_input);let h={...t.tool_input};delete h._devflow_session_id,delete h._devflow_execution_id,delete h._devflow_tool_use_id;let f=o?.executionId??n,p={eventId:T(n,t.tool_use_id),executionId:f,sessionId:n,projectRoot:this.projectRoot,toolUseId:t.tool_use_id,timestamp:Date.now(),toolName:t.tool_name,toolType:i?"mcp":t.tool_name==="Agent"?"subagent":"direct",isMcpTool:i,mcpToolName:s,mcpEnforced:i&&l==="context_gathering",mcpFallback:!i&&l==="context_gathering",kind:ko(t.tool_name),input:h,duration:0,blocked:d&&d.hookSpecificOutput?.permissionDecision==="deny"},y=await this.telemetry.sendEvent({...p,blockReason:p.blocked?c?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0,error:p.blocked?c?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0});return y&&!p.blocked&&(this.eventMap.push({toolName:t.tool_name,toolUseId:t.tool_use_id,eventId:y,sessionId:n,timestamp:p.timestamp}),this.noteTelemetryOperation()),y&&p.blocked&&await this.telemetry.completeEvent({eventId:y,sessionId:n,error:c?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-p.timestamp,completedAt:Date.now()}),d}catch{return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}}trackSession(e){let t=e?.trim()||(this.activeSessionIds.size===1?[...this.activeSessionIds][0]:"");if(!t)throw new Error("session_id_required");return this.registerSession(t),t}registerSession(e){this.activeSessionIds.has(e)||(this.activeSessionIds.size===0&&P(this.projectRoot,{bypassCount:0}),this.activeSessionIds.add(e),this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null),this.serverManager.addRef(e),this.telemetry.sendSessionStart(e,this.projectRoot,Date.now()).catch(()=>{})),this.runtimeStore.registerSession(e);}startSkillExecution(e,t){let n=this.runtimeStore.get(e)?.executionId,o=this.runtimeStore.startExecution(e,t,ve(t));o.executionId&&o.executionId!==n&&this.telemetry.sendExecutionStart(o.executionId,e,t,o.lastActivityAt,this.projectRoot,o.requiredMcpTools).catch(()=>{});}async handleSessionStart(e){try{let t=JSON.parse(e);if(typeof t.session_id!="string"||!t.session_id.trim())return {error:"session_id_required"};let n=t.session_id.trim();this.registerSession(n);let o=await this.getMemoryGate();await o.ensureSession(n,this.projectRoot,"Claude Code session"),await o.releasePendingDistillLeases(n);let i=o.getPendingEventCount();return {status:"ok",...i>0?{additionalContext:te({pendingEvents:i,releasedLeases:0,trigger:"session_end"})}:{}}}catch{return {error:"session_start_invalid"}}}popEventFromMap(e,t,n){let o=this.eventMap.filter(s=>s.toolName===e&&s.sessionId===t);if(o.length===0)return null;let i=n?o.find(s=>s.toolUseId===n):o.sort((s,a)=>s.timestamp-a.timestamp)[0];return i?(this.eventMap=this.eventMap.filter(s=>s.eventId!==i.eventId),i):null}enforcePostToolUse(e){if(!To[e])return null;let t=Math.floor(Date.now()/1e3),n=ee(this.projectRoot,s=>t-(s.lastMcpCall??0)<30?s:{...s,bypassCount:(s.bypassCount??0)+1});if(!n.applied||!n.changed)return null;let o=n.receipt.bypassCount??0;if(o===1)return null;let i;switch(e){case "Agent":i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u4F7F\u7528\u4E86 Agent \u5B50\u4EE3\u7406\u6267\u884C\u641C\u7D22\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Bash":i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Bash \u547D\u4EE4\u641C\u7D22\u4EE3\u7801\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Glob":i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Glob \u5339\u914D\u6587\u4EF6\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Grep":i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Grep \u641C\u7D22\u4EE3\u7801\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "WebSearch":case "WebFetch":i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86\u7F51\u7EDC\u641C\u7D22\u3002\u4E0B\u6B21\u8BF7\u7528 get_knowledge MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;default:i=`\u7B2C ${o} \u6B21\u8FDD\u89C4\uFF1A\u8BF7\u4F7F\u7528 DevFlow MCP \u5DE5\u5177\u66FF\u4EE3\u76F4\u63A5\u8C03\u7528\u3002`;}return o>=3?i=`${i} \u5DF2\u8FBE\u5230\u6700\u5927\u8FDD\u89C4\u6B21\u6570\uFF0C\u540E\u7EED\u7ED5\u8FC7\u5C06\u88AB\u786C\u963B\u6B62\u3002`:o>=2?i=`${i} \u4E0B\u6B21\u8FDD\u89C4\u5C06\u88AB\u963B\u6B62\u3002`:i=`${i} \u8BF7\u7ACB\u5373\u7EA0\u6B63\u3002`,i}async handlePostToolUse(e){if(!e)return null;let t;try{t=JSON.parse(e);}catch{return null}let n=t.tool_name||"",o=t.tool_input||{},i=t.tool_response,s=this.trackSession(t.session_id);if(n==="Skill"){let v=o?.skill,w=v?L(v):null;w&&(this.startSkillExecution(s,w),P(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}n.startsWith("mcp__")&&new b(this.projectRoot).recordMcpCall();let a=this.popEventFromMap(n,s,t.tool_use_id);if(a){let v=typeof i=="string"?i:JSON.stringify(i),w=v.length>5e3?{_truncated:true,_originalSize:v.length,text:v.slice(0,5e3)}:i,ct=Date.now()-a.timestamp;await this.telemetry.completeEvent({eventId:a.eventId,sessionId:s,output:w,duration:ct,completedAt:Date.now()})&&this.noteTelemetryOperation();}let l=typeof i=="object"&&i!==null?i:null,c=l?.exitCode,u=l?.stderr,d=/^\s*(ls|cat|pwd|cd|echo|head|tail|wc|which|whoami|date|env|printenv|id|hostname|uname)\b/,h=o.command||"",f=JSON.stringify(i),m=Buffer.byteLength(f,"utf8"),p=this.countResults(i),y,g,S=true;if(n.startsWith("mcp__"))y="mcp_call",g={mcpTool:n.replace(/^mcp__[^_]+__/,""),query:o.query??null,resultCount:p,resultSizeBytes:m};else if(n==="Read"||n==="Write"||n==="Edit")y=n==="Read"?"file_read":"file_write",g={filePath:o.file_path??null,fileContentSize:m};else if(n==="Bash"){let v=d.test(h),w=c!==void 0&&c!==0;S=!v||w,y=w?"bash_error":"bash_command",g={command:h||n,exitCode:c??null,stderr:u??null};}else n==="Agent"?(y="subagent",g={subagentType:o.subagent_type??null,description:typeof o.description=="string"?o.description.slice(0,200):null}):n==="WebSearch"||n==="WebFetch"?(y=n==="WebSearch"?"web_search":"web_fetch",g={query:typeof o.query=="string"?o.query.slice(0,200):null}):(S=false,y="tool_use",g={});if(S){let v={id:t.tool_use_id?`memory:${T(s,t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:s,tool:n,kind:y,payload:g,command:h||void 0,exitCode:c,stderr:u??void 0,durationMs:0,createdAt:Date.now()};this.postMemoryEvent(v);}let G=this.enforcePostToolUse(n);return G?(console.error("[devflow-daemon] Enforcement:",G),{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:JSON.stringify(G)}}):null}async handlePostToolUseFailure(e){let t;try{t=JSON.parse(e);}catch{return null}let n=this.trackSession(t.session_id),o=t.tool_name??"unknown",i=t.error??`${o} failed`,s=this.popEventFromMap(o,n,t.tool_use_id);if(s)await this.telemetry.completeEvent({eventId:s.eventId,sessionId:n,error:i,duration:Date.now()-s.timestamp,completedAt:Date.now()})&&this.noteTelemetryOperation();else {let a=T(n,t.tool_use_id);await this.telemetry.sendEvent({eventId:a,executionId:this.runtimeStore.get(n)?.executionId??n,sessionId:n,projectRoot:this.projectRoot,toolUseId:t.tool_use_id,timestamp:Date.now(),toolName:o,toolType:o.startsWith("mcp__")?"mcp":"direct",isMcpTool:o.startsWith("mcp__"),mcpToolName:o.startsWith("mcp__")?o.replace(/^mcp__[^_]+__/,""):void 0,mcpEnforced:false,mcpFallback:false,kind:"error",input:t.tool_input??{},duration:0,error:i,blocked:false});}return this.postMemoryEvent({id:t.tool_use_id?`memory:${T(n,t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:n,tool:o,command:typeof t.tool_input?.command=="string"?t.tool_input.command:o,exitCode:-1,stderr:i,durationMs:s?Date.now()-s.timestamp:0,createdAt:Date.now(),kind:o==="Bash"?"bash_error":"tool_use",payload:{command:t.tool_input?.command??o,exitCode:-1,stderr:i}}),null}countResults(e){if(!e)return 0;let t=e;if(typeof e=="string")try{t=JSON.parse(e);}catch{return 1}let n=t,o=["files","results","data","result","memories","nodes","chunks","findings","symbols"],i=Array.isArray(n.data)?n.data:n.structuredContent??n;if(Array.isArray(i))return i.length;if(typeof i=="object"&&i!==null){let s=i,a=0,l=false;for(let c of o)Array.isArray(s[c])&&(l=true,a+=s[c].length);for(let[,c]of Object.entries(s))c&&typeof c=="object"&&!Array.isArray(c)&&(a+=this.countResults(c));return a>0?a:l?0:Object.keys(s).length>0?1:0}return 0}async postMemoryEvent(e){Ee(`/api/memory/session-events?rootPath=${encodeURIComponent(this.projectRoot)}`,e);try{await(await this.getMemoryGate()).recordEvent(e);}catch(t){console.error("[devflow-daemon] Local memory event write failed:",t.message);}}async getMemoryGate(){let e=this.explicitMemoryGate??=new MemoryGate(this.projectRoot);return this.memoryWarmup??=e.forceWarmUp().catch(t=>{throw this.memoryWarmup=null,t}),await this.memoryWarmup,e}async handleUserPromptSubmit(e){let t=[];try{let n=JSON.parse(e),o=typeof n.prompt=="string"?n.prompt:"",i=typeof n.session_id=="string"&&n.session_id.trim()?this.trackSession(n.session_id):null,s=Ke(o),a=!1;if(o.trim()&&i){let l=await this.getMemoryGate();try{let c=await et({projectRoot:this.projectRoot,sessionId:i,prompt:o,memory:l});c&&(t.push(c.additionalContext),a=c.skipSkillRouting);}catch{let c=F(o);if(c){let u=openGlobalDevFlowDatabase(),d=null;try{d=u.getPendingMemoryTurn(this.projectRoot,i);}finally{u.close();}Be(this.projectRoot,{content:c,sessionId:i,turnId:d?.turnId,eventId:d?.eventId,createdAt:Date.now()}),t.push("DevFlow explicit memory save failed; no canonical receipt was created. Do not claim that the content was remembered."),a=!0;}}}i&&s&&!a&&this.startSkillExecution(i,s.skillName);}catch{}return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t.length?{additionalContext:t.join(`
|
|
10
|
-
`)}:{}}}}async handlePreCompact(e){let t;try{let s=JSON.parse(e);typeof s.session_id=="string"&&s.session_id.trim()&&(t=s.session_id.trim());}catch{}await this.flushTelemetry(),this.startExplicitIntentFlush(),await this.explicitIntentFlush;let n=await this.getMemoryGate(),o=await N({projectRoot:this.projectRoot,sessionId:t,trigger:"pre_compact",memory:n}),i=te(o);return {hookSpecificOutput:{hookEventName:"PreCompact",...i?{additionalContext:i}:{}}}}noteTelemetryOperation(){this.successfulTelemetryOperations++,this.successfulTelemetryOperations>=bo&&this.flushTelemetry();}async flushTelemetry(){this.successfulTelemetryOperations=0,await this.telemetry.flushAndAggregate();}startExplicitIntentFlush(){this.explicitIntentFlush||(this.explicitIntentFlush=this.flushExplicitMemoryIntents().finally(()=>{this.explicitIntentFlush=null;}));}async handleStop(e){let t=null,n=false;try{let o=JSON.parse(e);typeof o.session_id=="string"&&o.session_id.trim()&&(t=o.session_id.trim()),n=o.stop_hook_active===!0;}catch{}if(t??=this.activeSessionIds.size===1?[...this.activeSessionIds][0]:null,this.startExplicitIntentFlush(),await this.explicitIntentFlush,t){let o=Ze(this.projectRoot,t,n);if(o)return o;if(n)return null;let i=this.runtimeStore.completeExecution(t);if(i?.executionId){let s=openGlobalDevFlowDatabase(),a={};try{let l=s.listMemoryTurns(this.projectRoot,t,100);a={memoryReceiptIds:l.flatMap(c=>c.receiptId?[c.receiptId]:[]),missingMemoryDecisionCount:l.filter(c=>c.status==="pending").length};}finally{s.close();}await this.telemetry.sendExecutionComplete(i.executionId,"completed",Date.now(),a),this.deleteContextReceipt(t,i.executionId);}}return null}async flushExplicitMemoryIntents(){this.flushTelemetry();let e=Ve(this.projectRoot);if(e)try{let t=this.explicitMemoryGate??=new MemoryGate(this.projectRoot);for(await t.forceWarmUp();e.intents.length>0;){let n=e.intents[0],o=await t.saveExplicitMemoryIntent(n.content,n.sessionId,n.eventId);if(n.turnId){let i=openGlobalDevFlowDatabase();try{i.commitMemoryTurn({turnId:n.turnId,receiptId:ie(n.turnId,"committed",[o.id]),memoryIds:[o.id],source:"explicit_intent",reason:"explicit_user_request_retry"});}finally{i.close();}}ze(e);}}catch(t){console.error("[devflow-daemon] Explicit memory intent save failed:",t.message);}}deleteContextReceipt(e,t){let n;try{n=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),n.deleteContextReceipt(this.projectRoot,e,t);}catch{}finally{n?.close();}}async handleMemorySnapshot(){let e=loadConfig(this.projectRoot).sessionStart?.injectMemories??true;if(e===false)return {status:"ok",enabled:false,markdown:""};let t=typeof e=="object"?e.topN:void 0,n=typeof e=="object"?e.budgetTokens:void 0,o=Number.isFinite(t)?Math.max(0,Math.floor(t)):10,i=Number.isFinite(n)?Math.max(1,Math.floor(n)):800;try{let s=this.explicitMemoryGate??=new MemoryGate(this.projectRoot),l={...await s.getAll({purpose:"session_bootstrap",budgetTokens:i,limit:o}),_devflow_unique:{memory_version:1,structured_storage:!0,project_context_included:!0},_accuracy:{data_freshness_ms:0,source_layer:"memory",degradation:typeof s.getObservationVectorCoverage=="function"?s.getObservationVectorCoverage().missing>0?"bm25_only":"none":"partial"}};if(l.memories.length===0)return {status:"ok",enabled:!0,markdown:`## Project memory
|
|
11
|
-
|
|
12
|
-
${
|
|
5
|
+
`,{mode:384}),renameSync(e,n.path);}function q(n){let e=n.trim().replace(/^\//,"");if(!e.startsWith("devflow:"))return null;let t=e.slice(8).replace(/^devflow-/,"");return /^[a-z0-9][a-z0-9-]*$/i.test(t)?`devflow:${t.toLowerCase()}`:null}function kt(n){let e=n.trimStart().match(/^\/(devflow:[a-z0-9][a-z0-9-]*)\b/i);if(!e)return null;let t=q(e[1]);return t?{rawName:e[1],skillName:t}:null}function D(n,e){return e?`evt_tool_${createHash$1("sha256").update(`${n}\0${e}`).digest("hex").slice(0,24)}`:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}var Fn=/^(?:ok(?:ay)?|yes|no|thanks?|thank you|continue|好的?|可以|行|是|否|谢谢|继续|收到|明白了?)[.!。!\s]*$/iu;function Nn(n){let e=n.trim();return e.length>0&&!Fn.test(e)}function $n(n,e,t=Date.now()){let o=createHash("sha256").update(e.trim()).digest("hex"),r=createHash("sha256").update(`${n}\0${t}\0${o}`).digest("hex").slice(0,24);return {turnId:`turn:${r}`,eventId:`memory-turn:${r}`,promptHash:o,createdAt:t}}function me(n,e,t=[]){return `memory-receipt:${createHash("sha256").update(`${n}\0${e}\0${[...t].sort().join("\0")}`).digest("hex").slice(0,24)}`}function he(n){return `DevFlow memory decision required for ${n.turnId}. Before the final response, semantically decide whether this turn contains durable project knowledge. Call mcp__devflow__memory_commit_turn with evidence-bound candidates, or mcp__devflow__memory_skip_turn with a concrete reason. Do not claim memory success without a canonical receipt.`}function de(n){let e=n.memoryIds.length>0?n.memoryIds.join(","):"none",t=n.status==="committed"?"accepted":n.status,o=n.status==="committed"?"; indexStatus=pending":"";return `DevFlow canonical memory receipt: status=${t}; receiptId=${n.receiptId??"missing"}; turnId=${n.turnId}; memoryIds=${e}; source=${n.source??"unknown"}${o}.`}function Rt(n,e,t){if(t)return null;let o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{let r=o.getPendingMemoryTurn(n,e);return !r||!o.markMemoryTurnStopPrompted(r.turnId)?null:{decision:"block",reason:he(r)}}finally{o.close();}}function fe(n){if(!Nn(n.prompt))return null;let e=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{let t=n.prompt.trim().slice(0,4e3),o=createHash("sha256").update(t).digest("hex"),r=e.listMemoryTurns(n.projectRoot,n.sessionId,5).find(l=>l.promptHash===o&&Date.now()-l.createdAt<1e4),i=r?{turnId:r.turnId,eventId:r.eventId,promptHash:r.promptHash,createdAt:r.createdAt}:$n(n.sessionId,t),s=r??e.beginMemoryTurn({...i,projectRoot:n.projectRoot,sessionId:n.sessionId});if(s.status!=="pending")return {turn:s,additionalContext:de(s),skipSkillRouting:s.source==="explicit_intent"};let a=W(t)??void 0,c=a?"commit_explicit":"capture_prompt";return e.enqueueWork({idempotencyKey:`memory-turn:${c}:${s.turnId}`,kind:a?"memory.explicit_commit":"memory.turn_capture",projectRoot:n.projectRoot,sessionId:n.sessionId,turnId:s.turnId,payload:{operation:c,turnId:s.turnId,eventId:s.eventId,sessionId:n.sessionId,prompt:t,explicitContent:a,createdAt:s.createdAt}}),{turn:s,explicitContent:a,additionalContext:a?`DevFlow explicit memory is durably queued for ${s.turnId}, but no canonical receipt exists yet. Do not claim that it was remembered.`:he(s),skipSkillRouting:!!a}}finally{e.close();}}async function ye(n){let{payload:e,memory:t,projectRoot:o}=n,r=openGlobalDevFlowDatabase();try{let i=r.getMemoryTurn(e.turnId);if(!i)throw new Error(`Memory turn ${e.turnId} does not exist`);if(i.status!=="pending")return {turn:i,additionalContext:de(i),skipSkillRouting:i.source==="explicit_intent"};if(await t.recordUserMessage(e.prompt,e.sessionId,e.prompt.slice(0,200)),await t.recordEvent({id:e.eventId,sessionId:e.sessionId,tool:"UserPromptSubmit",kind:"user_message",payload:{prompt:e.prompt,turnId:e.turnId},createdAt:e.createdAt}),e.operation==="capture_prompt"||!e.explicitContent)return {turn:i,additionalContext:he(i),skipSkillRouting:!1};let s=await t.saveExplicitMemoryIntent(e.explicitContent,e.sessionId,e.eventId),a=me(i.turnId,"committed",[s.id]),c=r.commitMemoryTurn({turnId:i.turnId,receiptId:a,memoryIds:[s.id],source:"explicit_intent",reason:"explicit_user_request"});return r.enqueueWork({idempotencyKey:`vector:${o}:${s.id}`,kind:"memory.vector_backfill",projectRoot:o,sessionId:e.sessionId,turnId:c.turnId,payload:{observationId:s.id},maxAttempts:20}),{turn:c,explicitContent:e.explicitContent,additionalContext:de(c),skipSkillRouting:!0}}finally{r.close();}}var Hn=new Set(["Write","Edit","NotebookEdit"]),bt="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 Dt(n){if(!Hn.has(n.toolName))return null;let e=Wn(n.toolInput);if(!e)return null;let t=qn(e,n.projectRoot),o=resolve(n.projectRoot,".claude");if(It(t,o)&&basename(t).toLocaleUpperCase("en-US")==="MEMORY.MD")return bt;let r=resolve(n.home??homedir$1(),".claude","projects");return It(t,r)&&relative(r,t).split(sep).some(s=>s.toLocaleLowerCase("en-US")==="memory")?bt:null}function Wn(n){for(let e of ["file_path","notebook_path","path"]){let t=n[e];if(typeof t=="string"&&t.trim())return t.trim()}return null}function qn(n,e){return resolve(isAbsolute(n)?n:resolve(e,n))}function It(n,e){let t=relative(e,n);return t===""||!t.startsWith(`..${sep}`)&&t!==".."&&!isAbsolute(t)}var Vn=1024*1024;function Pt(n){let e=join$1(getProjectStateDir(n),"session-start-pending");mkdirSync$1(e,{recursive:true,mode:448});let t=readdirSync$1(e).filter(s=>s.endsWith(".json")||/\.json\.claim-\d+$/u.test(s)).sort()[0];if(!t)return null;let o=join$1(e,t),r=/\.json\.claim-\d+$/u.test(t),i=r?o:`${o}.claim-${process.pid}`;if(!r)try{renameSync(o,i);}catch{return null}try{let s=readFileSync$1(i,"utf8");if(Buffer.byteLength(s,"utf8")>Vn)throw unlinkSync$1(i),new Error("session_start_spool_input_too_large");return {receiptId:basename(t).replace(/\.json(?:\.claim-\d+)?$/u,""),input:s,path:i}}catch(s){try{unlinkSync$1(i);}catch{}throw s}}function Ot(n){unlinkSync$1(n.path);}function At(n){let e=n.path.replace(/\.claim-\d+$/u,"");try{renameSync(n.path,e);}catch{}}function Ft(n,e){let t=Ut(n);mkdirSync$1(t,{recursive:true,mode:448});let o=`memory-turn-spool-${Date.now()}-${process.pid}-${randomUUID$1()}`,r=join$1(t,`${o}.json`),i=`${r}.tmp`;return writeFileSync$1(i,JSON.stringify({...e,prompt:e.prompt.trim().slice(0,4e3)}),{mode:384}),renameSync(i,r),o}function Nt(n){let e=Ut(n);mkdirSync$1(e,{recursive:true,mode:448});let t=readdirSync$1(e).filter(s=>s.endsWith(".json")||/\.json\.claim-\d+$/u.test(s)).sort()[0];if(!t)return null;let o=join$1(e,t),r=/\.json\.claim-\d+$/u.test(t),i=r?o:`${o}.claim-${process.pid}`;if(!r)try{renameSync(o,i);}catch{return null}try{let s=JSON.parse(readFileSync$1(i,"utf8"));if(typeof s.sessionId!="string"||typeof s.prompt!="string"||typeof s.createdAt!="number")throw unlinkSync$1(i),new Error("memory_turn_spool_payload_invalid");return {receiptId:basename(t).replace(/\.json(?:\.claim-\d+)?$/u,""),payload:s,path:i}}catch(s){try{unlinkSync$1(i);}catch{}throw s}}function $t(n){unlinkSync$1(n.path);}function Lt(n){try{renameSync(n.path,n.path.replace(/\.claim-\d+$/u,""));}catch{}}function Ut(n){return join$1(_(n),"memory-turn-pending")}var G=class extends Error{constructor(e,t){super(t),this.name="PermanentWorkError",this.category=e;}},nr=1e3,rr=3e4,ir=1,sr=5*6e4,B=class{constructor(e){this.timer=null;this.draining=null;this.stopped=true;this.projectRoot=e.projectRoot,this.handlers=e.handlers,this.pollIntervalMs=we(e.pollIntervalMs,nr),this.leaseMs=we(e.leaseMs,rr),this.batchSize=we(e.batchSize,ir),this.owner=e.owner??`hook-daemon:${process.pid}:${randomUUID$1()}`,this.now=e.now??Date.now,this.random=e.random??Math.random,this.openDatabase=e.openDatabase??(()=>openGlobalDevFlowDatabase());}start(){this.stopped&&(this.stopped=false,this.schedule(0));}stop(){this.stopped=true,this.timer&&clearTimeout(this.timer),this.timer=null;}drainOnce(){return this.draining?this.draining:(this.draining=this.performDrain().finally(()=>{this.draining=null;}),this.draining)}schedule(e){this.stopped||(this.timer&&clearTimeout(this.timer),this.timer=setTimeout(()=>{this.timer=null,this.drainOnce().catch(t=>console.error("[devflow-work] Drain failed:",Ht(t))).finally(()=>this.schedule(this.pollIntervalMs));},e),this.timer.unref());}async performDrain(){let e=Object.keys(this.handlers);if(e.length===0)return 0;let t=this.openDatabase();try{let o=this.now();t.recoverExpiredWork(this.projectRoot,o);let r=t.leaseWork({projectRoot:this.projectRoot,owner:this.owner,kinds:e,limit:this.batchSize,leaseMs:this.leaseMs,now:o});for(let i of r)await this.processItem(t,i);return r.length}finally{t.close();}}async processItem(e,t){let o=this.handlers[t.kind];if(!o){e.deadLetterWork(t.id,this.owner,{category:"unsupported_work_kind",message:`No work handler is registered for ${t.kind}`});return}try{if(await o({item:t}),!e.completeWork(t.id,this.owner,this.now()))throw new Error(`Work lease was lost before completion: ${t.id}`)}catch(r){let i=ar(r);if(r instanceof G){e.deadLetterWork(t.id,this.owner,i);return}e.retryWork(t.id,this.owner,i,this.now()+cr(t.attempts,this.random()));}}};function we(n,e){return Number.isSafeInteger(n)&&n>0?n:e}function ar(n){if(n instanceof G)return {category:n.category,message:n.message};let e=n&&typeof n=="object"?n:null;return {category:typeof e?.category=="string"?e.category:"runtime_error",message:Ht(n)}}function cr(n,e){let t=Math.min(sr,500*2**Math.max(0,n-1)),o=Math.floor(t*.2*Math.max(0,Math.min(1,e)));return t+o}function Ht(n){return n instanceof Error?n.message:String(n)}var mr=250;function zt(n,e=process.env){let t=qt(join$1(homedir$1(),".devflow","config.json")),o=qt(join$1(n,".devflow","config.json")),r=ke(e.DEVFLOW_HOOK_PROFILE)??ke(o.profile)??ke(t.profile)??"standard",i=Number(e.DEVFLOW_HOOK_ACK_BUDGET_MS??o.acknowledgementBudgetMs??t.acknowledgementBudgetMs),s=Number.isSafeInteger(i)&&i>0?Math.min(i,5e3):mr,a=new Set([...Re(t.disabledHandlers),...Re(o.disabledHandlers),...Re(e.DEVFLOW_DISABLED_HOOK_HANDLERS?.split(","))].map(gr).filter(c=>!!c));return {profile:r,acknowledgementBudgetMs:s,disabledHandlers:a}}async function K(n,e,t,o){let r,i=new Promise(s=>{r=setTimeout(()=>{console.error(`[devflow-hook] ${n} exceeded ${e}ms acknowledgement budget`),s(o());},e),r.unref();});try{return await Promise.race([Promise.resolve().then(t),i])}finally{r&&clearTimeout(r);}}async function Jt(n,e=process.env){let t=e.DEVFLOW_HOST_ADAPTER??(e.CLAUDE_PROJECT_DIR||e.CLAUDE_PLUGIN_ROOT||e.CLAUDE_CODE_ENTRYPOINT?"claude-code":void 0),o=await selectHostAdapter({projectRoot:n,env:e,explicitHost:t});if(o.status==="failed")throw new Error(`host_adapter_selection_failed:${o.code}:${o.reason}`);let r=await o.adapter.capabilities({projectRoot:n,env:e,explicitHost:t});return {hostId:o.adapter.id,capabilities:new Map(r.map(i=>[i.capability,i])),profiles:new Set(o.adapter.hooks?.profileSupport??[])}}function Gt(n,e,t){let o=yr(n,e.profile);if(!t.profiles.has(e.profile))return {enabled:false,policy:"fail_open",reason:`hook_profile_${e.profile}_unsupported_by_${t.hostId}`,fallback:"host_event_continues_without_devflow_handler"};if(e.disabledHandlers.has(n))return {enabled:false,policy:"fail_open",reason:"hook_handler_disabled",fallback:"host_event_continues_without_devflow_handler"};if(e.profile==="minimal"&&!hr.has(n))return {enabled:false,policy:"fail_open",reason:"hook_handler_not_in_minimal_profile",fallback:"critical_receipts_only"};let r=fr[n];if(!r)return {enabled:true,policy:o};let i=t.capabilities.get(r);return !i||i.status!=="supported"?{enabled:false,policy:"fail_open",reason:i?.reason??`${r}_unsupported_by_${t.hostId}`,fallback:i?.fallback??"host_event_continues_without_native_hook_processing"}:{enabled:true,policy:o}}var hr=new Set(["session-start","user-prompt-submit","stop","session-end","memory-snapshot"]),fr={"session-start":"hooks.session_start","user-prompt-submit":"hooks.prompt_submit","pre-tool-use":"hooks.pre_tool_use","post-tool-use":"hooks.post_tool_use","post-tool-use-failure":"hooks.post_tool_use",stop:"hooks.stop","session-end":"hooks.session_end"};function yr(n,e){return n==="user-prompt-submit"||n==="stop"||n==="session-end"?"enqueue_and_open":n==="pre-tool-use"&&e==="strict"?"fail_closed":"fail_open"}function qt(n){if(!existsSync(n))return {};try{let t=JSON.parse(readFileSync$1(n,"utf8")).hooks;return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch{return {}}}function ke(n){return n==="minimal"||n==="standard"||n==="strict"?n:void 0}function Re(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):[]}function gr(n){let e=n.trim().replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/_/g,"-").toLowerCase();return ({sessionstart:"session-start",userpromptsubmit:"user-prompt-submit",pretooluse:"pre-tool-use",posttooluse:"post-tool-use",posttoolusefailure:"post-tool-use-failure",sessionend:"session-end",precompact:"pre-compact",memorysnapshot:"memory-snapshot"}[e.replace(/-/g,"")]??e)||void 0}var jr=600*1e3,Fr=2e3,Nr=250,$r=2e3,Lr=1e3,Bt=1024*1024,Ur=2*1024*1024,Hr=6e4,Wr=100,qr={Agent:"get_project_context",Bash:"get_project_context",Glob:"get_project_context",Grep:"get_project_context",WebSearch:"get_knowledge",WebFetch:"get_knowledge"};function zr(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"}}function Ie(n){return typeof n=="string"&&n.trim().length>0}function Jr(n,e,t=process.env,o){if(!n.startsWith("mcp__devflow__"))return e;let r=e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{};if(Ie(r.projectRoot))return r;let i=Ie(t.CLAUDE_PROJECT_DIR)?t.CLAUDE_PROJECT_DIR:o;return Ie(i)&&(r.projectRoot=i),r}var Te=class{constructor(e,t){this.socketIdentity=null;this.pidIdentity=null;this.server=null;this.activeSessionIds=new Set;this.eventMap=[];this.idleTimer=null;this.telemetryFlushTimer=null;this.successfulTelemetryOperations=0;this.shutdownPromise=null;this.explicitMemoryGate=null;this.memoryWarmup=null;this.explicitIntentFlush=null;this.hostRuntime=null;this.memoryTurnSpoolTimer=null;this.sessionFinalizeSpoolTimer=null;this.projectRoot=e,this.socketPath=getDaemonSocketPath(e),this.pidPath=getDaemonPidPath(e),this.telemetry=new b,this.runtimeStore=new I(this.projectRoot),this.serverManager=new A(e),this.hookRuntime=zt(e),this.initialSessionInput=t,this.workRuntime=new B({projectRoot:e,handlers:{"memory.explicit_commit":async({item:o})=>{await this.persistMemoryTurnItem(o.payload);},"memory.turn_capture":async({item:o})=>{await this.persistMemoryTurnItem(o.payload);},"session.bootstrap":async({item:o})=>{await this.bootstrapSessionWork(o.payload);},"memory.vector_backfill":async()=>{await(await this.getMemoryGate()).backfillObservationVectors({batchSize:32});},"memory.turn_distill":async({item:o})=>{await x({projectRoot:this.projectRoot,sessionId:o.sessionId,trigger:"session_end",memory:await this.getMemoryGate()});},"session.finalize":async({item:o})=>{await this.finalizeSessionWork(o.payload,o.id);},"telemetry.reconcile":async()=>{await this.flushTelemetry();}}});}async start(){this.hostRuntime=await Jt(this.projectRoot),mkdirSync(dirname(this.socketPath),{recursive:true,mode:448}),await this.cleanStaleStartupResources(),this.server=createServer(e=>this.handleConnection(e));try{await this.listen(),this.writePidFile(),nt(this.projectRoot,process.pid);}catch(e){throw await this.closeServer(),this.cleanupOwnedResources(),e}if(this.server.on("error",e=>{console.error("[devflow-daemon] Server error:",e.message);}),console.error("[devflow-daemon] Listening on",this.socketPath),await this.telemetry.flushAndAggregate(),this.telemetryFlushTimer=setInterval(()=>{this.flushTelemetry();},Hr),this.telemetryFlushTimer.unref(),this.workRuntime.start(),this.initialSessionInput){let e=this.initialSessionInput;this.initialSessionInput=void 0,this.handleRequest({type:"session-start",input:e});}this.drainSessionStartSpool(),this.scheduleMemoryTurnSpoolDrain(0),this.scheduleSessionFinalizeSpoolDrain(0),this.resetIdleTimer();}handleConnection(e){let t="",o=false,r=false,i=0,s=Promise.resolve();e.setEncoding("utf8");let a=()=>{r||(r=true,clearTimeout(c),e.destroy());},c=setTimeout(()=>{a();},Fr).unref(),l=async u=>{if(!r){r=true,clearTimeout(c);try{await this.writeFrame(e,u);}catch{}finally{e.destroy();}}};e.on("data",u=>{if(r)return;t+=u;let p=t.split(`
|
|
6
|
+
`);if(t=p.pop()??"",Buffer.byteLength(t,"utf8")>Bt){a();return}if(p.length===0)return;let m=0;for(let f of p){let d=Buffer.byteLength(f,"utf8");if(d>Bt){a();return}m+=d+1;}if(i+m>Ur){a();return}i+=m,s=s.then(async()=>{for(let f of p){if(r)return;if(!o){let d;try{d=JSON.parse(f);}catch{await l({error:"handshake_invalid"});return}if(d?.type!=="hello"||typeof d.rootPath!="string"){await l({error:"handshake_invalid"});return}if(d.rootPath!==this.projectRoot){await l({error:"handshake_root_mismatch",expected:this.projectRoot});return}o=true,clearTimeout(c),this.resetIdleTimer();continue}if(f.trim())try{let d=JSON.parse(f),y=await this.handleRequest(d);y!==null&&!r&&await this.writeFrame(e,y);}catch(d){r||await this.writeFrame(e,{error:d.message});}}}).catch(()=>{a();}).finally(()=>{i-=m;});}),e.on("close",()=>clearTimeout(c)),e.on("error",()=>{});}writeFrame(e,t){return new Promise((o,r)=>{if(e.destroyed||!e.writable){r(new Error("Socket is not writable"));return}let i=false,s=true,a=false,c=setTimeout(()=>{e.destroy(),u(new Error("Timed out writing daemon response"));},Lr),l=()=>{clearTimeout(c),e.off("close",p),e.off("error",m),e.off("drain",f);},u=y=>{a||!y&&(!i||!s)||(a=true,l(),y?r(y):o());},p=()=>u(new Error("Socket closed during write")),m=y=>u(y),f=()=>{s=true,u();};e.once("close",p),e.once("error",m),e.write(`${JSON.stringify(t)}
|
|
7
|
+
`,y=>{if(y){u(y);return}i=true,u();})||(s=false,e.once("drain",f));})}async cleanStaleStartupResources(){let e=this.getPathIdentity(this.socketPath);if(e){if(await this.isSocketAcceptingConnections())throw new Error(`Daemon socket already active for ${this.projectRoot}`);this.removePathIfOwned(this.socketPath,e,"stale socket");}let t=this.getPathIdentity(this.pidPath);t&&this.removePathIfOwned(this.pidPath,t,"stale PID file");}getPathIdentity(e){try{let t=lstatSync(e);return {dev:t.dev,ino:t.ino}}catch(t){if(t.code==="ENOENT")return null;throw t}}pathMatchesIdentity(e,t){if(!t)return false;try{let o=this.getPathIdentity(e);return o?.dev===t.dev&&o.ino===t.ino}catch(o){return console.error("[devflow-daemon] Failed to verify path ownership:",o.message),false}}writePidFile(){let e=openSync(this.pidPath,"wx",384);try{writeFileSync(e,`${process.pid}
|
|
8
|
+
`);let t=fstatSync(e);this.pidIdentity={dev:t.dev,ino:t.ino};}finally{closeSync(e);}}removePathIfOwned(e,t,o,r){try{return !this.pathMatchesIdentity(e,t)||r!==void 0&&readFileSync(e,"utf8")!==r||!this.pathMatchesIdentity(e,t)?!1:(unlinkSync(e),!0)}catch(i){return i.code!=="ENOENT"&&console.error(`[devflow-daemon] Failed to remove ${o}:`,i.message),false}}isSocketAcceptingConnections(){return new Promise((e,t)=>{let o=createConnection(this.socketPath),r=setTimeout(()=>{o.destroy(),t(new Error(`Timed out probing daemon socket ${this.socketPath}`));},Nr),i=s=>{clearTimeout(r),o.destroy(),e(s);};o.once("connect",()=>i(true)),o.once("error",s=>{let a=s.code;a==="ENOENT"||a==="ECONNREFUSED"?i(false):(clearTimeout(r),t(s));});})}listen(){return new Promise((e,t)=>{let o=this.server;if(!o){t(new Error("Daemon server is not initialized"));return}let r=s=>{o.off("listening",i),t(s);},i=()=>{o.off("error",r);try{let s=this.getPathIdentity(this.socketPath);if(!s)throw new Error(`Daemon socket missing after listen: ${this.socketPath}`);this.socketIdentity=s,e();}catch(s){t(s);}};o.once("error",r),o.once("listening",i),o.listen(this.socketPath);})}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=null,!(this.activeSessionIds.size>0)&&(this.idleTimer=setTimeout(()=>{console.error("[devflow-daemon] Idle timeout, exiting"),this.shutdown();},jr).unref());}async handleRequest(e){let t=this.hostRuntime;if(!t)return this.hookFailureResponse(e.type,{enabled:false,policy:"fail_open",reason:"host_adapter_not_ready",fallback:"host_event_continues_without_devflow_handler"});let o=Gt(e.type,this.hookRuntime,t);if(!o.enabled)return this.hookFailureResponse(e.type,o);try{switch(e.type){case "pre-tool-use":return this.handlePreToolUse(e.input);case "post-tool-use":return await this.handlePostToolUse(e.input)??{status:"ok"};case "post-tool-use-failure":return await this.handlePostToolUseFailure(e.input)??{status:"ok"};case "stop":return K("Stop",this.hookRuntime.acknowledgementBudgetMs,async()=>await this.handleStop(e.input??"")??{status:"ok"},()=>({status:"degraded",reason:"hook_budget_exceeded",fallback:"background_processing"}));case "memory-snapshot":return this.handleMemorySnapshot();case "session-start":return this.handleSessionStart(e.input??"");case "session-end":return K("SessionEnd",this.hookRuntime.acknowledgementBudgetMs,()=>this.handleSessionEnd(e.input??""),()=>({status:"degraded",reason:"hook_budget_exceeded",fallback:"durable_session_recovery"}));case "user-prompt-submit":return K("UserPromptSubmit",this.hookRuntime.acknowledgementBudgetMs,()=>this.handleUserPromptSubmit(e.input),()=>({hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",additionalContext:"DevFlow background processing exceeded its acknowledgement budget; continue in degraded mode and do not claim an unreceipted memory save."}}));case "pre-compact":return this.handlePreCompact(e.input);default:return {error:"unknown request type"}}}catch(r){return this.hookFailureResponse(e.type,o,r)}}async drainSessionStartSpool(){for(;;){let e=Pt(this.projectRoot);if(!e)return;try{let t=await this.handleRequest({type:"session-start",input:e.input});if(t&&"status"in t&&t.status==="degraded")throw new Error(`session_start_degraded:${String(t.reason??"unknown")}`);Ot(e),console.error(`[devflow-daemon] SessionStart accepted from durable spool: ${e.receiptId}`);}catch(t){At(e),console.error("[devflow-daemon] SessionStart spool deferred:",t.message);return}}}hookFailureResponse(e,t,o){let r=o instanceof Error?o.message:t.reason??"hook_handler_unavailable",i=t.fallback??(t.policy==="enqueue_and_open"?"durable_background_processing":"host_event_continues");return e==="pre-tool-use"?{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:t.policy==="fail_closed"?"deny":"allow",permissionDecisionReason:r,additionalContext:`DevFlow hook degraded: ${r}; fallback=${i}.`}}:e==="user-prompt-submit"?{hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",additionalContext:`DevFlow hook degraded: ${r}; fallback=${i}. Do not claim unreceipted work completed.`}}:{status:"degraded",reason:r,fallback:i}}async handlePreToolUse(e){try{if(!e||e.trim()==="")return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};let t=JSON.parse(e);t.tool_input=Jr(t.tool_name,t.tool_input,process.env,this.projectRoot);let o=this.trackSession(t.session_id),r="";if(t.tool_name==="Skill"){let S=t.tool_input?.skill,w=S?q(S):null;w&&(r=this.startSkillExecution(o,w));}let i=this.runtimeStore.get(o);t.tool_name.startsWith("mcp__devflow__")&&(t.tool_input._devflow_session_id=o,t.tool_input._devflow_execution_id=i?.executionId??o,t.tool_use_id&&(t.tool_input._devflow_tool_use_id=t.tool_use_id));let s=t.tool_name.startsWith("mcp__"),a=s?t.tool_name.replace(/^mcp__[^_]+__/,""):void 0,c=new E(this.projectRoot,o,i?.executionId),l=c.getPhase(),u=Dt({toolName:t.tool_name,toolInput:t.tool_input,projectRoot:this.projectRoot}),p=u?{permissionDecision:"deny",reason:u}:c.evaluate(t.tool_name,s),m;if(p.permissionDecision==="deny"?m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:p.reason??"MCP context required"}}:p.additionalContext?m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow",additionalContext:p.additionalContext}}:m={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}},r){let S=m.hookSpecificOutput,w=typeof S.additionalContext=="string"?S.additionalContext:"";S.additionalContext=w?`${w}
|
|
9
|
+
${r}`:r;}t.tool_name.startsWith("mcp__devflow__")&&(m.hookSpecificOutput.updatedInput=t.tool_input);let f={...t.tool_input};delete f._devflow_session_id,delete f._devflow_execution_id,delete f._devflow_tool_use_id;let d=i?.executionId??o,h={eventId:D(o,t.tool_use_id),executionId:d,sessionId:o,projectRoot:this.projectRoot,toolUseId:t.tool_use_id,timestamp:Date.now(),toolName:t.tool_name,toolType:s?"mcp":t.tool_name==="Agent"?"subagent":"direct",isMcpTool:s,mcpToolName:a,mcpEnforced:s&&l==="context_gathering",mcpFallback:!s&&l==="context_gathering",kind:zr(t.tool_name),input:f,duration:0,blocked:m&&m.hookSpecificOutput?.permissionDecision==="deny"},g=await this.telemetry.sendEvent({...h,blockReason:h.blocked?u?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0,error:h.blocked?u?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED":void 0});return g&&!h.blocked&&(this.eventMap.push({toolName:t.tool_name,toolUseId:t.tool_use_id,eventId:g,sessionId:o,timestamp:h.timestamp}),this.noteTelemetryOperation()),g&&h.blocked&&await this.telemetry.completeEvent({eventId:g,sessionId:o,error:u?"DEVFLOW_CANONICAL_MEMORY_REQUIRED":"DEVFLOW_CONTEXT_REQUIRED",duration:Date.now()-h.timestamp,completedAt:Date.now()}),m}catch{return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}}trackSession(e){let t=e?.trim()||(this.activeSessionIds.size===1?[...this.activeSessionIds][0]:"");if(!t)throw new Error("session_id_required");return this.registerSession(t),t}registerSession(e){this.activeSessionIds.has(e)||(this.activeSessionIds.size===0&&F(this.projectRoot,{bypassCount:0}),this.activeSessionIds.add(e),this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null),this.serverManager.addRef(e),this.telemetry.sendSessionStart(e,this.projectRoot,Date.now()).catch(()=>{})),this.runtimeStore.registerSession(e);}startSkillExecution(e,t){let o=this.runtimeStore.get(e)?.executionId,r=this.runtimeStore.startExecution(e,t,je(t));return r.executionId&&r.executionId!==o&&this.telemetry.sendExecutionStart(r.executionId,e,t,r.lastActivityAt,this.projectRoot,r.requiredMcpTools).catch(()=>{}),formatSkillRuntimeOverlay(createSkillRuntimeOverlay(t,this.projectRoot))}async handleSessionStart(e){try{let t=JSON.parse(e);if(typeof t.session_id!="string"||!t.session_id.trim())return {error:"session_id_required"};let o=t.session_id.trim();this.registerSession(o);let r=`session-start:${createHash("sha256").update(`${this.projectRoot}\0${o}`).digest("hex").slice(0,24)}`,i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50}),s="pending";try{s=i.enqueueWork({idempotencyKey:r,kind:"session.bootstrap",projectRoot:this.projectRoot,sessionId:o,payload:{sessionId:o}}).state;}finally{i.close();}return {status:s==="completed"?"completed":"accepted",receiptId:r,workState:s}}catch{return {error:"session_start_invalid"}}}popEventFromMap(e,t,o){let r=this.eventMap.filter(s=>s.toolName===e&&s.sessionId===t);if(r.length===0)return null;let i=o?r.find(s=>s.toolUseId===o):r.sort((s,a)=>s.timestamp-a.timestamp)[0];return i?(this.eventMap=this.eventMap.filter(s=>s.eventId!==i.eventId),i):null}enforcePostToolUse(e){if(!qr[e])return null;let t=Math.floor(Date.now()/1e3),o=se(this.projectRoot,s=>t-(s.lastMcpCall??0)<30?s:{...s,bypassCount:(s.bypassCount??0)+1});if(!o.applied||!o.changed)return null;let r=o.receipt.bypassCount??0;if(r===1)return null;let i;switch(e){case "Agent":i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u4F7F\u7528\u4E86 Agent \u5B50\u4EE3\u7406\u6267\u884C\u641C\u7D22\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Bash":i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Bash \u547D\u4EE4\u641C\u7D22\u4EE3\u7801\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Glob":i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Glob \u5339\u914D\u6587\u4EF6\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "Grep":i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86 Grep \u641C\u7D22\u4EE3\u7801\u3002\u4E0B\u6B21\u8BF7\u7528 get_project_context MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;case "WebSearch":case "WebFetch":i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u4F60\u521A\u624D\u7528\u4E86\u7F51\u7EDC\u641C\u7D22\u3002\u4E0B\u6B21\u8BF7\u7528 get_knowledge MCP \u5DE5\u5177\u66FF\u4EE3\u3002`;break;default:i=`\u7B2C ${r} \u6B21\u8FDD\u89C4\uFF1A\u8BF7\u4F7F\u7528 DevFlow MCP \u5DE5\u5177\u66FF\u4EE3\u76F4\u63A5\u8C03\u7528\u3002`;}return r>=3?i=`${i} \u5DF2\u8FBE\u5230\u6700\u5927\u8FDD\u89C4\u6B21\u6570\uFF0C\u540E\u7EED\u7ED5\u8FC7\u5C06\u88AB\u786C\u963B\u6B62\u3002`:r>=2?i=`${i} \u4E0B\u6B21\u8FDD\u89C4\u5C06\u88AB\u963B\u6B62\u3002`:i=`${i} \u8BF7\u7ACB\u5373\u7EA0\u6B63\u3002`,i}async handlePostToolUse(e){if(!e)return null;let t;try{t=JSON.parse(e);}catch{return null}let o=t.tool_name||"",r=t.tool_input||{},i=t.tool_response,s=this.trackSession(t.session_id);if(o==="Skill"){let v=r?.skill,k=v?q(v):null;k&&(this.startSkillExecution(s,k),F(this.projectRoot,{lastMcpCall:Math.floor(Date.now()/1e3),bypassCount:0}));}o.startsWith("mcp__")&&new E(this.projectRoot).recordMcpCall();let a=this.popEventFromMap(o,s,t.tool_use_id);if(a){let v=typeof i=="string"?i:JSON.stringify(i),k=v.length>5e3?{_truncated:true,_originalSize:v.length,text:v.slice(0,5e3)}:i,Kt=Date.now()-a.timestamp;await this.telemetry.completeEvent({eventId:a.eventId,sessionId:s,output:k,duration:Kt,completedAt:Date.now()})&&this.noteTelemetryOperation();}let c=typeof i=="object"&&i!==null?i:null,l=c?.exitCode,u=c?.stderr,p=/^\s*(ls|cat|pwd|cd|echo|head|tail|wc|which|whoami|date|env|printenv|id|hostname|uname)\b/,m=r.command||"",f=JSON.stringify(i),d=Buffer.byteLength(f,"utf8"),y=this.countResults(i),h,g,S=true;if(o.startsWith("mcp__"))h="mcp_call",g={mcpTool:o.replace(/^mcp__[^_]+__/,""),query:r.query??null,resultCount:y,resultSizeBytes:d};else if(o==="Read"||o==="Write"||o==="Edit")h=o==="Read"?"file_read":"file_write",g={filePath:r.file_path??null,fileContentSize:d};else if(o==="Bash"){let v=p.test(m),k=l!==void 0&&l!==0;S=!v||k,h=k?"bash_error":"bash_command",g={command:m||o,exitCode:l??null,stderr:u??null};}else o==="Agent"?(h="subagent",g={subagentType:r.subagent_type??null,description:typeof r.description=="string"?r.description.slice(0,200):null}):o==="WebSearch"||o==="WebFetch"?(h=o==="WebSearch"?"web_search":"web_fetch",g={query:typeof r.query=="string"?r.query.slice(0,200):null}):(S=false,h="tool_use",g={});if(S){let v={id:t.tool_use_id?`memory:${D(s,t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:s,tool:o,kind:h,payload:g,command:m||void 0,exitCode:l,stderr:u??void 0,durationMs:0,createdAt:Date.now()};this.postMemoryEvent(v);}let w=this.enforcePostToolUse(o);return w?(console.error("[devflow-daemon] Enforcement:",w),{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:JSON.stringify(w)}}):null}async handlePostToolUseFailure(e){let t;try{t=JSON.parse(e);}catch{return null}let o=this.trackSession(t.session_id),r=t.tool_name??"unknown",i=t.error??`${r} failed`,s=this.popEventFromMap(r,o,t.tool_use_id);if(s)await this.telemetry.completeEvent({eventId:s.eventId,sessionId:o,error:i,duration:Date.now()-s.timestamp,completedAt:Date.now()})&&this.noteTelemetryOperation();else {let a=D(o,t.tool_use_id);await this.telemetry.sendEvent({eventId:a,executionId:this.runtimeStore.get(o)?.executionId??o,sessionId:o,projectRoot:this.projectRoot,toolUseId:t.tool_use_id,timestamp:Date.now(),toolName:r,toolType:r.startsWith("mcp__")?"mcp":"direct",isMcpTool:r.startsWith("mcp__"),mcpToolName:r.startsWith("mcp__")?r.replace(/^mcp__[^_]+__/,""):void 0,mcpEnforced:false,mcpFallback:false,kind:"error",input:t.tool_input??{},duration:0,error:i,blocked:false});}return this.postMemoryEvent({id:t.tool_use_id?`memory:${D(o,t.tool_use_id)}`:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:o,tool:r,command:typeof t.tool_input?.command=="string"?t.tool_input.command:r,exitCode:-1,stderr:i,durationMs:s?Date.now()-s.timestamp:0,createdAt:Date.now(),kind:r==="Bash"?"bash_error":"tool_use",payload:{command:t.tool_input?.command??r,exitCode:-1,stderr:i}}),null}countResults(e){if(!e)return 0;let t=e;if(typeof e=="string")try{t=JSON.parse(e);}catch{return 1}let o=t,r=["files","results","data","result","memories","nodes","chunks","findings","symbols"],i=Array.isArray(o.data)?o.data:o.structuredContent??o;if(Array.isArray(i))return i.length;if(typeof i=="object"&&i!==null){let s=i,a=0,c=false;for(let l of r)Array.isArray(s[l])&&(c=true,a+=s[l].length);for(let[,l]of Object.entries(s))l&&typeof l=="object"&&!Array.isArray(l)&&(a+=this.countResults(l));return a>0?a:c?0:Object.keys(s).length>0?1:0}return 0}async postMemoryEvent(e){He(`/api/memory/session-events?rootPath=${encodeURIComponent(this.projectRoot)}`,e);try{await(await this.getMemoryGate()).recordEvent(e);}catch(t){console.error("[devflow-daemon] Local memory event write failed:",t.message);}}async getMemoryGate(){let e=this.explicitMemoryGate??=new MemoryGate(this.projectRoot);return this.memoryWarmup??=e.forceWarmUp().catch(t=>{throw this.memoryWarmup=null,t}),await this.memoryWarmup,e}async handleUserPromptSubmit(e){let t=[];try{let o=JSON.parse(e),r=typeof o.prompt=="string"?o.prompt:"",i=typeof o.session_id=="string"&&o.session_id.trim()?this.trackSession(o.session_id):null,s=kt(r),a=!1;if(r.trim()&&i)try{let c=fe({projectRoot:this.projectRoot,sessionId:i,prompt:r});if(c){let l=c;if(c.explicitContent&&c.turn.status==="pending")try{l=await ye({projectRoot:this.projectRoot,payload:{operation:"commit_explicit",turnId:c.turn.turnId,eventId:c.turn.eventId,sessionId:i,prompt:r.trim().slice(0,4e3),explicitContent:c.explicitContent,createdAt:c.turn.createdAt},memory:await this.getMemoryGate()});}catch(u){console.error("[devflow-daemon] Explicit memory commit deferred:",u.message);}t.push(l.additionalContext),a=l.skipSkillRouting;}}catch(c){a=!!W(r);try{let u=Ft(this.projectRoot,{sessionId:i,prompt:r,createdAt:Date.now()});t.push(`DevFlow memory turn status=accepted; durable=true; receiptId=${u}; canonicalMemory=false; SQLite queue replay pending. Do not claim memory success without a canonical receipt.`),this.scheduleMemoryTurnSpoolDrain(250),console.error("[devflow-daemon] Memory turn spooled after database contention:",c.message);}catch(u){t.push("DevFlow memory turn status=degraded; durable=false; no canonical receipt exists. Do not claim memory success."),console.error("[devflow-daemon] Memory turn persistence unavailable:",u.message);}}if(i&&s&&!a){let c=this.startSkillExecution(i,s.skillName);c&&t.push(c);}}catch{}return {hookSpecificOutput:{hookEventName:"UserPromptSubmit",permissionDecision:"allow",...t.length?{additionalContext:t.join(`
|
|
10
|
+
`)}:{}}}}async handlePreCompact(e){let t;try{let s=JSON.parse(e);typeof s.session_id=="string"&&s.session_id.trim()&&(t=s.session_id.trim());}catch{}await this.flushTelemetry(),this.startExplicitIntentFlush(),await this.explicitIntentFlush;let o=await this.getMemoryGate(),r=await x({projectRoot:this.projectRoot,sessionId:t,trigger:"pre_compact",memory:o}),i=it(r);return {hookSpecificOutput:{hookEventName:"PreCompact",...i?{additionalContext:i}:{}}}}async persistMemoryTurnItem(e){if(!e||typeof e!="object")throw new Error("memory_turn_payload_invalid");let t=e;if(t.operation!=="capture_prompt"&&t.operation!=="commit_explicit"||typeof t.turnId!="string"||typeof t.eventId!="string"||typeof t.sessionId!="string"||typeof t.prompt!="string"||typeof t.createdAt!="number")throw new Error("memory_turn_payload_invalid");await ye({projectRoot:this.projectRoot,payload:t,memory:await this.getMemoryGate()});}scheduleMemoryTurnSpoolDrain(e){this.memoryTurnSpoolTimer||(this.memoryTurnSpoolTimer=setTimeout(()=>{this.memoryTurnSpoolTimer=null,this.drainMemoryTurnSpool();},e),this.memoryTurnSpoolTimer.unref());}async drainMemoryTurnSpool(){for(;;){let e=Nt(this.projectRoot);if(!e)return;try{fe({projectRoot:this.projectRoot,sessionId:e.payload.sessionId,prompt:e.payload.prompt}),$t(e),this.workRuntime.drainOnce();}catch(t){Lt(e),console.error("[devflow-daemon] Memory turn spool replay deferred:",t.message),this.scheduleMemoryTurnSpoolDrain(1e3);return}}}async bootstrapSessionWork(e){if(!e||typeof e!="object"||typeof e.sessionId!="string")throw new Error("session_bootstrap_payload_invalid");let t=e.sessionId,o=await this.getMemoryGate();await o.ensureSession(t,this.projectRoot,"Host session"),await o.releasePendingDistillLeases(t);}noteTelemetryOperation(){this.successfulTelemetryOperations++,this.successfulTelemetryOperations>=Wr&&this.flushTelemetry();}async flushTelemetry(){this.successfulTelemetryOperations=0,await this.telemetry.flushAndAggregate();}startExplicitIntentFlush(){this.explicitIntentFlush||(this.explicitIntentFlush=this.flushExplicitMemoryIntents().finally(()=>{this.explicitIntentFlush=null;}));}async handleStop(e){let t=null,o=false;try{let r=JSON.parse(e);typeof r.session_id=="string"&&r.session_id.trim()&&(t=r.session_id.trim()),o=r.stop_hook_active===!0;}catch{}if(t??=this.activeSessionIds.size===1?[...this.activeSessionIds][0]:null,this.startExplicitIntentFlush(),t){let r=Rt(this.projectRoot,t,o);if(r)return r;if(o)return null;let i=this.runtimeStore.completeExecution(t);if(i?.executionId){let s=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50}),a={};try{let c=s.listMemoryTurns(this.projectRoot,t,100);a={memoryReceiptIds:c.flatMap(l=>l.receiptId?[l.receiptId]:[]),missingMemoryDecisionCount:c.filter(l=>l.status==="pending").length};}finally{s.close();}await this.telemetry.sendExecutionComplete(i.executionId,"completed",Date.now(),a),this.deleteContextReceipt(t,i.executionId);}}return null}async flushExplicitMemoryIntents(){this.flushTelemetry();let e=wt(this.projectRoot);if(e)try{let t=this.explicitMemoryGate??=new MemoryGate(this.projectRoot);for(await t.forceWarmUp();e.intents.length>0;){let o=e.intents[0];if(o.turnId){let i=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:50});try{let s=i.getMemoryTurn(o.turnId);if(!s||s.status!=="pending"){console.error(`[devflow-daemon] Dropping stale legacy memory intent for ${o.turnId}: ${s?.status??"missing"}`),ue(e);continue}}finally{i.close();}}let r=await t.saveExplicitMemoryIntent(o.content,o.sessionId,o.eventId);if(o.turnId){let i=openGlobalDevFlowDatabase();try{i.commitMemoryTurn({turnId:o.turnId,receiptId:me(o.turnId,"committed",[r.id]),memoryIds:[r.id],source:"explicit_intent",reason:"explicit_user_request_retry"});}finally{i.close();}}ue(e);}}catch(t){console.error("[devflow-daemon] Explicit memory intent save failed:",t.message);}}deleteContextReceipt(e,t){let o;try{o=openGlobalDevFlowDatabase(void 0,{busyTimeoutMs:250}),o.deleteContextReceipt(this.projectRoot,e,t);}catch{}finally{o?.close();}}async handleMemorySnapshot(){let e=loadConfig(this.projectRoot).sessionStart?.injectMemories??true;if(e===false)return {status:"ok",enabled:false,markdown:""};let t=typeof e=="object"?e.topN:void 0,o=typeof e=="object"?e.budgetTokens:void 0,r=Number.isFinite(t)?Math.max(0,Math.floor(t)):10,i=Number.isFinite(o)?Math.max(1,Math.floor(o)):800;try{let s=this.explicitMemoryGate??=new MemoryGate(this.projectRoot),c={...await s.getAll({purpose:"session_bootstrap",budgetTokens:i,limit:r}),_devflow_unique:{memory_version:1,structured_storage:!0,project_context_included:!0},_accuracy:{data_freshness_ms:0,source_layer:"memory",degradation:typeof s.getObservationVectorCoverage=="function"?s.getObservationVectorCoverage().missing>0?"bm25_only":"none":"partial"}};if(c.memories.length===0)return {status:"ok",enabled:!0,markdown:`## Project memory
|
|
11
|
+
\u672C\u9879\u76EE\u6682\u65E0\u8BB0\u5FC6`};let l=c.memories.map(u=>`- **${u.title||u.type}**: ${u.content} (confidence ${u.confidence.toFixed(2)}, ${u.source})`);return {status:"ok",enabled:!0,markdown:`## Project memory (auto-injected, ${c.memories.length} items, ${c.tokenCount} tokens)
|
|
12
|
+
${l.join(`
|
|
13
13
|
`)}`}}catch(s){return console.error("[devflow-daemon] Memory snapshot failed:",s.message),{status:"degraded",enabled:true,markdown:`## Project memory
|
|
14
|
-
\u672C\u9879\u76EE\u6682\u65E0\u8BB0\u5FC6`}}}async handleSessionEnd(e){let t=null;try{let s=JSON.parse(e);typeof s.session_id=="string"&&s.session_id.trim()&&(t=s.session_id.trim());}catch{}t??=this.activeSessionIds.size===1?[...this.activeSessionIds][0]:null;let
|
|
15
|
-
`);}};if(process.env.DEVFLOW_HOOK_DAEMON_DISABLE_AUTOSTART!=="1"){let
|
|
14
|
+
\u672C\u9879\u76EE\u6682\u65E0\u8BB0\u5FC6`}}}async handleSessionEnd(e){let t=null;try{let s=JSON.parse(e);typeof s.session_id=="string"&&s.session_id.trim()&&(t=s.session_id.trim());}catch{}t??=this.activeSessionIds.size===1?[...this.activeSessionIds][0]:null;let o=t===null?this.activeSessionIds.size<=1:this.activeSessionIds.size<=1&&this.activeSessionIds.has(t),r=t?this.runtimeStore.get(t)?.executionId:void 0,i=H(e,this.projectRoot,o,r);return i?.workState==="spooled"&&this.scheduleSessionFinalizeSpoolDrain(250),t&&(this.serverManager.removeRef(t),this.activeSessionIds.delete(t),this.eventMap=this.eventMap.filter(s=>s.sessionId!==t)),this.activeSessionIds.size===0&&i?.workState!=="spooled"?setImmediate(()=>{this.workRuntime.drainOnce().finally(()=>{this.shutdown();});}):this.resetIdleTimer(),i??{status:"ok"}}async finalizeSessionWork(e,t){if(!e||typeof e!="object")throw new Error("session_finalize_payload_invalid");let o=e;if(typeof o.inputJson!="string"||typeof o.sessionId!="string")throw new Error("session_finalize_payload_invalid");typeof o.executionId=="string"&&o.executionId&&await this.telemetry.sendExecutionComplete(o.executionId);let r=await this.getMemoryGate();await gt(o.inputJson,this.projectRoot,o.cleanupSharedState!==false,{telemetry:this.telemetry,memory:r});let i=openGlobalDevFlowDatabase();try{i.completeSessionClosure(this.projectRoot,o.sessionId,t);}finally{i.close();}}scheduleSessionFinalizeSpoolDrain(e){this.sessionFinalizeSpoolTimer||(this.sessionFinalizeSpoolTimer=setTimeout(()=>{this.sessionFinalizeSpoolTimer=null,this.drainSessionFinalizeSpool();},e),this.sessionFinalizeSpoolTimer.unref());}async drainSessionFinalizeSpool(){for(;;){let e=ut(this.projectRoot);if(!e)return;try{if(!H(e.payload.inputJson,this.projectRoot,e.payload.cleanupSharedState,e.payload.executionId,!1))throw new Error("session_finalize_spool_rejected");dt(e),this.workRuntime.drainOnce();}catch(t){pt(e),console.error("[devflow-daemon] Session finalize spool replay deferred:",t.message),this.scheduleSessionFinalizeSpoolDrain(1e3);return}}}shutdown(){return this.shutdownPromise?this.shutdownPromise:(this.shutdownPromise=this.performShutdown(),this.shutdownPromise)}async performShutdown(){this.workRuntime.stop(),this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null),this.telemetryFlushTimer&&(clearInterval(this.telemetryFlushTimer),this.telemetryFlushTimer=null),this.memoryTurnSpoolTimer&&(clearTimeout(this.memoryTurnSpoolTimer),this.memoryTurnSpoolTimer=null),this.sessionFinalizeSpoolTimer&&(clearTimeout(this.sessionFinalizeSpoolTimer),this.sessionFinalizeSpoolTimer=null),await this.flushTelemetry(),await this.closeServer(),this.cleanupOwnedResources(),await this.serverManager.stop(),await this.explicitIntentFlush,this.explicitMemoryGate?.close(),this.explicitMemoryGate=null,this.telemetry.close(),process.exit(0);}closeServer(){let e=this.server;return !e||!e.listening||!this.pathMatchesIdentity(this.socketPath,this.socketIdentity)?Promise.resolve():(this.server=null,new Promise(t=>{let o=false,r=()=>{o||(o=true,clearTimeout(i),t());},i=setTimeout(r,$r);e.close(r);}))}cleanupOwnedResources(){try{rt(this.projectRoot,process.pid);}catch(e){console.error("[devflow-daemon] Failed to unregister:",e.message);}this.removePathIfOwned(this.socketPath,this.socketIdentity,"socket"),this.removePathIfOwned(this.pidPath,this.pidIdentity,"PID file",`${process.pid}
|
|
15
|
+
`);}};if(process.env.DEVFLOW_HOOK_DAEMON_DISABLE_AUTOSTART!=="1"){let n=process.argv[2]||process.env.CLAUDE_PROJECT_DIR||process.cwd(),e=new Te(n,process.argv[3]);process.once("SIGTERM",()=>{e.shutdown();}),process.once("SIGINT",()=>{e.shutdown();}),e.start().catch(t=>{console.error("[devflow-daemon] Failed to start:",t),process.exit(1);});}export{Te as HookDaemon,Jr as injectProjectRootIfMissing};
|