@devflow-tools/devflow 0.11.0 → 0.12.0

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/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import zo,{unlinkSync,existsSync,readFileSync,rmSync,mkdirSync,writeFileSync,statSync,cpSync,readdirSync}from'fs';import xt,{dirname,join,resolve}from'path';import {homedir}from'os';import {createRequire}from'module';import Ee from'@colbymchenry/codegraph';import {createEngines,buildOnboardingPack}from'@devflow-tools/context-engine';import {Command}from'commander';import l from'chalk';import {execSync,spawn}from'child_process';import {checkbox}from'@inquirer/prompts';import {fileURLToPath}from'url';import {listAdapters,connect}from'@devflow-tools/adapters';import {DevFlowApiClient,loadPlugins}from'@devflow-tools/sdk';import'readline';import {KnowledgeEngine}from'@devflow-tools/knowledge-engine';import {createHash,createHmac}from'crypto';import {BenchmarkEngine}from'@devflow-tools/benchmark';var Yo=Object.defineProperty;var be=(e,o)=>()=>(e&&(o=e(e=0)),o);var Xo=(e,o)=>{for(var n in o)Yo(e,n,{get:o[n],enumerable:true});};function De(){let e=join(dirname(new URL(import.meta.url).pathname),"../../plugin-files");if(existsSync(e))return e;let o=join(dirname(new URL(import.meta.url).pathname),"../../../../plugins/claude-code");if(existsSync(o))return o;throw new Error("Plugin files not found. Run `npm run build` first.")}function Re(e){let o={};if(existsSync(e))try{o=JSON.parse(readFileSync(e,"utf-8"));}catch{console.warn("Warning: Could not parse settings.json, skipping plugin enablement");return}else mkdirSync(dirname(e),{recursive:true});let n=o.enabledPlugins??{};n[ke]!==true&&(n[ke]=true,o.enabledPlugins=n,writeFileSync(e,JSON.stringify(o,null,2)));}function Fe(e,o){let n=join(e,".claude"),t=join(n,"mcp.json"),r={};if(existsSync(t))try{r=JSON.parse(readFileSync(t,"utf-8"));}catch{console.warn("Warning: Could not parse existing mcp.json, skipping MCP config");return}else mkdirSync(n,{recursive:true});let i=r.mcpServers??{};i.devflow||(i.devflow={command:o,args:[],env:{}},r.mcpServers=i,writeFileSync(t,JSON.stringify(r,null,2)));}function Ie(e,o,n,t){let r=join(o,nn,tn,n);mkdirSync(r,{recursive:true});let i=join(e,"hooks");existsSync(i)&&N(i,join(r,"hooks"));for(let d of ["hooks.json","CLAUDE.md","package.json"]){let u=join(e,d);existsSync(u)&&cpSync(u,join(r,d),{force:true});}let s=join(e,".claude-plugin","plugin.json");existsSync(s)&&(mkdirSync(join(r,".claude-plugin"),{recursive:true}),cpSync(s,join(r,".claude-plugin","plugin.json"),{force:true}));let a=join(e,"dist");if(existsSync(a)&&N(a,join(r,"dist")),t){let d=join(e,"dist","skills");existsSync(d)&&N(d,t);}rn(r);}function N(e,o){mkdirSync(o,{recursive:true});for(let n of readdirSync(e)){let t=join(e,n),r=join(o,n);statSync(t).isDirectory()?N(t,r):cpSync(t,r,{force:true});}}function rn(e){let o=join(e,"..");if(!existsSync(o))return;let n=e.split("/").pop()??"";for(let t of readdirSync(o))if(t!==n){let r=join(o,t);statSync(r).isDirectory()&&rmSync(r,{recursive:true,force:true});}}var ke,nn,tn,Oe=be(()=>{ke="@devflow-tools/claude-code-plugin@devflow-local",nn="devflow-local",tn="@devflow-tools/claude-code-plugin";});var Ae={};Xo(Ae,{initProject:()=>Z,renderInitReport:()=>Te});async function Z(e,o={}){let n=join(e,".devflow"),t=[];existsSync(n)||(mkdirSync(n,{recursive:true}),t.push(".devflow/"));let r=join(n,"config.json");(!existsSync(r)||o.force)&&(writeFileSync(r,JSON.stringify({version:"0.1.0",initialized:new Date().toISOString()},null,2),"utf-8"),t.push(".devflow/config.json"));let i={created:t,pluginDeployed:false,pluginEnabled:false,mcpConfigured:false};if(Q.isInitialized(e)||await Q.init(e,{index:o.scan!==false}),o.scan!==false)try{let{indexer:s,graph:a}=await createEngines(e),{files:d,symbols:u,imports:p}=await s.indexAll(e),w=await a.build(u,p);i.indexed={files:d.length,symbols:u.length,graphNodes:w.nodes.length};}catch{i.indexed={files:0,symbols:0,graphNodes:0};}if(o.scan!==false)try{let{indexer:s,graph:a}=await createEngines(e),d=Q.openSync(e),u=await buildOnboardingPack(e,d,s,a),p=join(n,"onboarding-pack.json");writeFileSync(p,JSON.stringify(u,null,2),"utf-8"),t.push(".devflow/onboarding-pack.json");let w=join(n,"init-report.md");writeFileSync(w,Te(u),"utf-8"),t.push(".devflow/init-report.md"),i.onboardingPack=u;}catch(s){console.warn(`Warning: Onboarding pack generation skipped \u2014 ${s.message}`);}try{let s=De(),a=homedir(),d=join(a,".claude","plugins","cache"),u=join(a,".claude","skills"),p=join(s,"package.json"),w=existsSync(p)?JSON.parse(readFileSync(p,"utf-8")).version:"0.0.0";Ie(s,d,w,u),i.pluginDeployed=!0;}catch(s){console.warn(`Warning: Plugin deployment skipped \u2014 ${s.message}`);}try{let s=homedir(),a=join(s,".claude","settings.json");Re(a),i.pluginEnabled=!0;}catch(s){console.warn(`Warning: Plugin enablement skipped \u2014 ${s.message}`);}try{let s;try{s=dn.resolve("@devflow-tools/mcp-server/bin/devflow-mcp.cjs");}catch{s="devflow-mcp";}Fe(e,s),i.mcpConfigured=!0;}catch(s){console.warn(`Warning: MCP config skipped \u2014 ${s.message}`);}return i}function Te(e){return [`# ${e.projectName} \u2014 DevFlow Onboarding Report`,`Generated: ${e.createdAt}`,"","## Project Stats",`- Files: ${e.stats.files}`,`- Symbols: ${e.stats.symbols}`,`- Graph Nodes: ${e.stats.graphNodes}`,"","## Tech Stack",`- Languages: ${e.stack.languages.join(", ")||"unknown"}`,`- Frameworks: ${e.stack.frameworks.join(", ")||"none detected"}`,`- Build Tools: ${e.stack.buildTools.join(", ")||"none detected"}`,`- Test Tools: ${e.stack.testTools.join(", ")||"none detected"}`,"","## Architecture Layers",...e.architectureLayers.map(n=>`- **${n.name}**: ${n.files} files`),"","## Key Modules",...e.keyModules.slice(0,10).map(n=>`- \`${n.name}\` \u2014 ${n.reason}`),"","## Key Symbols",...e.keySymbols.slice(0,20).map(n=>`- \`${n.name}\` (${n.kind}) in \`${n.file}\``),"","## Recommended Next Steps",...e.recommendedPlugins.map(n=>`- Install plugin: \`${n}\``),...e.recommendedWorkflows.map(n=>`- Run workflow: \`devflow workflow ${n}\``),`- Try: \`devflow context "${e.recommendedQueries[0]??"\u9879\u76EE\u67B6\u6784"}"\``].join(`
3
- `)}var Q,dn,ee=be(()=>{Oe();Q=Ee.default??Ee,dn=createRequire(import.meta.url);});function z(e){let o=join(e,".devflow","config.json");if(existsSync(o))try{let n=readFileSync(o,"utf-8");if(JSON.parse(n).serverUrl)return "server"}catch{}return "local"}ee();var fn=fileURLToPath(import.meta.url),wn=dirname(fn);function D(){let e=[join(process.cwd(),"plugin-registry.json"),join(wn,"../plugin-registry.json"),join(process.cwd(),"packages/devflow/plugin-registry.json")];for(let o of e)try{let n=readFileSync(o,"utf-8");return JSON.parse(n)}catch{continue}return {version:"0.0.0",lastUpdated:new Date().toISOString(),plugins:[]}}function Me(){try{let e=execSync("npm list -g --depth=0 --json",{encoding:"utf-8"}),o=JSON.parse(e);return Object.keys(o.dependencies||{}).filter(n=>n.startsWith("@devflow-tools/plugin-"))}catch{return []}}function Sn(e){let o=[];try{let n=JSON.parse(readFileSync(join(e,"package.json"),"utf-8")),t={...n.dependencies??{},...n.devDependencies??{}};t.react&&o.push("react"),t.next&&o.push("nextjs"),t.vue&&o.push("vue"),t.tailwindcss&&o.push("tailwind"),(t.nest||t["@nestjs/core"])&&o.push("nest"),t.express&&o.push("express"),t.typescript&&o.push("typescript");}catch{}return o}function bn(e){let o=e.trim();return o.startsWith("@devflow-tools/")?o:`@devflow-tools/${o}`}async function Le(e){let o=e.split(",").map(bn).filter(Boolean);if(o.length!==0)for(let n of o){console.log(`Installing ${n}...`);try{execSync(`npm install -g ${n}`,{stdio:"inherit"}),console.log(`\u2713 ${n}`);}catch{console.error(`\u2717 Failed to install ${n}`);}}}async function We(e){let o=D();if(o.plugins.length===0)return console.log(`
2
+ import Ro,{readFileSync,existsSync,mkdirSync,writeFileSync,unlinkSync,statSync,cpSync,readdirSync,rmSync}from'fs';import Hn,{dirname,join,resolve}from'path';import {homedir}from'os';import {createRequire}from'module';import be from'@colbymchenry/codegraph';import {createEngines,buildOnboardingPack}from'@devflow-tools/context-engine';import {Command}from'commander';import l from'chalk';import {execSync,spawn}from'child_process';import {checkbox}from'@inquirer/prompts';import {fileURLToPath}from'url';import {listAdapters,connect}from'@devflow-tools/adapters';import {DevFlowApiClient,loadPlugins}from'@devflow-tools/sdk';import'readline';import {KnowledgeEngine}from'@devflow-tools/knowledge-engine';import {createHash,createHmac}from'crypto';import {BenchmarkEngine}from'@devflow-tools/benchmark';var Oo=Object.defineProperty;var de=(e,o)=>()=>(e&&(o=e(e=0)),o);var jo=(e,o)=>{for(var n in o)Oo(e,n,{get:o[n],enumerable:true});};function we(){let e=join(dirname(new URL(import.meta.url).pathname),"../../plugin-files");if(existsSync(e))return e;let o=join(dirname(new URL(import.meta.url).pathname),"../../../../plugins/claude-code");if(existsSync(o))return o;throw new Error("Plugin files not found. Run `npm run build` first.")}function ye(e){let o={};if(existsSync(e))try{o=JSON.parse(readFileSync(e,"utf-8"));}catch{console.warn("Warning: Could not parse settings.json, skipping plugin enablement");return}else mkdirSync(dirname(e),{recursive:true});let n=o.enabledPlugins??{};n[ge]!==true&&(n[ge]=true,o.enabledPlugins=n,writeFileSync(e,JSON.stringify(o,null,2)));}function he(e,o){let n=join(e,".claude"),t=join(n,"mcp.json"),r={};if(existsSync(t))try{r=JSON.parse(readFileSync(t,"utf-8"));}catch{console.warn("Warning: Could not parse existing mcp.json, skipping MCP config");return}else mkdirSync(n,{recursive:true});let i=r.mcpServers??{};i.devflow||(i.devflow={command:o,args:[],env:{}},r.mcpServers=i,writeFileSync(t,JSON.stringify(r,null,2)));}function ve(e,o,n,t){let r=join(o,Ao,Mo,n);mkdirSync(r,{recursive:true});let i=join(e,"hooks");existsSync(i)&&I(i,join(r,"hooks"));for(let d of ["hooks.json","CLAUDE.md","package.json"]){let m=join(e,d);existsSync(m)&&cpSync(m,join(r,d),{force:true});}let s=join(e,".claude-plugin","plugin.json");existsSync(s)&&(mkdirSync(join(r,".claude-plugin"),{recursive:true}),cpSync(s,join(r,".claude-plugin","plugin.json"),{force:true}));let c=join(e,"dist");if(existsSync(c)&&I(c,join(r,"dist")),t){let d=join(e,"dist","skills");existsSync(d)&&I(d,t);}Lo(r);}function I(e,o){mkdirSync(o,{recursive:true});for(let n of readdirSync(e)){let t=join(e,n),r=join(o,n);statSync(t).isDirectory()?I(t,r):cpSync(t,r,{force:true});}}function Lo(e){let o=join(e,"..");if(!existsSync(o))return;let n=e.split("/").pop()??"";for(let t of readdirSync(o))if(t!==n){let r=join(o,t);statSync(r).isDirectory()&&rmSync(r,{recursive:true,force:true});}}var ge,Ao,Mo,Se=de(()=>{ge="@devflow-tools/claude-code-plugin@devflow-local",Ao="devflow-local",Mo="@devflow-tools/claude-code-plugin";});var Pe={};jo(Pe,{initProject:()=>K,renderInitReport:()=>xe});async function K(e,o={}){let n=join(e,".devflow"),t=[];existsSync(n)||(mkdirSync(n,{recursive:true}),t.push(".devflow/"));let r=join(n,"config.json");(!existsSync(r)||o.force)&&(writeFileSync(r,JSON.stringify({version:"0.1.0",initialized:new Date().toISOString()},null,2),"utf-8"),t.push(".devflow/config.json"));let i={created:t,pluginDeployed:false,pluginEnabled:false,mcpConfigured:false};if(q.isInitialized(e)||await q.init(e,{index:o.scan!==false}),o.scan!==false)try{let{indexer:s,graph:c}=await createEngines(e),{files:d,symbols:m,imports:f}=await s.indexAll(e),w=await c.build(m,f);i.indexed={files:d.length,symbols:m.length,graphNodes:w.nodes.length};}catch{i.indexed={files:0,symbols:0,graphNodes:0};}if(o.scan!==false)try{let{indexer:s,graph:c}=await createEngines(e),d=q.openSync(e),m=await buildOnboardingPack(e,d,s,c),f=join(n,"onboarding-pack.json");writeFileSync(f,JSON.stringify(m,null,2),"utf-8"),t.push(".devflow/onboarding-pack.json");let w=join(n,"init-report.md");writeFileSync(w,xe(m),"utf-8"),t.push(".devflow/init-report.md"),i.onboardingPack=m;}catch(s){console.warn(`Warning: Onboarding pack generation skipped \u2014 ${s.message}`);}try{let s=we(),c=homedir(),d=join(c,".claude","plugins","cache"),m=join(c,".claude","skills"),f=join(s,"package.json"),w=existsSync(f)?JSON.parse(readFileSync(f,"utf-8")).version:"0.0.0";ve(s,d,w,m),i.pluginDeployed=!0;}catch(s){console.warn(`Warning: Plugin deployment skipped \u2014 ${s.message}`);}try{let s=homedir(),c=join(s,".claude","settings.json");ye(c),i.pluginEnabled=!0;}catch(s){console.warn(`Warning: Plugin enablement skipped \u2014 ${s.message}`);}try{let s;try{s=Go.resolve("@devflow-tools/mcp-server/bin/devflow-mcp.cjs");}catch{s="devflow-mcp";}he(e,s),i.mcpConfigured=!0;}catch(s){console.warn(`Warning: MCP config skipped \u2014 ${s.message}`);}return i}function xe(e){return [`# ${e.projectName} \u2014 DevFlow Onboarding Report`,`Generated: ${e.createdAt}`,"","## Project Stats",`- Files: ${e.stats.files}`,`- Symbols: ${e.stats.symbols}`,`- Graph Nodes: ${e.stats.graphNodes}`,"","## Tech Stack",`- Languages: ${e.stack.languages.join(", ")||"unknown"}`,`- Frameworks: ${e.stack.frameworks.join(", ")||"none detected"}`,`- Build Tools: ${e.stack.buildTools.join(", ")||"none detected"}`,`- Test Tools: ${e.stack.testTools.join(", ")||"none detected"}`,"","## Architecture Layers",...e.architectureLayers.map(n=>`- **${n.name}**: ${n.files} files`),"","## Key Modules",...e.keyModules.slice(0,10).map(n=>`- \`${n.name}\` \u2014 ${n.reason}`),"","## Key Symbols",...e.keySymbols.slice(0,20).map(n=>`- \`${n.name}\` (${n.kind}) in \`${n.file}\``),"","## Recommended Next Steps",...e.recommendedPlugins.map(n=>`- Install plugin: \`${n}\``),...e.recommendedWorkflows.map(n=>`- Run workflow: \`devflow workflow ${n}\``),`- Try: \`devflow context "${e.recommendedQueries[0]??"\u9879\u76EE\u67B6\u6784"}"\``].join(`
3
+ `)}var q,Go,B=de(()=>{Se();q=be.default??be,Go=createRequire(import.meta.url);});function W(e){let o=join(e,".devflow","config.json");if(existsSync(o))try{let n=readFileSync(o,"utf-8");if(JSON.parse(n).serverUrl)return "server"}catch{}return "local"}B();var Vo=fileURLToPath(import.meta.url),zo=dirname(Vo);function $(){let e=[join(process.cwd(),"plugin-registry.json"),join(zo,"../plugin-registry.json"),join(process.cwd(),"packages/devflow/plugin-registry.json")];for(let o of e)try{let n=readFileSync(o,"utf-8");return JSON.parse(n)}catch{continue}return {version:"0.0.0",lastUpdated:new Date().toISOString(),plugins:[]}}function Ce(){try{let e=execSync("npm list -g --depth=0 --json",{encoding:"utf-8"}),o=JSON.parse(e);return Object.keys(o.dependencies||{}).filter(n=>n.startsWith("@devflow-tools/plugin-"))}catch{return []}}function Zo(e){let o=[];try{let n=JSON.parse(readFileSync(join(e,"package.json"),"utf-8")),t={...n.dependencies??{},...n.devDependencies??{}};t.react&&o.push("react"),t.next&&o.push("nextjs"),t.vue&&o.push("vue"),t.tailwindcss&&o.push("tailwind"),(t.nest||t["@nestjs/core"])&&o.push("nest"),t.express&&o.push("express"),t.typescript&&o.push("typescript");}catch{}return o}function en(e){let o=e.trim();return o.startsWith("@devflow-tools/")?o:`@devflow-tools/${o}`}async function Re(e){let o=e.split(",").map(en).filter(Boolean);if(o.length!==0)for(let n of o){console.log(`Installing ${n}...`);try{execSync(`npm install -g ${n}`,{stdio:"inherit"}),console.log(`\u2713 ${n}`);}catch{console.error(`\u2717 Failed to install ${n}`);}}}async function De(e){let o=$();if(o.plugins.length===0)return console.log(`
4
4
  No plugins available. You can install plugins later with:`),console.log(" devflow plugin list"),console.log(` devflow plugin install <name>
5
5
  `),[];console.log(`
6
6
  \u{1F50C} Plugin Installation Guide
7
- `);let n=Sn(e);n.length>0&&console.log(`Detected tech stack: ${n.join(", ")}
8
- `);let t=new Set(o.plugins.filter(s=>s.compatibleStacks.some(a=>n.includes(a))).map(s=>s.name));if(!process.stdout.isTTY){console.log(`Non-interactive terminal detected. Installing recommended plugins...
9
- `);let s=[...t];for(let a of s)try{execSync(`npm install -g ${a}`,{stdio:"inherit"}),console.log(`\u2713 ${a}`);}catch{console.error(`\u2717 Failed to install ${a}`);}return s}let r=o.plugins.map(s=>({name:`${s.name.replace("@devflow-tools/","")} - ${s.description.substring(0,50)}`,value:s.name,checked:t.has(s.name)})),i;try{i=await checkbox({message:"Select plugins to install (space to select, enter to confirm):",choices:r});}catch{return console.log(`
7
+ `);let n=Zo(e);n.length>0&&console.log(`Detected tech stack: ${n.join(", ")}
8
+ `);let t=new Set(o.plugins.filter(s=>s.compatibleStacks.some(c=>n.includes(c))).map(s=>s.name));if(!process.stdout.isTTY){console.log(`Non-interactive terminal detected. Installing recommended plugins...
9
+ `);let s=[...t];for(let c of s)try{execSync(`npm install -g ${c}`,{stdio:"inherit"}),console.log(`\u2713 ${c}`);}catch{console.error(`\u2717 Failed to install ${c}`);}return s}let r=o.plugins.map(s=>({name:`${s.name.replace("@devflow-tools/","")} - ${s.description.substring(0,50)}`,value:s.name,checked:t.has(s.name)})),i;try{i=await checkbox({message:"Select plugins to install (space to select, enter to confirm):",choices:r});}catch{return console.log(`
10
10
  Plugin installation cancelled.
11
11
  `),[]}if(i.length>0){console.log(`
12
12
  Installing selected plugins...
@@ -14,33 +14,25 @@ Installing selected plugins...
14
14
  `);}catch{console.error(`\u2717 Failed to install ${s}
15
15
  `);}}else console.log(`
16
16
  Skipping plugin installation. You can install plugins later with:`),console.log(" devflow plugin list"),console.log(` devflow plugin install <name>
17
- `);return i}async function T(e){let o=[],n;e.sseUrl?n={url:e.sseUrl}:n={command:e.command??"devflow-mcp",args:["--mode","stdio"]};let t=e.agent?[e.agent]:await import('@devflow-tools/adapters').then(r=>r.detectAll());for(let r of t){let i=await connect(r,n);o.push(`${r}: ${i.configPath} (${i.written?"written":"skipped"})`);}return o}function Ue(){return listAdapters()}var Pn=process.env.DEVFLOW_SERVER_URL??"http://localhost:13337",Ge=new Map,Cn=3e4;async function m(e,o,n,t={}){let r=t.serverUrl??Pn;if(t.skipServer)return n();let i=false,s=Ge.get(r);if(s&&Date.now()-s.ts<Cn?i=s.result:(i=await new DevFlowApiClient({baseUrl:r,projectRoot:e}).ping(),Ge.set(r,{result:i,ts:Date.now()})),i){let a=new DevFlowApiClient({baseUrl:r,projectRoot:e});return o(a)}return console.error(l.dim(" (server not running, using local engine \u2014 telemetry disabled)")),n()}async function _e(e){return m(process.cwd(),o=>o.getIndexStatus(),async()=>{let{codegraph:o}=await createEngines(process.cwd()),n=o.getStats();return {totalFiles:n.fileCount,totalSymbols:n.nodeCount,lastIndexTime:n.lastUpdated,indexing:o.isIndexing()}},{skipServer:e})}async function qe(e={}){let o=e.target??"all",n=e.depth??2;return m(process.cwd(),t=>t.getGraph(o,n),async()=>{let{graph:t}=await createEngines(process.cwd());if(o==="all")return t.export();let r=t.getSubGraph(o,n);return {nodes:r.nodes,edges:r.edges}},{skipServer:e.skipServer})}async function Ve(e){return m(process.cwd(),o=>o.buildContext(e.query,e.mode??"fast",e.maxTokens),async()=>{let{context:o}=await createEngines(process.cwd());return o.build({query:e.query,mode:e.mode??"fast",maxTokens:e.maxTokens??8e3})},{skipServer:e.skipServer})}async function ze(e){let o=process.cwd(),n={mode:e.mode??"fast",maxTokens:e.maxTokens??8e3};return m(o,t=>t.buildTaskContext(e.query,o,n),async()=>{let{context:t}=await createEngines(o);return t.buildTaskContext(e.query,n)},{skipServer:e.skipServer})}async function Be(e){return m(process.cwd(),o=>o.listWorkflows(),async()=>{let{workflow:o}=await createEngines(process.cwd());return o.list()},{skipServer:e})}async function He(e,o,n){return m(process.cwd(),t=>t.runWorkflow(e,o),async()=>{let{workflow:t}=await createEngines(process.cwd());return t.run(e,o)},{skipServer:n})}async function Ye(e){return re(e)}async function re(e){return m(process.cwd(),o=>o.getWorkflowRuns(),async()=>{let{workflow:o}=await createEngines(process.cwd());return o.listRuns()},{skipServer:e})}async function Xe(e){return m(process.cwd(),o=>o.getMemory(),async()=>{let{memory:o}=await createEngines(process.cwd());return o.getAll()},{skipServer:e})}async function Qe(e,o,n){return m(process.cwd(),async t=>{await t.setMemory("project",e,o);},async()=>{let{memory:t}=await createEngines(process.cwd());await t.updateUserPreference(e,o);},{skipServer:n})}async function Ze(e){return m(process.cwd(),o=>o.reviewCandidates(),async()=>{let{memory:o}=await createEngines(process.cwd());return o.getCandidates()},{skipServer:e})}async function eo(e,o,n){return m(process.cwd(),t=>t.searchKnowledge(e,o),()=>new KnowledgeEngine({projectRoot:process.cwd()}).search(e,{sources:void 0}),{skipServer:n})}async function ie(e){return m(process.cwd(),async o=>(await o.listPlugins()).map(t=>({name:t.name,version:t.version,description:t.description,icon:t.icon,tags:t.tags??[],installed:true})),async()=>{let o=await loadPlugins();return Array.from(o.values()).map(n=>({name:n.meta.name,version:n.meta.version,description:n.meta.description,icon:n.meta.icon,tags:n.meta.tags,installed:true}))},{skipServer:e})}async function ro(e,o){let n=await ie(o),t=e.toLowerCase();return n.filter(r=>r.name.toLowerCase().includes(t)||r.description.toLowerCase().includes(t)||r.tags.some(i=>i.toLowerCase().includes(t)))}var A=join(process.env.HOME??"~",".devflow","skills");function so(e){let o=join(e,".devflow","config.json");return existsSync(o)?JSON.parse(readFileSync(o,"utf-8")):{plugins:[]}}function io(e,o){let n=join(e,".devflow","config.json");writeFileSync(n,JSON.stringify(o,null,2),"utf-8");}async function lo(e,o=process.cwd(),n){return m(o,async t=>await t.installPlugin(e),async()=>{let t=e.startsWith("@devflow-tools/plugin-")?e:`@devflow-tools/plugin-${e}`,r=e.replace(/^@devflow-tools\/plugin-/,"");mkdirSync(A,{recursive:true});try{execSync(`npm install --prefix "${A}" ${t}`,{stdio:"pipe",timeout:6e4});}catch{}let i=so(o);i.plugins||(i.plugins=[]),i.plugins.includes(r)||(i.plugins.push(r),io(o,i));let s=[];try{s=JSON.parse(readFileSync(join(A,"node_modules",t,"package.json"),"utf-8"))?.devflow?.templates??[];}catch{}return {name:r,version:"0.1.0",templates:s}},{skipServer:n})}async function ao(e,o=process.cwd(),n){return m(o,async t=>{await t.uninstallPlugin(e);},async()=>{let t=e.replace(/^@devflow-tools\/plugin-/,""),r=so(o);r.plugins&&(r.plugins=r.plugins.filter(s=>s!==t),io(o,r));let i=e.startsWith("@devflow-tools/plugin-")?e:`@devflow-tools/plugin-${e}`;try{let s=join(A,"node_modules",i);existsSync(s)&&rmSync(s,{recursive:!0,force:!0});}catch{}},{skipServer:n})}var go=createRequire(import.meta.url);function ce(e){let o=join(e,".devflow");return existsSync(o)||mkdirSync(o,{recursive:true}),join(o,"server.pid")}function Ln(){try{return go.resolve("./server.js")}catch{try{return go.resolve("@devflow-tools/server/dist/main.js")}catch{return join(process.cwd(),"apps","server","dist","main.js")}}}var de=13337;function ge(e){if(!existsSync(e))return null;let o=readFileSync(e,"utf-8").trim().split(`
18
- `);if(o.length>=2){let n=parseInt(o[0],10);if(!isNaN(n))return n}return null}function x(e){if(!existsSync(e))return null;let o=readFileSync(e,"utf-8").trim().split(`
19
- `),n=o.length>=2?o[1]:o[0],t=parseInt(n,10);return isNaN(t)?null:t}async function M(e){let o=Ln(),n=ce(process.cwd()),t=spawn("node",[o],{env:{...process.env,PORT:String(e.port)},stdio:"ignore",detached:true});return writeFileSync(n,`${e.port}
20
- ${t.pid??0}`),t.unref(),{pid:t.pid??0}}async function R(){let e=ce(process.cwd()),o=x(e);if(o===null)return false;try{return process.kill(o),unlinkSync(e),!0}catch{return unlinkSync(e),false}}async function F(){let e=ce(process.cwd()),o=ge(e)??de,{DevFlowApiClient:n}=await import('@devflow-tools/sdk');return await new n({baseUrl:`http://localhost:${o}`,projectRoot:process.cwd()}).ping()?{running:true,pid:x(e)??void 0,port:o}:{running:false,port:o}}async function mo(){let{codegraph:e,graph:o,memory:n,knowledge:t,workflow:r,data:i}=await createEngines(process.cwd()),s=e.getStats(),a=o.export(),d=0;try{d=(await r.list()).length;}catch{}let u=false,p=0;try{let E=await n.getAll();u=!!E?.project;let Ho=E?.user??{};p=Object.keys(Ho).length;}catch{}let w=0;try{w=(await t.getSources()).length;}catch{}let V={total:0,byTool:{}};try{V=await i.getToolCallStats();}catch{}let Se=await F(),b=0;return s.fileCount>0&&(b+=25),s.nodeCount>0&&(b+=15),a.nodes.length>0&&(b+=20),u&&(b+=15),w>0&&(b+=10),d>0&&(b+=5),Se.running&&(b+=10),V.total>0&&(b+=5),{index:{totalFiles:s.fileCount,totalSymbols:s.nodeCount,indexing:e.isIndexing()},graph:{nodes:a.nodes.length,edges:a.edges.length},memory:{projectReady:u,userPrefs:p},knowledge:{sources:w},plugins:{installed:0,names:[]},workflows:{registered:d},server:{running:Se.running},toolCalls:V,readyScore:b}}async function fo(){let{data:e}=await createEngines(process.cwd()),o=await e.auditGetSecret(),n=await e.auditGetAll(),t=createHash("sha256").update("genesis").digest("hex");for(let r of n){if(r.prevHash!==t)return {valid:false,brokenAt:r.seq,entryCount:n.length};let i=`${r.seq}|${r.ts}|${r.tool}|${r.argsHash}|${r.decision}|${r.ruleId??""}|${r.sessionId}|${t}`,s=createHmac("sha256",o).update(i).digest("hex");if(r.signature!==s)return {valid:false,brokenAt:r.seq,entryCount:n.length};t=r.signature;}return {valid:true,brokenAt:null,entryCount:n.length}}async function wo(){let{data:e}=await createEngines(process.cwd()),o=await e.auditGetSecret(),n=await e.auditGetAll(),t=createHash("sha256").update("genesis").digest("hex");for(let r of n){let i=`${r.seq}|${r.ts}|${r.tool}|${r.argsHash}|${r.decision}|${r.ruleId??""}|${r.sessionId}|${t}`,s=createHmac("sha256",o).update(i).digest("hex");await e.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[t,s,r.seq]),t=s;}return {rebuilt:true}}async function ho(e){let{data:o}=await createEngines(process.cwd()),t=(await o.auditGetAll()).filter(r=>r.decision!=="allow");if(e){let r=e.match(/^(\d+)([dh])$/);if(r){let i=parseInt(r[1],10),a=r[2]==="d"?i*864e5:i*36e5,d=Date.now()-a;t=t.filter(u=>u.ts>d);}}return {violations:t.map(r=>({tool:r.tool,decision:r.decision,ruleId:r.ruleId,ts:r.ts,sessionId:r.sessionId}))}}function yo(){let e=`${process.env.TMPDIR??"/tmp"}/.devflow-receipts`,o=createHash("sha256").update(process.cwd()).digest("hex").slice(0,16),n=`${e}/${o}.json`;try{let t=readFileSync(n,"utf-8");return {sessionId:o,data:JSON.parse(t)}}catch{return {sessionId:o,data:null}}}async function vo(e,o=3600){let n=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),t=Math.floor(Date.now()/1e3),r={sub:`devflow-session-${Date.now().toString(36)}`,project:e.split("/").pop()??"unknown",iat:t,exp:t+o,scope:["context","knowledge","memory","workflow","graph"]},i=Buffer.from(JSON.stringify(r)).toString("base64url"),a=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${n}.${i}`).digest("base64url");return {token:`${n}.${i}.${a}`,expiresAt:r.exp,scope:r.scope}}async function So(e,o){let t=new BenchmarkEngine().getTasks();return [l.blue("\u25C9 DevFlow Benchmark"),"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",`Available tasks: ${t.length}`,"","Benchmark requires a real runner implementation.","No fake data or estimated scores are shown.","","Setup: devflow benchmark --runner <path-to-runner>"].join(`
21
- `)}async function ko(e){let o,n;if(e.prUrl){let p=e.prUrl.match(/pull\/(\d+)/);n=`PR: ${p?`#${p[1]}`:e.prUrl}`;try{o=execSync(`gh pr diff ${e.prUrl}`,{encoding:"utf-8",maxBuffer:10*1024*1024});}catch{o=`Could not fetch PR diff from ${e.prUrl}. Ensure 'gh' CLI is installed and authenticated.`;}}else {n="Current branch vs main";try{o=execSync("git diff main...HEAD",{encoding:"utf-8",maxBuffer:10*1024*1024});}catch{o="Could not compute diff. Ensure you're on a feature branch.";}}let t=(o.match(/^diff --git/gm)??[]).length,r=(o.match(/^\+[^+]/gm)??[]).length,i=(o.match(/^-[^-]/gm)??[]).length,s=[],a=[],d=[];return o.includes("console.log")&&a.push("Contains console.log statements \u2014 remove before merge"),(o.includes(".only(")||o.includes("it.only"))&&s.push("Contains .only() test filters \u2014 remove before merge"),(o.includes("TODO")||o.includes("FIXME"))&&a.push("Contains TODO/FIXME comments \u2014 track or resolve"),(o.match(/^\+.*TODO/gm)||o.match(/^\+.*FIXME/gm))&&a.push("New code introduces TODO/FIXME comments"),o.includes("process.exit")&&a.push("Contains process.exit() \u2014 consider throwing instead"),o.includes(": any")&&o.match(/^\+.*: any/gm)&&d.push("New code uses `any` type \u2014 use explicit types instead"),[l.blue("\u25C9 Code Review"),"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",n,`Files changed: ${t}`,`+${r} / -${i}`,"",s.length>0?l.red(`Critical (${s.length})`):"",...s.map(p=>` ${l.red("\u25CF")} ${p}`),"",a.length>0?l.yellow(`Warning (${a.length})`):"",...a.map(p=>` ${l.yellow("\u25CB")} ${p}`),"",d.length>0?l.green(`Suggestion (${d.length})`):"",...d.map(p=>` ${l.green("\u25CB")} ${p}`),"",s.length>0?l.red("Overall: Need changes"):a.length>0?l.yellow("Overall: Approve with comments"):l.green("Overall: LGTM")].join(`
22
- `)}var pe=createRequire(import.meta.url);function me(e){return join(e,".devflow","dashboard")}function Do(e){return join(me(e),"version.txt")}function Ro(){try{return pe("../package.json").version??"0.0.0"}catch{return "0.0.0"}}function Kn(){try{let e=pe.resolve("@devflow-tools/devflow/package.json"),o=join(dirname(e),"dist","dashboard-standalone.tar.gz");if(existsSync(o))return o}catch{}return null}function Vn(e){let o=Do(e);if(!existsSync(o))return false;try{return readFileSync(o,"utf-8").trim()===Ro()&&existsSync(join(me(e),"apps","dashboard","server.js"))}catch{return false}}function U(e){let o=me(e),n=Do(e),t=Ro();if(Vn(e))return o;existsSync(o)&&rmSync(o,{recursive:true,force:true}),mkdirSync(o,{recursive:true});let r=Kn();if(r)return execSync(`tar -xzf "${r}" -C "${o}"`,{stdio:"pipe"}),writeFileSync(n,t),o;try{let i=pe.resolve("@devflow-tools/devflow/package.json"),s=join(dirname(i),"..",".."),a=join(s,"apps","dashboard",".next","standalone"),d=join(s,"apps","dashboard",".next","static"),u=join(s,"apps","dashboard","public"),p=join(a,"apps","dashboard","server.js");if(!existsSync(p))throw new Error(`Dashboard build not found.
23
- Expected: ${p}
24
- Run: npm run build:dist (requires Node >= 18)
25
- Or install from npm: npm install @devflow-tools/devflow@${t}`);if(execSync(`cp -r "${a}/"* "${o}/"`,{stdio:"pipe"}),existsSync(d)){let w=join(o,"apps","dashboard",".next");mkdirSync(w,{recursive:!0}),execSync(`cp -r "${d}" "${w}/"`,{stdio:"pipe"});}return existsSync(u)&&execSync(`cp -r "${u}" "${o}/"`,{stdio:"pipe"}),writeFileSync(n,t),o}catch(i){throw existsSync(o)&&rmSync(o,{recursive:true,force:true}),i}}function C(){return join(process.cwd(),".devflow","dashboard.pid")}async function Qn(e,o=15e3){let n=Date.now();for(;Date.now()-n<o;){try{if((await fetch(`http://localhost:${e}/api/health`)).ok)return !0}catch{}await new Promise(t=>setTimeout(t,500));}return false}async function Oo(e){let o=C();if(existsSync(o)){try{let r=x(o);if(r!==null)try{process.kill(r);}catch{}}catch{}try{unlinkSync(o);}catch{}}console.log(l.blue("Starting DevFlow server..."));let{pid:n}=await M({port:e.port});console.log(l.green(` Server started (PID: ${n})`)),console.log(l.blue(" Waiting for server..."));let t=await Qn(e.port);if(console.log(t?l.green(" Server ready"):l.yellow(" Server started but health check timed out")),!e.noDashboard){console.log(l.blue("Preparing Dashboard..."));try{let r=U(process.cwd()),i=join(r,"apps","dashboard","server.js"),s=spawn("node",[i],{env:{...process.env,PORT:String(e.dashboardPort)},cwd:r,stdio:"ignore",detached:!0});if(s.pid){let a=C(),d=join(process.cwd(),".devflow");existsSync(d)||mkdirSync(d,{recursive:!0}),writeFileSync(a,`${e.dashboardPort}
26
- ${s.pid}`),s.unref(),console.log(l.green(` Dashboard started (PID: ${s.pid})`));}}catch{console.log(l.red(" Dashboard failed to start")),console.log(l.yellow(` You can still use the API at http://localhost:${e.port}`));}}console.log(""),console.log(l.green("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),console.log(l.green("\u2551")+" \u{1F680} DevFlow Started! "+l.green("\u2551")),console.log(l.green("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563")),console.log(l.green("\u2551")+` \u{1F5A5}\uFE0F Server: http://localhost:${e.port}`.padEnd(57)+l.green("\u2551")),console.log(l.green("\u2551")+` \u{1F3A8} Dashboard: http://localhost:${e.dashboardPort}`.padEnd(57)+l.green("\u2551")),console.log(l.green("\u2551")+" "+l.green("\u2551")),console.log(l.green("\u2551")+" Press Ctrl+C to stop all services "+l.green("\u2551")),console.log(l.green("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.background||await new Promise(r=>{let i=false,s=async()=>{if(i)return;i=true,console.log(l.blue(`
27
- Shutting down...`));let a=C();if(existsSync(a))try{let d=readFileSync(a,"utf-8").trim().split(`
28
- `),u=d.length>=2?d[1]:d[0],p=parseInt(u,10);process.kill(p),unlinkSync(a);}catch{}await R(),console.log(l.green("All services stopped.")),r();};process.on("SIGINT",s),process.on("SIGTERM",s);});}async function Eo(){let e=false,o=C();if(existsSync(o))try{let t=x(o);t!==null&&(process.kill(t),console.log(l.green(`Dashboard stopped (PID: ${t})`))),unlinkSync(o),e=!0;}catch{unlinkSync(o),console.log(l.yellow("Dashboard process not found, cleaned up PID file"));}await R()&&(console.log(l.green("Server stopped")),e=true),e||console.log(l.dim("No DevFlow services running"));}function nt(){return join(process.cwd(),".devflow","devflow.db")}async function To(){console.log(l.blue("DevFlow Status")),console.log(l.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));let e=await F(),o=e.port??de;e.running?console.log(`Server: ${l.green("\u2713")} running (port ${o}${e.pid?`, PID ${e.pid}`:""})`):console.log(`Server: ${l.yellow("\u25CB")} not running`);let n=C();if(existsSync(n)){let r=ge(n),i=x(n);if(i!==null)try{process.kill(i,0);let s=r!==null?`port ${r}`:"port 17788";console.log(`Dashboard: ${l.green("\u2713")} running (${s}, PID ${i})`);}catch{console.log(`Dashboard: ${l.red("\u2717")} PID ${i} not found (stale PID file)`);}else console.log(`Dashboard: ${l.yellow("\u25CB")} not running (unreadable PID file)`);}else console.log(`Dashboard: ${l.yellow("\u25CB")} not running`);let t=nt();if(existsSync(t)){let i=(statSync(t).size/1024/1024).toFixed(1);console.log(`Data: .devflow/devflow.db (${i} MB)`);}else console.log(`Data: ${l.dim("no database")}`);}var ct=createRequire(import.meta.url);function dt(){let e=[resolve(dirname(ct.resolve("../../package.json")),"dist","plugin"),resolve(process.cwd(),"plugins","claude-code")];for(let o of e)if(existsSync(join(o,".claude-plugin","plugin.json")))return o;return null}function gt(e,o){let n={};if(existsSync(e))try{n=JSON.parse(readFileSync(e,"utf-8"));}catch{n={};}let t={...n,...o};writeFileSync(e,JSON.stringify(t,null,2));}async function Lo(e){if(console.log(l.blue("DevFlow Setup")),console.log(l.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!e.skipMcp)try{let o=await T({agent:e.agent,command:"devflow-mcp"});for(let n of o)console.log(l.green(` \u2713 MCP: ${n}`));}catch(o){console.log(l.yellow(` \u26A0 MCP setup failed: ${o.message}`)),console.log(l.dim(" You can configure MCP manually with: devflow connect"));}if(!e.skipPlugin){let o=dt();if(o){let n=join(homedir(),".claude","plugins");mkdirSync(n,{recursive:true});let t=join(n,"known_marketplaces.json");gt(t,{devflow:{source:{directory:o}}}),console.log(l.green(` \u2713 Plugin registered: ${o}`));}else console.log(l.yellow(" \u26A0 Plugin directory not found")),console.log(l.dim(" The Claude Code plugin may not be available."));}console.log(""),console.log(l.green("Setup complete!")),console.log(l.dim("Restart Claude Code to use /devflow:* commands"));}var Wo=new Command("list").description("List available plugins").option("-i, --installed","Show only installed plugins").action(async e=>{let o=D();if(e.installed){let n=Me();if(n.length===0){console.log("No plugins installed."),console.log(`
17
+ `);return i}async function O(e){let o=[],n;e.sseUrl?n={url:e.sseUrl}:n={command:e.command??"devflow-mcp",args:["--mode","stdio"]};let t=e.agent?[e.agent]:await import('@devflow-tools/adapters').then(r=>r.detectAll());for(let r of t){let i=await connect(r,n);o.push(`${r}: ${i.configPath} (${i.written?"written":"skipped"})`);}return o}function Ie(){return listAdapters()}var rn=process.env.DEVFLOW_SERVER_URL??"http://localhost:13337",je=new Map,sn=3e4;async function g(e,o,n,t={}){let r=t.serverUrl??rn;if(t.skipServer)return n();let i=false,s=je.get(r);if(s&&Date.now()-s.ts<sn?i=s.result:(i=await new DevFlowApiClient({baseUrl:r,projectRoot:e}).ping(),je.set(r,{result:i,ts:Date.now()})),i){let c=new DevFlowApiClient({baseUrl:r,projectRoot:e});return o(c)}return console.error(l.dim(" (server not running, using local engine \u2014 telemetry disabled)")),n()}async function Fe(e){return g(process.cwd(),o=>o.getIndexStatus(),async()=>{let{codegraph:o}=await createEngines(process.cwd()),n=o.getStats();return {totalFiles:n.fileCount,totalSymbols:n.nodeCount,lastIndexTime:n.lastUpdated,indexing:o.isIndexing()}},{skipServer:e})}async function Ne(e={}){let o=e.target??"all",n=e.depth??2;return g(process.cwd(),t=>t.getGraph(o,n),async()=>{let{graph:t}=await createEngines(process.cwd());if(o==="all")return t.export();let r=t.getSubGraph(o,n);return {nodes:r.nodes,edges:r.edges}},{skipServer:e.skipServer})}async function Te(e){return g(process.cwd(),o=>o.buildContext(e.query,e.mode??"fast",e.maxTokens),async()=>{let{context:o}=await createEngines(process.cwd());return o.build({query:e.query,mode:e.mode??"fast",maxTokens:e.maxTokens??8e3})},{skipServer:e.skipServer})}async function Ae(e){let o=process.cwd(),n={mode:e.mode??"fast",maxTokens:e.maxTokens??8e3};return g(o,t=>t.buildTaskContext(e.query,o,n),async()=>{let{context:t}=await createEngines(o);return t.buildTaskContext(e.query,n)},{skipServer:e.skipServer})}async function Me(e){return g(process.cwd(),o=>o.listWorkflows(),async()=>{let{workflow:o}=await createEngines(process.cwd());return o.list()},{skipServer:e})}async function Le(e,o,n){return g(process.cwd(),t=>t.runWorkflow(e,o),async()=>{let{workflow:t}=await createEngines(process.cwd());return t.run(e,o)},{skipServer:n})}async function We(e){return Y(e)}async function Y(e){return g(process.cwd(),o=>o.getWorkflowRuns(),async()=>{let{workflow:o}=await createEngines(process.cwd());return o.listRuns()},{skipServer:e})}async function Ue(e){return g(process.cwd(),o=>o.getMemory(),async()=>{let{memory:o}=await createEngines(process.cwd());return o.getAll()},{skipServer:e})}async function Je(e,o,n){return g(process.cwd(),async t=>{await t.setMemory("project",e,o);},async()=>{let{memory:t}=await createEngines(process.cwd());await t.updateUserPreference(e,o);},{skipServer:n})}async function _e(e){return g(process.cwd(),o=>o.reviewCandidates(),async()=>{let{memory:o}=await createEngines(process.cwd());return o.getCandidates()},{skipServer:e})}async function Ge(e,o,n){return g(process.cwd(),t=>t.searchKnowledge(e,o),()=>new KnowledgeEngine({projectRoot:process.cwd()}).search(e,{sources:void 0}),{skipServer:n})}async function Q(e){return g(process.cwd(),async o=>(await o.listPlugins()).map(t=>({name:t.name,version:t.version,description:t.description,icon:t.icon,tags:t.tags??[],installed:true})),async()=>{let o=await loadPlugins();return Array.from(o.values()).map(n=>({name:n.meta.name,version:n.meta.version,description:n.meta.description,icon:n.meta.icon,tags:n.meta.tags,installed:true}))},{skipServer:e})}async function He(e,o){let n=await Q(o),t=e.toLowerCase();return n.filter(r=>r.name.toLowerCase().includes(t)||r.description.toLowerCase().includes(t)||r.tags.some(i=>i.toLowerCase().includes(t)))}var j=join(process.env.HOME??"~",".devflow","skills");function Ve(e){let o=join(e,".devflow","config.json");return existsSync(o)?JSON.parse(readFileSync(o,"utf-8")):{plugins:[]}}function ze(e,o){let n=join(e,".devflow","config.json");writeFileSync(n,JSON.stringify(o,null,2),"utf-8");}async function Ye(e,o=process.cwd(),n){return g(o,async t=>await t.installPlugin(e),async()=>{let t=e.startsWith("@devflow-tools/plugin-")?e:`@devflow-tools/plugin-${e}`,r=e.replace(/^@devflow-tools\/plugin-/,"");mkdirSync(j,{recursive:true});try{execSync(`npm install --prefix "${j}" ${t}`,{stdio:"pipe",timeout:6e4});}catch{}let i=Ve(o);i.plugins||(i.plugins=[]),i.plugins.includes(r)||(i.plugins.push(r),ze(o,i));let s=[];try{s=JSON.parse(readFileSync(join(j,"node_modules",t,"package.json"),"utf-8"))?.devflow?.templates??[];}catch{}return {name:r,version:"0.1.0",templates:s}},{skipServer:n})}async function Xe(e,o=process.cwd(),n){return g(o,async t=>{await t.uninstallPlugin(e);},async()=>{let t=e.replace(/^@devflow-tools\/plugin-/,""),r=Ve(o);r.plugins&&(r.plugins=r.plugins.filter(s=>s!==t),ze(o,r));let i=e.startsWith("@devflow-tools/plugin-")?e:`@devflow-tools/plugin-${e}`;try{let s=join(j,"node_modules",i);existsSync(s)&&rmSync(s,{recursive:!0,force:!0});}catch{}},{skipServer:n})}var Ze=createRequire(import.meta.url);function oe(e){let o=join(e,".devflow");return existsSync(o)||mkdirSync(o,{recursive:true}),join(o,"server.pid")}function hn(){try{return Ze.resolve("./server.js")}catch{try{return Ze.resolve("@devflow-tools/server/dist/main.js")}catch{return join(process.cwd(),"apps","server","dist","main.js")}}}var ne=13337;function vn(e){if(!existsSync(e))return null;let o=readFileSync(e,"utf-8").trim().split(`
18
+ `);if(o.length>=2){let n=parseInt(o[0],10);if(!isNaN(n))return n}return null}function oo(e){if(!existsSync(e))return null;let o=readFileSync(e,"utf-8").trim().split(`
19
+ `),n=o.length>=2?o[1]:o[0],t=parseInt(n,10);return isNaN(t)?null:t}async function F(e){let o=hn(),n=oe(process.cwd()),t=spawn("node",[o],{env:{...process.env,PORT:String(e.port)},stdio:"ignore",detached:true});return writeFileSync(n,`${e.port}
20
+ ${t.pid??0}`),t.unref(),{pid:t.pid??0}}async function x(){let e=oe(process.cwd()),o=oo(e);if(o===null)return false;try{return process.kill(o),unlinkSync(e),!0}catch{return unlinkSync(e),false}}async function P(){let e=oe(process.cwd()),o=vn(e)??ne,{DevFlowApiClient:n}=await import('@devflow-tools/sdk');return await new n({baseUrl:`http://localhost:${o}`,projectRoot:process.cwd()}).ping()?{running:true,pid:oo(e)??void 0,port:o}:{running:false,port:o}}async function to(){let{codegraph:e,graph:o,memory:n,knowledge:t,workflow:r,data:i}=await createEngines(process.cwd()),s=e.getStats(),c=o.export(),d=0;try{d=(await r.list()).length;}catch{}let m=false,f=0;try{let D=await n.getAll();m=!!D?.project;let Io=D?.user??{};f=Object.keys(Io).length;}catch{}let w=0;try{w=(await t.getSources()).length;}catch{}let L={total:0,byTool:{}};try{L=await i.getToolCallStats();}catch{}let ce=await P(),S=0;return s.fileCount>0&&(S+=25),s.nodeCount>0&&(S+=15),c.nodes.length>0&&(S+=20),m&&(S+=15),w>0&&(S+=10),d>0&&(S+=5),ce.running&&(S+=10),L.total>0&&(S+=5),{index:{totalFiles:s.fileCount,totalSymbols:s.nodeCount,indexing:e.isIndexing()},graph:{nodes:c.nodes.length,edges:c.edges.length},memory:{projectReady:m,userPrefs:f},knowledge:{sources:w},plugins:{installed:0,names:[]},workflows:{registered:d},server:{running:ce.running},toolCalls:L,readyScore:S}}async function ro(){let{data:e}=await createEngines(process.cwd()),o=await e.auditGetSecret(),n=await e.auditGetAll(),t=createHash("sha256").update("genesis").digest("hex");for(let r of n){if(r.prevHash!==t)return {valid:false,brokenAt:r.seq,entryCount:n.length};let i=`${r.seq}|${r.ts}|${r.tool}|${r.argsHash}|${r.decision}|${r.ruleId??""}|${r.sessionId}|${t}`,s=createHmac("sha256",o).update(i).digest("hex");if(r.signature!==s)return {valid:false,brokenAt:r.seq,entryCount:n.length};t=r.signature;}return {valid:true,brokenAt:null,entryCount:n.length}}async function so(){let{data:e}=await createEngines(process.cwd()),o=await e.auditGetSecret(),n=await e.auditGetAll(),t=createHash("sha256").update("genesis").digest("hex");for(let r of n){let i=`${r.seq}|${r.ts}|${r.tool}|${r.argsHash}|${r.decision}|${r.ruleId??""}|${r.sessionId}|${t}`,s=createHmac("sha256",o).update(i).digest("hex");await e.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[t,s,r.seq]),t=s;}return {rebuilt:true}}async function io(e){let{data:o}=await createEngines(process.cwd()),t=(await o.auditGetAll()).filter(r=>r.decision!=="allow");if(e){let r=e.match(/^(\d+)([dh])$/);if(r){let i=parseInt(r[1],10),c=r[2]==="d"?i*864e5:i*36e5,d=Date.now()-c;t=t.filter(m=>m.ts>d);}}return {violations:t.map(r=>({tool:r.tool,decision:r.decision,ruleId:r.ruleId,ts:r.ts,sessionId:r.sessionId}))}}function lo(){let e=`${process.env.TMPDIR??"/tmp"}/.devflow-receipts`,o=createHash("sha256").update(process.cwd()).digest("hex").slice(0,16),n=`${e}/${o}.json`;try{let t=readFileSync(n,"utf-8");return {sessionId:o,data:JSON.parse(t)}}catch{return {sessionId:o,data:null}}}async function ao(e,o=3600){let n=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),t=Math.floor(Date.now()/1e3),r={sub:`devflow-session-${Date.now().toString(36)}`,project:e.split("/").pop()??"unknown",iat:t,exp:t+o,scope:["context","knowledge","memory","workflow","graph"]},i=Buffer.from(JSON.stringify(r)).toString("base64url"),c=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${n}.${i}`).digest("base64url");return {token:`${n}.${i}.${c}`,expiresAt:r.exp,scope:r.scope}}async function co(e,o){let t=new BenchmarkEngine().getTasks();return [l.blue("\u25C9 DevFlow Benchmark"),"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",`Available tasks: ${t.length}`,"","Benchmark requires a real runner implementation.","No fake data or estimated scores are shown.","","Setup: devflow benchmark --runner <path-to-runner>"].join(`
21
+ `)}async function uo(e){let o,n;if(e.prUrl){let f=e.prUrl.match(/pull\/(\d+)/);n=`PR: ${f?`#${f[1]}`:e.prUrl}`;try{o=execSync(`gh pr diff ${e.prUrl}`,{encoding:"utf-8",maxBuffer:10*1024*1024});}catch{o=`Could not fetch PR diff from ${e.prUrl}. Ensure 'gh' CLI is installed and authenticated.`;}}else {n="Current branch vs main";try{o=execSync("git diff main...HEAD",{encoding:"utf-8",maxBuffer:10*1024*1024});}catch{o="Could not compute diff. Ensure you're on a feature branch.";}}let t=(o.match(/^diff --git/gm)??[]).length,r=(o.match(/^\+[^+]/gm)??[]).length,i=(o.match(/^-[^-]/gm)??[]).length,s=[],c=[],d=[];return o.includes("console.log")&&c.push("Contains console.log statements \u2014 remove before merge"),(o.includes(".only(")||o.includes("it.only"))&&s.push("Contains .only() test filters \u2014 remove before merge"),(o.includes("TODO")||o.includes("FIXME"))&&c.push("Contains TODO/FIXME comments \u2014 track or resolve"),(o.match(/^\+.*TODO/gm)||o.match(/^\+.*FIXME/gm))&&c.push("New code introduces TODO/FIXME comments"),o.includes("process.exit")&&c.push("Contains process.exit() \u2014 consider throwing instead"),o.includes(": any")&&o.match(/^\+.*: any/gm)&&d.push("New code uses `any` type \u2014 use explicit types instead"),[l.blue("\u25C9 Code Review"),"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",n,`Files changed: ${t}`,`+${r} / -${i}`,"",s.length>0?l.red(`Critical (${s.length})`):"",...s.map(f=>` ${l.red("\u25CF")} ${f}`),"",c.length>0?l.yellow(`Warning (${c.length})`):"",...c.map(f=>` ${l.yellow("\u25CB")} ${f}`),"",d.length>0?l.green(`Suggestion (${d.length})`):"",...d.map(f=>` ${l.green("\u25CB")} ${f}`),"",s.length>0?l.red("Overall: Need changes"):c.length>0?l.yellow("Overall: Approve with comments"):l.green("Overall: LGTM")].join(`
22
+ `)}async function xn(e,o=15e3){let n=Date.now();for(;Date.now()-n<o;){try{if((await fetch(`http://localhost:${e}/api/health`)).ok)return !0}catch{}await new Promise(t=>setTimeout(t,500));}return false}async function po(e){console.log(l.blue("Starting DevFlow server..."));let{pid:o}=await F({port:e.port});console.log(l.green(` Server started (PID: ${o})`)),console.log(l.blue(" Waiting for server..."));let n=await xn(e.port);console.log(n?l.green(" Server ready"):l.yellow(" Server started but health check timed out")),console.log(""),console.log(l.green("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")),console.log(l.green("\u2551")+" DevFlow Started! "+l.green("\u2551")),console.log(l.green("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563")),console.log(l.green("\u2551")+` Server + Dashboard: http://localhost:${e.port}`.padEnd(57)+l.green("\u2551")),console.log(l.green("\u2551")+` API: http://localhost:${e.port}/api`.padEnd(57)+l.green("\u2551")),console.log(l.green("\u2551")+" "+l.green("\u2551")),console.log(l.green("\u2551")+" Press Ctrl+C to stop "+l.green("\u2551")),console.log(l.green("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),e.background||await new Promise(t=>{let r=false,i=async()=>{r||(r=true,console.log(l.blue(`
23
+ Shutting down...`)),await x(),console.log(l.green("Server stopped.")),t());};process.on("SIGINT",i),process.on("SIGTERM",i);});}async function fo(){let e=await x();console.log(e?l.green("Server stopped"):l.dim("No DevFlow services running"));}function Dn(){return join(process.cwd(),".devflow","devflow.db")}async function wo(){console.log(l.blue("DevFlow Status")),console.log(l.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));let e=await P(),o=e.port??ne;e.running?(console.log(`Server: ${l.green("\u2713")} running (port ${o}${e.pid?`, PID ${e.pid}`:""})`),console.log(`Dashboard: ${l.green("\u2713")} served at http://localhost:${o}`)):(console.log(`Server: ${l.yellow("\u25CB")} not running`),console.log(`Dashboard: ${l.yellow("\u25CB")} not running`));let n=Dn();if(existsSync(n)){let r=(statSync(n).size/1024/1024).toFixed(1);console.log(`Data: .devflow/devflow.db (${r} MB)`);}else console.log(`Data: ${l.dim("no database")}`);}var Tn=createRequire(import.meta.url);function An(){let e=[resolve(dirname(Tn.resolve("../../package.json")),"dist","plugin"),resolve(process.cwd(),"plugins","claude-code")];for(let o of e)if(existsSync(join(o,".claude-plugin","plugin.json")))return o;return null}function Mn(e,o){let n={};if(existsSync(e))try{n=JSON.parse(readFileSync(e,"utf-8"));}catch{n={};}let t={...n,...o};writeFileSync(e,JSON.stringify(t,null,2));}async function vo(e){if(console.log(l.blue("DevFlow Setup")),console.log(l.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!e.skipMcp)try{let o=await O({agent:e.agent,command:"devflow-mcp"});for(let n of o)console.log(l.green(` \u2713 MCP: ${n}`));}catch(o){console.log(l.yellow(` \u26A0 MCP setup failed: ${o.message}`)),console.log(l.dim(" You can configure MCP manually with: devflow connect"));}if(!e.skipPlugin){let o=An();if(o){let n=join(homedir(),".claude","plugins");mkdirSync(n,{recursive:true});let t=join(n,"known_marketplaces.json");Mn(t,{devflow:{source:{directory:o}}}),console.log(l.green(` \u2713 Plugin registered: ${o}`));}else console.log(l.yellow(" \u26A0 Plugin directory not found")),console.log(l.dim(" The Claude Code plugin may not be available."));}console.log(""),console.log(l.green("Setup complete!")),console.log(l.dim("Restart Claude Code to use /devflow:* commands"));}var So=new Command("list").description("List available plugins").option("-i, --installed","Show only installed plugins").action(async e=>{let o=$();if(e.installed){let n=Ce();if(n.length===0){console.log("No plugins installed."),console.log(`
29
24
  Run "devflow plugin list" to see available plugins.`);return}console.log(`Installed plugins:
30
25
  `),n.forEach(t=>{let r=o.plugins.find(i=>i.name===t);r?(console.log(` ${l.green(r.name)}@${r.version}`),console.log(` ${r.description}`)):console.log(` ${l.green(t)}`);});}else {if(o.plugins.length===0){console.log("No plugins available.");return}console.log(`Available plugins (${o.plugins.length}):
31
26
  `);let n=Math.max(...o.plugins.map(t=>t.name.length));o.plugins.forEach(t=>{let r=" ".repeat(n-t.name.length+2);console.log(` ${l.green(t.name)}${r}v${t.version}`),console.log(` ${" ".repeat(n)}${t.description.substring(0,60)}`),t.tags.length>0&&console.log(` ${" ".repeat(n)}Tags: ${t.tags.join(", ")}`),console.log("");}),console.log(`
32
- Install a plugin: devflow plugin install <name>`);}});var Uo=new Command("search").description("Search for plugins").argument("<keyword>","Search keyword").action(async e=>{let o=D(),n=e.toLowerCase(),t=o.plugins.filter(r=>r.name.toLowerCase().includes(n)||r.description.toLowerCase().includes(n)||r.tags.some(i=>i.toLowerCase().includes(n)));if(t.length===0){console.log(`No plugins found matching "${e}"`),console.log(`
27
+ Install a plugin: devflow plugin install <name>`);}});var ko=new Command("search").description("Search for plugins").argument("<keyword>","Search keyword").action(async e=>{let o=$(),n=e.toLowerCase(),t=o.plugins.filter(r=>r.name.toLowerCase().includes(n)||r.description.toLowerCase().includes(n)||r.tags.some(i=>i.toLowerCase().includes(n)));if(t.length===0){console.log(`No plugins found matching "${e}"`),console.log(`
33
28
  Try: devflow plugin list`);return}console.log(`Found ${t.length} plugin(s) matching "${e}":
34
- `),t.forEach(r=>{console.log(` ${l.green(r.name)}@${r.version}`),console.log(` ${r.description}`),r.tags.length>0&&console.log(` Tags: ${r.tags.join(", ")}`),console.log(` Size: ${r.size}`),console.log("");});});var Go=new Command("install").description("Install a plugin").argument("<name>","Plugin name (with or without @devflow-tools/ prefix)").action(async e=>{let o=e.startsWith("@devflow-tools/")?e:`@devflow-tools/${e}`;console.log(`Installing ${o}...`);try{execSync(`npm install -g ${o}`,{stdio:"inherit"}),console.log(`
29
+ `),t.forEach(r=>{console.log(` ${l.green(r.name)}@${r.version}`),console.log(` ${r.description}`),r.tags.length>0&&console.log(` Tags: ${r.tags.join(", ")}`),console.log(` Size: ${r.size}`),console.log("");});});var $o=new Command("install").description("Install a plugin").argument("<name>","Plugin name (with or without @devflow-tools/ prefix)").action(async e=>{let o=e.startsWith("@devflow-tools/")?e:`@devflow-tools/${e}`;console.log(`Installing ${o}...`);try{execSync(`npm install -g ${o}`,{stdio:"inherit"}),console.log(`
35
30
  ${l.green("\u2713")} ${o} installed successfully`),console.log(`
36
31
  Run "devflow plugin list --installed" to verify.`);}catch(n){console.error(`
37
- ${l.red("\u2717")} Installation failed: ${n.message}`),process.exit(1);}});var qo=new Command("uninstall").description("Uninstall a plugin").argument("<name>","Plugin name (with or without @devflow-tools/ prefix)").action(async e=>{let o=e.startsWith("@devflow-tools/")?e:`@devflow-tools/${e}`;console.log(`Uninstalling ${o}...`);try{execSync(`npm uninstall -g ${o}`,{stdio:"inherit"}),console.log(`
32
+ ${l.red("\u2717")} Installation failed: ${n.message}`),process.exit(1);}});var Po=new Command("uninstall").description("Uninstall a plugin").argument("<name>","Plugin name (with or without @devflow-tools/ prefix)").action(async e=>{let o=e.startsWith("@devflow-tools/")?e:`@devflow-tools/${e}`;console.log(`Uninstalling ${o}...`);try{execSync(`npm uninstall -g ${o}`,{stdio:"inherit"}),console.log(`
38
33
  ${l.green("\u2713")} ${o} uninstalled successfully`);}catch(n){console.error(`
39
- ${l.red("\u2717")} Uninstallation failed: ${n.message}`),process.exit(1);}});var Vo=new Command("dashboard").description("Start DevFlow Dashboard").option("-p, --port <port>","Port to run on","17788").option("--force","Force re-extract Dashboard from npm package").action(async e=>{try{if(e.force){let r=join(process.cwd(),".devflow","dashboard","version.txt");try{unlinkSync(r);}catch{}}console.log(l.blue("Preparing Dashboard..."));let o=U(process.cwd()),n=join(o,"apps","dashboard","server.js");existsSync(n)||(console.error(l.red(`Dashboard server.js not found at: ${n}
40
- The archive may be corrupted. Try: devflow dashboard --force`)),process.exit(1)),console.log(l.green(`
41
- Starting Dashboard: http://localhost:${e.port}
42
- `));let t=spawn("node",[n],{stdio:"inherit",env:{...process.env,PORT:e.port}});t.on("error",r=>{console.error(l.red("Failed to start Dashboard:"),r),process.exit(1);}),t.on("exit",r=>{process.exit(r||0);});}catch(o){console.error(l.red("Failed to start Dashboard:"),o.message),process.exit(1);}});var Bo=createRequire(import.meta.url),G="0.0.0";try{G=Bo("../package.json").version;}catch{try{G=Bo("../../package.json").version;}catch{}}var c=new Command;c.name("devflow").description("Developer Intelligence Platform for AI Coding Agents").version(G).option("--local","Force local engine, skip server");c.command("init").description("Initialize .devflow/ in the current project").option("--force","Overwrite existing config").option("--abort","Force delete .codegraph and .devflow directories before reinitializing").option("--report","Output onboarding markdown report to stdout").option("--json","Output onboarding pack as JSON to stdout").option("--plugins <names>","Comma-separated list of plugins to install (non-interactive)").option("--no-plugins","Skip plugin installation guide").action(async e=>{let o=process.cwd();if(e.abort){console.log(l.yellow("\u{1F5D1}\uFE0F --abort flag detected, removing existing directories..."));let r=[".codegraph",".devflow"];for(let i of r){let s=xt.join(o,i);zo.existsSync(s)&&(console.log(l.dim(` Removing ${i}/...`)),zo.rmSync(s,{recursive:true,force:true}));}console.log(l.green(`\u2705 Existing directories removed
43
- `));}let n=z(o);console.error(l.blue(`DevFlow init \u2014 mode: ${n}`));let t=await Z(o,{force:e.force});if(e.json&&t.onboardingPack)console.log(JSON.stringify(t.onboardingPack,null,2));else if(e.report&&t.onboardingPack){let{renderInitReport:r}=await Promise.resolve().then(()=>(ee(),Ae));console.log(r(t.onboardingPack));}else {if(t.created.length>0){console.log(l.green("Created:"));for(let r of t.created)console.log(` ${l.dim("+")} ${r}`);}else console.log(l.dim("Already initialized. Use --force to overwrite config."));if(t.indexed&&console.log(l.green(`\u2705 CodeGraph initialized (${t.indexed.files} files, ${t.indexed.symbols} symbols)`)),t.onboardingPack){let r=t.onboardingPack;console.log(l.green("\u2705 Onboarding pack generated")),console.log(l.dim(` ${r.stats.files} files, ${r.stack.frameworks.join(", ")||"no framework"}`));}t.pluginDeployed&&console.log(l.green("\u2705 Plugin deployed to ~/.claude/plugins/cache/")),t.pluginEnabled&&console.log(l.green("\u2705 Plugin enabled in ~/.claude/settings.json")),t.mcpConfigured&&console.log(l.green("\u2705 MCP config written to .claude/mcp.json")),t.pluginDeployed&&t.pluginEnabled&&t.mcpConfigured&&console.log(l.green("\nDevFlow is ready! Run `claude` to start.")),typeof e.plugins=="string"?await Le(e.plugins):e.plugins!==false&&await We(o);}});c.command("connect [agent]").description("Configure MCP connection for AI coding agents").option("--command <cmd>","MCP server command","devflow-mcp").option("--sse <url>","SSE server URL (instead of stdio)").action(async(e,o)=>{let n=process.cwd(),t=z(n);if(console.log(l.blue(`DevFlow connect \u2014 mode: ${t}`)),e){let r=Ue();r.includes(e)||(console.log(l.red(`Unknown agent: ${e}`)),console.log(`Available: ${r.join(", ")}`),process.exit(1));}try{let r=await T({agent:e,command:o.command,sseUrl:o.sse});for(let i of r)console.log(l.green(`\u2713 ${i}`));}catch(r){console.error(l.red(`Error: ${r.message}`)),process.exit(1);}});c.command("index").description("Show index status").option("--watch","Start file watcher for hot updates (stub)").action(async e=>{let o=await _e(c.opts().local);console.log(l.blue("Index Status")),console.log(` Files: ${o.totalFiles}`),console.log(` Symbols: ${o.totalSymbols}`),console.log(` Indexing: ${o.indexing?"active":"idle"}`),e.watch&&console.log(l.dim(" (watch mode not yet implemented)"));});c.command("graph [target]").description("Show dependency graph").option("--depth <n>","Expansion depth","2").action(async(e,o)=>{let n=await qe({target:e,depth:parseInt(o.depth,10),skipServer:c.opts().local});console.log(l.blue("Dependency Graph")),console.log(` Nodes: ${n.nodes.length}`),console.log(` Edges: ${n.edges.length}`);});c.command("context <query>").description("Retrieve project context for a query").option("--mode <mode>","fast | deep","fast").option("--max-tokens <n>","Max token budget","4000").option("--task","Use task-oriented mode with risk hints and next actions").option("--why","Show reasoning for file selection").action(async(e,o)=>{if(o.task){let n=await ze({query:e,mode:o.mode,maxTokens:parseInt(o.maxTokens,10),skipServer:c.opts().local});console.log(JSON.stringify({requiredFiles:n.requiredFiles,optionalFiles:n.optionalFiles,riskHints:n.riskHints,nextActions:n.nextActions,reasoning:o.why?n.reasoning:void 0},null,2));}else {let n=await Ve({query:e,mode:o.mode,maxTokens:parseInt(o.maxTokens,10),skipServer:c.opts().local});console.log(l.blue(`Context: "${e}"`)),console.log(` Files: ${n.files.length}`),console.log(` Confidence: ${(n.confidence*100).toFixed(0)}%`),console.log(` Tokens: ${n.tokenCount}`);}});var _=c.command("workflow").description("Workflow management");_.command("list").description("List available workflows").action(async()=>{let e=await Be(c.opts().local);if(e.length===0){console.log(l.dim("No workflows registered."));return}for(let o of e)console.log(`${l.green(o.name)} \u2014 ${o.description} (${o.stepCount} steps)`);});_.command("run <type> [input]").description("Run a workflow").action(async(e,o)=>{let n=await He(e,{input:o??""},c.opts().local);console.log(`Run: ${n.runId}`),console.log(`Status: ${n.status}`),console.log(`Duration: ${n.duration}ms`);});_.command("status").description("Show running workflows").action(async()=>{let e=await Ye(c.opts().local);console.log(`${e.length} run(s)`);for(let o of e)console.log(` ${o.runId} \u2014 ${o.status}`);});_.command("runs").description("Show workflow history").action(async()=>{let e=await re(c.opts().local);if(e.length===0){console.log(l.dim("No runs yet."));return}for(let o of e){let n=o.finishedAt?`${o.finishedAt-o.startedAt}ms`:"running";console.log(` ${o.runId} ${l.yellow(o.status)} ${n}`);}});var ye=c.command("memory").description("Memory management");ye.command("show").description("Show current project memory").action(async()=>{let e=await Xe(c.opts().local);console.log(JSON.stringify(e,null,2));});ye.command("set <key> <value>").description("Set a memory key").action(async(e,o)=>{await Qe(e,o,c.opts().local),console.log(l.green(`Memory set: ${e} = ${o}`));});ye.command("review").description("Review memory candidates").action(async()=>{let e=await Ze(c.opts().local);console.log(JSON.stringify(e,null,2));});c.command("knowledge <query>").description("Search knowledge base").action(async e=>{let o=await eo(e,void 0,c.opts().local);console.log(l.blue(`Knowledge: "${e}"`)),console.log(` Results: ${o.length}`);for(let n of o.slice(0,5))console.log(` \u2014 ${n.title}`);});c.command("docs sync [plugin-name]").description("Sync documentation for plugins").action(async e=>{console.log(l.blue(`\u25C9 Syncing docs${e?` for ${e} plugin`:""}`));let o=new KnowledgeEngine({projectRoot:process.cwd()});if(e){let n=await o.syncDocs(e);for(let t of n)t.added>0?console.log(` ${l.green("\u2713")} ${t.source} \u2192 ${t.added} chunks`):console.log(` ${l.red("\u2717")} ${t.source} \u2014 ${t.errors.join(", ")||"no content"}`);console.log(l.green(`
34
+ ${l.red("\u2717")} Uninstallation failed: ${n.message}`),process.exit(1);}});var Co=new Command("dashboard").description("Open DevFlow Dashboard").action(async()=>{console.log(l.blue("The Dashboard is served by the DevFlow server.")),console.log(l.dim("Run: devflow start")),console.log(l.dim("Then open: http://localhost:13337"));});var Do=createRequire(import.meta.url),E="0.0.0";try{E=Do("../package.json").version;}catch{try{E=Do("../../package.json").version;}catch{}}var a=new Command;a.name("devflow").description("Developer Intelligence Platform for AI Coding Agents").version(E).option("--local","Force local engine, skip server");a.command("init").description("Initialize .devflow/ in the current project").option("--force","Overwrite existing config").option("--abort","Force delete .codegraph and .devflow directories before reinitializing").option("--report","Output onboarding markdown report to stdout").option("--json","Output onboarding pack as JSON to stdout").option("--plugins <names>","Comma-separated list of plugins to install (non-interactive)").option("--no-plugins","Skip plugin installation guide").action(async e=>{let o=process.cwd();if(e.abort){console.log(l.yellow("\u{1F5D1}\uFE0F --abort flag detected, removing existing directories..."));let r=[".codegraph",".devflow"];for(let i of r){let s=Hn.join(o,i);Ro.existsSync(s)&&(console.log(l.dim(` Removing ${i}/...`)),Ro.rmSync(s,{recursive:true,force:true}));}console.log(l.green(`\u2705 Existing directories removed
35
+ `));}let n=W(o);console.error(l.blue(`DevFlow init \u2014 mode: ${n}`));let t=await K(o,{force:e.force});if(e.json&&t.onboardingPack)console.log(JSON.stringify(t.onboardingPack,null,2));else if(e.report&&t.onboardingPack){let{renderInitReport:r}=await Promise.resolve().then(()=>(B(),Pe));console.log(r(t.onboardingPack));}else {if(t.created.length>0){console.log(l.green("Created:"));for(let r of t.created)console.log(` ${l.dim("+")} ${r}`);}else console.log(l.dim("Already initialized. Use --force to overwrite config."));if(t.indexed&&console.log(l.green(`\u2705 CodeGraph initialized (${t.indexed.files} files, ${t.indexed.symbols} symbols)`)),t.onboardingPack){let r=t.onboardingPack;console.log(l.green("\u2705 Onboarding pack generated")),console.log(l.dim(` ${r.stats.files} files, ${r.stack.frameworks.join(", ")||"no framework"}`));}t.pluginDeployed&&console.log(l.green("\u2705 Plugin deployed to ~/.claude/plugins/cache/")),t.pluginEnabled&&console.log(l.green("\u2705 Plugin enabled in ~/.claude/settings.json")),t.mcpConfigured&&console.log(l.green("\u2705 MCP config written to .claude/mcp.json")),t.pluginDeployed&&t.pluginEnabled&&t.mcpConfigured&&console.log(l.green("\nDevFlow is ready! Run `claude` to start.")),typeof e.plugins=="string"?await Re(e.plugins):e.plugins!==false&&await De(o);}});a.command("connect [agent]").description("Configure MCP connection for AI coding agents").option("--command <cmd>","MCP server command","devflow-mcp").option("--sse <url>","SSE server URL (instead of stdio)").action(async(e,o)=>{let n=process.cwd(),t=W(n);if(console.log(l.blue(`DevFlow connect \u2014 mode: ${t}`)),e){let r=Ie();r.includes(e)||(console.log(l.red(`Unknown agent: ${e}`)),console.log(`Available: ${r.join(", ")}`),process.exit(1));}try{let r=await O({agent:e,command:o.command,sseUrl:o.sse});for(let i of r)console.log(l.green(`\u2713 ${i}`));}catch(r){console.error(l.red(`Error: ${r.message}`)),process.exit(1);}});a.command("index").description("Show index status").option("--watch","Start file watcher for hot updates (stub)").action(async e=>{let o=await Fe(a.opts().local);console.log(l.blue("Index Status")),console.log(` Files: ${o.totalFiles}`),console.log(` Symbols: ${o.totalSymbols}`),console.log(` Indexing: ${o.indexing?"active":"idle"}`),e.watch&&console.log(l.dim(" (watch mode not yet implemented)"));});a.command("graph [target]").description("Show dependency graph").option("--depth <n>","Expansion depth","2").action(async(e,o)=>{let n=await Ne({target:e,depth:parseInt(o.depth,10),skipServer:a.opts().local});console.log(l.blue("Dependency Graph")),console.log(` Nodes: ${n.nodes.length}`),console.log(` Edges: ${n.edges.length}`);});a.command("context <query>").description("Retrieve project context for a query").option("--mode <mode>","fast | deep","fast").option("--max-tokens <n>","Max token budget","4000").option("--task","Use task-oriented mode with risk hints and next actions").option("--why","Show reasoning for file selection").action(async(e,o)=>{if(o.task){let n=await Ae({query:e,mode:o.mode,maxTokens:parseInt(o.maxTokens,10),skipServer:a.opts().local});console.log(JSON.stringify({requiredFiles:n.requiredFiles,optionalFiles:n.optionalFiles,riskHints:n.riskHints,nextActions:n.nextActions,reasoning:o.why?n.reasoning:void 0},null,2));}else {let n=await Te({query:e,mode:o.mode,maxTokens:parseInt(o.maxTokens,10),skipServer:a.opts().local});console.log(l.blue(`Context: "${e}"`)),console.log(` Files: ${n.files.length}`),console.log(` Confidence: ${(n.confidence*100).toFixed(0)}%`),console.log(` Tokens: ${n.tokenCount}`);}});var T=a.command("workflow").description("Workflow management");T.command("list").description("List available workflows").action(async()=>{let e=await Me(a.opts().local);if(e.length===0){console.log(l.dim("No workflows registered."));return}for(let o of e)console.log(`${l.green(o.name)} \u2014 ${o.description} (${o.stepCount} steps)`);});T.command("run <type> [input]").description("Run a workflow").action(async(e,o)=>{let n=await Le(e,{input:o??""},a.opts().local);console.log(`Run: ${n.runId}`),console.log(`Status: ${n.status}`),console.log(`Duration: ${n.duration}ms`);});T.command("status").description("Show running workflows").action(async()=>{let e=await We(a.opts().local);console.log(`${e.length} run(s)`);for(let o of e)console.log(` ${o.runId} \u2014 ${o.status}`);});T.command("runs").description("Show workflow history").action(async()=>{let e=await Y(a.opts().local);if(e.length===0){console.log(l.dim("No runs yet."));return}for(let o of e){let n=o.finishedAt?`${o.finishedAt-o.startedAt}ms`:"running";console.log(` ${o.runId} ${l.yellow(o.status)} ${n}`);}});var le=a.command("memory").description("Memory management");le.command("show").description("Show current project memory").action(async()=>{let e=await Ue(a.opts().local);console.log(JSON.stringify(e,null,2));});le.command("set <key> <value>").description("Set a memory key").action(async(e,o)=>{await Je(e,o,a.opts().local),console.log(l.green(`Memory set: ${e} = ${o}`));});le.command("review").description("Review memory candidates").action(async()=>{let e=await _e(a.opts().local);console.log(JSON.stringify(e,null,2));});a.command("knowledge <query>").description("Search knowledge base").action(async e=>{let o=await Ge(e,void 0,a.opts().local);console.log(l.blue(`Knowledge: "${e}"`)),console.log(` Results: ${o.length}`);for(let n of o.slice(0,5))console.log(` \u2014 ${n.title}`);});a.command("docs sync [plugin-name]").description("Sync documentation for plugins").action(async e=>{console.log(l.blue(`\u25C9 Syncing docs${e?` for ${e} plugin`:""}`));let o=new KnowledgeEngine({projectRoot:process.cwd()});if(e){let n=await o.syncDocs(e);for(let t of n)t.added>0?console.log(` ${l.green("\u2713")} ${t.source} \u2192 ${t.added} chunks`):console.log(` ${l.red("\u2717")} ${t.source} \u2014 ${t.errors.join(", ")||"no content"}`);console.log(l.green(`
44
36
  ${e} docs synced to .devflow/knowledge/${e}/`));}else {let n=await o.getSources();for(let t of n){let r=await o.syncDocs(t.source.name);for(let i of r)i.added>0?console.log(` ${l.green("\u2713")} ${i.source} \u2192 ${i.added} chunks`):console.log(` ${l.red("\u2717")} ${i.source} \u2014 ${i.errors.join(", ")||"no content"}`);}console.log(l.green(`
45
- All docs synced.`));}});var q=c.command("skill").description("Plugin/Skill management");q.command("list").description("List installed skills").action(async()=>{let e=await ie(c.opts().local);if(e.length===0){console.log(l.dim("No skills installed. Use 'devflow skill search' to find plugins."));return}for(let o of e)console.log(` ${l.green(o.name)} @ ${o.version} \u2014 ${o.description}`);});q.command("search <query>").description("Search available plugins").action(async e=>{let o=await ro(e,c.opts().local);if(console.log(l.blue(`Search: "${e}"`)),o.length===0){console.log(l.dim(" No matching plugins found."));return}for(let n of o)console.log(` ${l.green(n.name)} @ ${n.version} \u2014 ${n.description}`);});q.command("install <name>").description("Install a plugin/skill").action(async e=>{try{let o=await lo(e,process.cwd(),c.opts().local);console.log(l.green(`\u2713 Installed @devflow-tools/plugin-${o.name}@${o.version}`)),o.templates.length>0&&console.log(` Templates: ${o.templates.join(", ")}`);}catch(o){console.log(l.red(`Error: ${o.message}`)),process.exit(1);}});q.command("uninstall <name>").description("Uninstall a plugin/skill").action(async e=>{try{await ao(e,process.cwd(),c.opts().local),console.log(l.green(`\u2713 Uninstalled ${e}`));}catch(o){console.log(l.red(`Error: ${o.message}`)),process.exit(1);}});c.command("doctor").description("Run project health check").option("--json","Output as JSON").option("--audit","Verify audit chain integrity").option("--audit-fix","Rebuild audit chain signatures").option("--violations","Show violation records").option("--last <period>","Filter violations by time (e.g. 7d, 24h)").option("--receipts","Show current session receipt status").action(async e=>{if(e.audit){let t=await fo();console.log(e.json?JSON.stringify(t):`Audit chain: ${t.valid?"VALID":`BROKEN at seq ${t.brokenAt}`} (${t.entryCount} entries)`);return}if(e.auditFix){let t=await wo();console.log(e.json?JSON.stringify(t):"Audit chain rebuilt.");return}if(e.violations){let t=await ho(e.last);console.log(e.json?JSON.stringify(t):JSON.stringify(t,null,2));return}if(e.receipts){let t=yo();e.json?console.log(JSON.stringify(t)):t.data?console.log(JSON.stringify(t.data,null,2)):console.log(`No active receipt found for session ${t.sessionId}.`);return}let o=await mo();if(e.json){console.log(JSON.stringify(o));return}if(console.log(l.blue(`DevFlow Doctor v${G}
46
- `)),console.log(l.bold("\u25C9 Index Status")),console.log(` Files ${o.index.totalFiles.toLocaleString()}`),console.log(` Symbols ${o.index.totalSymbols.toLocaleString()}`),console.log(` Graph (${o.graph.edges.toLocaleString()} edges)`),console.log(` Status ${o.index.indexing?"indexing":"idle"}`),console.log(),console.log(l.bold("\u25C9 Memory")),console.log(` Project ${o.memory.projectReady?"ready":"not set"}`),console.log(` Preferences ${o.memory.userPrefs} set`),console.log(),console.log(l.bold("\u25C9 Knowledge")),console.log(` Sources ${o.knowledge.sources}`),console.log(),console.log(l.bold("\u25C9 Server")),o.server.running?console.log(` ${l.green("\u2714")} Running on http://localhost:13337`):console.log(` ${l.yellow("\u25CB")} Not running \u2014 run \`devflow server start\` for telemetry`),console.log(),console.log(l.bold("\u25C9 Plugins")),o.plugins.installed===0)console.log(` ${l.dim("No plugins installed")}`);else for(let t of o.plugins.names)console.log(` ${t}`);console.log(),console.log(l.bold("\u25C9 Workflows")),console.log(` Registered ${o.workflows.registered}`),console.log();let n=o.readyScore>=70?l.green:o.readyScore>=40?l.yellow:l.red;console.log(`AI Ready: ${n(o.readyScore+"%")}`);});c.command("session token").description("Generate a session token for MCP Gateway authentication").option("--expires <seconds>","Token TTL in seconds","3600").action(async e=>{let o=await vo(process.cwd(),parseInt(e.expires,10));console.log(JSON.stringify(o,null,2));});c.command("benchmark [target]").description("Run benchmark on engines").option("--iterations <n>","Number of iterations","5").option("--output <format>","json | text","text").action(async(e,o)=>{let n=await So(e??"all",{iterations:parseInt(o.iterations,10),output:o.output});console.log(n);});c.command("review [pr-url]").description("Review a PR or current branch diff").option("--agent <agent>","AI agent to use","claude").action(async(e,o)=>{let n=await ko({prUrl:e,agent:o.agent});console.log(n);});var ve=c.command("server").description("Manage DevFlow server");ve.command("start").description("Start the DevFlow REST server").option("--port <n>","Port number","13337").action(async e=>{console.log(l.blue("Starting DevFlow server..."));let o=await M({port:parseInt(e.port,10)});console.log(l.green(`Server started (pid: ${o.pid}) on port ${e.port}`));});ve.command("stop").description("Stop the DevFlow REST server").action(async()=>{let e=await R();console.log(e?l.green("Server stopped"):l.dim("No server running"));});ve.command("status").description("Show server status").action(async()=>{let e=await F();e.running?console.log(l.green(`Running (pid: ${e.pid})`)):console.log(l.yellow("Not running"));});c.addCommand(Vo);c.command("start").description("Start DevFlow server and dashboard").option("--port <n>","Server port","13337").option("--dashboard-port <n>","Dashboard port","17788").option("--no-dashboard","Start server only, no dashboard").option("-d, --background","Run in background (detached)").action(async e=>{await Oo({port:parseInt(e.port,10),dashboardPort:parseInt(e.dashboardPort,10),noDashboard:!e.dashboard,background:!!e.background});});c.command("stop").description("Stop DevFlow server and dashboard").action(async()=>{await Eo();});c.command("status").description("Show DevFlow services status").action(async()=>{await To();});c.command("setup").description("Configure Claude Code integration (MCP + plugin)").option("--agent <agent>","Target agent (claude/cursor/cline)").option("--skip-mcp","Skip MCP configuration").option("--skip-plugin","Skip plugin registration").action(async e=>{await Lo({agent:e.agent,skipMcp:!!e.skipMcp,skipPlugin:!!e.skipPlugin});});var K=c.command("plugin").description("Manage DevFlow plugins");K.addCommand(Wo);K.addCommand(Uo);K.addCommand(Go);K.addCommand(qo);c.parse();
37
+ All docs synced.`));}});var A=a.command("skill").description("Plugin/Skill management");A.command("list").description("List installed skills").action(async()=>{let e=await Q(a.opts().local);if(e.length===0){console.log(l.dim("No skills installed. Use 'devflow skill search' to find plugins."));return}for(let o of e)console.log(` ${l.green(o.name)} @ ${o.version} \u2014 ${o.description}`);});A.command("search <query>").description("Search available plugins").action(async e=>{let o=await He(e,a.opts().local);if(console.log(l.blue(`Search: "${e}"`)),o.length===0){console.log(l.dim(" No matching plugins found."));return}for(let n of o)console.log(` ${l.green(n.name)} @ ${n.version} \u2014 ${n.description}`);});A.command("install <name>").description("Install a plugin/skill").action(async e=>{try{let o=await Ye(e,process.cwd(),a.opts().local);console.log(l.green(`\u2713 Installed @devflow-tools/plugin-${o.name}@${o.version}`)),o.templates.length>0&&console.log(` Templates: ${o.templates.join(", ")}`);}catch(o){console.log(l.red(`Error: ${o.message}`)),process.exit(1);}});A.command("uninstall <name>").description("Uninstall a plugin/skill").action(async e=>{try{await Xe(e,process.cwd(),a.opts().local),console.log(l.green(`\u2713 Uninstalled ${e}`));}catch(o){console.log(l.red(`Error: ${o.message}`)),process.exit(1);}});a.command("doctor").description("Run project health check").option("--json","Output as JSON").option("--audit","Verify audit chain integrity").option("--audit-fix","Rebuild audit chain signatures").option("--violations","Show violation records").option("--last <period>","Filter violations by time (e.g. 7d, 24h)").option("--receipts","Show current session receipt status").action(async e=>{if(e.audit){let t=await ro();console.log(e.json?JSON.stringify(t):`Audit chain: ${t.valid?"VALID":`BROKEN at seq ${t.brokenAt}`} (${t.entryCount} entries)`);return}if(e.auditFix){let t=await so();console.log(e.json?JSON.stringify(t):"Audit chain rebuilt.");return}if(e.violations){let t=await io(e.last);console.log(e.json?JSON.stringify(t):JSON.stringify(t,null,2));return}if(e.receipts){let t=lo();e.json?console.log(JSON.stringify(t)):t.data?console.log(JSON.stringify(t.data,null,2)):console.log(`No active receipt found for session ${t.sessionId}.`);return}let o=await to();if(e.json){console.log(JSON.stringify(o));return}if(console.log(l.blue(`DevFlow Doctor v${E}
38
+ `)),console.log(l.bold("\u25C9 Index Status")),console.log(` Files ${o.index.totalFiles.toLocaleString()}`),console.log(` Symbols ${o.index.totalSymbols.toLocaleString()}`),console.log(` Graph (${o.graph.edges.toLocaleString()} edges)`),console.log(` Status ${o.index.indexing?"indexing":"idle"}`),console.log(),console.log(l.bold("\u25C9 Memory")),console.log(` Project ${o.memory.projectReady?"ready":"not set"}`),console.log(` Preferences ${o.memory.userPrefs} set`),console.log(),console.log(l.bold("\u25C9 Knowledge")),console.log(` Sources ${o.knowledge.sources}`),console.log(),console.log(l.bold("\u25C9 Server")),o.server.running?console.log(` ${l.green("\u2714")} Running on http://localhost:13337`):console.log(` ${l.yellow("\u25CB")} Not running \u2014 run \`devflow server start\` for telemetry`),console.log(),console.log(l.bold("\u25C9 Plugins")),o.plugins.installed===0)console.log(` ${l.dim("No plugins installed")}`);else for(let t of o.plugins.names)console.log(` ${t}`);console.log(),console.log(l.bold("\u25C9 Workflows")),console.log(` Registered ${o.workflows.registered}`),console.log();let n=o.readyScore>=70?l.green:o.readyScore>=40?l.yellow:l.red;console.log(`AI Ready: ${n(o.readyScore+"%")}`);});a.command("session token").description("Generate a session token for MCP Gateway authentication").option("--expires <seconds>","Token TTL in seconds","3600").action(async e=>{let o=await ao(process.cwd(),parseInt(e.expires,10));console.log(JSON.stringify(o,null,2));});a.command("benchmark [target]").description("Run benchmark on engines").option("--iterations <n>","Number of iterations","5").option("--output <format>","json | text","text").action(async(e,o)=>{let n=await co(e??"all",{iterations:parseInt(o.iterations,10),output:o.output});console.log(n);});a.command("review [pr-url]").description("Review a PR or current branch diff").option("--agent <agent>","AI agent to use","claude").action(async(e,o)=>{let n=await uo({prUrl:e,agent:o.agent});console.log(n);});var ae=a.command("server").description("Manage DevFlow server");ae.command("start").description("Start the DevFlow REST server").option("--port <n>","Port number","13337").action(async e=>{console.log(l.blue("Starting DevFlow server..."));let o=await F({port:parseInt(e.port,10)});console.log(l.green(`Server started (pid: ${o.pid}) on port ${e.port}`));});ae.command("stop").description("Stop the DevFlow REST server").action(async()=>{let e=await x();console.log(e?l.green("Server stopped"):l.dim("No server running"));});ae.command("status").description("Show server status").action(async()=>{let e=await P();e.running?console.log(l.green(`Running (pid: ${e.pid})`)):console.log(l.yellow("Not running"));});a.addCommand(Co);a.command("start").description("Start DevFlow server (API + Dashboard)").option("--port <n>","Server port","13337").option("-d, --background","Run in background (detached)").action(async e=>{await po({port:parseInt(e.port,10),background:!!e.background});});a.command("stop").description("Stop DevFlow server").action(async()=>{await fo();});a.command("status").description("Show DevFlow services status").action(async()=>{await wo();});a.command("setup").description("Configure Claude Code integration (MCP + plugin)").option("--agent <agent>","Target agent (claude/cursor/cline)").option("--skip-mcp","Skip MCP configuration").option("--skip-plugin","Skip plugin registration").action(async e=>{await vo({agent:e.agent,skipMcp:!!e.skipMcp,skipPlugin:!!e.skipPlugin});});var M=a.command("plugin").description("Manage DevFlow plugins");M.addCommand(So);M.addCommand(ko);M.addCommand($o);M.addCommand(Po);a.parse();
@@ -0,0 +1,7 @@
1
+ import {createConnection}from'net';import {join}from'path';import {homedir}from'os';var f=join(homedir(),".devflow","hook-daemon.sock"),s=process.argv[2],u=process.argv[3];function t(){s==="pre-tool-use"&&console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}})),process.exit(0);}var o=createConnection(f,()=>{if(s==="stop")o.write(JSON.stringify({type:"stop"})+`
2
+ `);else if(s==="post-tool-use")o.write(JSON.stringify({type:"post-tool-use",input:u||""})+`
3
+ `);else if(s==="pre-tool-use"){let e="";process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n;}),process.stdin.on("end",()=>{o.write(JSON.stringify({type:"pre-tool-use",input:e})+`
4
+ `);}),process.stdin.on("error",()=>t());}else t();}),i="";o.on("data",e=>{if(i+=e.toString(),i.includes(`
5
+ `)){let n=i.split(`
6
+ `).filter(Boolean);for(let r of n)process.stdout.write(r+`
7
+ `);o.end();}});o.on("error",()=>t());o.on("close",()=>process.exit(0));setTimeout(()=>t(),4e3).unref();
@@ -0,0 +1,4 @@
1
+ import {createServer}from'net';import {join}from'path';import {homedir}from'os';import {existsSync,unlinkSync,readdirSync,readFileSync,mkdirSync,writeFileSync}from'fs';import {createHash}from'crypto';import {request}from'http';var E=1e4,J=3e4,L=300*1e3;function y(a,t,e){return new Promise(n=>{try{let o=new URL(a),s=request({hostname:o.hostname,port:o.port||80,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":e,"Content-Length":Buffer.byteLength(t)},timeout:5e3},r=>{let i=[];r.on("data",c=>i.push(c)),r.on("end",()=>{let c=Buffer.concat(i).toString();n(r.statusCode!=null&&r.statusCode>=200&&r.statusCode<300?c:null);});});s.on("error",()=>n(null)),s.on("timeout",()=>{s.destroy(),n(null);}),s.write(t),s.end();}catch{n(null);}})}var v=class{constructor(t){this.retryScheduled=false;this.retryAttempts=0;this.apiUrl=t?.apiUrl??process.env.DEVFLOW_API_URL??"http://127.0.0.1:13337",this.apiKey=t?.apiKey??process.env.DEVFLOW_API_KEY??"dev-key-000000",this.cacheDir=t?.cacheDir??join(homedir(),".devflow","telemetry-cache");}async sendEvent(t){let e=this.truncateInput(t.input),n={...t,input:e},o=`${this.apiUrl}/api/telemetry/tool-call`,s=await y(o,JSON.stringify(n),this.apiKey);if(s)try{let r=JSON.parse(s),i=r.data?.eventId??r.eventId??null;if(i)return i}catch{}return this.cacheEvent({type:"tool_call",payload:n}),null}async sendExecutionStart(t,e,n,o){let s={executionId:t,sessionId:e,skillName:n,startedAt:o},r=`${this.apiUrl}/api/telemetry/skill-execution/start`;await y(r,JSON.stringify(s),this.apiKey)||this.cacheEvent({type:"execution_start",payload:s});}async sendSessionStart(t,e,n){let o={id:t,projectRoot:e,startedAt:n,label:e.split("/").pop()??"unknown"},s=`${this.apiUrl}/api/telemetry/sessions`;return await y(s,JSON.stringify(o),this.apiKey)!==null}async flushCache(){if(!existsSync(this.cacheDir))return;let t=readdirSync(this.cacheDir).filter(e=>e.endsWith(".json"));for(let e of t)try{let n=join(this.cacheDir,e),o=readFileSync(n,"utf8"),s=JSON.parse(o),r=s.type==="execution_start"?"/api/telemetry/skill-execution/start":"/api/telemetry/tool-call",i=`${this.apiUrl}${r}`;await y(i,JSON.stringify(s.payload),this.apiKey)&&unlinkSync(n);}catch{}}cacheEvent(t){try{existsSync(this.cacheDir)||mkdirSync(this.cacheDir,{recursive:!0});let e=join(this.cacheDir,`${Date.now()}_${Math.random().toString(36).slice(2,11)}.json`);writeFileSync(e,JSON.stringify(t,null,2)),this.scheduleRetry();}catch{}}scheduleRetry(){if(this.retryScheduled)return;this.retryScheduled=true;let t=Math.min(J*Math.pow(2,this.retryAttempts),L);setTimeout(()=>{this.retryScheduled=false,this.flushCache().then(()=>{this.retryAttempts=0;}).catch(()=>{this.retryAttempts++;});},t).unref();}truncateInput(t){let e=JSON.stringify(t);return e.length<=E?t:{_truncated:true,_original_size:e.length,_preview:e.substring(0,E)+"..."}}};var W=1800*1e3;function G(){return process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow")}var S=class{constructor(t){this.stateDir=G();}detect(){let t=join(this.stateDir,"current-skill.json");if(!existsSync(t))return null;try{let e=readFileSync(t,"utf8"),n=JSON.parse(e);return !n.registeredAt||Date.now()-n.registeredAt>W?(this.endExecution(),null):n}catch{return null}}startExecution(t,e){existsSync(this.stateDir)||mkdirSync(this.stateDir,{recursive:true});let n=this.getCurrentExecutionId();if(n)return n;let o=`exec_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return writeFileSync(join(this.stateDir,"current-execution-id"),o),writeFileSync(join(this.stateDir,"current-skill.json"),JSON.stringify({name:t,required_mcp_tools:e?.required_mcp_tools??[],registeredAt:Date.now()})),o}getCurrentExecutionId(){let t=join(this.stateDir,"current-execution-id");if(!existsSync(t))return null;try{return readFileSync(t,"utf8").trim()}catch{return null}}endExecution(){let t=join(this.stateDir,"current-skill.json"),e=join(this.stateDir,"current-execution-id");try{existsSync(t)&&unlinkSync(t);}catch{}try{existsSync(e)&&unlinkSync(e);}catch{}}};var m=join(homedir(),".devflow","hook-daemon.sock");join(homedir(),".devflow");var Q=600*1e3,tt=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function et(a){switch(a){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 C(a){let t=createHash("sha256").update(a).digest("hex").slice(0,16);return join(process.env.TMPDIR||"/tmp",".devflow-receipts",`${t}.json`)}function nt(a){try{let t=C(a);return existsSync(t)?JSON.parse(readFileSync(t,"utf-8")):{}}catch{return {}}}function R(a,t){try{let e=C(a),n=join(process.env.TMPDIR||"/tmp",".devflow-receipts");existsSync(n)||mkdirSync(n,{recursive:!0}),writeFileSync(e,JSON.stringify(t));}catch{}}var k=class{constructor(t){this.sessionId=null;this.eventMap=[];this.idleTimer=null;this.projectRoot=t,this.projectName=t.split("/").pop()||"unknown",this.telemetry=new v,this.skillManager=new S;}async start(){try{existsSync(m)&&unlinkSync(m);}catch{}let t=createServer(e=>{this.resetIdleTimer();let n="";e.on("data",async o=>{n+=o.toString();let s=n.split(`
2
+ `);n=s.pop()||"";for(let r of s)if(r.trim())try{let i=JSON.parse(r),c=await this.handleRequest(i);c!==null&&e.write(JSON.stringify(c)+`
3
+ `);}catch(i){e.write(JSON.stringify({error:i.message})+`
4
+ `);}}),e.on("error",()=>{});});t.on("error",e=>{console.error("[devflow-daemon] Server error:",e.message);}),t.listen(m,()=>{console.error("[devflow-daemon] Listening on",m);}),this.resetIdleTimer();}resetIdleTimer(){this.idleTimer&&clearTimeout(this.idleTimer),this.idleTimer=setTimeout(()=>{console.error("[devflow-daemon] Idle timeout, exiting"),this.shutdown();},Q).unref();}async handleRequest(t){switch(t.type){case "pre-tool-use":return this.handlePreToolUse(t.input);case "post-tool-use":return this.handlePostToolUse(t.input);case "stop":return await this.handleStop(),{status:"ok"};default:return {error:"unknown request type"}}}async handlePreToolUse(t){try{if(!t||t.trim()==="")return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};let e=JSON.parse(t);if(this.sessionId||(this.sessionId=`session:${this.projectName}:${Date.now().toString(36)}`,this.telemetry.sendSessionStart(this.sessionId,this.projectRoot,Date.now()).catch(()=>{})),e.tool_name==="Skill"){let l=e.tool_input?.skill;if(l&&l.startsWith("devflow:")){let N=this.skillManager.startExecution(l);this.telemetry.sendExecutionStart(N,this.sessionId,l,Date.now()).catch(()=>{});}}let n=this.skillManager.detect(),o=e.tool_name.startsWith("mcp__devflow__"),s=o?e.tool_name.replace("mcp__devflow__",""):void 0,r=n?.required_mcp_tools??[],i=r.length>0,c=i&&!o,p;c?p={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:`Skill "${n?.name||"unknown"}" requires MCP tools. Use one of: ${r.join(", ")}`}}:p={hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}};let d=this.skillManager.getCurrentExecutionId()??this.sessionId,g={eventId:`evt_${Date.now()}_${Math.random().toString(36).slice(2,11)}`,executionId:d,sessionId:this.sessionId,timestamp:Date.now(),toolName:e.tool_name,toolType:o?"mcp":e.tool_name==="Agent"?"subagent":"direct",isMcpTool:o,mcpToolName:s,mcpEnforced:o&&i,mcpFallback:!o&&i,kind:et(e.tool_name),input:e.tool_input,duration:0,blocked:c};return this.telemetry.sendEvent(g).then(l=>{l&&this.eventMap.push({toolName:e.tool_name,eventId:l,timestamp:g.timestamp});}).catch(()=>{}),p}catch{return {hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"allow"}}}}popEventFromMap(t){let e=this.eventMap.filter(o=>o.toolName===t);if(e.length===0)return null;e.sort((o,s)=>Math.abs(o.timestamp-Date.now())-Math.abs(s.timestamp-Date.now()));let n=e[0];return this.eventMap=this.eventMap.filter(o=>o.eventId!==n.eventId),n}enforcePostToolUse(t){if(!tt.has(t))return null;let e=nt(this.projectRoot),n=e.lastMcpCall??0;if(Math.floor(Date.now()/1e3)-n<30)return null;let s=e.bypassCount??0;if(s===0)return R(this.projectRoot,{...e,bypassCount:1}),null;let r=s+1;R(this.projectRoot,{...e,bypassCount:r});let i;switch(t){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(t){if(!t)return null;let e;try{e=JSON.parse(t);}catch{return null}let n=e.tool_name||"",o=e.tool_input||{},s=e.tool_response,r=this.popEventFromMap(n);if(r&&this.sessionId){let f=typeof s=="string"?s:JSON.stringify(s),g=f.length>5e3?{_truncated:true,_originalSize:f.length,text:f.slice(0,5e3)}:s,l=Date.now()-r.timestamp;this.sendHttp("/api/telemetry/tool-call/output",{eventId:r.eventId,sessionId:this.sessionId,output:g,duration:l,completedAt:Date.now()});}let i=typeof s=="object"&&s!==null?s:null,c=i?.exitCode,p=i?.stderr;n==="Bash"&&c!==void 0&&c!==0&&this.sendHttp(`/api/memory/events?rootPath=${encodeURIComponent(this.projectRoot)}`,{id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:this.sessionId??`session:${this.projectName}`,tool:n,command:o.command||n,exitCode:c,stderr:p??null,durationMs:0,createdAt:Date.now()});let d=this.enforcePostToolUse(n);return d?(console.error("[devflow-daemon] Enforcement:",d),{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:JSON.stringify(d)}}):null}sendHttp(t,e){let n=JSON.stringify(e),o=new URL(t,"http://127.0.0.1:13337"),s=request({hostname:o.hostname,port:o.port,path:o.pathname+o.search,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":"dev-key-000000","Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>{});s.on("error",()=>{}),s.write(n),s.end();}async handleStop(){this.sessionId&&this.sendHttp(`/api/telemetry/sessions/${this.sessionId}/close`,{finishedAt:Date.now()}),this.sendHttp(`/api/memory/process?rootPath=${encodeURIComponent(this.projectRoot)}`,{}),await this.telemetry.flushCache().catch(()=>{}),this.shutdown();}shutdown(){this.idleTimer&&clearTimeout(this.idleTimer);try{unlinkSync(m);}catch{}process.exit(0);}},ot=process.argv[2]||process.env.CLAUDE_PROJECT_DIR||process.cwd(),st=new k(ot);st.start().catch(a=>{console.error("[devflow-daemon] Failed to start:",a),process.exit(1);});
@@ -1,2 +1,2 @@
1
- import {request}from'http';import {existsSync,readFileSync,writeFileSync}from'fs';import {join}from'path';import {homedir}from'os';var x=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",A=process.env.DEVFLOW_API_KEY||"dev-key-000000",w=process.env.CLAUDE_PROJECT_DIR||process.cwd(),v=join(homedir(),".devflow","session-id"),f=join(homedir(),".devflow","event-map.json");function y(d,a){return new Promise(e=>{let n=JSON.stringify(a),t=new URL(d,x),o=request({hostname:t.hostname,port:t.port,path:t.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":A,"Content-Length":Buffer.byteLength(n)},timeout:5e3},()=>e());o.on("error",()=>e()),o.write(n),o.end();})}function L(){try{if(existsSync(v))return readFileSync(v,"utf-8").trim()}catch{}return null}function C(d,a){try{if(!existsSync(f))return null;let e=JSON.parse(readFileSync(f,"utf-8")),n=e.filter(c=>c.toolName===d);if(n.length===0)return null;let t=a??Date.now();n.sort((c,m)=>Math.abs(c.timestamp-t)-Math.abs(m.timestamp-t));let o=n[0],s=e.findIndex(c=>c.eventId===o.eventId);return s!==-1&&e.splice(s,1),writeFileSync(f,JSON.stringify(e)),{eventId:o.eventId,timestamp:o.timestamp}}catch{return null}}async function M(d){if(!d)return;let a;try{a=JSON.parse(d);}catch{return}let e=a.tool_name||"",n=a.tool_input||{},t=a.tool_response||{},o=L(),s=C(e,Date.now());if(s&&o){let r=typeof t=="string"?t:JSON.stringify(t),g=r.length>5e3?{_truncated:true,_originalSize:r.length,text:r.slice(0,5e3)}:t,i=Date.now()-s.timestamp;y("/api/telemetry/tool-call/output",{eventId:s.eventId,sessionId:o,output:g,duration:i,completedAt:Date.now()}).catch(()=>{});}let c=typeof n=="object"&&n.command?n.command:"",m=typeof t=="object"&&t!==null?t:null,p=m?.exitCode,O=m?.stderr;if(e==="Bash"&&p!==void 0&&p!==0){let r={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:o??`session:${w.split("/").pop()||"default"}`,tool:e,command:c||e,exitCode:p,stderr:O??null,durationMs:0,createdAt:Date.now()};y(`/api/memory/events?rootPath=${encodeURIComponent(w)}`,r).catch(()=>{});}let R=["get_project_context","get_knowledge","get_memory","search_symbol","get_dependency_graph","react_diagnose_bug","react_new_component","react_audit_performance","vue_diagnose_bug","nest_diagnose_bug","nextjs_diagnose_bug","electron_diagnose_bug","graphql_diagnose_bug","run_workflow"],l=e.replace("mcp__devflow__","");if(e.startsWith("mcp__devflow__")&&R.includes(l)){let r=typeof t=="object"&&t!==null?t:null,g=["files","results","data","result","memories","nodes","chunks"],i=0,u=r?.data??r;if(Array.isArray(u))i=u.length;else if(typeof u=="object"&&u!==null){let _=u;for(let h of g)Array.isArray(_[h])&&(i+=_[h].length);i===0&&Object.keys(_).length>0&&(i=1);}let k=JSON.stringify(t),j=Buffer.byteLength(k,"utf8"),D={id:`metric:${Date.now()}:${Math.random().toString(36).slice(2,11)}`,toolCallEventId:s?.eventId??`unknown:${Date.now()}`,sessionId:o??"",toolName:l,query:typeof n=="object"&&n.query?n.query:void 0,status:r?.error?"error":i===0?"empty":"success",resultCount:i,resultSizeBytes:j,latencyMs:s?Date.now()-s.timestamp:0,engine:l.startsWith("get_project_context")||l==="search_symbol"||l==="get_dependency_graph"?"codegraph":l==="get_knowledge"?"knowledge":l==="get_memory"?"memory":void 0};y("/api/telemetry/tool-metrics",D).catch(()=>{});}}(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js"))&&M(process.argv[2]||"").catch(()=>process.exit(0));
2
- export{M as handlePostToolUse};
1
+ import {request}from'http';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';import {join}from'path';import {homedir}from'os';import {createHash}from'crypto';var T=process.env.DEVFLOW_SERVER_URL||"http://127.0.0.1:13337",L=process.env.DEVFLOW_API_KEY||"dev-key-000000",v=process.env.CLAUDE_PROJECT_DIR||process.cwd(),C=join(homedir(),".devflow","session-id"),w=join(homedir(),".devflow","event-map.json"),F=new Set(["Agent","Bash","Glob","Grep","WebSearch","WebFetch"]);function b(r,s){return new Promise(t=>{let c=JSON.stringify(s),o=new URL(r,T),n=request({hostname:o.hostname,port:o.port,path:o.pathname,method:"POST",headers:{"Content-Type":"application/json","X-API-Key":L,"Content-Length":Buffer.byteLength(c)},timeout:5e3},()=>t());n.on("error",()=>t()),n.write(c),n.end();})}function J(){try{if(existsSync(C))return readFileSync(C,"utf-8").trim()}catch{}return null}function W(r,s){try{if(!existsSync(w))return null;let t=JSON.parse(readFileSync(w,"utf-8")),c=t.filter(l=>l.toolName===r);if(c.length===0)return null;let o=s??Date.now();c.sort((l,d)=>Math.abs(l.timestamp-o)-Math.abs(d.timestamp-o));let n=c[0],e=t.findIndex(l=>l.eventId===n.eventId);return e!==-1&&t.splice(e,1),writeFileSync(w,JSON.stringify(t)),{eventId:n.eventId,timestamp:n.timestamp}}catch{return null}}function P(){let r=createHash("sha256").update(v).digest("hex").slice(0,16);return join(process.env.TMPDIR||"/tmp",".devflow-receipts",`${r}.json`)}function U(){try{let r=P();return existsSync(r)?JSON.parse(readFileSync(r,"utf-8")):{}}catch{return {}}}function k(r){try{let s=P(),t=join(process.env.TMPDIR||"/tmp",".devflow-receipts");existsSync(t)||mkdirSync(t,{recursive:!0}),writeFileSync(s,JSON.stringify(r));}catch{}}function B(r){if(!F.has(r))return null;let s=U(),t=s.lastMcpCall??0;if(Math.floor(Date.now()/1e3)-t<30)return null;let o=s.bypassCount??0;if(o===0)return k({...s,bypassCount:1}),null;let n=o+1;k({...s,bypassCount:n});let e;switch(r){case "Agent":e=`\u7B2C ${n} \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":e=`\u7B2C ${n} \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":e=`\u7B2C ${n} \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":e=`\u7B2C ${n} \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":e=`\u7B2C ${n} \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:e=`\u7B2C ${n} \u6B21\u8FDD\u89C4\uFF1A\u8BF7\u4F7F\u7528 DevFlow MCP \u5DE5\u5177\u66FF\u4EE3\u76F4\u63A5\u8C03\u7528\u3002`;}return n>=3?e=`${e} \u5DF2\u8FBE\u5230\u6700\u5927\u8FDD\u89C4\u6B21\u6570\uFF0C\u540E\u7EED\u7ED5\u8FC7\u5C06\u88AB\u786C\u963B\u6B62\u3002`:n>=2?e=`${e} \u4E0B\u6B21\u8FDD\u89C4\u5C06\u88AB\u963B\u6B62\u3002`:e=`${e} \u8BF7\u7ACB\u5373\u7EA0\u6B63\u3002`,e}async function q(r){if(!r)return null;let s;try{s=JSON.parse(r);}catch{return null}let t=s.tool_name||"",c=s.tool_input||{},o=s.tool_response||{},n=J(),e=W(t,Date.now());if(e&&n){let a=typeof o=="string"?o:JSON.stringify(o),h=a.length>5e3?{_truncated:true,_originalSize:a.length,text:a.slice(0,5e3)}:o,i=Date.now()-e.timestamp;b("/api/telemetry/tool-call/output",{eventId:e.eventId,sessionId:n,output:h,duration:i,completedAt:Date.now()}).catch(()=>{});}let l=typeof c=="object"&&c.command?c.command:"",d=typeof o=="object"&&o!==null?o:null,f=d?.exitCode,R=d?.stderr;if(t==="Bash"&&f!==void 0&&f!==0){let a={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:n??`session:${v.split("/").pop()||"default"}`,tool:t,command:l||t,exitCode:f,stderr:R??null,durationMs:0,createdAt:Date.now()};b(`/api/memory/events?rootPath=${encodeURIComponent(v)}`,a).catch(()=>{});}let M=["get_project_context","get_knowledge","get_memory","search_symbol","get_dependency_graph","react_diagnose_bug","react_new_component","react_audit_performance","vue_diagnose_bug","nest_diagnose_bug","nextjs_diagnose_bug","electron_diagnose_bug","graphql_diagnose_bug","run_workflow"],u=t.replace("mcp__devflow__","");if(t.startsWith("mcp__devflow__")&&M.includes(u)){let a=typeof o=="object"&&o!==null?o:null,h=["files","results","data","result","memories","nodes","chunks"],i=0,p=a?.data??a;if(Array.isArray(p))i=p.length;else if(typeof p=="object"&&p!==null){let y=p;for(let I of h)Array.isArray(y[I])&&(i+=y[I].length);i===0&&Object.keys(y).length>0&&(i=1);}let j=JSON.stringify(o),D=Buffer.byteLength(j,"utf8"),N={id:`metric:${Date.now()}:${Math.random().toString(36).slice(2,11)}`,toolCallEventId:e?.eventId??`unknown:${Date.now()}`,sessionId:n??"",toolName:u,query:typeof c=="object"&&c.query?c.query:void 0,status:a?.error?"error":i===0?"empty":"success",resultCount:i,resultSizeBytes:D,latencyMs:e?Date.now()-e.timestamp:0,engine:u.startsWith("get_project_context")||u==="search_symbol"||u==="get_dependency_graph"?"codegraph":u==="get_knowledge"?"knowledge":u==="get_memory"?"memory":void 0};b("/api/telemetry/tool-metrics",N).catch(()=>{});}let _=B(t);return _&&console.error("[devflow] Enforcement:",_),_}if(process.argv[1]?.endsWith("post-tool-use")||process.argv[1]?.endsWith("post-tool-use.js")){let r="";process.stdin.setEncoding("utf8"),process.stdin.on("data",s=>{r+=s;}),process.stdin.on("end",async()=>{let s=await q(r.trim()||process.argv[2]||"");if(s){let t=JSON.stringify(s);console.log(JSON.stringify({hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:t}}));}}),process.stdin.on("error",()=>process.exit(0)),setTimeout(()=>process.exit(0),5e3).unref();}
2
+ export{q as handlePostToolUse};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-tools/devflow",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "description": "DevFlow - Developer Intelligence Platform (Distribution Package)",
6
6
  "bin": {
@@ -15,17 +15,17 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@colbymchenry/codegraph": "^1.1.1",
18
- "@devflow-tools/adapters": "^0.11.0",
19
- "@devflow-tools/benchmark": "^0.11.0",
20
- "@devflow-tools/context-engine": "^0.11.0",
21
- "@devflow-tools/database": "^0.11.0",
22
- "@devflow-tools/knowledge-engine": "^0.11.0",
23
- "@devflow-tools/mcp-server": "^0.11.0",
24
- "@devflow-tools/memory-engine": "^0.11.0",
25
- "@devflow-tools/sdk": "^0.11.0",
26
- "@devflow-tools/server": "^0.11.0",
27
- "@devflow-tools/telemetry": "^0.11.0",
28
- "@devflow-tools/workflow-engine": "^0.11.0",
18
+ "@devflow-tools/adapters": "^0.12.0",
19
+ "@devflow-tools/benchmark": "^0.12.0",
20
+ "@devflow-tools/context-engine": "^0.12.0",
21
+ "@devflow-tools/database": "^0.12.0",
22
+ "@devflow-tools/knowledge-engine": "^0.12.0",
23
+ "@devflow-tools/mcp-server": "^0.12.0",
24
+ "@devflow-tools/memory-engine": "^0.12.0",
25
+ "@devflow-tools/sdk": "^0.12.0",
26
+ "@devflow-tools/server": "^0.12.0",
27
+ "@devflow-tools/telemetry": "^0.12.0",
28
+ "@devflow-tools/workflow-engine": "^0.12.0",
29
29
  "@inquirer/prompts": "^7.10.1",
30
30
  "@modelcontextprotocol/sdk": "^1.0.0",
31
31
  "@nestjs/common": "^10.4.0",
@@ -52,5 +52,5 @@
52
52
  "plugin-registry.json",
53
53
  "scripts/postinstall.js"
54
54
  ],
55
- "gitHead": "ff6ac69b0f3cc95cb32ffe8bcbf21b24767aa914"
55
+ "gitHead": "b7b5606e419887fe8c1f921a8a5a564ce9afcbac"
56
56
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "lastUpdated": "2026-07-11T08:12:49.883Z",
3
+ "lastUpdated": "2026-07-11T11:13:33.819Z",
4
4
  "plugins": [
5
5
  {
6
6
  "name": "@devflow-tools/plugin-animation",
7
- "version": "0.10.0",
7
+ "version": "0.11.0",
8
8
  "description": "",
9
9
  "tags": [],
10
10
  "compatibleStacks": [
@@ -16,7 +16,7 @@
16
16
  },
17
17
  {
18
18
  "name": "@devflow-tools/claude-code-plugin",
19
- "version": "0.10.0",
19
+ "version": "0.11.0",
20
20
  "description": "DevFlow — Developer Intelligence Platform for Claude Code",
21
21
  "tags": [
22
22
  "pi-package",
@@ -26,13 +26,13 @@
26
26
  "knowledge-base"
27
27
  ],
28
28
  "compatibleStacks": [],
29
- "size": "280K",
29
+ "size": "300K",
30
30
  "author": "DevFlow Team",
31
31
  "homepage": ""
32
32
  },
33
33
  {
34
34
  "name": "@devflow-tools/plugin-css",
35
- "version": "0.10.0",
35
+ "version": "0.11.0",
36
36
  "description": "",
37
37
  "tags": [],
38
38
  "compatibleStacks": [
@@ -44,7 +44,7 @@
44
44
  },
45
45
  {
46
46
  "name": "@devflow-tools/plugin-docker",
47
- "version": "0.10.0",
47
+ "version": "0.11.0",
48
48
  "description": "",
49
49
  "tags": [],
50
50
  "compatibleStacks": [
@@ -56,7 +56,7 @@
56
56
  },
57
57
  {
58
58
  "name": "@devflow-tools/plugin-electron",
59
- "version": "0.10.0",
59
+ "version": "0.11.0",
60
60
  "description": "",
61
61
  "tags": [],
62
62
  "compatibleStacks": [
@@ -68,7 +68,7 @@
68
68
  },
69
69
  {
70
70
  "name": "@devflow-tools/plugin-git",
71
- "version": "0.10.0",
71
+ "version": "0.11.0",
72
72
  "description": "",
73
73
  "tags": [],
74
74
  "compatibleStacks": [
@@ -80,7 +80,7 @@
80
80
  },
81
81
  {
82
82
  "name": "@devflow-tools/plugin-graphql",
83
- "version": "0.10.0",
83
+ "version": "0.11.0",
84
84
  "description": "",
85
85
  "tags": [],
86
86
  "compatibleStacks": [
@@ -92,7 +92,7 @@
92
92
  },
93
93
  {
94
94
  "name": "@devflow-tools/plugin-nest",
95
- "version": "0.10.0",
95
+ "version": "0.11.0",
96
96
  "description": "",
97
97
  "tags": [],
98
98
  "compatibleStacks": [
@@ -104,7 +104,7 @@
104
104
  },
105
105
  {
106
106
  "name": "@devflow-tools/plugin-nextjs",
107
- "version": "0.10.0",
107
+ "version": "0.11.0",
108
108
  "description": "",
109
109
  "tags": [],
110
110
  "compatibleStacks": [
@@ -116,7 +116,7 @@
116
116
  },
117
117
  {
118
118
  "name": "@devflow-tools/plugin-performance",
119
- "version": "0.10.0",
119
+ "version": "0.11.0",
120
120
  "description": "",
121
121
  "tags": [],
122
122
  "compatibleStacks": [
@@ -128,7 +128,7 @@
128
128
  },
129
129
  {
130
130
  "name": "@devflow-tools/plugin-react",
131
- "version": "0.10.0",
131
+ "version": "0.11.0",
132
132
  "description": "",
133
133
  "tags": [],
134
134
  "compatibleStacks": [
@@ -140,7 +140,7 @@
140
140
  },
141
141
  {
142
142
  "name": "@devflow-tools/plugin-tailwind",
143
- "version": "0.10.0",
143
+ "version": "0.11.0",
144
144
  "description": "",
145
145
  "tags": [],
146
146
  "compatibleStacks": [
@@ -152,7 +152,7 @@
152
152
  },
153
153
  {
154
154
  "name": "@devflow-tools/plugin-taro",
155
- "version": "0.10.0",
155
+ "version": "0.11.0",
156
156
  "description": "",
157
157
  "tags": [],
158
158
  "compatibleStacks": [
@@ -164,7 +164,7 @@
164
164
  },
165
165
  {
166
166
  "name": "@devflow-tools/plugin-ui-layout",
167
- "version": "0.10.0",
167
+ "version": "0.11.0",
168
168
  "description": "",
169
169
  "tags": [],
170
170
  "compatibleStacks": [
@@ -176,7 +176,7 @@
176
176
  },
177
177
  {
178
178
  "name": "@devflow-tools/plugin-vue",
179
- "version": "0.10.0",
179
+ "version": "0.11.0",
180
180
  "description": "",
181
181
  "tags": [],
182
182
  "compatibleStacks": [
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env node
2
- import {createHmac,createHash}from'crypto';import {Server}from'@modelcontextprotocol/sdk/server/index.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {ListToolsRequestSchema,ListResourcesRequestSchema,ReadResourceRequestSchema,ListPromptsRequestSchema,GetPromptRequestSchema,CallToolRequestSchema}from'@modelcontextprotocol/sdk/types.js';import {FallbackLLMClient,CliSubAgentClient,DevFlowApiClient,loadPlugins}from'@devflow-tools/sdk';import {join}from'path';import {existsSync,mkdirSync,readFileSync,writeFileSync,statSync}from'fs';var Se=Object.defineProperty;var Re=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,t)=>(typeof require<"u"?require:o)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var k=(e,o)=>()=>(e&&(o=e(e=0)),o);var K=(e,o)=>{for(var t in o)Se(e,t,{get:o[t],enumerable:true});};var B={};K(B,{TOOL_GROUPS:()=>Te,createPluginHandlers:()=>Pe,createToolHandlers:()=>Ee,getCoreTools:()=>A,getPluginTools:()=>O});function A(){return [{name:"get_project_context",description:"\u83B7\u53D6\u4E0E\u7F16\u7801\u4EFB\u52A1\u6700\u76F8\u5173\u7684\u6700\u5C0F\u4E0A\u4E0B\u6587",inputSchema:{type:"object",properties:{query:{type:"string",description:"\u81EA\u7136\u8BED\u8A00\u67E5\u8BE2"},mode:{type:"string",enum:["fast","deep"],default:"fast"},expandedTerms:{type:"string",description:"Agent \u9884\u7FFB\u8BD1\u7684\u82F1\u6587\u5173\u952E\u8BCD\uFF08\u7A7A\u683C\u5206\u9694\uFF09\uFF0C\u7528\u4E8E\u63D0\u5347\u4E2D\u6587\u67E5\u8BE2\u7684\u641C\u7D22\u6548\u679C"}},required:["query"]}},{name:"search_symbol",description:"\u6309\u7B26\u53F7\u540D\u641C\u7D22\u4EE3\u7801\u2014\u2014\u8BED\u4E49\u7EA7\u4EE3\u7801\u7ED3\u6784\u641C\u7D22",inputSchema:{type:"object",properties:{symbol:{type:"string",description:"\u7B26\u53F7\u540D\u79F0"}},required:["symbol"]}},{name:"get_dependency_graph",description:"\u83B7\u53D6\u6587\u4EF6/\u7EC4\u4EF6\u7684\u4F9D\u8D56\u5173\u7CFB",inputSchema:{type:"object",properties:{target:{type:"string",default:"all"},depth:{type:"number",default:2}}}},{name:"run_workflow",description:"\u6267\u884C\u6807\u51C6\u5316\u5F00\u53D1\u5DE5\u4F5C\u6D41",inputSchema:{type:"object",properties:{type:{type:"string",enum:["bugfix","feature","review"]},input:{type:"string"}},required:["type"]}},{name:"get_memory",description:"\u83B7\u53D6\u9879\u76EE\u8BB0\u5FC6\uFF1A\u6280\u672F\u6808\u3001\u7EA6\u5B9A\u3001\u504F\u597D\u3001\u5386\u53F2\u51B3\u7B56",inputSchema:{type:"object",properties:{}}},{name:"get_knowledge",description:"\u67E5\u8BE2\u6280\u672F\u6587\u6863\u77E5\u8BC6\u5E93",inputSchema:{type:"object",properties:{query:{type:"string"},scope:{type:"string",enum:["react","vue","nest","all"],default:"all"}},required:["query"]}},{name:"devflow_report_event",description:"Report fine-grained events within workflow steps (LLM calls, tool usage, file read/write etc.). Optional, for more granular observability.",inputSchema:{type:"object",properties:{runId:{type:"string"},stepId:{type:"string"},kind:{type:"string",enum:["llm_call","tool_use","memory_read","memory_write","file_read","file_write","bash_command","mcp_tool_call","error","user_input"]},duration:{type:"number"},model:{type:"string"},prompt:{type:"string"},response:{type:"string"},inputTokens:{type:"number"},outputTokens:{type:"number"},toolName:{type:"string"},toolInput:{type:"string"},toolOutput:{type:"string"},filePath:{type:"string"},command:{type:"string"},exitCode:{type:"number"},stdout:{type:"string"},stderr:{type:"string"},mcpToolName:{type:"string"},errorMessage:{type:"string"},errorStack:{type:"string"},memoryKey:{type:"string"},userMessage:{type:"string"}},required:["runId","stepId","kind"]}}]}function Ee(e){function o(){try{let t=e.codegraph.getStats();return t.lastUpdated>0?Date.now()-t.lastUpdated:0}catch{return 0}}return {get_project_context:async({query:t,mode:r,expandedTerms:s})=>{let n=await e.context.buildTaskContext(t,{mode:r??"fast",sessionId:process.env.DEVFLOW_SESSION_ID??void 0});return {taskType:n.taskType,requiredFiles:n.requiredFiles,optionalFiles:n.optionalFiles,keySymbols:n.keySymbols,graphSummary:n.graphSummary,riskHints:n.riskHints,nextActions:n.nextActions,reasoning:n.reasoning,confidence:n.confidence,tokenCount:n.tokenCount,_timing:n._timing,_devflow_unique:{search_method:"bm25_semantic",task_oriented:true,risk_aware:true,memory_injected:true,knowledge_injected:true,token_estimated:true,required_vs_optional:true},_accuracy:{data_freshness_ms:o(),source_layer:"composite",degradation:n._devflow?.fallback?"fallback":"none"}}},search_symbol:async({symbol:t})=>{let r=await e.indexer.findSymbol(t);return {result:Array.isArray(r)?r:[],_devflow_unique:{index_backed:true,kind_annotated:true,searched:t,match_count:Array.isArray(r)?r.length:0}}},get_dependency_graph:async({target:t,depth:r,layer:s})=>{let n=t?.trim()||void 0,a=r??2,c=s??"auto",l=e.graph.query({target:n,depth:a,layer:c==="auto"?void 0:c});if(l.nodes.length===0&&n){let d=e.graph.export();return {nodes:d.nodes.filter(p=>p.file.includes(n)),edges:d.edges.filter(p=>d.nodes.some(u=>u.id===p.from&&u.file.includes(n))||d.nodes.some(u=>u.id===p.to&&u.file.includes(n))),_devflow_unique:{layer:l.layer,truncated:l.truncated,layer_annotated:true,architecture_grouped:true,query_depth:a,query_target:n},_fallback:"filename-filter",_accuracy:{data_freshness_ms:o(),source_layer:"codegraph",degradation:"fallback"},seeds:[n],depth:a}}return {nodes:l.nodes,edges:l.edges,_devflow_unique:{layer:l.layer,truncated:l.truncated,layer_annotated:true,architecture_grouped:true,query_depth:a,query_target:n??"all"},_accuracy:{data_freshness_ms:o(),source_layer:"codegraph",degradation:l.edges.length===0&&l.nodes.length>0?"partial":"none"}}},run_workflow:async({type:t,input:r})=>({...await e.workflow.run(t,{input:r}),_devflow_unique:{dag_orchestrated:true,step_tracked:true,workflow_type:t}}),get_memory:async()=>({...await e.memory.getAll(),_devflow_unique:{memory_version:1,structured_storage:true,project_context_included:true},_accuracy:{data_freshness_ms:o(),source_layer:"memory",degradation:"none"}}),get_knowledge:async({query:t,scope:r})=>({...await e.knowledge.search(t,{sources:r==="all"?void 0:[r]}),_devflow_unique:{source_versioned:true,code_examples_included:true,search_scope:r},_accuracy:{data_freshness_ms:o(),source_layer:"knowledge",degradation:"none"}}),devflow_report_event:async t=>{let r=(p,u)=>!p||p.length<=u?{value:p??"",truncated:false}:{value:p.slice(0,u),truncated:true},s=r(t.prompt,500),n=r(t.response,500),a=r(t.stdout,1e3),c=r(t.stderr,500),l=s.truncated||n.truncated||a.truncated||c.truncated,d={id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,runId:t.runId,stepId:t.stepId,kind:t.kind,timestamp:Date.now(),duration:t.duration,data:{model:t.model,prompt:s.value,response:n.value,inputTokens:t.inputTokens,outputTokens:t.outputTokens,toolName:t.toolName,toolInput:t.toolInput,toolOutput:t.toolOutput,filePath:t.filePath,command:t.command,exitCode:t.exitCode,stdout:a.value,stderr:c.value,mcpToolName:t.mcpToolName,errorMessage:t.errorMessage,errorStack:t.errorStack,memoryKey:t.memoryKey,userMessage:t.userMessage},metadata:{source:"manual"},...l&&{metadata:{truncated:true,source:"manual"}}};return await e.telemetry.recordEvent(d),{acknowledged:true,eventId:d.id}}}}function O(e){let o=[];for(let t of e){let r=t.meta.name;for(let n of t.tools??[])o.push({name:n.name,description:n.description,inputSchema:n.inputSchema});let s=new Set(o.map(n=>n.name));for(let n of t.workflow?.templates??[]){let a=n.triggers?.find(l=>l.type==="mcp");if(!a?.tool)continue;let c=`${r}_${a.tool}`;s.has(c)||o.push({name:c,description:n.description,inputSchema:{type:"object",properties:n.steps.filter(l=>l.inputSchema).reduce((l,d)=>({...l,...d.inputSchema??{}}),{}),required:[]}});}}return o}function Pe(e,o){let t={};for(let r of o){let s=r.meta.name;for(let n of r.tools??[])n.handler&&(t[n.name]=n.handler);for(let n of r.workflow?.templates??[]){let a=n.triggers?.find(l=>l.type==="mcp");if(!a?.tool)continue;let c=`${s}_${a.tool}`;t[c]||(t[c]=async l=>{let d=await e.workflow.run(n.name,l),p="";try{let u={id:d.runId??`run:${Date.now()}`,source:"mcp",tool:c,workflow:n.name,input:l,status:"running",startedAt:Date.now(),finishedAt:null,steps:[],metadata:{}};p=e.workflow.renderPlan(u,n);}catch{}return {...d,plan:p,_devflow_unique:{dag_orchestrated:true,step_tracked:true,plugin_name:s,template_name:n.name}}});}}return t}var Te,I=k(()=>{Te={get_project_context:{group:"context",cacheable:true,idempotent:true},search_symbol:{group:"context",cacheable:true,idempotent:true},get_dependency_graph:{group:"context",cacheable:true,idempotent:true},get_memory:{group:"memory",cacheable:false,idempotent:true},devflow_report_event:{group:"memory",cacheable:false,idempotent:false},get_knowledge:{group:"knowledge",cacheable:true,idempotent:true},run_workflow:{group:"workflow",cacheable:false,idempotent:false},react_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},nest_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},nextjs_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},vue_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},graphql_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},electron_diagnose_bug:{group:"workflow",cacheable:false,idempotent:false},react_new_component:{group:"workflow",cacheable:false,idempotent:false},react_refactor_component:{group:"workflow",cacheable:false,idempotent:false},react_review_hooks:{group:"workflow",cacheable:false,idempotent:false},react_audit_performance:{group:"workflow",cacheable:false,idempotent:false},nest_new_module:{group:"workflow",cacheable:false,idempotent:false},graphql_new_graphql_type:{group:"workflow",cacheable:false,idempotent:false},nextjs_new_page:{group:"workflow",cacheable:false,idempotent:false},taro_new_page:{group:"workflow",cacheable:false,idempotent:false},vue_new_component:{group:"workflow",cacheable:false,idempotent:false},tailwind_new_component:{group:"workflow",cacheable:false,idempotent:false},docker_dockerize_project:{group:"lifecycle",cacheable:false,idempotent:false},performance_audit_performance:{group:"lifecycle",cacheable:false,idempotent:false}};});var $,N=k(()=>{$=[{id:"C001",name:"\u5FC5\u987B\u643A\u5E26 Session Token",level:"constitutional",condition:{requireFields:["_devflow_token"]},action:"deny",message:"\u7F3A\u5C11 Session Token\u3002\u8BF7\u901A\u8FC7 /devflow: \u547D\u4EE4\u542F\u52A8\u4F1A\u8BDD\uFF0C\u6216\u8FD0\u884C devflow session token \u83B7\u53D6\u4EE4\u724C\u3002"},{id:"C002",name:"Token \u5DF2\u8FC7\u671F",level:"constitutional",condition:{},action:"deny",message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"},{id:"C003",name:"\u901F\u7387\u9650\u5236",level:"constitutional",condition:{maxCallsPerMinute:60},action:"warn",message:"\u8C03\u7528\u9891\u7387\u8FC7\u9AD8\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}];});async function ee(e){let o=await e.ruleGetAll();return [...$,...o]}function $e(e,o){let t=e.condition;if(t.tools&&!t.tools.includes("*")&&!t.tools.includes(o.toolName))return "allow";if(t.requireFields){for(let r of t.requireFields)if(!(r in o.args))return e.action}if(t.forbidPatterns){for(let r of t.forbidPatterns)for(let s of Object.values(o.args))if(typeof s=="string"&&new RegExp(r).test(s))return e.action}if(t.paramPatterns)for(let[r,s]of Object.entries(t.paramPatterns)){let n=String(o.args[r]??"");if(new RegExp(s).test(n))return e.action}if(t.maxCallsPerMinute){let r=`${o.toolName}:${o.sessionId??"anon"}`,s=Date.now(),n=Z.get(r);if((!n||s>n.resetAt)&&(n={count:0,resetAt:s+6e4},Z.set(r,n)),n.count++,n.count>t.maxCallsPerMinute)return e.action}return "allow"}function te(e,o){let t=[...e].sort((r,s)=>{let n={constitutional:0,project:1,session:2};return n[r.level]-n[s.level]});for(let r of t){let s=$e(r,o);if(s!=="allow")return {decision:s,rule:r}}return {decision:"allow"}}var Z,oe=k(()=>{N();Z=new Map;});function x(e){let o=JSON.stringify(e,Object.keys(e).sort());return createHash("sha256").update(o).digest("hex")}async function H(e,o,t,r,s,n){let a=await e.auditGetSecret(),c=await e.auditGetAll(),l=c.length>0?c[c.length-1].signature:createHash("sha256").update("genesis").digest("hex"),d=Date.now(),p=c.length+1,u=`${p}|${d}|${o}|${t}|${r}|${s??""}|${n}|${l}`,m=createHmac("sha256",a).update(u).digest("hex");await e.auditAppend({seq:p,ts:d,tool:o,argsHash:t,decision:r,ruleId:s,sessionId:n,prevHash:l,signature:m});}async function ne(e){let o=await e.auditGetSecret(),t=await e.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let s of t){if(s.prevHash!==r)return {valid:false,brokenAt:s.seq};let n=`${s.seq}|${s.ts}|${s.tool}|${s.argsHash}|${s.decision}|${s.ruleId??""}|${s.sessionId}|${r}`,a=createHmac("sha256",o).update(n).digest("hex");if(s.signature!==a)return {valid:false,brokenAt:s.seq};r=s.signature;}return {valid:true,brokenAt:null}}async function re(e){let o=await e.auditGetSecret(),t=await e.auditGetAll(),r=createHash("sha256").update("genesis").digest("hex");for(let s of t){let n=`${s.seq}|${s.ts}|${s.tool}|${s.argsHash}|${s.decision}|${s.ruleId??""}|${s.sessionId}|${r}`,a=createHmac("sha256",o).update(n).digest("hex");await e.sqlExecute("UPDATE devflow_audit_chain SET prev_hash = ?, signature = ? WHERE seq = ?",[r,a,s.seq]),r=a;}}var L=k(()=>{});function S(e,o,t){let r=Date.now(),s=r+je,n=createHash("sha256").update(JSON.stringify(o)).digest("hex"),a=`${e}|${r}|${s}|${n}`,c=createHmac("sha256",t).update(a).digest("hex");return {tool:e,ts:r,exp:s,queryHash:n,hmac:c}}function ie(e,o,t,r){if(Date.now()>e.exp)return false;let s=createHash("sha256").update(JSON.stringify(t)).digest("hex");if(e.queryHash!==s)return false;let n=`${o}|${e.ts}|${e.exp}|${s}`,a=createHmac("sha256",r).update(n).digest("hex");return e.hmac===a}function ce(e){return Date.now()>e.exp}var je,J=k(()=>{je=3e4;});var ue={};K(ue,{CONSTITUTIONAL_RULES:()=>$,enforce:()=>De,hashArgs:()=>x,isReceiptExpired:()=>ce,issueReceipt:()=>S,parseJwtPayload:()=>le,rebuildAuditChain:()=>re,verifyAuditChain:()=>ne,verifyReceipt:()=>ie});function le(e){try{let o=e.split(".");if(o.length!==3)return null;let t=o[1],r=Buffer.from(t,"base64url").toString("utf-8");return JSON.parse(r)}catch{return null}}async function De(e,o,t){if(!o._devflow_token){let u=process.env.DEVFLOW_SESSION_TOKEN;if(u){let m=le(u);m&&(o={...o,_devflow_token:m});}}let r=o._devflow_token?.sub??"anon",s={toolName:e,args:o,sessionId:r,tokenPayload:o._devflow_token};if(s.tokenPayload){let u=Math.floor(Date.now()/1e3);if(s.tokenPayload.exp&&u>s.tokenPayload.exp){let m=x(o);return await H(t,e,m,"deny","C002",r),{result:{allowed:false,message:"Session Token \u5DF2\u8FC7\u671F\uFF08\u8D85\u8FC7 1 \u5C0F\u65F6\uFF09\u3002\u8BF7\u91CD\u65B0\u8FD0\u884C devflow session token \u83B7\u53D6\u65B0\u4EE4\u724C\u3002"}}}}let n=await ee(t),{decision:a,rule:c}=te(n,s),l=x(o);if(await H(t,e,l,a,c?.id??null,r),a==="deny"&&c)return {result:{allowed:false,rule:c,message:c.message}};if(a==="warn"&&c){let u=await t.auditGetSecret(),m=S(e,o,u);return {result:{allowed:true,warning:c.message,rule:c},receipt:m}}let d=await t.auditGetSecret(),p=S(e,o,d);return {result:{allowed:true},receipt:p}}var de=k(()=>{oe();L();J();L();J();N();});I();async function V(e){let o=await e.memory.listMemories({status:"approved"}),t=await e.knowledge.getSources();return {resources:[{uri:"devflow://memory/recent",name:"Recent Memories",description:`${o.length} approved project memories`,mimeType:"application/json"},{uri:"devflow://memory/pending",name:"Pending Memories",description:"Memory candidates awaiting approval",mimeType:"application/json"},{uri:"devflow://code/{file}:{line}",name:"Code Context",description:"Source code at specific file and line",mimeType:"text/plain"},{uri:"devflow://knowledge/{source}",name:"Knowledge Base",description:`Technical documentation (${t.length} sources)`,mimeType:"application/json"}]}}async function z(e,o){if(e==="devflow://memory/recent"){let t=await o.memory.listMemories({status:"approved"});return {contents:[{uri:e,mimeType:"application/json",text:JSON.stringify(t.slice(0,20),null,2)}]}}if(e==="devflow://memory/pending"){let t=await o.memory.getPendingMemories();return {contents:[{uri:e,mimeType:"application/json",text:JSON.stringify(t,null,2)}]}}if(e.startsWith("devflow://knowledge/")){let t=e.replace("devflow://knowledge/",""),r=await o.knowledge.search("",{sources:[t],limit:20});return {contents:[{uri:e,mimeType:"application/json",text:JSON.stringify(r,null,2)}]}}return {contents:[{uri:e,mimeType:"text/plain",text:JSON.stringify({message:"Resource not found"})}]}}var Y={"debug-react":{name:"Debug React Component",description:"Load React knowledge + project memories + related code for debugging",arguments:[{name:"query",description:"Bug description or component name",required:true}]},"code-review":{name:"Code Review",description:"Load project conventions + dependency graph for code review",arguments:[{name:"file",description:"File to review",required:true}]},"new-feature":{name:"New Feature",description:"Load project structure + knowledge base for feature planning",arguments:[{name:"feature",description:"Feature description",required:true}]},"fix-bug":{name:"Fix Bug",description:"Load failure lessons + dependency graph for bug fixing",arguments:[{name:"bug",description:"Bug description",required:true}]}};async function X(){return {prompts:Object.entries(Y).map(([e,o])=>({name:e,description:o.description,arguments:o.arguments}))}}async function Q(e,o){let t=Y[e];if(!t)throw new Error(`Prompt "${e}" not found`);return {messages:[{role:"user",content:{type:"text",text:`You are working on: ${t.description}
3
-
4
- Context: ${JSON.stringify(o)}
5
-
6
- Use available tools to complete this task.`}}]}}var P=class{constructor(o){this.server=o;this.name="mcp-sampling";}get isAvailable(){try{return this.server.getClientCapabilities()?.sampling!==void 0}catch{return false}}async chat(o){let t=await this.server.createMessage({messages:o.messages.map(n=>({role:n.role,content:{type:"text",text:n.content}})),maxTokens:o.maxTokens??4096,temperature:o.temperature,...o.systemPrompt?{systemPrompt:o.systemPrompt}:{}}),r=t.content,s="";return typeof r=="string"?s=r:"type"in r&&r.type==="text"?s=r.text:Array.isArray(r)&&(s=r.filter(n=>typeof n=="object"&&"type"in n&&n.type==="text").map(n=>n.text).join(`
7
- `)),{content:s,model:t.model,usage:t.usage?{input:t.usage.inputTokens??0,output:t.usage.outputTokens??0}:void 0}}};async function fe(e){ze(e.projectRoot),Xe(e.projectRoot);let o=new Server({name:"devflow-mcp",version:"0.1.0"},{capabilities:{tools:{},resources:{},prompts:{}}}),t=new FallbackLLMClient(new P(o),new CliSubAgentClient),r=process.env.DEVFLOW_SERVER_URL??"http://127.0.0.1:13337",s=process.env.DEVFLOW_API_KEY??"dev-key-000000",n=new DevFlowApiClient({baseUrl:r,projectRoot:e.projectRoot,apiKey:s}),a=await n.ping(),c=await loadPlugins(),l=Array.from(c.values()),d=A(),p=O(l),u=[...d,...p];o.setRequestHandler(ListToolsRequestSchema,async()=>({tools:u})),o.setRequestHandler(ListResourcesRequestSchema,async()=>{if(a)return {resources:[]};let w=await C();return V(w)}),o.setRequestHandler(ReadResourceRequestSchema,async w=>{if(a)throw new Error("Resources not available in remote mode");let i=await C();return z(w.params.uri,i)}),o.setRequestHandler(ListPromptsRequestSchema,async()=>X()),o.setRequestHandler(GetPromptRequestSchema,async w=>Q(w.params.name,w.params.arguments??{}));let m=null;async function C(){if(m)return m;let[{createEngines:w}]=await Promise.all([import('@devflow-tools/context-engine')]),i=2;for(;i>0;)try{m=await w(e.projectRoot,t);break}catch(v){if(i--,i===0)throw v;console.error(`[devflow-mcp] createEngines failed, retrying... (${i} left):`,v.message),await new Promise(y=>setTimeout(y,1500));}for(let v of l)for(let y of v.workflow?.templates??[])m.workflow.register(y);return console.error(`[devflow-mcp] Warning: DevFlow server not reachable at ${r}`),console.error("[devflow-mcp] Running in local mode."),m}let we=new Set(d.map(w=>w.name));o.setRequestHandler(CallToolRequestSchema,async w=>{let{name:i,arguments:v}=w.params,y=v??{},M=Date.now(),g=0;try{let f;if(we.has(i)&&a){f=await et(n,i,y),pe(e.projectRoot,i),g=Date.now()-M;let h=i.split("_")[0];try{await n.recordTelemetryEvent({toolName:i,args:y,durationMs:g,success:!0,pluginName:h,metadata:{projectRoot:e.projectRoot}});}catch(b){console.error("[devflow-mcp] Failed to record telemetry:",b);}try{await n.recordMemoryEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${e.projectRoot.split("/").pop()??"default"}`,tool:i,command:R(i)||i,exitCode:0,durationMs:g});}catch(b){console.error("[devflow-mcp] Failed to record memory event:",b);}}else {let h=await C(),{enforce:b}=await Promise.resolve().then(()=>(de(),ue)),_=await b(i,y,h.data);if(!_.result.allowed)return {content:[{type:"text",text:JSON.stringify({_devflow:{v:1,tool:i,ts:Date.now(),marker:"devflow-mcp-v1"},error:_.result.message,rule:_.result.rule?.id})}],isError:!0};let{createToolHandlers:_e,createPluginHandlers:ve}=await Promise.resolve().then(()=>(I(),B)),ke=_e(h),be=ve(h,l),U={...ke,...be}[i];if(!U)throw new Error(`Unknown tool: ${i}`);f=await U(y),pe(e.projectRoot,i),g=Date.now()-M;try{await h.data.recordToolCall(i,y,g);let G=i.startsWith("devflow_")||i.includes("_"),xe=i.split("_")[0],q=ge.has(xe);await h.telemetry.recordToolCall({eventId:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,executionId:`exec:${e.projectRoot.split("/").pop()??"default"}:${Date.now()}`,timestamp:Date.now(),toolName:i,toolType:G||q?"mcp":"direct",isMcpTool:G||q,mcpToolName:q?i:void 0,mcpEnforced:!0,mcpFallback:!1,input:y,output:Ye(f),tokensUsed:0,duration:g,blocked:!1});}catch{}try{await h.memory.recordEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${e.projectRoot.split("/").pop()??"default"}`,tool:i,command:R(i)||i,exitCode:0,stderr:void 0,durationMs:g,createdAt:Date.now()}),h.memory.processSessionEvents().catch(()=>{});}catch{}_.receipt&&(f={...f,_receipt:_.receipt}),_.result.warning&&(f={...f,_warning:_.result.warning});}let he=Qe(i,f,g);return {content:[{type:"text",text:JSON.stringify(he,null,2)}]}}catch(f){if(g=Date.now()-M,a){try{await n.recordTelemetryEvent({toolName:i,args:y,durationMs:g,success:!1,error:f.message,pluginName:i.split("_")[0],metadata:{projectRoot:e.projectRoot}});}catch(E){console.error("[devflow-mcp] Failed to record error telemetry:",E);}try{await n.recordMemoryEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${e.projectRoot.split("/").pop()??"default"}`,tool:i,command:R(i)||i,exitCode:1,stderr:f.message,durationMs:g});}catch(E){console.error("[devflow-mcp] Failed to record error memory event:",E);}}else if(m){try{await m.data.recordToolCall(i,y,g,f.message);}catch{}try{await m.memory.recordEvent({id:`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,sessionId:`session:${e.projectRoot.split("/").pop()??"default"}`,tool:i,command:R(i)||i,exitCode:1,stderr:f.message,durationMs:g,createdAt:Date.now()});}catch{}}return {content:[{type:"text",text:`Error: ${f.message}`}],isError:true}}});let ye=new StdioServerTransport;await o.connect(ye);}function ze(e){if(process.env.DEVFLOW_SESSION_TOKEN)return;let o=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),t=Math.floor(Date.now()/1e3),r={sub:`devflow-mcp-${Date.now().toString(36)}`,project:e.split("/").pop()??"unknown",iat:t,exp:t+86400,scope:["context","knowledge","memory","workflow","graph"]},s=Buffer.from(JSON.stringify(r)).toString("base64url"),a=createHmac("sha256","devflow-local-mcp-secret-v1").update(`${o}.${s}`).digest("base64url");process.env.DEVFLOW_SESSION_TOKEN=`${o}.${s}.${a}`;let c=`session:${r.project}:${Date.now().toString(36)}`;process.env.DEVFLOW_SESSION_ID=c,console.error("[devflow-mcp] Auto-generated session token (no env token provided).");}var ge=new Set(["react","vue","nest","nextjs","graphql","docker","tailwind","taro","electron","performance"]);function R(e){let o={get_project_context:"context",search_symbol:"context",get_dependency_graph:"graph",get_knowledge:"knowledge",get_memory:"memory",run_workflow:"workflow"};if(o[e])return `devflow:${o[e]}`;let t=e.split("_")[0];return ge.has(t)?`devflow:${t}`:""}function pe(e,o){try{let t=process.env.TMPDIR||"/tmp",r=join(t,".devflow-receipts"),s=createHash("sha256").update(e).digest("hex").slice(0,16),n=join(r,`${s}.json`);existsSync(r)||mkdirSync(r,{recursive:!0});let a={};if(existsSync(n))try{a=JSON.parse(readFileSync(n,"utf-8"));}catch{}a.lastMcpCall=Date.now(),a.bypassCount=0;let c=R(o);c&&(a.activeCommand=c),writeFileSync(n,JSON.stringify(a));}catch{}}function Ye(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let{_devflow:o,_receipt:t,_warning:r,...s}=e;return Object.keys(s).length>0?s:e}return e}function Xe(e){try{let o=join(e,"apps/mcp-server/src"),t=join(e,"apps/mcp-server/dist");if(!existsSync(o)||!existsSync(t))return;let r=W(o),s=W(t);r>s&&console.error("[devflow-mcp] WARNING: dist/ is stale. Source files newer than build output. Run: npm run build --workspace=apps/mcp-server");}catch{}}function W(e){let o=0;try{let{readdirSync:t}=Re("fs"),r=t(e,{withFileTypes:!0});for(let s of r){let n=join(e,s.name);s.isDirectory()?o=Math.max(o,W(n)):o=Math.max(o,statSync(n).mtimeMs);}}catch{}return o}function Qe(e,o,t){let r={_devflow:{v:1,tool:e,ts:Date.now(),marker:"devflow-mcp-v1",...t!==void 0?{took_ms:t}:{}}};return o&&typeof o=="object"&&!Array.isArray(o)?{...o,...r}:{result:o,...r}}async function Ze(){let e=new Map,o=await loadPlugins(),t=Array.from(o.values());for(let r of t){let s=r.meta.name;for(let n of r.workflow?.templates??[]){let a=n.triggers?.find(c=>c.type==="mcp");if(a?.tool){let c=`${s}_${a.tool}`;e.set(c,n.name);}}}return e}async function et(e,o,t){switch(o){case "get_project_context":return e.buildContext(t.query,t.mode??"fast");case "search_symbol":return e.searchSymbol(t.symbol);case "get_dependency_graph":return e.getGraph(t.target??"all",t.depth??2);case "run_workflow":return e.runWorkflow(t.type,t.input);case "get_memory":return e.getMemory();case "get_knowledge":return e.searchKnowledge(t.query,t.scope??"all");case "devflow_report_event":return e.recordEvent(t);default:{let s=(await Ze()).get(o)??o;return e.runWorkflow(s,t)}}}async function tt(){let e=process.env.DEVFLOW_PROJECT_ROOT||process.cwd();await fe({mode:"stdio",projectRoot:e});}tt().catch(e=>{console.error("MCP Server error:",e),process.exit(1);});
package/dist/server.js DELETED
@@ -1,10 +0,0 @@
1
- import'reflect-metadata';import {Reflector,APP_GUARD,APP_INTERCEPTOR,NestFactory}from'@nestjs/core';import {FastifyAdapter}from'@nestjs/platform-fastify';import {Readable}from'stream';import {Injectable,Inject,Global,Module,Optional,Get,Query,Param,Post,Body,Delete,Controller,Headers,Put,forwardRef,Res,Catch,UnauthorizedException,NotFoundException,BadRequestException,SetMetadata,Logger,HttpException,HttpStatus}from'@nestjs/common';import {existsSync,readFileSync}from'fs';import {join}from'path';import {createEngines}from'@devflow-tools/context-engine';import {TelemetryEngine}from'@devflow-tools/telemetry';import {MemoryEngine,checkOllama,getOllamaInfoMessage}from'@devflow-tools/memory-engine';import {WorkflowEngine}from'@devflow-tools/workflow-engine';import {clearPluginCache,loadPlugins}from'@devflow-tools/sdk';import {Subject}from'rxjs';import {KnowledgeEngine}from'@devflow-tools/knowledge-engine';import {BenchmarkEngine}from'@devflow-tools/benchmark';import {DevFlowDatabase}from'@devflow-tools/database';import {homedir}from'os';import {map}from'rxjs/operators';var we=Object.defineProperty;var ke=Object.getOwnPropertyDescriptor;var i=(c,t,e,s)=>{for(var n=s>1?void 0:s?ke(t,e):t,o=c.length-1,a;o>=0;o--)(a=c[o])&&(n=(s?a(t,e,n):a(n))||n);return s&&n&&we(t,e,n),n},r=(c,t)=>(e,s)=>t(e,s,c);var xt="isPublic",Yt=()=>SetMetadata(xt,true);var Tt={MISSING_API_KEY:"AUTH_MISSING_API_KEY",INVALID_API_KEY:"AUTH_INVALID_API_KEY"};var xe=(process.env.DEVFLOW_API_KEYS??"dev-key-000000").split(",").map(c=>c.trim()).filter(Boolean),X=class{constructor(t){this.reflector=t;}canActivate(t){if(this.reflector.getAllAndOverride(xt,[t.getHandler(),t.getClass()]))return true;let n=t.switchToHttp().getRequest().headers["x-api-key"];if(!n)throw new UnauthorizedException({error:{code:Tt.MISSING_API_KEY,message:"X-API-Key header is required",details:{}}});if(!xe.includes(n))throw new UnauthorizedException({error:{code:Tt.INVALID_API_KEY,message:"Invalid API key",details:{}}});return true}};X=i([Injectable(),r(0,Inject(Reflector))],X);var st=class{};st=i([Global(),Module({providers:[X,{provide:APP_GUARD,useClass:X}]})],st);var g={WORKFLOW_NOT_FOUND:"WORKFLOW_NOT_FOUND",RUN_NOT_FOUND:"RUN_NOT_FOUND",PROJECT_NOT_FOUND:"PROJECT_NOT_FOUND",NODE_NOT_FOUND:"NODE_NOT_FOUND",PLUGIN_NOT_FOUND:"PLUGIN_NOT_FOUND",BAD_REQUEST:"BAD_REQUEST",VALIDATION_ERROR:"VALIDATION_ERROR",INTERNAL_ERROR:"INTERNAL_ERROR"};var f=class{constructor(t){this.database=t;this.projects=new Map;this.activeProjectRoot=process.env.DEVFLOW_PROJECT_ROOT??null;}onModuleInit(){if(!process.env.DEVFLOW_PROJECT_ROOT&&this.database){let t=this.database.getSetting("activeProjectRoot");t&&(this.activeProjectRoot=t);}}setActiveProject(t){this.activeProjectRoot=t,this.database&&this.database.setSetting("activeProjectRoot",t);}disconnectProject(){this.activeProjectRoot=null,this.database&&this.database.deleteSetting("activeProjectRoot");}getActiveProjectRoot(){return this.activeProjectRoot}async list(){return Array.from(this.projects.values())}async getById(t){let e=this.projects.get(t);if(!e)throw new NotFoundException({error:{code:g.PROJECT_NOT_FOUND,message:`Project "${t}" not found`,details:{}}});return e}async create(t){let e=`proj_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,s={id:e,name:t.name,rootPath:t.rootPath,stack:t.stack,createdAt:Date.now()};return this.projects.set(e,s),this.activeProjectRoot||this.setActiveProject(t.rootPath),s}async delete(t){if(!this.projects.has(t))throw new NotFoundException({error:{code:g.PROJECT_NOT_FOUND,message:`Project "${t}" not found`,details:{}}});this.projects.delete(t);}async getOnboardingPack(t){let e=join(t,".devflow","onboarding-pack.json");if(!existsSync(e))throw new NotFoundException({error:{code:g.PROJECT_NOT_FOUND,message:"Onboarding pack not found. Run `devflow init` first.",details:{}}});return JSON.parse(readFileSync(e,"utf-8"))}async getOnboardingPackByRoot(t){let e=join(t,".devflow","onboarding-pack.json");try{return existsSync(e)?JSON.parse(readFileSync(e,"utf-8")):null}catch{return null}}};f=i([Injectable(),r(0,Optional()),r(0,Inject("DATABASE"))],f);var b=class{constructor(t){this.service=t;}async list(){return this.service.list()}async getOnboardingPackByRoot(t){if(!t)throw new BadRequestException({error:{code:g.BAD_REQUEST,message:"rootPath is required",details:{}}});return this.service.getOnboardingPackByRoot(t)}async getById(t){return this.service.getById(t)}async getOnboardingPack(t){let e=await this.service.getById(t);return this.service.getOnboardingPack(e.rootPath)}async create(t){return this.service.create(t)}async connect(t){return this.service.setActiveProject(t.rootPath),{rootPath:t.rootPath}}async switchProject(t){return this.service.setActiveProject(t.rootPath),{rootPath:t.rootPath}}async getActive(){return {rootPath:this.service.getActiveProjectRoot()}}async disconnect(){return this.service.disconnectProject(),{ok:true}}async delete(t){return this.service.delete(t)}};i([Get()],b.prototype,"list",1),i([Get("onboarding-pack"),r(0,Query("rootPath"))],b.prototype,"getOnboardingPackByRoot",1),i([Get(":id"),r(0,Param("id"))],b.prototype,"getById",1),i([Get(":id/onboarding-pack"),r(0,Param("id"))],b.prototype,"getOnboardingPack",1),i([Post(),r(0,Body())],b.prototype,"create",1),i([Post("connect"),r(0,Body())],b.prototype,"connect",1),i([Post("switch"),r(0,Body())],b.prototype,"switchProject",1),i([Get("active")],b.prototype,"getActive",1),i([Delete("active")],b.prototype,"disconnect",1),i([Delete(":id"),r(0,Param("id"))],b.prototype,"delete",1),b=i([Controller("projects"),r(0,Inject(f))],b);var w=class{};w=i([Module({controllers:[b],providers:[f],exports:[f]})],w);var kt=class{constructor(t){this.db=t;}checkAll(){return [...this.checkMemorySemanticDupes(),...this.checkMemoryPendingBacklog(),...this.checkKnowledgeEmptyResults(),...this.checkCodeGraphLowConfidence(),...this.checkOutputCaptureRate()]}checkMemorySemanticDupes(){try{return (this.db.get("SELECT COUNT(*) as c FROM tool_metrics WHERE engine = 'memory'")?.c??0)===0?[{name:"memory-semantic-dupes",severity:"ok",detail:"No memory tool calls \u2014 semantic dedup check skipped"}]:[{name:"memory-semantic-dupes",severity:"ok",detail:"Semantic dedup active \u2014 checked at write time by memory-engine"}]}catch{return [{name:"memory-semantic-dupes",severity:"ok",detail:"Check skipped \u2014 embedding data not available"}]}}checkMemoryPendingBacklog(){try{let t=this.db.get("SELECT COUNT(*) as c FROM tool_metrics WHERE engine = 'memory'")?.c??0;return t===0?[{name:"memory-pending-backlog",severity:"ok",detail:"No memory calls recorded yet"}]:[{name:"memory-pending-backlog",severity:"ok",detail:`${t} memory tool calls recorded`,value:t}]}catch{return [{name:"memory-pending-backlog",severity:"ok",detail:"Check skipped"}]}}checkKnowledgeEmptyResults(){try{let t=this.db.get("SELECT COUNT(*) as c FROM tool_metrics WHERE tool_name = 'get_knowledge'")?.c??0;if(t===0)return [{name:"knowledge-empty-results",severity:"ok",detail:"No get_knowledge calls yet"}];let e=this.db.get("SELECT COUNT(*) as c FROM tool_metrics WHERE tool_name = 'get_knowledge' AND result_count = 0")?.c??0,s=t>0?Math.round(e/t*100):0;return [{name:"knowledge-empty-results",severity:s>50?"warning":"ok",detail:`${s}% empty result rate for get_knowledge (${e}/${t})`,value:s,threshold:50}]}catch{return [{name:"knowledge-empty-results",severity:"ok",detail:"Check skipped"}]}}checkCodeGraphLowConfidence(){try{let t=this.db.get("SELECT COUNT(*) as c FROM accuracy_queries WHERE engine = 'codegraph'")?.c??0;if(t===0)return [{name:"codegraph-low-confidence",severity:"ok",detail:"No codegraph queries yet"}];let e=this.db.all("SELECT top_k_results FROM accuracy_queries WHERE engine = 'codegraph' ORDER BY created_at DESC LIMIT 100"),s=0;for(let o of e)try{let a=JSON.parse(o.top_k_results);if(a.length===0){s++;continue}a.reduce((p,Q)=>p+(Q.score??.5),0)/a.length<.3&&s++;}catch{}let n=t>0?Math.round(s/Math.min(t,100)*100):0;return [{name:"codegraph-low-confidence",severity:n>30?"warning":"ok",detail:`${n}% of recent codegraph queries have low confidence (avg score < 0.3)`,value:n,threshold:30}]}catch{return [{name:"codegraph-low-confidence",severity:"ok",detail:"Check skipped"}]}}checkOutputCaptureRate(){try{let t=this.db.get("SELECT COUNT(*) as c FROM tool_call_events WHERE is_mcp_tool = 1")?.c??0;if(t===0)return [{name:"output-capture-rate",severity:"ok",detail:"No MCP tool calls yet"}];let e=this.db.get("SELECT COUNT(*) as c FROM tool_call_events WHERE is_mcp_tool = 1 AND output IS NOT NULL")?.c??0,s=t>0?Math.round(e/t*100):0;return [{name:"output-capture-rate",severity:s<80?"error":s<95?"warning":"ok",detail:`${s}% of MCP tool calls have output captured (${e}/${t})`,value:s,threshold:95}]}catch{return [{name:"output-capture-rate",severity:"ok",detail:"Check skipped"}]}}};var S=class{constructor(t){this.engine=new TelemetryEngine;this.db=t??null;}async recordEvent(t){this.db&&this.db.insertEvent?.({runId:t.runId,kind:t.kind,timestamp:t.timestamp,duration:t.duration,toolName:t.data?.toolName,pluginName:t.data?.mcpToolName,metadata:t.data});}async createSession(t){this.db&&this.db.insertSession({id:t.id,projectRoot:t.projectRoot,label:t.label,startedAt:t.startedAt});}async getSession(t){if(!this.db)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Session "${t}" not found`,details:{}}});let e=this.db.getSession(t);if(!e)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Session "${t}" not found`,details:{}}});return e}async listSessions(t,e,s){return this.db?this.db.listSessions(t,e,s):[]}async getSessionEvents(t){return this.db?this.db.listToolCallEventsBySession?.(t)??[]:[]}async closeSession(t,e){this.db&&this.db.closeSession(t,e);}async createSkillExecution(t){this.db&&this.db.insertSkillExecution({executionId:t.executionId,sessionId:t.sessionId,skillName:t.skillName,startedAt:t.startedAt,status:"running"});}async listRuns(t,e,s){if(this.db)try{return this.db.listSessions(t,e).map(o=>({id:o.id,agent:"claude-code",mode:"hook",source:"hook",status:o.status,startedAt:o.startedAt,totalToolCalls:o.totalToolCalls,mcpToolCalls:o.mcpToolCalls,mcpComplianceRate:o.mcpToolCalls>0?Math.round(o.mcpToolCalls/o.totalToolCalls*100)/100:0}))}catch{}return []}async getRun(t){if(this.db)try{let s=this.db.getSession(t);if(s)return {meta:{runId:s.id,agent:"claude-code",mode:"hook",source:"hook"},status:s.status,startedAt:s.startedAt,finishedAt:s.finishedAt,totalToolCalls:s.totalToolCalls,mcpToolCalls:s.mcpToolCalls,steps:[]};let n=this.db.getSkillExecution(t);if(n)return {meta:{runId:n.executionId,agent:"claude-code",mode:"hook",source:"hook"},status:n.status,startedAt:n.startedAt,finishedAt:n.finishedAt,skillName:n.skillName,totalToolCalls:n.totalToolCalls,mcpToolCalls:n.mcpToolCalls,mcpComplianceRate:n.mcpComplianceRate,steps:[]}}catch{}let e=this.engine.runs.get(t);if(e)return e;throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Run "${t}" not found`,details:{}}})}async getTimeline(t,e){if(!this.db)return [];try{return this.db.listSessions(500,0).filter(n=>!(t&&n.startedAt<Number(t)||e&&n.startedAt>Number(e))).map(n=>({runId:n.id,stepId:n.id,type:"session",duration:n.durationMs,timestamp:n.startedAt}))}catch{return []}}async getRunEvents(t){if(this.db)try{let s=this.db.listToolCallEventsBySession(t);if(s&&s.length>0)return s;let n=this.db.listToolCallEvents(t);if(n&&n.length>0)return n}catch{}return await this.engine.listEvents(t)??[]}async getRunStats(t){if(this.db)try{let e=this.db.listToolCallEventsBySession(t)??this.db.listToolCallEvents(t)??[];if(e.length>0)return {totalEvents:e.length,llmCalls:0,totalTokens:0,toolUses:e.length,fileReads:0,fileWrites:0,bashCommands:0,errors:e.filter(s=>s.error).length,totalDuration:0,mcpToolCalls:e.filter(s=>s.isMcpTool).length,directToolCalls:e.filter(s=>!s.isMcpTool).length,mcpComplianceRate:e.length>0?e.filter(s=>s.isMcpTool).length/e.length:0}}catch{}return this.engine.getRunStats(t)}async endRun(t,e){await this.engine.endRun(t,e);}async getStats(t=7){if(!this.db)return this.emptyStats();let e=Date.now(),s=e-t*24*60*60*1e3;try{let o=this.db.listSessions(1e3,0).filter(u=>u.startedAt>=s),a={},m=0;for(let u of o){let d=new Date(u.startedAt).toISOString().slice(0,10);a[d]||(a[d]={runs:0}),a[d].runs++,m+=u.totalToolCalls??0;}let p=o.map(u=>u.id),Q=this.db.listToolCallEventsBySessions?.(p)??{},W=0,ht=0,H={},z={};for(let[,u]of Object.entries(Q))for(let d of u){W+=d.tokensUsed??0,d.kind==="llm_call"&&ht++;let I=d.toolName?.split("_")?.[1];I&&(H[I]=(H[I]??0)+1);let R=d.mcpToolName?.split("_")?.[0];R&&(z[R]=(z[R]??0)+1);}return {period:{from:new Date(s).toISOString().slice(0,10),to:new Date(e).toISOString().slice(0,10)},summary:{totalRuns:o.length,completedRuns:o.filter(u=>u.status==="completed").length,failedRuns:o.filter(u=>u.status==="failed").length,totalTokens:W,totalLlmCalls:ht,totalToolUses:m,avgRunDuration:o.length>0?Math.round(o.reduce((u,d)=>u+(d.durationMs??0),0)/o.length):0},byDay:Object.entries(a).map(([u,d])=>({date:u,tokens:0,...d})).sort((u,d)=>u.date.localeCompare(d.date)),byWorkflow:Object.entries(H).map(([u,d])=>({workflow:u,count:d})).sort((u,d)=>d.count-u.count),byPlugin:Object.entries(z).map(([u,d])=>({plugin:u,count:d})).sort((u,d)=>d.count-u.count)}}catch{return this.emptyStats()}}emptyStats(){return {period:{from:"",to:""},summary:{totalRuns:0,completedRuns:0,failedRuns:0,totalTokens:0,totalLlmCalls:0,totalToolUses:0,avgRunDuration:0},byDay:[],byWorkflow:[],byPlugin:[]}}async getRoiSummary(t=7){if(!this.db)return this.emptyRoiSummary();let e=Date.now(),s=e-t*24*60*60*1e3;try{let o=this.db.listSessions(1e3,0).filter(u=>u.startedAt>=s),a=o.length,m=o.filter(u=>u.status==="completed").length,p=o.filter(u=>u.status==="failed").length,Q=a>0?Math.round(o.reduce((u,d)=>u+(d.durationMs??0),0)/a):0,W={};for(let u of o){let d=new Date(u.startedAt).toISOString().slice(0,10);W[d]||(W[d]={runs:0,failures:0}),W[d].runs++,u.status==="failed"&&W[d].failures++;}let ht=this.db.listToolCallEventsBySessions(o.map(u=>u.id)),H={tool_error:0,mcp_unavailable:0,unknown:0},z={};for(let u of o){let d=ht[u.id]??[];for(let I of d){if(I.error){let R=I.error.toLowerCase();R.includes("mcp")||R.includes("unavailable")||R.includes("not found")?H.mcp_unavailable++:R.includes("tool")||R.includes("command")||R.includes("error")?H.tool_error++:H.unknown++;}if(I.mcpToolName){let R=I.mcpToolName.split("_")[0];R&&(z[R]=(z[R]??0)+1);}}}return {period:{from:new Date(s).toISOString().slice(0,10),to:new Date(e).toISOString().slice(0,10)},overview:{totalRuns:a,completedRuns:m,failedRuns:p,avgDuration:Q,firstPassSuccessRate:a>0?Math.round(m/a*1e4)/100:0},efficiency:{avgTimePerTask:Q},failures:{total:p,breakdown:H},workflows:[],plugins:Object.entries(z).map(([u,d])=>{let I=o.filter(It=>(ht[It.id]??[]).some(be=>be.mcpToolName?.startsWith(u+"_"))),R=I.filter(It=>It.status==="completed").length,Re=I.length>0?Math.round(R/I.length*1e4)/100:0;return {name:u,runs:d,successRate:Re}}),byDay:Object.entries(W).map(([u,d])=>({date:u,...d,tokens:0})).sort((u,d)=>u.date.localeCompare(d.date))}}catch{return this.emptyRoiSummary()}}emptyRoiSummary(){return {period:{from:"",to:""},overview:{totalRuns:0,completedRuns:0,failedRuns:0,avgDuration:0,firstPassSuccessRate:0},efficiency:{avgTimePerTask:0},failures:{total:0,breakdown:{tool_error:0,mcp_unavailable:0,unknown:0}},workflows:[],plugins:[],byDay:[]}}async recordExecutionStart(t){this.db&&this.db.insertSkillExecution({executionId:t.executionId,sessionId:t.sessionId,skillName:t.skillName,startedAt:t.startedAt,status:"running"});}async recordToolCall(t){if(this.db)try{this.db.insertToolCallEvent({eventId:t.eventId,executionId:t.executionId,sessionId:t.sessionId,timestamp:t.timestamp,toolName:t.toolName,toolType:t.toolType,isMcpTool:t.isMcpTool,mcpToolName:t.mcpToolName,mcpEnforced:t.mcpEnforced,mcpFallback:t.mcpFallback,kind:t.kind??"tool_use",input:t.input,duration:t.duration,parentToolCallId:t.parentToolCallId,subagentId:t.subagentId,error:t.error,blocked:t.blocked,blockReason:t.blockReason});}catch{}}async updateToolCallOutput(t,e,s,n){if(this.db)try{this.db.updateToolCallEvent(t,{output:JSON.stringify(e),duration:n});}catch{}}async recordExecutionComplete(t){this.db&&this.db.updateSkillExecution(t.executionId,{status:t.status,finishedAt:t.finishedAt,totalDuration:t.summary.totalDuration,mcpComplianceRate:t.summary.mcpComplianceRate,totalToolCalls:t.summary.totalToolCalls,mcpToolCalls:t.summary.mcpToolCalls,directToolCalls:t.summary.directToolCalls,subagentCount:t.summary.subagentCount});}async getExecutions(t,e){return this.db?this.db.listSkillExecutions(t,e):[]}async getExecutionEvents(t){return this.db?this.db.listToolCallEvents(t):[]}async getMcpCompliance(){return this.db?this.db.getMcpCompliance():{overall:0,bySkill:{},missedTools:[]}}async classifyFailure(t){let e=await this.getRun(t).catch(()=>null);if(!e||e.status!=="failed")return {};let s=e.steps?.find(o=>o.status==="failed");if(!s)return {};let n=s.error?.toLowerCase()??"";return n.includes("context")||n.includes("insufficient")?{failureCategory:"context_insufficient",failureReason:"Context provided was insufficient for the task",suggestedActions:[{action:"Supplement task context",priority:"high"},{action:"View graph roots",priority:"medium"},{action:"Add related memory",priority:"medium"}]}:n.includes("knowledge")||n.includes("docs")?{failureCategory:"knowledge_missing",failureReason:"Required knowledge was not available",suggestedActions:[{action:"Sync knowledge source",priority:"high"},{action:"Add docs source",priority:"medium"}]}:n.includes("workflow")||n.includes("step")?{failureCategory:"workflow_design_issue",failureReason:"Workflow design issue detected",suggestedActions:[{action:"Adjust specific step",priority:"high"},{action:"Split workflow",priority:"medium"}]}:n.includes("tool")||n.includes("connection")?{failureCategory:"tool_error",failureReason:"Tool execution error",suggestedActions:[{action:"Check tool connectivity",priority:"high"},{action:"Retry or fallback",priority:"medium"}]}:{failureCategory:"agent_override",failureReason:"Agent override detected",suggestedActions:[{action:"Enable/strengthen enforcer",priority:"high"}]}}async cleanup(t){if(!this.db)return 0;try{this.db.cleanupStaleRecords?.();}catch{}let e=this.engine.runs,s=Date.now()-t*24*60*60*1e3,n=0;for(let[o,a]of e)a.startedAt&&a.startedAt<s&&(e.delete(o),n++);return n}async cleanupStaleRecords(){if(this.db)try{this.db.cleanupStaleRecords?.();}catch{}}async recordToolMetric(t){this.db&&this.db.insertToolMetric({...t,createdAt:Date.now()});}async getToolMetrics(t,e,s=100,n=0){return this.db?this.db.getToolMetrics(t,e,s,n):[]}async getToolMetricsSummary(t=7){return this.db?this.db.getToolMetricsSummary(t):[]}async recordAccuracyQuery(t){this.db&&this.db.insertAccuracyQuery({...t,createdAt:Date.now()});}async getAccuracyQueries(t){return this.db?this.db.getAccuracyQueries(t):[]}async updateAccuracyFeedback(t,e){this.db&&this.db.updateAccuracyFeedback(t,e);}async getAccuracyStats(t,e){return this.db?this.db.getAccuracyStats(t,e):{totalQueries:0,annotatedQueries:0,hitRate:null}}async runAutoCheck(){return this.db?new kt(this.db).checkAll():[]}async getFeedbackStats(t,e){return {total:0,hits:0,partials:0,misses:0,hitRate:0,partialRate:0,missRate:0}}async getOpsRoiSummary(){return {period:"all-time",totalRuns:0,successfulRuns:0,successRate:0,avgDuration:0,trend:"stable"}}async getExperimentalRoiSummary(){return {totalScenarios:0,avgTimeSavedRate:null,avgTokenReductionRate:null,avgFirstPassLift:null,avgReworkReductionRate:null,conclusion:"No experimental data available yet"}}async getPluginEffectiveness(t,e){if(!this.db)return {name:t,totalRuns:0,successRate:0,lastUsedAt:null};let s=this.db.listSessions(1e3,0),n=0;for(let o of s){let a=this.db.listToolCallEventsBySession(o.id);for(let m of a)m.mcpToolName?.startsWith(t+"_")&&n++;}return {name:t,totalRuns:n,successRate:0,lastUsedAt:null}}async getPluginUsageStats(t){let e=await this.getPluginEffectiveness(t);return {activeProjects:0,totalRuns:e.totalRuns,successfulRuns:0,lastUsedAt:e.lastUsedAt??void 0}}};S=i([Injectable(),r(0,Optional()),r(0,Inject("DATABASE"))],S);var O=class{constructor(t,e){this.telemetryService=t;this.database=e;this.projectStats=new Map;this.benchmarkResults=[];}async recordTelemetryEvent(t){let e=`evt_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,s=t.toolName?"tool_use":"step_end",n={id:e,runId:t.metadata?.runId??`event_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,stepId:e,kind:s,timestamp:Date.now(),duration:t.durationMs,data:{toolName:t.toolName,toolInput:t.args,errorMessage:t.error},metadata:{source:"claude-code"}};return await this.telemetryService.recordEvent(n),{eventId:e}}async getProjectStats(t){return this.database?this.database.getProjectStats(t):this.projectStats.get(t)??null}async updateProjectStats(t,e){if(this.database){let a={...await this.getProjectStats(t)??{projectRoot:t,totalRuns:0,successfulRuns:0,totalTokens:0,lastActiveAt:Date.now(),topTools:[]},...e,lastActiveAt:Date.now()};return await this.database.upsertProjectStats(a),a}let n={...this.projectStats.get(t)??{projectRoot:t,totalRuns:0,successfulRuns:0,totalTokens:0,lastActiveAt:Date.now(),topTools:[]},...e,lastActiveAt:Date.now()};return this.projectStats.set(t,n),n}recordBenchmarkResult(t){this.benchmarkResults.push(t);}getBenchmarkResults(t){return t?this.benchmarkResults.filter(e=>this.projectStats.get(e.scenarioId)?.projectRoot===t):this.benchmarkResults}async getPluginEffectiveness(t){return []}};O=i([Injectable(),r(0,Inject(S)),r(1,Optional()),r(1,Inject("DATABASE"))],O);var F=class{constructor(t){this.dataService=t;this.feedbackEntries=[];}async indexProject(t){let{indexer:e,codegraph:s}=await createEngines(t);await e.reconcile();let n=s.getStats();return {totalFiles:n.fileCount,totalSymbols:n.nodeCount,lastIndexTime:n.lastUpdated,indexing:s.isIndexing()}}async getStatus(t){try{let{codegraph:e}=await createEngines(t),s=e.getStats();return {totalFiles:s.fileCount,totalSymbols:s.nodeCount,lastIndexTime:s.lastUpdated,indexing:e.isIndexing()}}catch{return {totalFiles:0,totalSymbols:0,lastIndexTime:0,indexing:false}}}async buildContext(t,e,s,n){let{context:o}=await createEngines(t);return o.build({query:e,mode:s,maxTokens:n??8e3,includeGraph:s==="deep"})}async buildTaskContext(t,e,s,n){let{context:o}=await createEngines(t);return o.buildTaskContext(e,{mode:s,maxTokens:n??8e3})}async findSymbol(t,e){let{indexer:s}=await createEngines(t);return s.findSymbol(e)}async recordFeedback(t,e,s,n){let o={query:e,feedback:s,timestamp:Date.now(),projectRoot:t};return this.feedbackEntries.push(o),this.dataService&&await this.dataService.recordTelemetryEvent({toolName:"context_feedback",args:{query:e,feedback:s,taskType:n?.taskType,contextMode:n?.contextMode,projectRoot:t},durationMs:0,success:true,metadata:{projectRoot:t,query:e,taskType:n?.taskType}}),o}async getFeedbackSummaries(){let t=this.feedbackEntries.length,e=this.feedbackEntries.filter(o=>o.feedback==="hit").length,s=this.feedbackEntries.filter(o=>o.feedback==="partial").length,n=this.feedbackEntries.filter(o=>o.feedback==="miss").length;return {total:t,hits:e,partials:s,misses:n,hitRate:t>0?e/t:0}}};F=i([Injectable(),r(0,Optional()),r(0,Inject(O))],F);var E=class{constructor(t,e){this.service=t;this.projects=e;}resolveRootPath(t,e){let s=t??e??this.projects.getActiveProjectRoot();if(!s)throw new BadRequestException("rootPath is required \u2014 no active project connected");return s}async status(t,e){let s=t??e??this.projects.getActiveProjectRoot();return s?this.service.getStatus(s):null}async index(t,e){return this.service.indexProject(this.resolveRootPath(t.rootPath,e))}async build(t,e){return this.service.buildContext(this.resolveRootPath(t.rootPath,e),t.query,t.mode??"fast",t.maxTokens)}async buildTask(t,e){return this.service.buildTaskContext(this.resolveRootPath(t.rootPath,e),t.query,t.mode??"fast",t.maxTokens)}async feedback(t,e){return this.service.recordFeedback(this.resolveRootPath(t.rootPath,e),t.query,t.feedback,{taskType:t.taskType,contextMode:t.contextMode,runId:t.runId,tokenCount:t.tokenCount})}async feedbackSummary(){return this.service.getFeedbackSummaries()}async findSymbol(t,e,s){return this.service.findSymbol(this.resolveRootPath(e,s),t)}};i([Get("status"),r(0,Query("rootPath")),r(1,Headers("x-devflow-project"))],E.prototype,"status",1),i([Post("index"),r(0,Body()),r(1,Headers("x-devflow-project"))],E.prototype,"index",1),i([Post("build"),r(0,Body()),r(1,Headers("x-devflow-project"))],E.prototype,"build",1),i([Post("build-task"),r(0,Body()),r(1,Headers("x-devflow-project"))],E.prototype,"buildTask",1),i([Post("feedback"),r(0,Body()),r(1,Headers("x-devflow-project"))],E.prototype,"feedback",1),i([Get("feedback-summary")],E.prototype,"feedbackSummary",1),i([Get("symbol/:name"),r(0,Param("name")),r(1,Query("rootPath")),r(2,Headers("x-devflow-project"))],E.prototype,"findSymbol",1),E=i([Controller("context"),r(0,Inject(F)),r(1,Inject(f))],E);var _=class{constructor(t){this.dataService=t;}async recordTelemetryEvent(t){return {success:true,...await this.dataService.recordTelemetryEvent(t)}}async getProjectStats(t){return this.dataService.getProjectStats(t)}async updateProjectStats(t){return this.dataService.updateProjectStats(t.projectRoot,t.stats)}recordBenchmarkResult(t){return this.dataService.recordBenchmarkResult(t),{success:true}}getBenchmarkResults(t){return this.dataService.getBenchmarkResults(t)}};i([Post("telemetry/event"),r(0,Body())],_.prototype,"recordTelemetryEvent",1),i([Get("project/stats"),r(0,Query("rootPath"))],_.prototype,"getProjectStats",1),i([Post("project/stats"),r(0,Body())],_.prototype,"updateProjectStats",1),i([Post("benchmark/result"),r(0,Body())],_.prototype,"recordBenchmarkResult",1),i([Get("benchmark/results"),r(0,Query("projectRoot"))],_.prototype,"getBenchmarkResults",1),_=i([Controller("data"),r(0,Inject(O))],_);var D=class{constructor(){this.engines=new Map;this.ENGINE_TTL=3600*1e3;}getEngine(t){let e=Date.now();for(let[o,a]of this.engines)if(e-a.lastAccess>this.ENGINE_TTL){try{a.engine.close?.();}catch{}this.engines.delete(o);}let s=t.replace(/\/+$/,""),n=this.engines.get(s);return n?n.lastAccess=e:(n={engine:new MemoryEngine(s),lastAccess:e},this.engines.set(s,n)),n.engine}async getAll(t){let e=this.getEngine(t),[s,n]=await Promise.all([e.listMemories(),checkOllama()]);return {memories:s.map(o=>({id:o.id,category:o.category,content:o.content,originalText:o.originalText,source:o.source,status:o.status,confidence:o.confidence,scope:o.scope,createdAt:o.createdAt,approvedAt:o.approvedAt})),ollama:{installed:n.installed,running:n.running,modelAvailable:n.modelAvailable,modelName:n.modelName,infoMessage:getOllamaInfoMessage(n)}}}async add(t,e){return this.getEngine(t).addMemory({category:e.category,content:e.content,source:"manual",confidence:1,scope:e.scope??""})}async update(t,e,s){await this.getEngine(t).updateMemory(e,s);}async delete(t,e){await this.getEngine(t).deleteMemory(e);}async getCandidates(t){return this.getEngine(t).getPendingMemories()}async approveCandidate(t,e){await this.getEngine(t).approveMemory(e);}async rejectCandidate(t,e){await this.getEngine(t).rejectMemory(e);}async search(t,e,s){return (await this.getEngine(t).search(e,s)).map(o=>o.entry)}async extract(t,e){return this.getEngine(t).extractMemories(e)}async getOllamaStatus(){let t=await checkOllama();return {...t,infoMessage:getOllamaInfoMessage(t)}}async updateLegacy(t,e,s,n){e!=="user"&&await this.getEngine(t).addMemory({category:"semantic",content:`${s}: ${JSON.stringify(n)}`,source:"manual",confidence:1,scope:s});}async recordEvent(t,e){let s=this.getEngine(t);return await s.recordEvent({id:e.id,sessionId:e.sessionId,tool:e.tool,command:e.command,exitCode:e.exitCode,stderr:e.stderr,durationMs:e.durationMs,createdAt:Date.now()}),{acknowledged:true,extracted:(await s.extractFromEventsRealtime([{tool:e.tool,command:e.command,exitCode:e.exitCode,stderr:e.stderr}])).length}}async processSessionEvents(t){return this.getEngine(t).processSessionEvents()}};D=i([Injectable()],D);var l=class{constructor(t,e,s){this.service=t;this.memoryService=e;this.projectsService=s;}async listRuns(t,e,s){return this.service.listRuns(Number(t)||20,Number(e)||0,s)}async getRun(t){let e=await this.service.getRun(t),s=await this.service.classifyFailure(t);return {...e,...s}}async getTimeline(t,e){return this.service.getTimeline(t,e)}async getRunEvents(t){return this.service.getRunEvents(t)}async recordRunEvent(t,e){let s={...e,runId:t,id:e.id||`evt:${Date.now()}:${Math.random().toString(36).slice(2,7)}`,stepId:e.stepId||e.metadata?.stepId||"unknown"};return await this.service.recordEvent(s),{ok:true,eventId:s.id}}async getRunStats(t){return this.service.getRunStats(t)}async completeRun(t){await this.service.endRun(t,{status:"success"});let e=await this.service.getRunEvents(t),s=this.projectsService.getActiveProjectRoot(),n=await this.memoryService.extract(s??"",e);return {extracted:Array.isArray(n)?n.length:0}}async getStats(t){return this.service.getStats(Number(t)||7)}async getRoiSummary(t){return this.service.getRoiSummary(Number(t)||7)}async cleanup(t){return {removedRuns:await this.service.cleanup(t.olderThanDays??30)}}async cleanupStale(){return await this.service.cleanupStaleRecords(),{ok:true}}async createSession(t){return await this.service.createSession(t),{id:t.id}}async listSessions(t,e,s){return this.service.listSessions(Number(t)||20,Number(e)||0,s)}async getSession(t){return this.service.getSession(t)}async getSessionEvents(t){return this.service.getSessionEvents(t)}async closeSession(t,e){return await this.service.closeSession(t,e.finishedAt),{}}async startSessionSkillExecution(t,e){return await this.service.createSkillExecution({...e,sessionId:t}),{executionId:e.executionId}}async startSkillExecution(t){return await this.service.recordExecutionStart(t),{executionId:t.executionId}}async recordToolCall(t){return await this.service.recordToolCall(t),{eventId:t.eventId}}async updateToolCallOutput(t){return await this.service.updateToolCallOutput(t.eventId,t.output,t.completedAt,t.duration),{}}async completeSkillExecution(t){return await this.service.recordExecutionComplete(t),{}}async getExecutions(t,e){return this.service.getExecutions(Number(t)||20,e)}async getExecutionEvents(t){return this.service.getExecutionEvents(t)}async getMcpCompliance(){return await this.service.getMcpCompliance()}async recordToolMetric(t){return await this.service.recordToolMetric(t),{ok:true}}async getToolMetrics(t,e,s,n){return this.service.getToolMetrics(t,e,Number(s)||100,Number(n)||0)}async getToolMetricsSummary(t){return this.service.getToolMetricsSummary(Number(t)||7)}async recordAccuracyQuery(t){return await this.service.recordAccuracyQuery({...t,topKResults:JSON.stringify(t.topKResults),selectedIds:t.selectedIds?JSON.stringify(t.selectedIds):void 0}),{id:t.id}}async getAccuracyQueries(t,e,s,n){return this.service.getAccuracyQueries({engine:t,status:e,limit:Number(s)||50,offset:Number(n)||0})}async updateAccuracyFeedback(t){return await this.service.updateAccuracyFeedback(t.queryId,{relevance:t.relevance,note:t.note}),{ok:true}}async getAccuracyStats(t,e){return this.service.getAccuracyStats(t,e?Number(e):void 0)}async runAutoCheck(){return this.service.runAutoCheck()}};i([Get("runs"),r(0,Query("limit")),r(1,Query("offset")),r(2,Query("source"))],l.prototype,"listRuns",1),i([Get("runs/:id"),r(0,Param("id"))],l.prototype,"getRun",1),i([Get("timeline"),r(0,Query("from")),r(1,Query("to"))],l.prototype,"getTimeline",1),i([Get("runs/:runId/events"),r(0,Param("runId"))],l.prototype,"getRunEvents",1),i([Post("runs/:runId/events"),r(0,Param("runId")),r(1,Body())],l.prototype,"recordRunEvent",1),i([Get("runs/:runId/stats"),r(0,Param("runId"))],l.prototype,"getRunStats",1),i([Post("runs/:id/complete"),r(0,Param("id"))],l.prototype,"completeRun",1),i([Get("stats"),r(0,Query("days"))],l.prototype,"getStats",1),i([Get("roi-summary"),r(0,Query("days"))],l.prototype,"getRoiSummary",1),i([Post("cleanup"),r(0,Body())],l.prototype,"cleanup",1),i([Post("cleanup-stale")],l.prototype,"cleanupStale",1),i([Post("sessions"),r(0,Body())],l.prototype,"createSession",1),i([Get("sessions"),r(0,Query("limit")),r(1,Query("offset")),r(2,Query("projectRoot"))],l.prototype,"listSessions",1),i([Get("sessions/:id"),r(0,Param("id"))],l.prototype,"getSession",1),i([Get("sessions/:id/events"),r(0,Param("id"))],l.prototype,"getSessionEvents",1),i([Post("sessions/:id/close"),r(0,Param("id")),r(1,Body())],l.prototype,"closeSession",1),i([Post("sessions/:id/skill-executions"),r(0,Param("id")),r(1,Body())],l.prototype,"startSessionSkillExecution",1),i([Post("skill-execution/start"),r(0,Body())],l.prototype,"startSkillExecution",1),i([Post("tool-call"),r(0,Body())],l.prototype,"recordToolCall",1),i([Post("tool-call/output"),r(0,Body())],l.prototype,"updateToolCallOutput",1),i([Post("skill-execution/complete"),r(0,Body())],l.prototype,"completeSkillExecution",1),i([Get("executions"),r(0,Query("limit")),r(1,Query("skillName"))],l.prototype,"getExecutions",1),i([Get("executions/:id/events"),r(0,Param("id"))],l.prototype,"getExecutionEvents",1),i([Get("mcp-compliance")],l.prototype,"getMcpCompliance",1),i([Post("tool-metrics"),r(0,Body())],l.prototype,"recordToolMetric",1),i([Get("tool-metrics"),r(0,Query("sessionId")),r(1,Query("toolName")),r(2,Query("limit")),r(3,Query("offset"))],l.prototype,"getToolMetrics",1),i([Get("tool-metrics/summary"),r(0,Query("days"))],l.prototype,"getToolMetricsSummary",1),i([Post("accuracy/query"),r(0,Body())],l.prototype,"recordAccuracyQuery",1),i([Get("accuracy/queries"),r(0,Query("engine")),r(1,Query("status")),r(2,Query("limit")),r(3,Query("offset"))],l.prototype,"getAccuracyQueries",1),i([Post("accuracy/feedback"),r(0,Body())],l.prototype,"updateAccuracyFeedback",1),i([Get("accuracy/stats"),r(0,Query("engine")),r(1,Query("since"))],l.prototype,"getAccuracyStats",1),i([Get("auto-check")],l.prototype,"runAutoCheck",1),l=i([Controller("telemetry"),r(0,Inject(S)),r(1,Inject(D)),r(2,Inject(f))],l);var y=class{constructor(t,e){this.service=t;this.projects=e;}resolveRootPath(t,e){let s=t??e??this.projects.getActiveProjectRoot();if(!s)throw new BadRequestException({error:{code:g.BAD_REQUEST,message:"rootPath is required \u2014 no active project connected",details:{}}});return s}async getAll(t,e){return this.service.getAll(this.resolveRootPath(t,e))}async add(t,e,s){return this.service.add(this.resolveRootPath(t,s),e)}async update(t,e,s,n){return await this.service.update(this.resolveRootPath(t,n),e,s),{ok:true}}async delete(t,e,s){return await this.service.delete(this.resolveRootPath(t,s),e),{ok:true}}async getCandidates(t,e){return this.service.getCandidates(this.resolveRootPath(t,e))}async approve(t,e,s){return await this.service.approveCandidate(this.resolveRootPath(t,s),e),{approved:true}}async reject(t,e,s){return await this.service.rejectCandidate(this.resolveRootPath(t,s),e),{rejected:true}}async search(t,e,s){return this.service.search(this.resolveRootPath(t,s),e.query,{limit:e.limit,categories:e.categories})}async extract(t,e,s){return this.service.extract(this.resolveRootPath(t,s),e.events)}async ollamaStatus(){return this.service.getOllamaStatus()}async updateLegacy(t,e,s,n,o){return await this.service.updateLegacy(this.resolveRootPath(t,o),e,s,n.value),{ok:true}}async recordEvent(t,e,s){return this.service.recordEvent(this.resolveRootPath(t,s),e)}async processEvents(t,e,s){return this.service.processSessionEvents(this.resolveRootPath(t,e))}};i([Get(),r(0,Query("rootPath")),r(1,Headers("x-devflow-project"))],y.prototype,"getAll",1),i([Post(),r(0,Query("rootPath")),r(1,Body()),r(2,Headers("x-devflow-project"))],y.prototype,"add",1),i([Put(":id"),r(0,Query("rootPath")),r(1,Param("id")),r(2,Body()),r(3,Headers("x-devflow-project"))],y.prototype,"update",1),i([Delete(":id"),r(0,Query("rootPath")),r(1,Param("id")),r(2,Headers("x-devflow-project"))],y.prototype,"delete",1),i([Get("candidates"),r(0,Query("rootPath")),r(1,Headers("x-devflow-project"))],y.prototype,"getCandidates",1),i([Post("candidates/:id/approve"),r(0,Query("rootPath")),r(1,Param("id")),r(2,Headers("x-devflow-project"))],y.prototype,"approve",1),i([Post("candidates/:id/reject"),r(0,Query("rootPath")),r(1,Param("id")),r(2,Headers("x-devflow-project"))],y.prototype,"reject",1),i([Post("search"),r(0,Query("rootPath")),r(1,Body()),r(2,Headers("x-devflow-project"))],y.prototype,"search",1),i([Post("extract"),r(0,Query("rootPath")),r(1,Body()),r(2,Headers("x-devflow-project"))],y.prototype,"extract",1),i([Get("ollama/status")],y.prototype,"ollamaStatus",1),i([Put(":layer/:key"),r(0,Query("rootPath")),r(1,Param("layer")),r(2,Param("key")),r(3,Body()),r(4,Headers("x-devflow-project"))],y.prototype,"updateLegacy",1),i([Post("events"),r(0,Query("rootPath")),r(1,Body()),r(2,Headers("x-devflow-project"))],y.prototype,"recordEvent",1),i([Post("process"),r(0,Query("rootPath")),r(1,Headers("x-devflow-project")),r(2,Body())],y.prototype,"processEvents",1),y=i([Controller("memory"),r(0,Inject(D)),r(1,Inject(f))],y);var it=class{};it=i([Module({imports:[forwardRef(()=>N),w],controllers:[y],providers:[D],exports:[D]})],it);var J=class{};J=i([Module({imports:[it,w],controllers:[l],providers:[S],exports:[S]})],J);var ot=class{};ot=i([Module({imports:[J],controllers:[_],providers:[O],exports:[O]})],ot);var N=class{};N=i([Module({imports:[w,ot],controllers:[E],providers:[F],exports:[F]})],N);var U=class{async getFullGraph(t){let{graph:e}=await createEngines(t);return e.export()}async getSubGraph(t,e,s){let{graph:n}=await createEngines(t);return n.getSubGraph(e,s)}async getLayeredGraph(t){let{graph:e}=await createEngines(t);return e.getLayeredGraph()}async getNode(t,e){let{codegraph:s}=await createEngines(t),n=s.getNode(e);if(!n)throw new NotFoundException({error:{code:g.NODE_NOT_FOUND,message:`Node "${e}" not found`,details:{}}});return n}async expandNode(t,e,s,n){let{graph:o}=await createEngines(t),a=o.expand([e],{depth:s,direction:n});return {node:a.nodes.find(m=>m.id===e),subGraph:a}}};U=i([Injectable()],U);var B=class{constructor(t,e){this.service=t;this.projects=e;}resolveRootPath(t,e){let s=t??e??this.projects.getActiveProjectRoot();if(!s)throw new BadRequestException({error:{code:g.BAD_REQUEST,message:"rootPath is required \u2014 no active project connected",details:{}}});return s}async getFullGraph(t,e,s,n,o){let a=this.resolveRootPath(t,o);return s?this.service.getSubGraph(a,s,Number(n)||2):e==="layered"?this.service.getLayeredGraph(a):this.service.getFullGraph(a)}async getNode(t,e,s){return this.service.getNode(this.resolveRootPath(t,s),e)}async expandNode(t,e,s,n,o){return this.service.expandNode(this.resolveRootPath(t,o),e,Number(s)||2,n||"both")}};i([Get(),r(0,Query("rootPath")),r(1,Query("view")),r(2,Query("target")),r(3,Query("depth")),r(4,Headers("x-devflow-project"))],B.prototype,"getFullGraph",1),i([Get(":nodeId"),r(0,Query("rootPath")),r(1,Param("nodeId")),r(2,Headers("x-devflow-project"))],B.prototype,"getNode",1),i([Get(":nodeId/expand"),r(0,Query("rootPath")),r(1,Param("nodeId")),r(2,Query("depth")),r(3,Query("direction")),r(4,Headers("x-devflow-project"))],B.prototype,"expandNode",1),B=i([Controller("graph"),r(0,Inject(U)),r(1,Inject(f))],B);var at=class{};at=i([Module({imports:[N,w],controllers:[B],providers:[U],exports:[U]})],at);var L=class{constructor(t){this.db=t;this.engine=new WorkflowEngine;this.events=new Map;this.engineRunIds=new Map;}async onModuleInit(){try{clearPluginCache();let t=await loadPlugins(),e=Array.from(t.values());for(let n of e)for(let o of n.workflow?.templates??[])this.engine.register(o);let s=await this.engine.list();console.log(`[WorkflowService] Loaded ${e.length} plugins with ${s.length} workflows`);}catch(t){console.error("[WorkflowService] Failed to load plugins:",t);}}async list(){return this.engine.list()}async run(t,e){if(!(await this.engine.list()).find(a=>a.name===t))throw new NotFoundException({error:{code:g.WORKFLOW_NOT_FOUND,message:`Workflow "${t}" not found`,details:{}}});let n=`run_${Date.now()}_${Math.random().toString(36).slice(2,7)}`,o=new Subject;if(this.events.set(n,o),this.db)try{this.db.insertSkillExecution({executionId:n,skillName:`workflow:${t}`,startedAt:Date.now(),status:"running"});}catch{}return this.engine.run(t,e).then(a=>{if(this.engineRunIds.set(n,a.runId),a.status!=="running"&&this.db)try{this.db.updateSkillExecution(n,{status:a.status==="success"?"completed":"failed",finishedAt:Date.now()});}catch{}this.engineRunIds.set(n,a.runId);let m=this.engine.getRun(a.runId);if(m){for(let p of m.steps)o.next({runId:n,stepId:p.stepId,status:p.status==="success"?"completed":p.status==="failed"?"failed":"started",output:p.output,error:p.error,timestamp:Date.now()});a.status!=="running"&&o.complete();}a.status==="running"&&this.engine.onEvent(a.runId,p=>{o.next({runId:n,stepId:p.stepId,status:p.type==="step-done"?"completed":p.type==="step-error"?"failed":"started",output:"output"in p?p.output:void 0,error:"error"in p?p.error:void 0,timestamp:Date.now()});});}).catch(a=>{if(this.db)try{this.db.updateSkillExecution(n,{status:"failed",finishedAt:Date.now()});}catch{}o.next({runId:n,stepId:"engine",status:"failed",error:a.message,timestamp:Date.now()}),o.complete();}),{runId:n}}async listRuns(t,e){return (await this.engine.listRuns()).map(o=>({runId:Array.from(this.engineRunIds.entries()).find(([,m])=>m===o.runId)?.[0]??o.runId,workflowName:o.type,status:o.status,steps:o.steps.map(m=>({stepId:m.stepId,status:m.status,output:m.output,error:m.error,startedAt:0})),startedAt:o.startedAt,finishedAt:o.finishedAt})).slice(e,e+t)}async getRun(t){let e=this.engineRunIds.get(t)??t,s=this.engine.getRun(e);if(!s)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Run "${t}" not found`,details:{}}});return {runId:t,workflowName:s.type,status:s.status,steps:s.steps.map(n=>({stepId:n.stepId,status:n.status,output:n.output,error:n.error})),startedAt:s.startedAt,finishedAt:s.finishedAt}}streamRun(t){let e=this.events.get(t);if(!e)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Run "${t}" not found`,details:{}}});return e}async approveRun(t){let e=this.engineRunIds.get(t)??t,s=this.engine.getRun(e);if(!s)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Run "${t}" not found`,details:{}}});let n=s.steps.find(o=>o.status==="awaiting_approval");n&&await this.engine.approve(e,n.stepId);}async rejectRun(t,e){let s=this.engineRunIds.get(t)??t,n=this.engine.getRun(s);if(!n)throw new NotFoundException({error:{code:g.RUN_NOT_FOUND,message:`Run "${t}" not found`,details:{}}});let o=n.steps.find(a=>a.status==="awaiting_approval");o&&await this.engine.reject(s,o.stepId,e??"Rejected");}async getNextStep(t){if(!t){(await this.engine.list())[0];return null}let e=this.engineRunIds.get(t)??t,s=this.engine.getRun(e);return s?(Array.isArray(s.steps)?s.steps:[]).find(o=>o.status==="pending")??null:null}};L=i([Injectable(),r(0,Optional()),r(0,Inject("DATABASE"))],L);var P=class{constructor(t){this.service=t;}async list(){return this.service.list()}async run(t,e){return this.service.run(t,e.input??{})}async listRuns(t,e){return this.service.listRuns(Number(t)||20,Number(e)||0)}async getRun(t){return this.service.getRun(t)}async stream(t,e){e.raw.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let n=this.service.streamRun(t).subscribe({next:o=>{e.raw.write(`event: step-${o.status}
2
- data: ${JSON.stringify(o)}
3
-
4
- `);},error:o=>{e.raw.write(`event: error
5
- data: ${JSON.stringify({error:o.message})}
6
-
7
- `),e.raw.end();},complete:()=>{e.raw.write(`event: done
8
- data: {}
9
-
10
- `),e.raw.end();}});e.raw.on("close",()=>n.unsubscribe());}async approve(t){return await this.service.approveRun(t),{approved:true}}async reject(t,e){return await this.service.rejectRun(t,e.reason),{rejected:true}}async nextStep(t){return this.service.getNextStep(t)}};i([Get()],P.prototype,"list",1),i([Post(":type/run"),r(0,Param("type")),r(1,Body())],P.prototype,"run",1),i([Get("runs"),r(0,Query("limit")),r(1,Query("offset"))],P.prototype,"listRuns",1),i([Get("runs/:id"),r(0,Param("id"))],P.prototype,"getRun",1),i([Get("runs/:id/stream"),r(0,Param("id")),r(1,Res())],P.prototype,"stream",1),i([Post("runs/:id/approve"),r(0,Param("id"))],P.prototype,"approve",1),i([Post("runs/:id/reject"),r(0,Param("id")),r(1,Body())],P.prototype,"reject",1),i([Get("next-step"),r(0,Query("runId"))],P.prototype,"nextStep",1),P=i([Controller("workflows"),r(0,Inject(L))],P);var ct=class{};ct=i([Module({controllers:[P],providers:[L],exports:[L]})],ct);var q=class{constructor(t){this.projectsService=t;}getEngine(t){return new KnowledgeEngine({projectRoot:t})}async onModuleInit(){this._initKnowledge();}async _initKnowledge(){let t=this.projectsService.getActiveProjectRoot()??process.env.DEVFLOW_PROJECT_ROOT??process.cwd();try{let e=this.getEngine(t),s=await loadPlugins(),n=Array.from(s.values());for(let m of n)for(let p of m.knowledge?.sources??[])await e.registerSource({...p,version:p.version||m.meta.version});let o=await e.getSources(),a=Date.now()-10080*60*1e3;for(let m of o)(!m.lastSyncTime||m.lastSyncTime<a)&&await e.syncDocs(m.source.name);}catch{}}async search(t,e,s){return this.getEngine(t).search(e,{sources:s&&s!=="all"?[s]:void 0})}async sync(t,e){return this.getEngine(t).syncDocs(e??"")}async getSources(t){return this.getEngine(t).getSources()}};q=i([Injectable(),r(0,Inject(f))],q);var $=class{constructor(t,e){this.service=t;this.projects=e;}resolveRootPath(t,e){let s=t??e??this.projects.getActiveProjectRoot();if(!s)throw new BadRequestException("rootPath is required \u2014 no active project connected");return s}async search(t,e,s,n){return this.service.search(this.resolveRootPath(t,n),e??"",s)}async sync(t,e){return this.service.sync(this.resolveRootPath(t.rootPath,e),t.pluginName)}async getSources(t,e){return this.service.getSources(this.resolveRootPath(t,e))}};i([Get("search"),r(0,Query("rootPath")),r(1,Query("q")),r(2,Query("scope")),r(3,Headers("x-devflow-project"))],$.prototype,"search",1),i([Post("sync"),r(0,Body()),r(1,Headers("x-devflow-project"))],$.prototype,"sync",1),i([Get("sources"),r(0,Query("rootPath")),r(1,Headers("x-devflow-project"))],$.prototype,"getSources",1),$=i([Controller("knowledge"),r(0,Inject(q)),r(1,Inject(f))],$);var ut=class{};ut=i([Module({imports:[N,w],controllers:[$],providers:[q],exports:[q]})],ut);var G=class{constructor(){this.results=[];this.scenarioIds=[];this.engine=new BenchmarkEngine,this.registerDefaultScenarios();}registerDefaultScenarios(){let t=[{id:"understand-codebase",category:"understand",desc:"\u7406\u89E3\u4EE3\u7801\u5E93\u67B6\u6784",expectedFiles:2},{id:"modify-component",category:"modify",desc:"\u4FEE\u6539 React \u7EC4\u4EF6",expectedFiles:1,expectedComponents:1},{id:"review-code",category:"review",desc:"\u4EE3\u7801\u5BA1\u67E5",expectedIssues:2}];for(let e of t)this.engine.registerScenario(e),this.scenarioIds.push(e.id);}async runScenarioSet(t){let e=async a=>({prepTimeMs:1e3+Math.random()*500,tokenCount:500+Math.floor(Math.random()*200),firstPassSuccess:Math.random()>.5,reworkCount:Math.floor(Math.random()*3),durationMs:5e3+Math.random()*3e3}),s=async a=>({prepTimeMs:500+Math.random()*300,tokenCount:300+Math.floor(Math.random()*100),firstPassSuccess:Math.random()>.2,reworkCount:Math.floor(Math.random()*2),durationMs:3e3+Math.random()*2e3}),n=t??this.scenarioIds,o=await this.engine.runScenarioBatch(n,e,s);return this.results=o,o}async getScenarioResults(){return this.results.length===0&&await this.runScenarioSet(),this.results}async getComparisonSummary(){let t=await this.getScenarioResults(),e=t.length;return {totalScenarios:e,avgTimeSavedRate:t.reduce((s,n)=>s+n.comparison.timeSavedRate,0)/e,avgTokenReductionRate:t.reduce((s,n)=>s+n.comparison.tokenReductionRate,0)/e,avgFirstPassLift:t.reduce((s,n)=>s+n.comparison.firstPassLift,0)/e,avgReworkReductionRate:t.reduce((s,n)=>s+n.comparison.reworkReductionRate,0)/e}}async getExperimentalRoiSummary(){let t=await this.getComparisonSummary();return {totalScenarios:t.totalScenarios,avgTimeSavedRate:t.avgTimeSavedRate,avgTokenReductionRate:t.avgTokenReductionRate,avgFirstPassLift:t.avgFirstPassLift,avgReworkReductionRate:t.avgReworkReductionRate,conclusion:"DevFlow shows significant improvement in all metrics"}}};G=i([Injectable()],G);var M=class{constructor(t){this.service=t;}async run(t){return this.service.runScenarioSet(t.scenarioIds)}async getResults(){return this.service.getScenarioResults()}async getComparisonSummary(){return this.service.getComparisonSummary()}async getExperimentalRoiSummary(){return this.service.getExperimentalRoiSummary()}};i([Post("run"),r(0,Body())],M.prototype,"run",1),i([Get("results")],M.prototype,"getResults",1),i([Get("summary")],M.prototype,"getComparisonSummary",1),i([Get("roi-summary")],M.prototype,"getExperimentalRoiSummary",1),M=i([Controller("benchmark"),r(0,Inject(G))],M);var lt=class{};lt=i([Module({controllers:[M],providers:[G],exports:[G]})],lt);var K=class{constructor(t){this.telemetryService=t;this.plugins=new Map;this.installRecords=[];}async list(t,e){let s=Array.from(this.plugins.values());if(t){let n=t.toLowerCase();s=s.filter(o=>o.name.toLowerCase().includes(n)||o.description.toLowerCase().includes(n));}return e&&(s=s.filter(n=>n.tags.includes(e))),s}async getByName(t){let e=this.plugins.get(t);if(!e)throw new NotFoundException({error:{code:g.PLUGIN_NOT_FOUND,message:`Plugin "${t}" not found`,details:{}}});return e}async publish(t){let e=t.npmPackage.replace(/^@devflow-tools\/plugin-/,""),s={name:e,npmPackage:t.npmPackage,version:t.version,description:t.description,tags:t.tags??[],createdAt:Date.now()};return this.plugins.set(e,s),s}async install(t,e){let s=t.startsWith("@devflow-tools/plugin-")?t:`@devflow-tools/plugin-${t}`,n=t.replace(/^@devflow-tools\/plugin-/,"");return this.plugins.set(n,{name:n,npmPackage:s,version:"0.1.0",description:"Installed plugin",tags:[],createdAt:Date.now()}),e&&await this.recordPluginInstall(n,e),{ok:true,name:n}}async uninstall(t,e){let s=t.replace(/^@devflow-tools\/plugin-/,"");return this.plugins.delete(s),e&&await this.recordPluginUninstall(s,e),{ok:true,name:s}}async recordPluginInstall(t,e){let s=this.installRecords.find(n=>n.pluginName===t&&n.projectRoot===e);s?s.uninstalledAt=void 0:this.installRecords.push({pluginName:t,projectRoot:e,installedAt:Date.now()});}async recordPluginUninstall(t,e){let s=this.installRecords.find(n=>n.pluginName===t&&n.projectRoot===e);s&&(s.uninstalledAt=Date.now());}async listInstalledProjects(t){return this.installRecords.filter(e=>e.pluginName===t&&!e.uninstalledAt).map(e=>e.projectRoot)}async buildPluginEffectiveness(t){let s=(await this.listInstalledProjects(t)).length,n=await this.telemetryService.getPluginUsageStats(t),o=s>0?n.activeProjects/s:0,a=n.totalRuns>0?n.successfulRuns/n.totalRuns:0,m="optimize";return o>.7&&a>.8?m="install":(o<.3||a<.5)&&(m="remove"),{name:t,installCount:s,usageCount:n.totalRuns,activeRate:o,successRate:a,lastUsedAt:n.lastUsedAt,recommendation:m}}async getPluginEffectiveness(t){let e=t?this.installRecords.filter(o=>o.projectRoot===t&&!o.uninstalledAt):this.installRecords.filter(o=>!o.uninstalledAt),s=[...new Set(e.map(o=>o.pluginName))],n=[];for(let o of s){let a=await this.buildPluginEffectiveness(o);n.push(a);}return n}};K=i([Injectable(),r(0,Inject(S))],K);var j=class{constructor(t){this.service=t;}async list(t,e){return this.service.list(t,e)}async getPluginEffectiveness(t){return this.service.getPluginEffectiveness(t)}async getByName(t){return this.service.getByName(t)}async publish(t){return this.service.publish(t)}async install(t,e){return this.service.install(t.name,t.rootPath??e)}async uninstall(t,e,s){return this.service.uninstall(t,e.rootPath??s)}};i([Get("plugins"),r(0,Query("search")),r(1,Query("tag"))],j.prototype,"list",1),i([Get("plugins/effectiveness"),r(0,Query("rootPath"))],j.prototype,"getPluginEffectiveness",1),i([Get("plugins/:name"),r(0,Param("name"))],j.prototype,"getByName",1),i([Post("plugins"),r(0,Body())],j.prototype,"publish",1),i([Post("plugins/install"),r(0,Body()),r(1,Headers("x-devflow-project"))],j.prototype,"install",1),i([Post("plugins/:name/uninstall"),r(0,Param("name")),r(1,Body()),r(2,Headers("x-devflow-project"))],j.prototype,"uninstall",1),j=i([Controller("registry"),r(0,Inject(K))],j);var dt=class{};dt=i([Module({imports:[J],controllers:[j],providers:[K],exports:[K]})],dt);var ye={provide:"DATABASE",useFactory:()=>{let c=process.env.DEVFLOW_STATE_DIR??join(homedir(),".devflow","global");return new DevFlowDatabase(c)}},mt=class{};mt=i([Global(),Module({providers:[ye],exports:[ye]})],mt);var gt=class{intercept(t,e){return e.handle().pipe(map(s=>s&&typeof s=="object"&&"error"in s?s:{ok:true,data:s??null}))}};gt=i([Injectable()],gt);var et=class{constructor(){this.startTime=Date.now();}health(){return {version:"0.2.3",uptime:Date.now()-this.startTime}}};i([Yt(),Get("health")],et.prototype,"health",1),et=i([Controller()],et);var pt=class{};pt=i([Module({imports:[mt,st,w,N,at,ut,ct,lt,dt],controllers:[et],providers:[{provide:APP_INTERCEPTOR,useClass:gt}]})],pt);function ve(c){return c===400?g.BAD_REQUEST:c===404?g.PROJECT_NOT_FOUND:c===422?g.VALIDATION_ERROR:g.INTERNAL_ERROR}var V=class{constructor(){this.logger=new Logger(V.name);}catch(t,e){let n=e.switchToHttp().getResponse();if(t instanceof HttpException){let o=t.getStatus(),a=t.getResponse();if(typeof a=="object"&&a!==null&&"error"in a){let p=a.error;if(typeof p=="object"&&p!==null&&"code"in p){n.status(o).send(a);return}let Q=typeof a.message=="string"?a.message:"Request failed";n.status(o).send({error:{code:ve(o),message:Q,details:{}}});return}let m=typeof a=="string"?a:a.message??"Request failed";n.status(o).send({error:{code:ve(o),message:m,details:{}}});return}this.logger.error("Unhandled exception",t instanceof Error?t.stack:String(t)),n.status(HttpStatus.INTERNAL_SERVER_ERROR).send({error:{code:g.INTERNAL_ERROR,message:"Internal server error",details:{}}});}};V=i([Catch()],V);async function mr(){let c=new FastifyAdapter,t=await NestFactory.create(pt,c);return t.setGlobalPrefix("api"),t.useGlobalFilters(new V),t.enableCors({origin:true,credentials:true}),c.getInstance().addHook("preParsing",async(s,n,o)=>{if(s.headers["content-length"]==="0"){let a=Buffer.from("{}");return s.headers["content-length"]=String(a.length),Readable.from([a])}return o}),await t.listen({port:parseInt(process.env.PORT||"13337",10),host:"127.0.0.1"}),t}(process.argv[1]?.endsWith("main.js")||process.argv[1]?.endsWith("main.ts")||process.argv[1]?.endsWith("server.js"))&&mr();export{mr as bootstrap};