glenn-code 1.0.0 → 1.0.2

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Glenn Code - Bundled and minified
2
2
  // (c) DNM Lab - All rights reserved
3
3
 
4
- import{createSdkMcpServer as jt}from"@anthropic-ai/claude-agent-sdk";import{tool as ce}from"@anthropic-ai/claude-agent-sdk";import{z as ae}from"zod";import*as le from"fs";import*as Je from"path";var N=null;function de(e){N=e}function Fe(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}var xn=ce("save_specification",`Save a specification to the database.
4
+ import{createSdkMcpServer as Bt}from"@anthropic-ai/claude-agent-sdk";import{tool as de}from"@anthropic-ai/claude-agent-sdk";import{z as le}from"zod";import*as pe from"fs";import*as Ze from"path";var N=null;function ue(e){N=e}function Fe(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")}var Rn=de("save_specification",`Save a specification to the database.
5
5
 
6
6
  IMPORTANT: First write the specification content to a file using the Write tool, then call this with the file path.
7
7
 
@@ -12,10 +12,10 @@ Workflow:
12
12
 
13
13
  Example:
14
14
  1. Write tool \u2192 save to /tmp/user-auth-spec.md
15
- 2. save_specification(name: "User Authentication", filePath: "/tmp/user-auth-spec.md")`,{name:ae.string().describe("Specification name (e.g., 'User Authentication')"),filePath:ae.string().describe("Path to the file containing the specification content (written via Write tool)")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Je.resolve(e.filePath);if(!le.existsSync(t))return{content:[{type:"text",text:`\u274C File not found: ${e.filePath}. Use Write tool first to create the file.`}]};let n=le.readFileSync(t,"utf-8"),s=Fe(e.name);return await N.saveSpecification(s,n),{content:[{type:"text",text:`\u2705 Saved specification: ${s}.spec.md`}]}}),In=ce("read_specification","Read the content of a specification.",{name:ae.string().describe("Name of the specification to read")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Fe(e.name),n=await N.getSpecification(t);return n?{content:[{type:"text",text:n}]}:{content:[{type:"text",text:`\u274C Specification "${e.name}" not found.`}]}}),Rn=ce("list_specifications","List all specifications.",{},async()=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let e=await N.listSpecifications();return e.length===0?{content:[{type:"text",text:"\u{1F4CB} No specifications found."}]}:{content:[{type:"text",text:`\u{1F4CB} Specifications:
15
+ 2. save_specification(name: "User Authentication", filePath: "/tmp/user-auth-spec.md")`,{name:le.string().describe("Specification name (e.g., 'User Authentication')"),filePath:le.string().describe("Path to the file containing the specification content (written via Write tool)")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Ze.resolve(e.filePath);if(!pe.existsSync(t))return{content:[{type:"text",text:`\u274C File not found: ${e.filePath}. Use Write tool first to create the file.`}]};let n=pe.readFileSync(t,"utf-8"),s=Fe(e.name);return await N.saveSpecification(s,n),{content:[{type:"text",text:`\u2705 Saved specification: ${s}.spec.md`}]}}),On=de("read_specification","Read the content of a specification.",{name:le.string().describe("Name of the specification to read")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Fe(e.name),n=await N.getSpecification(t);return n?{content:[{type:"text",text:n}]}:{content:[{type:"text",text:`\u274C Specification "${e.name}" not found.`}]}}),Dn=de("list_specifications","List all specifications.",{},async()=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let e=await N.listSpecifications();return e.length===0?{content:[{type:"text",text:"\u{1F4CB} No specifications found."}]}:{content:[{type:"text",text:`\u{1F4CB} Specifications:
16
16
 
17
17
  ${e.map(n=>`- ${n.name} (${n.slug}.spec.md)`).join(`
18
- `)}`}]}}),On=ce("delete_specification","Delete a specification.",{name:ae.string().describe("Name of the specification to delete")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Fe(e.name);return await N.deleteSpecification(t)?{content:[{type:"text",text:`\u{1F5D1}\uFE0F Deleted: ${t}.spec.md`}]}:{content:[{type:"text",text:`\u274C Specification "${e.name}" not found.`}]}});import{tool as q}from"@anthropic-ai/claude-agent-sdk";import{z as J}from"zod";var S=null;function pe(e){S=e}var Xe=q("restart_services",`Rebuild and restart services. Call this after making backend changes (.cs files) to apply them.
18
+ `)}`}]}}),Fn=de("delete_specification","Delete a specification.",{name:le.string().describe("Name of the specification to delete")},async e=>{if(!N)return{content:[{type:"text",text:"\u274C Planning transport not initialized"}]};let t=Fe(e.name);return await N.deleteSpecification(t)?{content:[{type:"text",text:`\u{1F5D1}\uFE0F Deleted: ${t}.spec.md`}]}:{content:[{type:"text",text:`\u274C Specification "${e.name}" not found.`}]}});import{tool as q}from"@anthropic-ai/claude-agent-sdk";import{z as J}from"zod";var S=null;function ge(e){S=e}var et=q("restart_services",`Rebuild and restart services. Call this after making backend changes (.cs files) to apply them.
19
19
 
20
20
  Parameters:
21
21
  - target: "backend" (default) | "frontend" | "both"
@@ -25,37 +25,37 @@ Use target="frontend" if Vite is stuck (rare, HMR usually works).
25
25
  Use target="both" if unsure or both need restart.`,{target:J.enum(["backend","frontend","both"]).default("backend").describe("Which service to restart")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=e.target||"backend";console.log(`[MCP] restart_services called (target: ${t})`);let n=await S.restartServices(t);if(!n.success){let o=[];return n.backendError&&o.push(`Backend: ${n.backendError}`),n.frontendError&&o.push(`Frontend: ${n.frontendError}`),{content:[{type:"text",text:`\u274C Restart failed:
26
26
  ${o.join(`
27
27
 
28
- `)}`}]}}return{content:[{type:"text",text:`\u2705 ${t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend"} restarted successfully.`}]}}),Ze=q("stop_services",`Stop running services. Call this BEFORE running scaffold to prevent port conflicts and ensure clean migrations.
28
+ `)}`}]}}return{content:[{type:"text",text:`\u2705 ${t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend"} restarted successfully.`}]}}),tt=q("stop_services",`Stop running services. Call this BEFORE running scaffold to prevent port conflicts and ensure clean migrations.
29
29
 
30
30
  Parameters:
31
31
  - target: "backend" (default) | "frontend" | "both"
32
32
 
33
- Use target="backend" before running scaffold (required for migrations).`,{target:J.enum(["backend","frontend","both"]).default("backend").describe("Which service to stop")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=e.target||"backend";console.log(`[MCP] stop_services called (target: ${t})`);let n=t==="backend"||t==="both",s=t==="frontend"||t==="both";n&&await S.stopBackend(),s&&await S.stopFrontend();let o=5e3,r=Date.now(),i=!n,l=!s;for(;Date.now()-r<o;){let m=await S.checkHealth();if(n&&!m.api&&(i=!0),s&&!m.web&&(l=!0),i&&l)break;await new Promise(v=>setTimeout(v,500))}let h=t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend";return{content:[{type:"text",text:i&&l?`\u2705 ${h} stopped successfully.`:`\u26A0\uFE0F ${h} stop requested but health check still shows running. Proceeding anyway.`}]}}),et=q("start_services",`Start services. Call this AFTER running scaffold to bring services back up.
33
+ Use target="backend" before running scaffold (required for migrations).`,{target:J.enum(["backend","frontend","both"]).default("backend").describe("Which service to stop")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=e.target||"backend";console.log(`[MCP] stop_services called (target: ${t})`);let n=t==="backend"||t==="both",s=t==="frontend"||t==="both";n&&await S.stopBackend(),s&&await S.stopFrontend();let o=5e3,r=Date.now(),i=!n,l=!s;for(;Date.now()-r<o;){let m=await S.checkHealth();if(n&&!m.api&&(i=!0),s&&!m.web&&(l=!0),i&&l)break;await new Promise(v=>setTimeout(v,500))}let h=t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend";return{content:[{type:"text",text:i&&l?`\u2705 ${h} stopped successfully.`:`\u26A0\uFE0F ${h} stop requested but health check still shows running. Proceeding anyway.`}]}}),nt=q("start_services",`Start services. Call this AFTER running scaffold to bring services back up.
34
34
 
35
35
  Parameters:
36
36
  - target: "backend" (default) | "frontend" | "both"
37
37
 
38
- Use target="backend" after running scaffold.`,{target:J.enum(["backend","frontend","both"]).default("backend").describe("Which service to start")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=e.target||"backend";console.log(`[MCP] start_services called (target: ${t})`);let n=t==="backend"||t==="both",s=t==="frontend"||t==="both";n&&await S.startBackend(),s&&await S.startFrontend();let o=await S.waitForHealth(15e3),r=!n||o.api,i=!s||o.web,l=r&&i,h=t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend";if(!l){let f=[];return n&&!o.api&&f.push("Backend failed to start"),s&&!o.web&&f.push("Frontend failed to start"),{content:[{type:"text",text:`\u274C ${h} failed to start: ${f.join(", ")}`}]}}return{content:[{type:"text",text:`\u2705 ${h} started successfully.`}]}}),tt=q("check_service_health",`Check if services are running and healthy. Returns current status of backend API and frontend.
38
+ Use target="backend" after running scaffold.`,{target:J.enum(["backend","frontend","both"]).default("backend").describe("Which service to start")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=e.target||"backend";console.log(`[MCP] start_services called (target: ${t})`);let n=t==="backend"||t==="both",s=t==="frontend"||t==="both";n&&await S.startBackend(),s&&await S.startFrontend();let o=await S.waitForHealth(15e3),r=!n||o.api,i=!s||o.web,l=r&&i,h=t==="both"?"Backend and frontend":t==="backend"?"Backend":"Frontend";if(!l){let f=[];return n&&!o.api&&f.push("Backend failed to start"),s&&!o.web&&f.push("Frontend failed to start"),{content:[{type:"text",text:`\u274C ${h} failed to start: ${f.join(", ")}`}]}}return{content:[{type:"text",text:`\u2705 ${h} started successfully.`}]}}),ot=q("check_service_health",`Check if services are running and healthy. Returns current status of backend API and frontend.
39
39
  Note: This only checks if ports are responding, NOT build/type errors. Use check_backend_build or check_frontend_types for that.`,{},async()=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let e=await S.checkHealth();return{content:[{type:"text",text:`Service Health:
40
40
  \u{1F5A5}\uFE0F Backend API: ${e.api?"\u2705 running":"\u274C not running"}
41
- \u{1F310} Frontend: ${e.web?"\u2705 running":"\u274C not running"}`}]}}),nt=q("check_backend_build","Run dotnet build to check for C# compilation errors. Use this after fixing backend code to verify the fix works.",{},async()=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};console.log("[MCP] check_backend_build called");let e=await S.checkBackendBuild();return e.success?{content:[{type:"text",text:"\u2705 Backend build succeeded - no errors"}]}:{content:[{type:"text",text:`\u274C Backend build failed:
41
+ \u{1F310} Frontend: ${e.web?"\u2705 running":"\u274C not running"}`}]}}),st=q("check_backend_build","Run dotnet build to check for C# compilation errors. Use this after fixing backend code to verify the fix works.",{},async()=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};console.log("[MCP] check_backend_build called");let e=await S.checkBackendBuild();return e.success?{content:[{type:"text",text:"\u2705 Backend build succeeded - no errors"}]}:{content:[{type:"text",text:`\u274C Backend build failed:
42
42
 
43
- ${e.errors}`}]}}),ot=q("check_frontend_types","Run TypeScript type check (tsc) on frontend code. Use this after fixing frontend code to verify the fix works.",{},async()=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};console.log("[MCP] check_frontend_types called");let e=await S.checkFrontendTypes();return e.success?{content:[{type:"text",text:"\u2705 Frontend type check passed - no errors"}]}:{content:[{type:"text",text:`\u274C Frontend type errors:
43
+ ${e.errors}`}]}}),rt=q("check_frontend_types","Run TypeScript type check (tsc) on frontend code. Use this after fixing frontend code to verify the fix works.",{},async()=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};console.log("[MCP] check_frontend_types called");let e=await S.checkFrontendTypes();return e.success?{content:[{type:"text",text:"\u2705 Frontend type check passed - no errors"}]}:{content:[{type:"text",text:`\u274C Frontend type errors:
44
44
 
45
- ${e.errors}`}]}}),Nn=q("tail_service_log",`Get the last N lines of service logs. Use this to debug startup failures or verify that the application is running correctly.
45
+ ${e.errors}`}]}}),Ln=q("tail_service_log",`Get the last N lines of service logs. Use this to debug startup failures or verify that the application is running correctly.
46
46
 
47
47
  Parameters:
48
48
  - target: "backend" | "frontend"
49
49
  - lines: number (default 50)`,{target:J.enum(["backend","frontend"]).describe("Which log to read"),lines:J.number().default(50).describe("Number of lines to read")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=await S.tailLogs(e.target,e.lines);return{content:[{type:"text",text:`Last ${e.lines} lines of ${e.target} log:
50
50
 
51
51
  ${t.join(`
52
- `)}`}]}}),Ln=q("check_swagger_endpoints",`Search for endpoints in the generated swagger.json. Use this to verify that new backend endpoints are correctly exposed.
52
+ `)}`}]}}),jn=q("check_swagger_endpoints",`Search for endpoints in the generated swagger.json. Use this to verify that new backend endpoints are correctly exposed.
53
53
 
54
54
  Parameters:
55
55
  - pattern: string (e.g., "users", "api/reports")`,{pattern:J.string().describe("Text to search for in endpoint paths")},async e=>{if(!S)return{content:[{type:"text",text:"\u274C Service manager not initialized"}]};let t=await S.checkSwaggerEndpoints(e.pattern);return t.foundEndpoints.length===0?{content:[{type:"text",text:`\u274C No endpoints found matching "${e.pattern}" (Total endpoints: ${t.totalEndpoints})`}]}:{content:[{type:"text",text:`\u2705 Found ${t.foundEndpoints.length} matching endpoints:
56
56
 
57
57
  ${t.foundEndpoints.join(`
58
- `)}`}]}});import*as W from"fs";import*as st from"path";var Mt="/tmp";function ee(e){let t=st.join(Mt,`agent-questions-${e}.json`);if(!W.existsSync(t))return null;try{let n=W.readFileSync(t,"utf-8");return W.unlinkSync(t),JSON.parse(n)}catch{return null}}import*as E from"fs";import*as ue from"path";function te(e){let t=ue.join(e,".sdd","specifications");function n(){E.existsSync(t)||E.mkdirSync(t,{recursive:!0})}function s(o){return ue.join(t,`${o}.spec.md`)}return{async saveSpecification(o,r){n(),E.writeFileSync(s(o),r,"utf-8")},async getSpecification(o){n();let r=s(o);return E.existsSync(r)?E.readFileSync(r,"utf-8"):null},async listSpecifications(){return n(),E.readdirSync(t).filter(r=>r.endsWith(".spec.md")).map(r=>{let i=E.readFileSync(ue.join(t,r),"utf-8"),l=i.match(/name: "([^"]+)"/),h=i.match(/status: (\w+)/),f=i.match(/version: "([^"]+)"/);return{slug:r.replace(".spec.md",""),name:l?.[1]||r,status:h?.[1]||"unknown",version:f?.[1]||"1.0.0"}})},async deleteSpecification(o){n();let r=s(o);return E.existsSync(r)?(E.unlinkSync(r),!0):!1},async specificationExists(o){return n(),E.existsSync(s(o))}}}function Ue(){return jt({name:"agent-insights",version:"1.0.0",tools:[Xe,Ze,et,tt,nt,ot]})}import{query as on}from"@anthropic-ai/claude-agent-sdk";var Ne={description:"Delegate to this agent when scaffolding new entities or creating CRUD features. This agent handles entity generation using the scaffold CLI with multi-entity support.",model:"inherit",prompt:`You are a scaffolding specialist. Your ONLY job is:
58
+ `)}`}]}});import*as W from"fs";import*as it from"path";var $t="/tmp";function ee(e){let t=it.join($t,`agent-questions-${e}.json`);if(!W.existsSync(t))return null;try{let n=W.readFileSync(t,"utf-8");return W.unlinkSync(t),JSON.parse(n)}catch{return null}}import*as E from"fs";import*as fe from"path";function te(e){let t=fe.join(e,".sdd","specifications");function n(){E.existsSync(t)||E.mkdirSync(t,{recursive:!0})}function s(o){return fe.join(t,`${o}.spec.md`)}return{async saveSpecification(o,r){n(),E.writeFileSync(s(o),r,"utf-8")},async getSpecification(o){n();let r=s(o);return E.existsSync(r)?E.readFileSync(r,"utf-8"):null},async listSpecifications(){return n(),E.readdirSync(t).filter(r=>r.endsWith(".spec.md")).map(r=>{let i=E.readFileSync(fe.join(t,r),"utf-8"),l=i.match(/name: "([^"]+)"/),h=i.match(/status: (\w+)/),f=i.match(/version: "([^"]+)"/);return{slug:r.replace(".spec.md",""),name:l?.[1]||r,status:h?.[1]||"unknown",version:f?.[1]||"1.0.0"}})},async deleteSpecification(o){n();let r=s(o);return E.existsSync(r)?(E.unlinkSync(r),!0):!1},async specificationExists(o){return n(),E.existsSync(s(o))}}}function Ue(){return Bt({name:"agent-insights",version:"1.0.0",tools:[et,tt,nt,ot,st,rt]})}import{query as rn}from"@anthropic-ai/claude-agent-sdk";var Ne={description:"Delegate to this agent when scaffolding new entities or creating CRUD features. This agent handles entity generation using the scaffold CLI with multi-entity support.",model:"inherit",prompt:`You are a scaffolding specialist. Your ONLY job is:
59
59
  1. Check existing features (quick ls)
60
60
  2. Write ALL entities to ONE /tmp/scaffold.json (big bang, no phasing!)
61
61
  3. Run scaffold CLI ONCE
@@ -239,7 +239,7 @@ DO NOT phase/split into multiple runs - that's slower and error-prone.
239
239
  - Enrollment depends on Student + CourseOffering - CLI handles it
240
240
  - ONE scaffold run creates ALL 6 entities with correct FK relationships
241
241
 
242
- REMEMBER: ls \u2192 Write \u2192 Run \u2192 Restart \u2192 STOP. No verification needed.`};var ge={description:"Delegate to this agent to fix errors, type issues, or bugs in the code",model:"inherit",prompt:`You are a bug-fixing specialist. Your job is to FIX errors, not just report them.
242
+ REMEMBER: ls \u2192 Write \u2192 Run \u2192 Restart \u2192 STOP. No verification needed.`};var me={description:"Delegate to this agent to fix errors, type issues, or bugs in the code",model:"inherit",prompt:`You are a bug-fixing specialist. Your job is to FIX errors, not just report them.
243
243
 
244
244
  ## Process
245
245
  1. Read the error message carefully - understand WHAT and WHERE
@@ -269,7 +269,7 @@ REMEMBER: ls \u2192 Write \u2192 Run \u2192 Restart \u2192 STOP. No verification
269
269
  - Fix the ROOT CAUSE, not symptoms
270
270
  - Make minimal changes
271
271
  - Don't add unnecessary code
272
- - If multiple files have the same issue, fix all of them`};var fe={description:"Delegate to this agent for specification-driven development. Use when the user wants to plan, specify, or design a feature before implementation.",model:"inherit",prompt:`You are a Spec-Driven Development (SDD) specialist.
272
+ - If multiple files have the same issue, fix all of them`};var he={description:"Delegate to this agent for specification-driven development. Use when the user wants to plan, specify, or design a feature before implementation.",model:"inherit",prompt:`You are a Spec-Driven Development (SDD) specialist.
273
273
 
274
274
  ## \u26D4 CRITICAL RULES - READ FIRST
275
275
 
@@ -428,7 +428,7 @@ Save your spec. The spec will appear in the user's UI.
428
428
  - Ask ONE question at a time (not all at once!)
429
429
  - STOP asking if user says "start implementing"
430
430
  - NEVER output the spec as text - use save_specification
431
- - Maximum 7 questions - don't exhaust the user!`};var Le={description:"Delegate to this agent for writing new backend features (non-scaffold). Custom endpoints, queries, commands, business logic.",model:"inherit",prompt:`You are a backend specialist for .NET 9 / ASP.NET Core.
431
+ - Maximum 7 questions - don't exhaust the user!`};var Me={description:"Delegate to this agent for writing new backend features (non-scaffold). Custom endpoints, queries, commands, business logic.",model:"inherit",prompt:`You are a backend specialist for .NET 9 / ASP.NET Core.
432
432
 
433
433
  ## YOUR ROLE
434
434
  Write custom backend code that goes BEYOND what scaffold generates:
@@ -500,7 +500,7 @@ public class Get{EntityB}LookupHandler : IQueryHandler<Get{EntityB}LookupQuery,
500
500
  2. If build succeeds, generate swagger: \`mcp__agent-insights__restart_services\` (this regenerates swagger)
501
501
  3. Report what you created and STOP
502
502
 
503
- **\u26A0\uFE0F CRITICAL:** Always generate swagger before frontend work begins!`};var Me={description:"Delegate to this agent for writing frontend features. Components, hooks, pages using generated API hooks.",model:"inherit",prompt:`You are a frontend specialist for React 19 + TypeScript + MUI.
503
+ **\u26A0\uFE0F CRITICAL:** Always generate swagger before frontend work begins!`};var Le={description:"Delegate to this agent for writing frontend features. Components, hooks, pages using generated API hooks.",model:"inherit",prompt:`You are a frontend specialist for React 19 + TypeScript + MUI.
504
504
 
505
505
  ## YOUR ROLE
506
506
  Write frontend code using GENERATED API hooks (never manual fetch):
@@ -575,7 +575,7 @@ queryClient.invalidateQueries({ queryKey: getGetApi{Entities}QueryKey() })
575
575
  ## WHEN DONE
576
576
  1. Run typecheck: \`cd /workspace/packages/backoffice-web && npx tsc --noEmit\`
577
577
  2. If errors, fix them
578
- 3. Report what you created and STOP`};var me={description:"Delegate to this agent to help the user write or improve their project context. This agent researches the codebase, asks strategic questions about product goals and users, then writes comprehensive project context.",model:"inherit",prompt:`You are a Project Context Specialist - an expert at understanding codebases and extracting the essential context that helps AI agents work effectively on projects.
578
+ 3. Report what you created and STOP`};var ye={description:"Delegate to this agent to help the user write or improve their project context. This agent researches the codebase, asks strategic questions about product goals and users, then writes comprehensive project context.",model:"inherit",prompt:`You are a Project Context Specialist - an expert at understanding codebases and extracting the essential context that helps AI agents work effectively on projects.
579
579
 
580
580
  ## \u26D4 CRITICAL RULES - READ FIRST
581
581
 
@@ -769,13 +769,13 @@ Before saving, verify your context:
769
769
  3. **Show patterns** - Include small code examples for common tasks
770
770
  4. **Prioritize** - Put most critical info in <critical_rules>
771
771
  5. **Keep it scannable** - Use bullets, clear sections
772
- 6. **Update, don't replace** - If context exists, improve it rather than starting fresh`};import*as X from"fs";import*as it from"path";var he=class{buffer=[];flushInterval=null;sessionId=null;outputDir;flushIntervalMs;constructor(t){this.outputDir=t.outputDir||"/tmp/agent-debug",this.flushIntervalMs=t.flushIntervalMs||3e3,t.enabled&&(this.ensureOutputDir(),this.startFlushInterval())}ensureOutputDir(){X.existsSync(this.outputDir)||X.mkdirSync(this.outputDir,{recursive:!0})}startFlushInterval(){this.flushInterval=setInterval(()=>{this.flush()},this.flushIntervalMs)}setSessionId(t){this.sessionId=t}log(t){let s={timestamp:new Date().toISOString(),message:t};this.buffer.push(JSON.stringify(s,null,2)+`
772
+ 6. **Update, don't replace** - If context exists, improve it rather than starting fresh`};import*as X from"fs";import*as ct from"path";var be=class{buffer=[];flushInterval=null;sessionId=null;outputDir;flushIntervalMs;constructor(t){this.outputDir=t.outputDir||"/tmp/agent-debug",this.flushIntervalMs=t.flushIntervalMs||3e3,t.enabled&&(this.ensureOutputDir(),this.startFlushInterval())}ensureOutputDir(){X.existsSync(this.outputDir)||X.mkdirSync(this.outputDir,{recursive:!0})}startFlushInterval(){this.flushInterval=setInterval(()=>{this.flush()},this.flushIntervalMs)}setSessionId(t){this.sessionId=t}log(t){let s={timestamp:new Date().toISOString(),message:t};this.buffer.push(JSON.stringify(s,null,2)+`
773
773
  ---
774
- `)}getLogFilePath(){let n=(this.sessionId||"unknown").replace(/[^a-zA-Z0-9-]/g,"_").slice(0,50),s=new Date().toISOString().split("T")[0];return it.join(this.outputDir,`session-${s}-${n}.log`)}flush(){if(this.buffer.length===0)return;let t=this.buffer.join("");this.buffer=[];let n=this.getLogFilePath();X.appendFileSync(n,t)}stop(){this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),this.flush()}};function at(e){return e?typeof e=="boolean"?e?new he({enabled:!0}):null:e.enabled?new he(e):null:null}import{z as p}from"zod";import*as je from"fs/promises";import*as K from"path";var ct=p.object({port:p.number(),startCommand:p.string(),buildCommand:p.string().optional(),typecheckCommand:p.string().optional(),logFile:p.string().optional(),healthEndpoint:p.string().optional(),extensions:p.array(p.string())}),$t=p.object({port:p.number(),type:p.enum(["postgres","mysql","sqlite","mongodb"])}),Bt=p.object({command:p.string(),schemaPath:p.string().optional()}),qt=p.object({email:p.string().optional(),name:p.string().optional(),commitPrefix:p.string().optional()}),Wt=p.object({enabled:p.boolean(),port:p.number().optional()}),lt=p.object({version:p.literal("1.0"),paths:p.object({workspace:p.string(),backend:p.string().optional(),frontend:p.string().optional(),features:p.object({backend:p.string().optional(),frontend:p.string().optional()}).optional()}),services:p.object({backend:ct.optional(),frontend:ct.optional(),database:$t.optional()}).optional(),scaffold:Bt.optional(),git:qt.optional(),techStack:p.object({backend:p.array(p.string()).optional(),frontend:p.array(p.string()).optional(),patterns:p.array(p.string()).optional()}).optional(),tunnel:Wt.optional()});function G(e){return{version:"1.0",paths:{workspace:e||process.env.WORKSPACE_DIR||"/workspace",backend:"packages/dotnet-api",frontend:"packages/backoffice-web",features:{backend:"Source/Features",frontend:"src/applications/super-admin/features"}},services:{backend:{port:5338,startCommand:"dotnet run",buildCommand:"dotnet build",typecheckCommand:"dotnet build --no-restore",logFile:"/tmp/api.log",healthEndpoint:"http://localhost:5338",extensions:[".cs",".csproj"]},frontend:{port:5173,startCommand:"npm run dev",typecheckCommand:"npx tsc -p tsconfig.app.json --noEmit",logFile:"/tmp/web.log",healthEndpoint:"http://localhost:5173",extensions:[".ts",".tsx",".json"]},database:{port:43594,type:"postgres"}},scaffold:{command:"scaffold --schema /tmp/scaffold.json --output /workspace --force --full",schemaPath:"/tmp/scaffold.json"},git:{email:"agent@dotnetmentor.se",name:"Agent",commitPrefix:"[agent]"},techStack:{backend:[".NET 9","PostgreSQL","MediatR (CQRS)","EF Core"],frontend:["React 19","TypeScript","Vite","MUI","TanStack Query"],patterns:["Vertical slices","CQRS","Soft delete","Timestamps"]},tunnel:{enabled:!0,port:5173}}}function ye(e,t){if(t)return K.isAbsolute(t)?t:K.join(e.paths.workspace,t)}function H(e){return ye(e,e.paths.backend)}function Y(e){return ye(e,e.paths.frontend)}function be(e){let t=H(e);if(!(!t||!e.paths.features?.backend))return K.join(t,e.paths.features.backend)}function ne(e){let t=Y(e);if(!(!t||!e.paths.features?.frontend))return K.join(t,e.paths.features.frontend)}function ke(e){let t=[];return e.techStack?.backend?.length&&t.push(`**Backend:** ${e.techStack.backend.join(", ")}`),e.techStack?.frontend?.length&&t.push(`**Frontend:** ${e.techStack.frontend.join(", ")}`),e.techStack?.patterns?.length&&t.push(`**Patterns:** ${e.techStack.patterns.join(", ")}`),t.join(`
775
- `)}function Se(e){let t=[];return e.services?.backend&&t.push(`| Backend | ${H(e)} | ${e.services.backend.port} | ${e.services.backend.logFile||"N/A"} |`),e.services?.frontend&&t.push(`| Frontend | ${Y(e)} | ${e.services.frontend.port} | ${e.services.frontend.logFile||"N/A"} |`),e.services?.database&&t.push(`| Database (${e.services.database.type}) | localhost | ${e.services.database.port} | - |`),t.length===0?"":`| Service | Location | Port | Logs |
774
+ `)}getLogFilePath(){let n=(this.sessionId||"unknown").replace(/[^a-zA-Z0-9-]/g,"_").slice(0,50),s=new Date().toISOString().split("T")[0];return ct.join(this.outputDir,`session-${s}-${n}.log`)}flush(){if(this.buffer.length===0)return;let t=this.buffer.join("");this.buffer=[];let n=this.getLogFilePath();X.appendFileSync(n,t)}stop(){this.flushInterval&&(clearInterval(this.flushInterval),this.flushInterval=null),this.flush()}};function lt(e){return e?typeof e=="boolean"?e?new be({enabled:!0}):null:e.enabled?new be(e):null:null}import{z as p}from"zod";import*as je from"fs/promises";import*as K from"path";var dt=p.object({port:p.number(),startCommand:p.string(),buildCommand:p.string().optional(),typecheckCommand:p.string().optional(),logFile:p.string().optional(),healthEndpoint:p.string().optional(),extensions:p.array(p.string())}),qt=p.object({port:p.number(),type:p.enum(["postgres","mysql","sqlite","mongodb"])}),Wt=p.object({command:p.string(),schemaPath:p.string().optional()}),Gt=p.object({email:p.string().optional(),name:p.string().optional(),commitPrefix:p.string().optional()}),Ht=p.object({enabled:p.boolean(),port:p.number().optional()}),pt=p.object({version:p.literal("1.0"),paths:p.object({workspace:p.string(),backend:p.string().optional(),frontend:p.string().optional(),features:p.object({backend:p.string().optional(),frontend:p.string().optional()}).optional()}),services:p.object({backend:dt.optional(),frontend:dt.optional(),database:qt.optional()}).optional(),scaffold:Wt.optional(),git:Gt.optional(),techStack:p.object({backend:p.array(p.string()).optional(),frontend:p.array(p.string()).optional(),patterns:p.array(p.string()).optional()}).optional(),tunnel:Ht.optional()});function G(e){return{version:"1.0",paths:{workspace:e||process.env.WORKSPACE_DIR||"/workspace",backend:"packages/dotnet-api",frontend:"packages/backoffice-web",features:{backend:"Source/Features",frontend:"src/applications/super-admin/features"}},services:{backend:{port:5338,startCommand:"dotnet run",buildCommand:"dotnet build",typecheckCommand:"dotnet build --no-restore",logFile:"/tmp/api.log",healthEndpoint:"http://localhost:5338",extensions:[".cs",".csproj"]},frontend:{port:5173,startCommand:"npm run dev",typecheckCommand:"npx tsc -p tsconfig.app.json --noEmit",logFile:"/tmp/web.log",healthEndpoint:"http://localhost:5173",extensions:[".ts",".tsx",".json"]},database:{port:43594,type:"postgres"}},scaffold:{command:"scaffold --schema /tmp/scaffold.json --output /workspace --force --full",schemaPath:"/tmp/scaffold.json"},git:{email:"agent@dotnetmentor.se",name:"Agent",commitPrefix:"[agent]"},techStack:{backend:[".NET 9","PostgreSQL","MediatR (CQRS)","EF Core"],frontend:["React 19","TypeScript","Vite","MUI","TanStack Query"],patterns:["Vertical slices","CQRS","Soft delete","Timestamps"]},tunnel:{enabled:!0,port:5173}}}function ke(e,t){if(t)return K.isAbsolute(t)?t:K.join(e.paths.workspace,t)}function H(e){return ke(e,e.paths.backend)}function Y(e){return ke(e,e.paths.frontend)}function Se(e){let t=H(e);if(!(!t||!e.paths.features?.backend))return K.join(t,e.paths.features.backend)}function ne(e){let t=Y(e);if(!(!t||!e.paths.features?.frontend))return K.join(t,e.paths.features.frontend)}function we(e){let t=[];return e.techStack?.backend?.length&&t.push(`**Backend:** ${e.techStack.backend.join(", ")}`),e.techStack?.frontend?.length&&t.push(`**Frontend:** ${e.techStack.frontend.join(", ")}`),e.techStack?.patterns?.length&&t.push(`**Patterns:** ${e.techStack.patterns.join(", ")}`),t.join(`
775
+ `)}function _e(e){let t=[];return e.services?.backend&&t.push(`| Backend | ${H(e)} | ${e.services.backend.port} | ${e.services.backend.logFile||"N/A"} |`),e.services?.frontend&&t.push(`| Frontend | ${Y(e)} | ${e.services.frontend.port} | ${e.services.frontend.logFile||"N/A"} |`),e.services?.database&&t.push(`| Database (${e.services.database.type}) | localhost | ${e.services.database.port} | - |`),t.length===0?"":`| Service | Location | Port | Logs |
776
776
  |---------|----------|------|------|
777
777
  ${t.join(`
778
- `)}`}function dt(e={}){let{debugMode:t=!1,projectPrompt:n=null,isLocal:s=!1,projectConfig:o=G(),useDefaultStack:r=!0}=e,i=n?`
778
+ `)}`}function ut(e={}){let{debugMode:t=!1,projectPrompt:n=null,isLocal:s=!1,projectConfig:o=G(),useDefaultStack:r=!0}=e,i=n?`
779
779
  <project_context>
780
780
  ${n}
781
781
  </project_context>
@@ -820,7 +820,7 @@ Then STOP. Do not continue. Do not try to fix it. Wait for user.
820
820
 
821
821
  ---
822
822
 
823
- `:"",h=Vt(o),f=zt(o,s),m=Zt(o,r),v=Jt(r),T=r?en(o):"",_=r?tn(o,s):"",O=Xt(r);return`${i}${l}# Agent Instructions
823
+ `:"",h=Jt(o),f=Xt(o,s),m=tn(o,r),v=Zt(r),T=r?nn(o):"",_=r?on(o,s):"",O=en(r);return`${i}${l}# Agent Instructions
824
824
 
825
825
  ## \u26D4 CRITICAL: EVERYTHING IS A KANBAN TASK
826
826
 
@@ -964,7 +964,7 @@ ${O}
964
964
  ${T}
965
965
 
966
966
  ${_}
967
- `}function Vt(e){let t=ke(e),n=H(e),s=Y(e),o=be(e),r=ne(e),i=[];o&&i.push(`- Backend: "${o}/{Entity}/"`),r&&i.push(`- Frontend: "${r}/{entity}/"`);let l=e.techStack?.patterns?.length?`
967
+ `}function Jt(e){let t=we(e),n=H(e),s=Y(e),o=Se(e),r=ne(e),i=[];o&&i.push(`- Backend: "${o}/{Entity}/"`),r&&i.push(`- Frontend: "${r}/{entity}/"`);let l=e.techStack?.patterns?.length?`
968
968
  **Key patterns:**
969
969
  ${e.techStack.patterns.map(m=>`- ${m}`).join(`
970
970
  `)}`:"",f=e.techStack?.backend?.some(m=>m.includes(".NET")||m.includes("C#"))??!1?`
@@ -976,7 +976,7 @@ ${i.length>0?`
976
976
  ${i.join(`
977
977
  `)}`:""}
978
978
  ${l}${f}
979
- </tech-stack>`}function zt(e,t){return t?`<environment>
979
+ </tech-stack>`}function Xt(e,t){return t?`<environment>
980
980
  **LOCAL MODE - User manages their own services.**
981
981
 
982
982
  You are running on the user's local machine, NOT in a Docker container.
@@ -997,11 +997,11 @@ The user is responsible for:
997
997
  </environment>`:`<environment>
998
998
  Docker container with pre-started services:
999
999
 
1000
- ${Se(e)}
1000
+ ${_e(e)}
1001
1001
  ${e.tunnel?.enabled?"| Tunnel | - | - | Exposes frontend to user |":""}
1002
1002
 
1003
1003
  User sees app through **Cloudflare tunnel** (live preview in browser).
1004
- </environment>`}function Jt(e){return e?`**\u2705 ALWAYS delegate to these subagents:**
1004
+ </environment>`}function Zt(e){return e?`**\u2705 ALWAYS delegate to these subagents:**
1005
1005
 
1006
1006
  | Trigger | Subagent | Example |
1007
1007
  |---------|----------|---------|
@@ -1021,7 +1021,7 @@ User sees app through **Cloudflare tunnel** (live preview in browser).
1021
1021
  **Flow:** @planning \u2192 **[Create Kanban Cards]** \u2192 Execute work \u2192 @debugger (if issues)
1022
1022
 
1023
1023
  Note: For this project, you implement the code directly after planning (no stack-specific subagents).
1024
- Check \`.claude/skills/\` for project-specific patterns and conventions.`}function Xt(e){return e?`<workflow>
1024
+ Check \`.claude/skills/\` for project-specific patterns and conventions.`}function en(e){return e?`<workflow>
1025
1025
  **Standard feature flow:**
1026
1026
  1. **@planning** - Gather requirements, design spec, saves it.
1027
1027
  2. **\u23F8\uFE0F STOP & WAIT** - Tell user: "Spec is ready! Review it and tell me when to implement."
@@ -1104,7 +1104,7 @@ Check \`.claude/skills/\` for project-specific patterns and conventions.`}functi
1104
1104
  - After @planning \u2192 STOP and wait for user to approve the spec
1105
1105
  - Check project's existing code for patterns before implementing
1106
1106
  - Use @debugger if you encounter build errors or bugs
1107
- </workflow>`}function Zt(e,t){let n=`**@planning** - Design before building:
1107
+ </workflow>`}function tn(e,t){let n=`**@planning** - Design before building:
1108
1108
  - Complex features \u2192 plan first
1109
1109
  - Asks questions, designs spec
1110
1110
  - **Saves spec using save_specification MCP tool**
@@ -1135,7 +1135,7 @@ ${r?"- **Must complete before @frontend starts!**":""}
1135
1135
  **\u26A0\uFE0F MANDATORY DELEGATION - You MUST use subagents:**
1136
1136
 
1137
1137
  ${n}
1138
- </subagents>`}function en(e){return e.services?.frontend?e.techStack?.frontend?.some(n=>n.includes("TanStack")||n.includes("React Query")||n.includes("MUI"))??!1?`<frontend-api>
1138
+ </subagents>`}function nn(e){return e.services?.frontend?e.techStack?.frontend?.some(n=>n.includes("TanStack")||n.includes("React Query")||n.includes("MUI"))??!1?`<frontend-api>
1139
1139
  ## Orval-Generated API Hooks
1140
1140
 
1141
1141
  Frontend uses **Orval** to auto-generate React Query hooks from Swagger. Import from 'api/queries-commands.ts'.
@@ -1169,7 +1169,7 @@ queryClient.invalidateQueries({ queryKey: getGetApiPeopleQueryKey() })
1169
1169
 
1170
1170
  Check the project's existing patterns for API calls and data fetching.
1171
1171
  Look for existing feature code to understand the correct patterns before writing new API calls.
1172
- </frontend-api>`:""}function tn(e,t){if(!e.services?.frontend)return"";let n=e.services.frontend.port,s=ne(e),o=`http://localhost:${n}`;return`<ui-verification>
1172
+ </frontend-api>`:""}function on(e,t){if(!e.services?.frontend)return"";let n=e.services.frontend.port,s=ne(e),o=`http://localhost:${n}`;return`<ui-verification>
1173
1173
  ## \u{1F50D} UI Verification with Playwright
1174
1174
 
1175
1175
  You have access to **Playwright MCP** tools to verify the UI works correctly after making changes.
@@ -1216,34 +1216,34 @@ You have access to **Playwright MCP** tools to verify the UI works correctly aft
1216
1216
  - Use \`browser_evaluate\` to run JavaScript when you need complex interactions
1217
1217
  - Use screenshots when you want to show the user what you see
1218
1218
  - ${t?"In local mode, the browser window will be visible to you":"In container mode, browser runs headless"}
1219
- </ui-verification>`}function pt(e){return e&&e.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g,"\uFFFD")}var nn=null;function ut(){return pt(nn)}import*as _e from"path";import{fileURLToPath as sn}from"url";var rn=Ue(),gt=_e.dirname(sn(import.meta.url)),we=_e.resolve(gt,"../mcps/stdio-server.js");console.log("[MCP] Stdio server path resolved:",we);console.log("[MCP] __dirname:",gt);async function ve(e,t={}){let{model:n,sessionId:s=null,projectId:o=null,apiUrl:r=null,callbacks:i={},debugLog:l,abortController:h,debugMode:f=!1,isLocal:m=process.env.LOCAL_MODE==="true",projectConfig:v=G(process.env.WORKSPACE_DIR||process.cwd()),useDefaultStack:T=!0}=t,_=at(l),O=new Set,y=s||"",R,U,x,j=!1,Z=!1,$=process.env.WORKSPACE_DIR||process.cwd();console.log("[MCP] Configuring agent-planning stdio server:"),console.log("[MCP] Command: node"),console.log("[MCP] Args:",[we]),console.log("[MCP] Env: API_URL=",process.env.API_URL||"http://localhost:5338",", PROJECT_ID=",o||process.env.PROJECT_ID||"",", PROJECT_KEY=",process.env.PROJECT_KEY?"***set***":"(not set)",", WORKSPACE_DIR=",$),console.log("[MCP] File exists check:",we);try{for await(let u of on({prompt:e,options:{abortController:h,cwd:$,resume:s??void 0,allowedTools:["Bash","Read","Write","Edit","MultiEdit","Glob","Grep","LS","WebFetch","NotebookRead","NotebookEdit","mcp__agent-insights__check_backend_build","mcp__agent-insights__check_frontend_types","mcp__agent-insights__check_service_health",...m?[]:["mcp__agent-insights__stop_services","mcp__agent-insights__start_services","mcp__agent-insights__restart_services"],"mcp__agent-planning__start_question_session","mcp__agent-planning__ask_question","mcp__agent-planning__end_question_session","mcp__agent-planning__save_specification","mcp__agent-planning__list_specifications","mcp__agent-planning__read_specification","mcp__agent-planning__delete_specification","mcp__agent-planning__report_learning","mcp__agent-planning__report_bug","mcp__agent-planning__report_debug_insight","mcp__agent-planning__get_kanban_board","mcp__agent-planning__get_column_cards","mcp__agent-planning__get_card_details","mcp__agent-planning__create_kanban_card","mcp__agent-planning__update_kanban_card","mcp__agent-planning__move_kanban_card","mcp__agent-planning__delete_kanban_card","mcp__agent-planning__create_subtask","mcp__agent-planning__toggle_subtask","mcp__agent-planning__delete_subtask","mcp__agent-planning__get_project_prompt","mcp__agent-planning__update_project_prompt","mcp__agent-planning__create_command","mcp__agent-planning__get_test_suites","mcp__agent-planning__get_test_suite_details","mcp__agent-planning__get_test_details","mcp__agent-planning__run_test","mcp__agent-planning__run_test_suite","mcp__agent-planning__report_test_status","mcp__agent-planning__create_test_suite","mcp__agent-planning__create_test","mcp__agent-planning__update_test","mcp__playwright__browser_navigate","mcp__playwright__browser_snapshot","mcp__playwright__browser_take_screenshot","mcp__playwright__browser_click","mcp__playwright__browser_type","mcp__playwright__browser_scroll_down","mcp__playwright__browser_scroll_up","mcp__playwright__browser_go_back","mcp__playwright__browser_go_forward","mcp__playwright__browser_wait","mcp__playwright__browser_screen_capture","mcp__playwright__browser_screen_move_mouse","mcp__playwright__browser_screen_click","mcp__playwright__browser_screen_drag","mcp__playwright__browser_screen_type","mcp__playwright__browser_evaluate","mcp__playwright__browser_tab_list","mcp__playwright__browser_tab_new","mcp__playwright__browser_tab_select","mcp__playwright__browser_tab_close"],model:n,mcpServers:{"agent-insights":rn,"agent-planning":{type:"stdio",command:"node",args:[we],env:{WORKSPACE_DIR:$,API_URL:r||process.env.API_URL||process.env.MASTER_URL||"http://localhost:5338",PROJECT_ID:o||process.env.PROJECT_ID||"",PROJECT_KEY:process.env.PROJECT_KEY||""}},playwright:{type:"stdio",command:"npx",args:["@playwright/mcp@latest","--caps=vision",...m?[]:["--headless"]]}},settingSources:["project"],disallowedTools:["AskUserQuestion","TodoWrite","EnterPlanMode"],agents:T?{scaffolding:Ne,debugger:ge,planning:fe,backend:Le,frontend:Me,"project-context":me}:{debugger:ge,planning:fe,"project-context":me},systemPrompt:dt({debugMode:f,projectPrompt:ut(),isLocal:m,projectConfig:v,useDefaultStack:T})}}))if(!(!u.uuid||O.has(u.uuid))){switch(O.add(u.uuid),_?.log(u),i.onRawMessage?.(u),u.type){case"assistant":if(u.message?.content)for(let P of u.message.content)P.type==="text"?i.onAssistantText?.(P.text):P.type==="tool_use"?i.onAssistantToolUse?.(P.name,P.input):P.type==="tool_result"&&i.onAssistantToolResult?.(P.tool_use_id,P.content);break;case"user":i.onUserMessage?.(u);break;case"result":if(u.subtype==="success")R=u.result,U=u.total_cost_usd,i.onResult?.(u.result,u.total_cost_usd);else{let P=`Agent error: ${u.subtype}`;x=P,i.onError?.(P)}Z=!0;break;case"system":switch(u.subtype){case"init":y=u.session_id,_?.setSessionId(u.session_id),i.onSystemInit?.(u.session_id);break;case"status":i.onSystemStatus?.(JSON.stringify(u));break;case"compact_boundary":break;case"hook_response":break}break;case"stream_event":i.onStreamEvent?.(u);break;case"tool_progress":i.onToolProgress?.(u);break;case"auth_status":i.onAuthStatus?.(u);break}if(Z)break}}catch(u){u instanceof Error&&u.name==="AbortError"||u instanceof Error&&u.message.includes("aborted by user")?(j=!0,i.onAborted?.()):(x=u instanceof Error?u.message:String(u),i.onError?.(x))}finally{_?.stop()}return console.log("after try"),{sessionId:y,result:R,cost:U,error:x,aborted:j}}function Ce(e){return`User answered the questions:
1219
+ </ui-verification>`}function gt(e){return e&&e.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g,"\uFFFD")}var sn=null;function ft(){return gt(sn)}import*as se from"path";import*as Be from"fs";import{fileURLToPath as an}from"url";var cn=Ue(),$e=se.dirname(an(import.meta.url)),mt=[se.resolve($e,"../mcps/stdio-server.js"),se.resolve($e,"./adapters/mcps/stdio-server.js")],oe=mt.find(e=>Be.existsSync(e))||mt[0];console.log("[MCP] Stdio server path resolved:",oe);console.log("[MCP] __dirname:",$e);console.log("[MCP] File exists:",Be.existsSync(oe));async function ve(e,t={}){let{model:n,sessionId:s=null,projectId:o=null,apiUrl:r=null,callbacks:i={},debugLog:l,abortController:h,debugMode:f=!1,isLocal:m=process.env.LOCAL_MODE==="true",projectConfig:v=G(process.env.WORKSPACE_DIR||process.cwd()),useDefaultStack:T=!0}=t,_=lt(l),O=new Set,y=s||"",R,U,x,j=!1,Z=!1,$=process.env.WORKSPACE_DIR||process.cwd();console.log("[MCP] Configuring agent-planning stdio server:"),console.log("[MCP] Command: node"),console.log("[MCP] Args:",[oe]),console.log("[MCP] Env: API_URL=",process.env.API_URL||"http://localhost:5338",", PROJECT_ID=",o||process.env.PROJECT_ID||"",", PROJECT_KEY=",process.env.PROJECT_KEY?"***set***":"(not set)",", WORKSPACE_DIR=",$),console.log("[MCP] File exists check:",oe);try{for await(let u of rn({prompt:e,options:{abortController:h,cwd:$,resume:s??void 0,allowedTools:["Bash","Read","Write","Edit","MultiEdit","Glob","Grep","LS","WebFetch","NotebookRead","NotebookEdit","mcp__agent-insights__check_backend_build","mcp__agent-insights__check_frontend_types","mcp__agent-insights__check_service_health",...m?[]:["mcp__agent-insights__stop_services","mcp__agent-insights__start_services","mcp__agent-insights__restart_services"],"mcp__agent-planning__start_question_session","mcp__agent-planning__ask_question","mcp__agent-planning__end_question_session","mcp__agent-planning__save_specification","mcp__agent-planning__list_specifications","mcp__agent-planning__read_specification","mcp__agent-planning__delete_specification","mcp__agent-planning__report_learning","mcp__agent-planning__report_bug","mcp__agent-planning__report_debug_insight","mcp__agent-planning__get_kanban_board","mcp__agent-planning__get_column_cards","mcp__agent-planning__get_card_details","mcp__agent-planning__create_kanban_card","mcp__agent-planning__update_kanban_card","mcp__agent-planning__move_kanban_card","mcp__agent-planning__delete_kanban_card","mcp__agent-planning__create_subtask","mcp__agent-planning__toggle_subtask","mcp__agent-planning__delete_subtask","mcp__agent-planning__get_project_prompt","mcp__agent-planning__update_project_prompt","mcp__agent-planning__create_command","mcp__agent-planning__get_test_suites","mcp__agent-planning__get_test_suite_details","mcp__agent-planning__get_test_details","mcp__agent-planning__run_test","mcp__agent-planning__run_test_suite","mcp__agent-planning__report_test_status","mcp__agent-planning__create_test_suite","mcp__agent-planning__create_test","mcp__agent-planning__update_test","mcp__playwright__browser_navigate","mcp__playwright__browser_snapshot","mcp__playwright__browser_take_screenshot","mcp__playwright__browser_click","mcp__playwright__browser_type","mcp__playwright__browser_scroll_down","mcp__playwright__browser_scroll_up","mcp__playwright__browser_go_back","mcp__playwright__browser_go_forward","mcp__playwright__browser_wait","mcp__playwright__browser_screen_capture","mcp__playwright__browser_screen_move_mouse","mcp__playwright__browser_screen_click","mcp__playwright__browser_screen_drag","mcp__playwright__browser_screen_type","mcp__playwright__browser_evaluate","mcp__playwright__browser_tab_list","mcp__playwright__browser_tab_new","mcp__playwright__browser_tab_select","mcp__playwright__browser_tab_close"],model:n,mcpServers:{"agent-insights":cn,"agent-planning":{type:"stdio",command:"node",args:[oe],env:{WORKSPACE_DIR:$,API_URL:r||process.env.API_URL||process.env.MASTER_URL||"http://localhost:5338",PROJECT_ID:o||process.env.PROJECT_ID||"",PROJECT_KEY:process.env.PROJECT_KEY||""}},playwright:{type:"stdio",command:"npx",args:["@playwright/mcp@latest","--caps=vision",...m?[]:["--headless"]]}},settingSources:["project"],disallowedTools:["AskUserQuestion","TodoWrite","EnterPlanMode"],agents:T?{scaffolding:Ne,debugger:me,planning:he,backend:Me,frontend:Le,"project-context":ye}:{debugger:me,planning:he,"project-context":ye},systemPrompt:ut({debugMode:f,projectPrompt:ft(),isLocal:m,projectConfig:v,useDefaultStack:T})}}))if(!(!u.uuid||O.has(u.uuid))){switch(O.add(u.uuid),_?.log(u),i.onRawMessage?.(u),u.type){case"assistant":if(u.message?.content)for(let P of u.message.content)P.type==="text"?i.onAssistantText?.(P.text):P.type==="tool_use"?i.onAssistantToolUse?.(P.name,P.input):P.type==="tool_result"&&i.onAssistantToolResult?.(P.tool_use_id,P.content);break;case"user":i.onUserMessage?.(u);break;case"result":if(u.subtype==="success")R=u.result,U=u.total_cost_usd,i.onResult?.(u.result,u.total_cost_usd);else{let P=`Agent error: ${u.subtype}`;x=P,i.onError?.(P)}Z=!0;break;case"system":switch(u.subtype){case"init":y=u.session_id,_?.setSessionId(u.session_id),i.onSystemInit?.(u.session_id);break;case"status":i.onSystemStatus?.(JSON.stringify(u));break;case"compact_boundary":break;case"hook_response":break}break;case"stream_event":i.onStreamEvent?.(u);break;case"tool_progress":i.onToolProgress?.(u);break;case"auth_status":i.onAuthStatus?.(u);break}if(Z)break}}catch(u){u instanceof Error&&u.name==="AbortError"||u instanceof Error&&u.message.includes("aborted by user")?(j=!0,i.onAborted?.()):(x=u instanceof Error?u.message:String(u),i.onError?.(x))}finally{_?.stop()}return console.log("after try"),{sessionId:y,result:R,cost:U,error:x,aborted:j}}function Ce(e){return`User answered the questions:
1220
1220
 
1221
1221
  ${Object.entries(e).map(([n,s])=>{let o=Array.isArray(s)?s.join(", "):s;return`${n}: ${o}`}).join(`
1222
- `)}`}import{spawn as ft,execSync as V}from"child_process";import*as w from"fs";import*as mt from"http";import*as Q from"path";function Te(e){let{workspaceDir:t,apiPort:n,webPort:s,onBackendError:o,onFrontendError:r,projectConfig:i=G(t)}=e,l=n??i.services?.backend?.port??5338,h=s??i.services?.frontend?.port??5173,f=H(i),m=Y(i),v=i.services?.backend?.startCommand??"dotnet run",T=i.services?.backend?.buildCommand??"dotnet build",_=i.services?.backend?.typecheckCommand??"dotnet build --no-restore",O=i.services?.frontend?.startCommand??"npm run dev",y=i.services?.frontend?.typecheckCommand??"npx tsc -p tsconfig.app.json --noEmit",R=i.services?.backend?.logFile??"/tmp/api.log",U=i.services?.frontend?.logFile??"/tmp/web.log",x=null,j=null,Z=d=>new Promise(c=>{let g=setTimeout(()=>c(!1),3e3);mt.get(`http://localhost:${d}`,A=>{clearTimeout(g),c(A.statusCode!==void 0&&A.statusCode<500)}).on("error",()=>{clearTimeout(g),c(!1)})}),$=d=>{try{let c=V(`lsof -ti:${d} 2>/dev/null || true`,{encoding:"utf-8"}).trim();if(c){let g=c.split(`
1223
- `).filter(Boolean);console.log(`[Services] Killing ${g.length} process(es) on port ${d}: ${g.join(", ")}`);for(let b of g)try{process.kill(parseInt(b,10),"SIGKILL")}catch{}}}catch{try{V(`fuser -k ${d}/tcp 2>/dev/null || true`,{encoding:"utf-8"})}catch{}}},u=(d,c)=>new Promise(g=>{if(!d||!d.pid){g();return}console.log(`[Services] Stopping ${c} (PID: ${d.pid})...`);try{process.kill(-d.pid,"SIGTERM")}catch{try{d.kill("SIGTERM")}catch{}}setTimeout(g,500)}),P=async()=>{if(!f||!w.existsSync(f)){console.log("[Services] No backend found, skipping backend start");return}$(l),console.log(`[Services] Starting backend with: ${v}...`);let d=Q.dirname(R);w.existsSync(d)||w.mkdirSync(d,{recursive:!0});let c=w.createWriteStream(R,{flags:"a"}),[g,...b]=v.split(" ");x=ft(g,b,{cwd:f,stdio:["ignore","pipe","pipe"],detached:!0,shell:!0});let A="",C=k=>{let B=k.toString();c.write(B);let D=(A+B).split(`
1224
- `);A=D.pop()||"";for(let F of D)F&&an(F)&&o&&o(F)};x.stdout?.on("data",C),x.stderr?.on("data",C),x.on("exit",k=>{c.end(),k!==0&&k!==null&&o&&o(`Process exited with code ${k}`)}),x.unref()},Ge=async()=>{if(!m||!w.existsSync(Q.join(m,"package.json"))){console.log("[Services] No frontend found, skipping frontend start");return}$(h),console.log(`[Services] Starting frontend with: ${O}...`);let d=Q.dirname(U);w.existsSync(d)||w.mkdirSync(d,{recursive:!0});let[c,...g]=O.split(" ");j=ft(c,g,{cwd:m,stdio:["ignore",w.openSync(U,"w"),w.openSync(U,"w")],detached:!0,shell:!0}),j.unref()},He=async()=>{await u(x,"backend"),x=null,$(l)},Ye=async()=>{await u(j,"frontend"),j=null,$(h)},De=async()=>{let[d,c]=await Promise.all([Z(l),Z(h)]);return{api:d,web:c}},Qe=async(d=15e3)=>{let c=Date.now(),g=1e3,b=0,A=null,C=null;for(console.log(`[Services] Waiting for health (timeout: ${d}ms)...`);Date.now()-c<d;){b++;let D=await De(),F=Date.now()-c;if(D.web&&C===null&&(C=F,console.log(`[Services] \u2713 Frontend (Vite) ready after ${F}ms`)),D.api&&A===null&&(A=F,console.log(`[Services] \u2713 Backend (dotnet) ready after ${F}ms`)),console.log(`[Services] Health poll #${b} (${F}ms): api=${D.api}, web=${D.web}`),D.api&&D.web)return console.log(`[Services] \u2713 Both services healthy after ${F}ms (${b} polls)`),D;await new Promise(Lt=>setTimeout(Lt,g))}let k=await De(),B=Date.now()-c;return k.web&&C===null&&console.log(`[Services] \u2713 Frontend (Vite) ready after ${B}ms`),k.api&&A===null&&console.log(`[Services] \u2713 Backend (dotnet) ready after ${B}ms`),console.log(`[Services] \u26A0 Health timeout after ${B}ms: api=${k.api}, web=${k.web}`),k},Ut=async d=>{console.log(`[Services] Restarting ${d}...`);let c={success:!0},g=d==="backend"||d==="both",b=d==="frontend"||d==="both";if(g&&await He(),b&&await Ye(),g&&f&&w.existsSync(f)){console.log(`[Services] Building backend with: ${T}...`);try{V(T,{cwd:f,stdio:"pipe",timeout:12e4,encoding:"utf-8"}),console.log("[Services] \u2713 Backend build succeeded")}catch(C){let k=C;c.success=!1,c.backendError=k.stderr||k.stdout||"Build failed",console.error("[Services] \u2717 Backend build failed")}}if(b&&m&&w.existsSync(Q.join(m,"package.json"))){console.log(`[Services] Type-checking frontend with: ${y}...`);try{V(y,{cwd:m,stdio:"pipe",timeout:6e4,encoding:"utf-8"}),console.log("[Services] \u2713 Frontend types OK")}catch(C){let k=C;c.success=!1,c.frontendError=k.stderr||k.stdout||"Type check failed",console.error("[Services] \u2717 Frontend type check failed")}}console.log(`[Services] Starting ${d}...`),g&&await P(),b&&await Ge();let A=await Qe(1e4);if(g&&!A.api){c.success=!1;let C=await ze("backend",20),k=C.length>0?`
1222
+ `)}`}import{spawn as ht,execSync as V}from"child_process";import*as w from"fs";import*as yt from"http";import*as Q from"path";function Te(e){let{workspaceDir:t,apiPort:n,webPort:s,onBackendError:o,onFrontendError:r,projectConfig:i=G(t)}=e,l=n??i.services?.backend?.port??5338,h=s??i.services?.frontend?.port??5173,f=H(i),m=Y(i),v=i.services?.backend?.startCommand??"dotnet run",T=i.services?.backend?.buildCommand??"dotnet build",_=i.services?.backend?.typecheckCommand??"dotnet build --no-restore",O=i.services?.frontend?.startCommand??"npm run dev",y=i.services?.frontend?.typecheckCommand??"npx tsc -p tsconfig.app.json --noEmit",R=i.services?.backend?.logFile??"/tmp/api.log",U=i.services?.frontend?.logFile??"/tmp/web.log",x=null,j=null,Z=d=>new Promise(c=>{let g=setTimeout(()=>c(!1),3e3);yt.get(`http://localhost:${d}`,A=>{clearTimeout(g),c(A.statusCode!==void 0&&A.statusCode<500)}).on("error",()=>{clearTimeout(g),c(!1)})}),$=d=>{try{let c=V(`lsof -ti:${d} 2>/dev/null || true`,{encoding:"utf-8"}).trim();if(c){let g=c.split(`
1223
+ `).filter(Boolean);console.log(`[Services] Killing ${g.length} process(es) on port ${d}: ${g.join(", ")}`);for(let b of g)try{process.kill(parseInt(b,10),"SIGKILL")}catch{}}}catch{try{V(`fuser -k ${d}/tcp 2>/dev/null || true`,{encoding:"utf-8"})}catch{}}},u=(d,c)=>new Promise(g=>{if(!d||!d.pid){g();return}console.log(`[Services] Stopping ${c} (PID: ${d.pid})...`);try{process.kill(-d.pid,"SIGTERM")}catch{try{d.kill("SIGTERM")}catch{}}setTimeout(g,500)}),P=async()=>{if(!f||!w.existsSync(f)){console.log("[Services] No backend found, skipping backend start");return}$(l),console.log(`[Services] Starting backend with: ${v}...`);let d=Q.dirname(R);w.existsSync(d)||w.mkdirSync(d,{recursive:!0});let c=w.createWriteStream(R,{flags:"a"}),[g,...b]=v.split(" ");x=ht(g,b,{cwd:f,stdio:["ignore","pipe","pipe"],detached:!0,shell:!0});let A="",C=k=>{let B=k.toString();c.write(B);let D=(A+B).split(`
1224
+ `);A=D.pop()||"";for(let F of D)F&&ln(F)&&o&&o(F)};x.stdout?.on("data",C),x.stderr?.on("data",C),x.on("exit",k=>{c.end(),k!==0&&k!==null&&o&&o(`Process exited with code ${k}`)}),x.unref()},Ye=async()=>{if(!m||!w.existsSync(Q.join(m,"package.json"))){console.log("[Services] No frontend found, skipping frontend start");return}$(h),console.log(`[Services] Starting frontend with: ${O}...`);let d=Q.dirname(U);w.existsSync(d)||w.mkdirSync(d,{recursive:!0});let[c,...g]=O.split(" ");j=ht(c,g,{cwd:m,stdio:["ignore",w.openSync(U,"w"),w.openSync(U,"w")],detached:!0,shell:!0}),j.unref()},Qe=async()=>{await u(x,"backend"),x=null,$(l)},Ke=async()=>{await u(j,"frontend"),j=null,$(h)},De=async()=>{let[d,c]=await Promise.all([Z(l),Z(h)]);return{api:d,web:c}},Ve=async(d=15e3)=>{let c=Date.now(),g=1e3,b=0,A=null,C=null;for(console.log(`[Services] Waiting for health (timeout: ${d}ms)...`);Date.now()-c<d;){b++;let D=await De(),F=Date.now()-c;if(D.web&&C===null&&(C=F,console.log(`[Services] \u2713 Frontend (Vite) ready after ${F}ms`)),D.api&&A===null&&(A=F,console.log(`[Services] \u2713 Backend (dotnet) ready after ${F}ms`)),console.log(`[Services] Health poll #${b} (${F}ms): api=${D.api}, web=${D.web}`),D.api&&D.web)return console.log(`[Services] \u2713 Both services healthy after ${F}ms (${b} polls)`),D;await new Promise(jt=>setTimeout(jt,g))}let k=await De(),B=Date.now()-c;return k.web&&C===null&&console.log(`[Services] \u2713 Frontend (Vite) ready after ${B}ms`),k.api&&A===null&&console.log(`[Services] \u2713 Backend (dotnet) ready after ${B}ms`),console.log(`[Services] \u26A0 Health timeout after ${B}ms: api=${k.api}, web=${k.web}`),k},Mt=async d=>{console.log(`[Services] Restarting ${d}...`);let c={success:!0},g=d==="backend"||d==="both",b=d==="frontend"||d==="both";if(g&&await Qe(),b&&await Ke(),g&&f&&w.existsSync(f)){console.log(`[Services] Building backend with: ${T}...`);try{V(T,{cwd:f,stdio:"pipe",timeout:12e4,encoding:"utf-8"}),console.log("[Services] \u2713 Backend build succeeded")}catch(C){let k=C;c.success=!1,c.backendError=k.stderr||k.stdout||"Build failed",console.error("[Services] \u2717 Backend build failed")}}if(b&&m&&w.existsSync(Q.join(m,"package.json"))){console.log(`[Services] Type-checking frontend with: ${y}...`);try{V(y,{cwd:m,stdio:"pipe",timeout:6e4,encoding:"utf-8"}),console.log("[Services] \u2713 Frontend types OK")}catch(C){let k=C;c.success=!1,c.frontendError=k.stderr||k.stdout||"Type check failed",console.error("[Services] \u2717 Frontend type check failed")}}console.log(`[Services] Starting ${d}...`),g&&await P(),b&&await Ye();let A=await Ve(1e4);if(g&&!A.api){c.success=!1;let C=await Xe("backend",20),k=C.length>0?`
1225
1225
  Recent logs:
1226
1226
  ${C.join(`
1227
- `)}`:"";c.backendError||(c.backendError=`Backend failed to start.${k}`)}return b&&!A.web&&(c.success=!1,c.frontendError||(c.frontendError="Frontend failed to start")),c},Ke=async()=>{if(!f||!w.existsSync(f))return{success:!0};try{return V(_,{cwd:f,stdio:"pipe",timeout:12e4,encoding:"utf-8"}),{success:!0}}catch(d){let c=d;return{success:!1,errors:c.stdout||c.stderr||"Build failed"}}},Ve=async()=>{if(!m||!w.existsSync(Q.join(m,"package.json")))return{success:!0};try{return V(y,{cwd:m,stdio:"pipe",timeout:6e4,encoding:"utf-8"}),{success:!0}}catch(d){let c=d;return{success:!1,errors:c.stdout||c.stderr||"Type check failed"}}},Nt=async()=>{let[d,c]=await Promise.all([Ke(),Ve()]);return{backend:d,frontend:c}},ze=async(d,c)=>{let g=d==="backend"?R:U;if(!w.existsSync(g))return[`Log file not found: ${g}`];try{return V(`tail -n ${c} ${g}`,{encoding:"utf-8"}).split(`
1228
- `).filter(Boolean)}catch(b){return[`Error reading logs: ${b instanceof Error?b.message:String(b)}`]}};return{startBackend:P,startFrontend:Ge,stopBackend:He,stopFrontend:Ye,restartServices:Ut,checkHealth:De,waitForHealth:Qe,getProcesses:()=>({backend:x,frontend:j}),checkBackendBuild:Ke,checkFrontendTypes:Ve,runTypeChecks:Nt,tailLogs:ze,checkSwaggerEndpoints:async d=>{let c=Q.join(t,"swagger.json");if(!w.existsSync(c))return{foundEndpoints:["Error: swagger.json not found"],totalEndpoints:0};try{let g=JSON.parse(w.readFileSync(c,"utf-8")),b=Object.keys(g.paths||{}),A=[];for(let C of b)if(C.toLowerCase().includes(d.toLowerCase())){let k=Object.keys(g.paths[C]);for(let B of k)A.push(`${B.toUpperCase()} ${C}`)}return{foundEndpoints:A,totalEndpoints:b.length}}catch(g){return{foundEndpoints:[`Error parsing swagger.json: ${g instanceof Error?g.message:String(g)}`],totalEndpoints:0}}}}}function an(e){let t=e.toLowerCase();return t.includes("exception")||t.includes("fail:")||t.includes("[err]")||t.includes("[error]")}import{execSync as z}from"child_process";function Ee(e){let t=async()=>{try{return z("git status --porcelain",{cwd:e,encoding:"utf-8"}).trim().length>0}catch{return!1}},n=async()=>{try{return z("git branch --show-current",{cwd:e,encoding:"utf-8"}).trim()}catch{return"unknown"}};return{hasChanges:t,commitAndPush:async(o,r)=>{try{if(!await t())return{success:!0,noChanges:!0};let i=o.length>60?o.substring(0,60)+"...":o,h=`${r?"[agent] (partial)":"[agent]"} ${i}`;z("git add -A",{cwd:e}),z(`git commit -m "${h.replace(/"/g,'\\"')}"`,{cwd:e,encoding:"utf-8"});let f=z("git rev-parse --short HEAD",{cwd:e,encoding:"utf-8"}).trim();try{z("git push",{cwd:e,stdio:"pipe"})}catch(m){let v=m instanceof Error?m.message:String(m);if(v.includes("no upstream branch")){let T=await n();z(`git push --set-upstream origin ${T}`,{cwd:e,stdio:"pipe"})}else return console.error("[Git] Push failed:",v),{success:!0,commitHash:f,error:`Committed but push failed: ${v}`}}return{success:!0,commitHash:f}}catch(i){let l=i instanceof Error?i.message:String(i);return console.error("[Git] Error:",l),{success:!1,error:l}}},getCurrentBranch:n}}import se from"inquirer";var oe="\u2192 Other (type custom answer)";async function Pe(e){let t={};for(let n of e){let s=await cn(n);t[n.id]=s}return t}async function cn(e){return e.multiSelect&&e.options.length>0?ln(e):e.options.length>0?dn(e):pn(e)}async function ln(e){let t=[...e.options];e.allowFreeText&&t.push(oe);let{selection:n}=await se.prompt([{type:"checkbox",name:"selection",message:e.question,choices:t}]);if(n.includes(oe)){let{customAnswer:s}=await se.prompt([{type:"input",name:"customAnswer",message:"Enter your custom answer:"}]);return[...n.filter(r=>r!==oe),s]}return n}async function dn(e){let t=[...e.options];e.allowFreeText&&t.push(oe);let{selection:n}=await se.prompt([{type:"select",name:"selection",message:e.question,choices:t}]);if(n===oe){let{customAnswer:s}=await se.prompt([{type:"input",name:"customAnswer",message:"Enter your custom answer:"}]);return s}return n}async function pn(e){let{answer:t}=await se.prompt([{type:"input",name:"answer",message:e.question}]);return t}import*as L from"fs";import*as Ae from"path";var un=".sdd/cli-sessions.json";function $e(){return Ae.join(process.cwd(),un)}function gn(){let e=Ae.dirname($e());L.existsSync(e)||L.mkdirSync(e,{recursive:!0})}function Be(){try{let e=$e();if(!L.existsSync(e))return[];let t=L.readFileSync(e,"utf-8");return JSON.parse(t).sort((s,o)=>new Date(o.lastUsedAt).getTime()-new Date(s.lastUsedAt).getTime())}catch{return[]}}function ht(e){gn();let t=Be(),n=t.findIndex(o=>o.sessionId===e.sessionId);n>=0?t[n]={...t[n],lastUsedAt:e.lastUsedAt,turnCount:e.turnCount}:t.unshift(e);let s=t.slice(0,20);L.writeFileSync($e(),JSON.stringify(s,null,2))}function yt(e){let t=e.firstPrompt.length>50?e.firstPrompt.slice(0,50)+"...":e.firstPrompt,n=new Date(e.lastUsedAt),s=fn(n);return`${t} (${s}, ${e.turnCount} turns)`}function fn(e){let n=new Date().getTime()-e.getTime(),s=Math.floor(n/6e4),o=Math.floor(n/36e5),r=Math.floor(n/864e5);return s<1?"just now":s<60?`${s}m ago`:o<24?`${o}h ago`:r<7?`${r}d ago`:e.toLocaleDateString()}var bt={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",red:"\x1B[31m",gray:"\x1B[90m"};function a(e,t){return`${bt[e]}${t}${bt.reset}`}var mn={Bash:"\u26A1",Read:"\u{1F4D6}",Write:"\u270F\uFE0F",Edit:"\u{1F527}",MultiEdit:"\u{1F527}",Glob:"\u{1F50D}",Grep:"\u{1F50E}",LS:"\u{1F4C1}",WebFetch:"\u{1F310}",NotebookRead:"\u{1F4D3}",NotebookEdit:"\u{1F4DD}",Task:"\u{1F4CB}",ask_questions:"\u2753",save_specification:"\u{1F4C4}",list_specifications:"\u{1F4CB}",read_specification:"\u{1F4D6}",delete_specification:"\u{1F5D1}\uFE0F",scaffold_entity:"\u{1F3D7}\uFE0F"};function hn(e){return mn[e]||"\u{1F527}"}function re(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}function kt(e){let t=e.split("/");return t.length<=3?e:".../"+t.slice(-2).join("/")}function qe(e){console.log(`
1227
+ `)}`:"";c.backendError||(c.backendError=`Backend failed to start.${k}`)}return b&&!A.web&&(c.success=!1,c.frontendError||(c.frontendError="Frontend failed to start")),c},ze=async()=>{if(!f||!w.existsSync(f))return{success:!0};try{return V(_,{cwd:f,stdio:"pipe",timeout:12e4,encoding:"utf-8"}),{success:!0}}catch(d){let c=d;return{success:!1,errors:c.stdout||c.stderr||"Build failed"}}},Je=async()=>{if(!m||!w.existsSync(Q.join(m,"package.json")))return{success:!0};try{return V(y,{cwd:m,stdio:"pipe",timeout:6e4,encoding:"utf-8"}),{success:!0}}catch(d){let c=d;return{success:!1,errors:c.stdout||c.stderr||"Type check failed"}}},Lt=async()=>{let[d,c]=await Promise.all([ze(),Je()]);return{backend:d,frontend:c}},Xe=async(d,c)=>{let g=d==="backend"?R:U;if(!w.existsSync(g))return[`Log file not found: ${g}`];try{return V(`tail -n ${c} ${g}`,{encoding:"utf-8"}).split(`
1228
+ `).filter(Boolean)}catch(b){return[`Error reading logs: ${b instanceof Error?b.message:String(b)}`]}};return{startBackend:P,startFrontend:Ye,stopBackend:Qe,stopFrontend:Ke,restartServices:Mt,checkHealth:De,waitForHealth:Ve,getProcesses:()=>({backend:x,frontend:j}),checkBackendBuild:ze,checkFrontendTypes:Je,runTypeChecks:Lt,tailLogs:Xe,checkSwaggerEndpoints:async d=>{let c=Q.join(t,"swagger.json");if(!w.existsSync(c))return{foundEndpoints:["Error: swagger.json not found"],totalEndpoints:0};try{let g=JSON.parse(w.readFileSync(c,"utf-8")),b=Object.keys(g.paths||{}),A=[];for(let C of b)if(C.toLowerCase().includes(d.toLowerCase())){let k=Object.keys(g.paths[C]);for(let B of k)A.push(`${B.toUpperCase()} ${C}`)}return{foundEndpoints:A,totalEndpoints:b.length}}catch(g){return{foundEndpoints:[`Error parsing swagger.json: ${g instanceof Error?g.message:String(g)}`],totalEndpoints:0}}}}}function ln(e){let t=e.toLowerCase();return t.includes("exception")||t.includes("fail:")||t.includes("[err]")||t.includes("[error]")}import{execSync as z}from"child_process";function Ee(e){let t=async()=>{try{return z("git status --porcelain",{cwd:e,encoding:"utf-8"}).trim().length>0}catch{return!1}},n=async()=>{try{return z("git branch --show-current",{cwd:e,encoding:"utf-8"}).trim()}catch{return"unknown"}};return{hasChanges:t,commitAndPush:async(o,r)=>{try{if(!await t())return{success:!0,noChanges:!0};let i=o.length>60?o.substring(0,60)+"...":o,h=`${r?"[agent] (partial)":"[agent]"} ${i}`;z("git add -A",{cwd:e}),z(`git commit -m "${h.replace(/"/g,'\\"')}"`,{cwd:e,encoding:"utf-8"});let f=z("git rev-parse --short HEAD",{cwd:e,encoding:"utf-8"}).trim();try{z("git push",{cwd:e,stdio:"pipe"})}catch(m){let v=m instanceof Error?m.message:String(m);if(v.includes("no upstream branch")){let T=await n();z(`git push --set-upstream origin ${T}`,{cwd:e,stdio:"pipe"})}else return console.error("[Git] Push failed:",v),{success:!0,commitHash:f,error:`Committed but push failed: ${v}`}}return{success:!0,commitHash:f}}catch(i){let l=i instanceof Error?i.message:String(i);return console.error("[Git] Error:",l),{success:!1,error:l}}},getCurrentBranch:n}}import ie from"inquirer";var re="\u2192 Other (type custom answer)";async function Pe(e){let t={};for(let n of e){let s=await dn(n);t[n.id]=s}return t}async function dn(e){return e.multiSelect&&e.options.length>0?pn(e):e.options.length>0?un(e):gn(e)}async function pn(e){let t=[...e.options];e.allowFreeText&&t.push(re);let{selection:n}=await ie.prompt([{type:"checkbox",name:"selection",message:e.question,choices:t}]);if(n.includes(re)){let{customAnswer:s}=await ie.prompt([{type:"input",name:"customAnswer",message:"Enter your custom answer:"}]);return[...n.filter(r=>r!==re),s]}return n}async function un(e){let t=[...e.options];e.allowFreeText&&t.push(re);let{selection:n}=await ie.prompt([{type:"select",name:"selection",message:e.question,choices:t}]);if(n===re){let{customAnswer:s}=await ie.prompt([{type:"input",name:"customAnswer",message:"Enter your custom answer:"}]);return s}return n}async function gn(e){let{answer:t}=await ie.prompt([{type:"input",name:"answer",message:e.question}]);return t}import*as M from"fs";import*as Ae from"path";var fn=".sdd/cli-sessions.json";function qe(){return Ae.join(process.cwd(),fn)}function mn(){let e=Ae.dirname(qe());M.existsSync(e)||M.mkdirSync(e,{recursive:!0})}function We(){try{let e=qe();if(!M.existsSync(e))return[];let t=M.readFileSync(e,"utf-8");return JSON.parse(t).sort((s,o)=>new Date(o.lastUsedAt).getTime()-new Date(s.lastUsedAt).getTime())}catch{return[]}}function bt(e){mn();let t=We(),n=t.findIndex(o=>o.sessionId===e.sessionId);n>=0?t[n]={...t[n],lastUsedAt:e.lastUsedAt,turnCount:e.turnCount}:t.unshift(e);let s=t.slice(0,20);M.writeFileSync(qe(),JSON.stringify(s,null,2))}function kt(e){let t=e.firstPrompt.length>50?e.firstPrompt.slice(0,50)+"...":e.firstPrompt,n=new Date(e.lastUsedAt),s=hn(n);return`${t} (${s}, ${e.turnCount} turns)`}function hn(e){let n=new Date().getTime()-e.getTime(),s=Math.floor(n/6e4),o=Math.floor(n/36e5),r=Math.floor(n/864e5);return s<1?"just now":s<60?`${s}m ago`:o<24?`${o}h ago`:r<7?`${r}d ago`:e.toLocaleDateString()}var St={reset:"\x1B[0m",dim:"\x1B[2m",bold:"\x1B[1m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",red:"\x1B[31m",gray:"\x1B[90m"};function a(e,t){return`${St[e]}${t}${St.reset}`}var yn={Bash:"\u26A1",Read:"\u{1F4D6}",Write:"\u270F\uFE0F",Edit:"\u{1F527}",MultiEdit:"\u{1F527}",Glob:"\u{1F50D}",Grep:"\u{1F50E}",LS:"\u{1F4C1}",WebFetch:"\u{1F310}",NotebookRead:"\u{1F4D3}",NotebookEdit:"\u{1F4DD}",Task:"\u{1F4CB}",ask_questions:"\u2753",save_specification:"\u{1F4C4}",list_specifications:"\u{1F4CB}",read_specification:"\u{1F4D6}",delete_specification:"\u{1F5D1}\uFE0F",scaffold_entity:"\u{1F3D7}\uFE0F"};function bn(e){return yn[e]||"\u{1F527}"}function ae(e,t){return e.length<=t?e:e.slice(0,t-3)+"..."}function wt(e){let t=e.split("/");return t.length<=3?e:".../"+t.slice(-2).join("/")}function Ge(e){console.log(`
1229
1229
  ${a("bold",a("cyan","\u2550".repeat(60)))}`),console.log(a("bold",` ${e}`)),console.log(`${a("bold",a("cyan","\u2550".repeat(60)))}
1230
- `)}function St(e){let t=e.split(`
1231
- `);for(let n of t)n.trim()?console.log(` ${n}`):console.log()}function wt(e,t){if(t&&typeof t=="object"){let s=t;if(e==="Task"&&s.subagent_type){let o=String(s.subagent_type);if(console.log(`
1232
- \u{1F916} ${a("bold",a("magenta",`Delegating to @${o}`))}`),s.prompt){let r=re(String(s.prompt),100);console.log(` ${a("dim","\u2192")} ${a("gray",r)}`)}return}}let n=hn(e);if(console.log(`
1233
- ${n} ${a("bold",a("blue",e))}`),t&&typeof t=="object"){let s=t;if(e==="Bash"&&s.command)console.log(` ${a("dim","$")} ${a("yellow",re(String(s.command),80))}`);else if((e==="Read"||e==="Write"||e==="Edit")&&s.file_path)console.log(` ${a("dim","\u2192")} ${a("cyan",kt(String(s.file_path)))}`);else if(e==="Grep"&&s.pattern)console.log(` ${a("dim","/")}${a("magenta",String(s.pattern))}${a("dim","/")}`);else if(e==="LS"&&s.path)console.log(` ${a("dim","\u2192")} ${a("cyan",kt(String(s.path)))}`);else if(e==="scaffold_entity"&&s.name)console.log(` ${a("dim","\u2192")} Creating entity: ${a("green",String(s.name))}`);else if(e==="ask_questions"&&s.questions){let o=s.questions;console.log(` ${a("dim","\u2192")} ${o.length} question(s)`)}else e==="save_specification"&&s.name&&console.log(` ${a("dim","\u2192")} ${a("green",String(s.name))}`)}}function _t(e,t){console.log(`
1234
- ${a("bold",a("green","\u2713 Complete"))}`),console.log(` ${a("dim","Result:")} ${re(e,100)}`),console.log(` ${a("dim","Cost:")} ${a("yellow",`$${t.toFixed(4)}`)}`)}function vt(e){console.log(`
1235
- ${a("bold",a("red","\u2717 Error"))}`),console.log(` ${e}`)}function Ct(){console.log(`
1236
- ${a("bold",a("yellow","\u23F9\uFE0F Aborted"))}`),console.log(` ${a("dim","Session stopped by user. Progress has been preserved.")}`)}function Tt(){console.log(`
1230
+ `)}function _t(e){let t=e.split(`
1231
+ `);for(let n of t)n.trim()?console.log(` ${n}`):console.log()}function vt(e,t){if(t&&typeof t=="object"){let s=t;if(e==="Task"&&s.subagent_type){let o=String(s.subagent_type);if(console.log(`
1232
+ \u{1F916} ${a("bold",a("magenta",`Delegating to @${o}`))}`),s.prompt){let r=ae(String(s.prompt),100);console.log(` ${a("dim","\u2192")} ${a("gray",r)}`)}return}}let n=bn(e);if(console.log(`
1233
+ ${n} ${a("bold",a("blue",e))}`),t&&typeof t=="object"){let s=t;if(e==="Bash"&&s.command)console.log(` ${a("dim","$")} ${a("yellow",ae(String(s.command),80))}`);else if((e==="Read"||e==="Write"||e==="Edit")&&s.file_path)console.log(` ${a("dim","\u2192")} ${a("cyan",wt(String(s.file_path)))}`);else if(e==="Grep"&&s.pattern)console.log(` ${a("dim","/")}${a("magenta",String(s.pattern))}${a("dim","/")}`);else if(e==="LS"&&s.path)console.log(` ${a("dim","\u2192")} ${a("cyan",wt(String(s.path)))}`);else if(e==="scaffold_entity"&&s.name)console.log(` ${a("dim","\u2192")} Creating entity: ${a("green",String(s.name))}`);else if(e==="ask_questions"&&s.questions){let o=s.questions;console.log(` ${a("dim","\u2192")} ${o.length} question(s)`)}else e==="save_specification"&&s.name&&console.log(` ${a("dim","\u2192")} ${a("green",String(s.name))}`)}}function Ct(e,t){console.log(`
1234
+ ${a("bold",a("green","\u2713 Complete"))}`),console.log(` ${a("dim","Result:")} ${ae(e,100)}`),console.log(` ${a("dim","Cost:")} ${a("yellow",`$${t.toFixed(4)}`)}`)}function Tt(e){console.log(`
1235
+ ${a("bold",a("red","\u2717 Error"))}`),console.log(` ${e}`)}function Et(){console.log(`
1236
+ ${a("bold",a("yellow","\u23F9\uFE0F Aborted"))}`),console.log(` ${a("dim","Session stopped by user. Progress has been preserved.")}`)}function Pt(){console.log(`
1237
1237
  ${a("bold",a("yellow","\u2753 Agent needs your input"))}
1238
- `)}function Et(){console.log(`
1238
+ `)}function At(){console.log(`
1239
1239
  ${a("dim","\u2192 Answers sent, agent continuing...")}
1240
1240
  `)}function xe(){console.log(a("dim",`
1241
1241
  `+"\u2500".repeat(50)+`
1242
- `))}function Pt(e,t){let n="";if(typeof t=="string")n=re(t,100);else if(Array.isArray(t)){let s=t.find(o=>typeof o=="object"&&o!==null&&o.type==="text");if(s&&typeof s=="object"){let o=s.text;if(typeof o=="string"){let r=o.split(`
1243
- `).filter(i=>i.trim());r.length>3?n=r.slice(0,3).join(" \u21B5 ")+` (+${r.length-3} more lines)`:n=r.join(" \u21B5 "),n=re(n,100)}}}console.log(n?` ${a("dim","\u2190")} ${a("gray",n)}`:` ${a("dim","\u2190")} ${a("green","done")}`)}function At(e){return{onAssistantText:St,onAssistantToolUse:(t,n)=>{if(wt(t,n),["Write","Edit","MultiEdit"].includes(t)){let s=n,o=s.file_path||s.target_file;o&&e.onFileModified(o)}},onAssistantToolResult:Pt,onResult:(t,n)=>{e.onCostUpdate(n),_t(t,n)},onError:vt,onAborted:Ct,onSystemInit:t=>{e.sessionId||(e.onSessionInit(t),console.log(` Session: ${t.slice(0,12)}...`))}}}import I from"inquirer";import*as M from"fs";import*as Ie from"path";var{Separator:yn}=I,bn=".sdd/api-config.json";function We(){return Ie.join(process.cwd(),bn)}function kn(){let e=Ie.dirname(We());M.existsSync(e)||M.mkdirSync(e,{recursive:!0})}function Sn(){try{let e=We();if(!M.existsSync(e))return null;let t=M.readFileSync(e,"utf-8");return JSON.parse(t)}catch{return null}}function wn(e){kn();let t={...e,lastUsedAt:new Date().toISOString()};M.writeFileSync(We(),JSON.stringify(t,null,2))}async function xt(){let{options:e}=await I.prompt([{type:"checkbox",name:"options",message:"Session options:",choices:[{name:"\u{1F50D} Auto-typecheck (self-correcting mode)",value:"typecheck"},{name:"\u{1F4E6} Auto-commit & push",value:"autoCommit"}]}]),{model:t}=await I.prompt([{type:"list",name:"model",message:"Select Claude model:",choices:[{name:"\u{1F916} Auto (let Claude choose)",value:"auto"},{name:"\u{1F9E0} Opus 4.5 (most capable)",value:"claude-opus-4-5-20251101"},{name:"\u26A1 Sonnet 4.5 (fast & capable)",value:"claude-sonnet-4-5-20250929"},{name:"\u{1F4A8} Haiku 4.5 (fastest)",value:"claude-haiku-4-5-20251001"}],default:"auto"}]);return{typecheck:e.includes("typecheck"),autoCommit:e.includes("autoCommit"),model:t}}async function It(){let e=Be();if(e.length===0){let{prompt:r}=await I.prompt([{type:"input",name:"prompt",message:"What would you like to build?"}]);return{sessionId:null,firstPrompt:r,isResume:!1,existingTurnCount:0}}let t=[{name:"\u{1F195} Start new session",value:"new"},new yn("\u2500\u2500\u2500 Previous Sessions \u2500\u2500\u2500"),...e.map(r=>({name:yt(r),value:r.sessionId}))],{selection:n}=await I.prompt([{type:"select",name:"selection",message:"Select a session:",choices:t}]);if(n==="new"){let{prompt:r}=await I.prompt([{type:"input",name:"prompt",message:"What would you like to build?"}]);return{sessionId:null,firstPrompt:r,isResume:!1,existingTurnCount:0}}let s=e.find(r=>r.sessionId===n);console.log(`
1244
- \u{1F4C2} Resuming session: ${s.firstPrompt.slice(0,50)}...`);let{prompt:o}=await I.prompt([{type:"input",name:"prompt",message:"Continue with:"}]);return{sessionId:s.sessionId,firstPrompt:s.firstPrompt,isResume:!0,existingTurnCount:s.turnCount||0}}async function Re(){let{action:e}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4DD} Send follow-up message",value:"followup"},{name:"\u{1F6AA} Exit",value:"exit"}]}]);if(e==="exit")return null;let{prompt:t}=await I.prompt([{type:"input",name:"prompt",message:"Your message:"}]);return t}async function Rt(){let{action:e}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"Continue with a new prompt",value:"continue"},{name:"Exit (session saved)",value:"exit"}]}]);return e}async function Ot(){let e=process.env.API_URL||process.env.MASTER_URL,t=process.env.PROJECT_ID,n=Sn();if(n&&!e&&!t){console.log(`
1242
+ `))}function xt(e,t){let n="";if(typeof t=="string")n=ae(t,100);else if(Array.isArray(t)){let s=t.find(o=>typeof o=="object"&&o!==null&&o.type==="text");if(s&&typeof s=="object"){let o=s.text;if(typeof o=="string"){let r=o.split(`
1243
+ `).filter(i=>i.trim());r.length>3?n=r.slice(0,3).join(" \u21B5 ")+` (+${r.length-3} more lines)`:n=r.join(" \u21B5 "),n=ae(n,100)}}}console.log(n?` ${a("dim","\u2190")} ${a("gray",n)}`:` ${a("dim","\u2190")} ${a("green","done")}`)}function It(e){return{onAssistantText:_t,onAssistantToolUse:(t,n)=>{if(vt(t,n),["Write","Edit","MultiEdit"].includes(t)){let s=n,o=s.file_path||s.target_file;o&&e.onFileModified(o)}},onAssistantToolResult:xt,onResult:(t,n)=>{e.onCostUpdate(n),Ct(t,n)},onError:Tt,onAborted:Et,onSystemInit:t=>{e.sessionId||(e.onSessionInit(t),console.log(` Session: ${t.slice(0,12)}...`))}}}import I from"inquirer";import*as L from"fs";import*as Ie from"path";var{Separator:kn}=I,Sn=".sdd/api-config.json";function He(){return Ie.join(process.cwd(),Sn)}function wn(){let e=Ie.dirname(He());L.existsSync(e)||L.mkdirSync(e,{recursive:!0})}function _n(){try{let e=He();if(!L.existsSync(e))return null;let t=L.readFileSync(e,"utf-8");return JSON.parse(t)}catch{return null}}function vn(e){wn();let t={...e,lastUsedAt:new Date().toISOString()};L.writeFileSync(He(),JSON.stringify(t,null,2))}async function Rt(){let{options:e}=await I.prompt([{type:"checkbox",name:"options",message:"Session options:",choices:[{name:"\u{1F50D} Auto-typecheck (self-correcting mode)",value:"typecheck"},{name:"\u{1F4E6} Auto-commit & push",value:"autoCommit"}]}]),{model:t}=await I.prompt([{type:"list",name:"model",message:"Select Claude model:",choices:[{name:"\u{1F916} Auto (let Claude choose)",value:"auto"},{name:"\u{1F9E0} Opus 4.5 (most capable)",value:"claude-opus-4-5-20251101"},{name:"\u26A1 Sonnet 4.5 (fast & capable)",value:"claude-sonnet-4-5-20250929"},{name:"\u{1F4A8} Haiku 4.5 (fastest)",value:"claude-haiku-4-5-20251001"}],default:"auto"}]);return{typecheck:e.includes("typecheck"),autoCommit:e.includes("autoCommit"),model:t}}async function Ot(){let e=We();if(e.length===0){let{prompt:r}=await I.prompt([{type:"input",name:"prompt",message:"What would you like to build?"}]);return{sessionId:null,firstPrompt:r,isResume:!1,existingTurnCount:0}}let t=[{name:"\u{1F195} Start new session",value:"new"},new kn("\u2500\u2500\u2500 Previous Sessions \u2500\u2500\u2500"),...e.map(r=>({name:kt(r),value:r.sessionId}))],{selection:n}=await I.prompt([{type:"select",name:"selection",message:"Select a session:",choices:t}]);if(n==="new"){let{prompt:r}=await I.prompt([{type:"input",name:"prompt",message:"What would you like to build?"}]);return{sessionId:null,firstPrompt:r,isResume:!1,existingTurnCount:0}}let s=e.find(r=>r.sessionId===n);console.log(`
1244
+ \u{1F4C2} Resuming session: ${s.firstPrompt.slice(0,50)}...`);let{prompt:o}=await I.prompt([{type:"input",name:"prompt",message:"Continue with:"}]);return{sessionId:s.sessionId,firstPrompt:s.firstPrompt,isResume:!0,existingTurnCount:s.turnCount||0}}async function Re(){let{action:e}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"\u{1F4DD} Send follow-up message",value:"followup"},{name:"\u{1F6AA} Exit",value:"exit"}]}]);if(e==="exit")return null;let{prompt:t}=await I.prompt([{type:"input",name:"prompt",message:"Your message:"}]);return t}async function Dt(){let{action:e}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"Continue with a new prompt",value:"continue"},{name:"Exit (session saved)",value:"exit"}]}]);return e}async function Ft(){let e=process.env.API_URL||process.env.MASTER_URL,t=process.env.PROJECT_ID,n=_n();if(n&&!e&&!t){console.log(`
1245
1245
  \u{1F4CB} Previous API Configuration Found
1246
- `),console.log(` \u{1F517} API URL: ${n.apiUrl}`),console.log(` \u{1F194} Project ID: ${n.projectId}`);let{action:r}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"\u2705 Proceed with saved configuration",value:"proceed"},{name:"\u{1F504} Override with new configuration",value:"override"}]}]);if(r==="proceed")return{apiUrl:n.apiUrl,projectId:n.projectId}}let s=await I.prompt([{type:"input",name:"apiUrl",message:"API URL (backend endpoint):",default:e||n?.apiUrl||"http://localhost:5338",validate:r=>{if(!r.trim())return"API URL is required";try{return new URL(r),!0}catch{return"Please enter a valid URL"}}},{type:"input",name:"projectId",message:"Project ID:",default:t||n?.projectId,validate:r=>r.trim()?!0:"Project ID is required"}]),o={apiUrl:s.apiUrl,projectId:s.projectId};return wn(o),o}async function Dt(e,t){if(t.size===0)return console.log(`
1246
+ `),console.log(` \u{1F517} API URL: ${n.apiUrl}`),console.log(` \u{1F194} Project ID: ${n.projectId}`);let{action:r}=await I.prompt([{type:"select",name:"action",message:"What would you like to do?",choices:[{name:"\u2705 Proceed with saved configuration",value:"proceed"},{name:"\u{1F504} Override with new configuration",value:"override"}]}]);if(r==="proceed")return{apiUrl:n.apiUrl,projectId:n.projectId}}let s=await I.prompt([{type:"input",name:"apiUrl",message:"API URL (backend endpoint):",default:e||n?.apiUrl||"http://localhost:5338",validate:r=>{if(!r.trim())return"API URL is required";try{return new URL(r),!0}catch{return"Please enter a valid URL"}}},{type:"input",name:"projectId",message:"Project ID:",default:t||n?.projectId,validate:r=>r.trim()?!0:"Project ID is required"}]),o={apiUrl:s.apiUrl,projectId:s.projectId};return vn(o),o}async function Ut(e,t){if(t.size===0)return console.log(`
1247
1247
  ${a("dim","\u23ED\uFE0F No code changes, skipping type checks")}`),{passed:!0};let n=[...t].some(l=>l.includes("dotnet-api")||l.endsWith(".cs")),s=[...t].some(l=>l.includes("backoffice-web")||l.endsWith(".ts")||l.endsWith(".tsx"));if(!n&&!s)return console.log(`
1248
1248
  ${a("dim","\u23ED\uFE0F No code changes, skipping type checks")}`),{passed:!0};let o=[];n&&o.push("backend"),s&&o.push("frontend"),console.log(`
1249
1249
  ${a("dim",`\u{1F50D} Type checking ${o.join(" & ")}...`)}`);let r=process.env.WORKSPACE_DIR||process.cwd(),i=[];if(n){let l=await e.checkBackendBuild();!l.success&&l.errors&&i.push(`## Backend Build Errors (in ${r}/packages/dotnet-api)
@@ -1261,14 +1261,14 @@ ${i.join(`
1261
1261
 
1262
1262
  `)}
1263
1263
 
1264
- File paths like "src/..." are relative to the package directory shown in parentheses.`}):(console.log(` ${a("green","\u2713 All type checks passed")}`),{passed:!0})}async function Ft(e,t,n){if(!await e.hasChanges())return;console.log(`
1265
- ${a("dim","\u{1F4E6} Committing changes...")}`);let o=await e.commitAndPush(t,n);if(o.noChanges)console.log(` ${a("dim","No changes to commit")}`);else if(o.success){let r=await e.getCurrentBranch();console.log(` ${a("green","\u2713 Committed")} ${a("dim",o.commitHash||"")}`),console.log(` ${a("dim",` \u2192 Pushed to ${r}`)}`),o.error&&console.log(` ${a("yellow",`\u26A0\uFE0F ${o.error}`)}`)}else console.log(` ${a("red",`\u274C Git error: ${o.error}`)}`)}var ie=null;process.stdout.on("error",e=>{e.code!=="EPIPE"&&console.error("stdout error:",e)});process.stderr.on("error",e=>{e.code!=="EPIPE"&&console.error("stderr error:",e)});process.on("SIGINT",()=>{ie?(console.log(`
1264
+ File paths like "src/..." are relative to the package directory shown in parentheses.`}):(console.log(` ${a("green","\u2713 All type checks passed")}`),{passed:!0})}async function Nt(e,t,n){if(!await e.hasChanges())return;console.log(`
1265
+ ${a("dim","\u{1F4E6} Committing changes...")}`);let o=await e.commitAndPush(t,n);if(o.noChanges)console.log(` ${a("dim","No changes to commit")}`);else if(o.success){let r=await e.getCurrentBranch();console.log(` ${a("green","\u2713 Committed")} ${a("dim",o.commitHash||"")}`),console.log(` ${a("dim",` \u2192 Pushed to ${r}`)}`),o.error&&console.log(` ${a("yellow",`\u26A0\uFE0F ${o.error}`)}`)}else console.log(` ${a("red",`\u274C Git error: ${o.error}`)}`)}var ce=null;process.stdout.on("error",e=>{e.code!=="EPIPE"&&console.error("stdout error:",e)});process.stderr.on("error",e=>{e.code!=="EPIPE"&&console.error("stderr error:",e)});process.on("SIGINT",()=>{ce?(console.log(`
1266
1266
 
1267
1267
  \u23F9\uFE0F Stopping agent...
1268
- `),ie.abort()):(console.log(`
1269
- `),process.exit(0))});async function Oe(e,t={}){let{serviceManager:n,gitManager:s}=t,o=null,r,i,l=0,h=0,f=t.typecheck??!1,m=t.autoCommit??!1,v=t.model;if(e)r=e,i=e;else{let T=await xt();n&&(f=T.typecheck),s&&(m=T.autoCommit),t.skipModelPrompt||(v=T.model);let _=await It();o=_.sessionId,r=_.firstPrompt,l=_.existingTurnCount,i=_.isResume&&await Re()||r}for(_n(f,m,!!n,!!s,v);;){l++,console.log(`
1270
- Turn ${l}`),xe();let T=new Set;ie=new AbortController;let _=await ve(i,{model:v==="auto"?void 0:v,sessionId:o,projectId:process.env.PROJECT_ID||null,debugLog:!0,abortController:ie,callbacks:At({sessionId:o,onSessionInit:y=>{o=y},onCostUpdate:y=>{h+=y},onFileModified:y=>{T.add(y)}})});if(console.log("after runAgent"),ie=null,_.sessionId&&(o=_.sessionId),_.cost&&(h=_.cost),console.log("after result"),Cn(o,r,l),console.log("after saveSessionIfNeeded"),_.aborted){if(await new Promise(U=>setTimeout(U,100)),xe(),h>0&&console.log(` \u{1F4B0} Session cost so far: $${h.toFixed(4)}
1271
- `),await Rt()==="exit")break;let R=await Re();if(!R)break;i=R;continue}if(console.log("after abort"),o){let y=ee(o);if(y&&y.length>0){Tt();let R=await Pe(y);i=Ce(R),Et();continue}}if(console.log("after pending questions"),f&&n){let y=await Dt(n,T);if(!y.passed&&y.errorPrompt){i=y.errorPrompt;continue}}if(console.log("after typecheck"),m&&s){let y=_.aborted||!!_.error;await Ft(s,r,y)}console.log("after auto-commit"),xe();let O=await Re();if(!O)break;i=O}vn(o,h)}function _n(e,t,n,s,o){qe("\u{1F680} Agent Started"),console.log(" \u{1F4DD} Debug logs \u2192 /tmp/agent-debug/"),o&&console.log(` \u{1F916} Model: ${o==="auto"?"Auto":o==="claude-opus-4-5-20251101"?"Opus 4.5":o==="claude-sonnet-4-5-20250929"?"Sonnet 4.5":o==="claude-haiku-4-5-20251001"?"Haiku 4.5":"Unknown"}`),e&&n&&console.log(" \u{1F50D} Auto-typecheck enabled (self-correcting mode)"),t&&s&&console.log(" \u{1F4E6} Auto-commit enabled"),console.log(` \u{1F4A1} Press Ctrl+C to stop the agent
1272
- `)}function vn(e,t){qe("\u2705 Session Complete"),e&&console.log(" \u{1F4BE} Session saved - you can resume it next time"),t>0&&console.log(` \u{1F4B0} Total cost: $${t.toFixed(4)}`),console.log()}function Cn(e,t,n){e&&ht({sessionId:e,firstPrompt:t,createdAt:new Date().toISOString(),lastUsedAt:new Date().toISOString(),turnCount:n})}process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT=process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT||"60000";async function Tn(){let e=process.env.API_URL||process.env.MASTER_URL,t=process.env.PROJECT_ID,n=e,s=t;if(!e||!t){console.log(`
1268
+ `),ce.abort()):(console.log(`
1269
+ `),process.exit(0))});async function Oe(e,t={}){let{serviceManager:n,gitManager:s}=t,o=null,r,i,l=0,h=0,f=t.typecheck??!1,m=t.autoCommit??!1,v=t.model;if(e)r=e,i=e;else{let T=await Rt();n&&(f=T.typecheck),s&&(m=T.autoCommit),t.skipModelPrompt||(v=T.model);let _=await Ot();o=_.sessionId,r=_.firstPrompt,l=_.existingTurnCount,i=_.isResume&&await Re()||r}for(Cn(f,m,!!n,!!s,v);;){l++,console.log(`
1270
+ Turn ${l}`),xe();let T=new Set;ce=new AbortController;let _=await ve(i,{model:v==="auto"?void 0:v,sessionId:o,projectId:process.env.PROJECT_ID||null,debugLog:!0,abortController:ce,callbacks:It({sessionId:o,onSessionInit:y=>{o=y},onCostUpdate:y=>{h+=y},onFileModified:y=>{T.add(y)}})});if(console.log("after runAgent"),ce=null,_.sessionId&&(o=_.sessionId),_.cost&&(h=_.cost),console.log("after result"),En(o,r,l),console.log("after saveSessionIfNeeded"),_.aborted){if(await new Promise(U=>setTimeout(U,100)),xe(),h>0&&console.log(` \u{1F4B0} Session cost so far: $${h.toFixed(4)}
1271
+ `),await Dt()==="exit")break;let R=await Re();if(!R)break;i=R;continue}if(console.log("after abort"),o){let y=ee(o);if(y&&y.length>0){Pt();let R=await Pe(y);i=Ce(R),At();continue}}if(console.log("after pending questions"),f&&n){let y=await Ut(n,T);if(!y.passed&&y.errorPrompt){i=y.errorPrompt;continue}}if(console.log("after typecheck"),m&&s){let y=_.aborted||!!_.error;await Nt(s,r,y)}console.log("after auto-commit"),xe();let O=await Re();if(!O)break;i=O}Tn(o,h)}function Cn(e,t,n,s,o){Ge("\u{1F680} Agent Started"),console.log(" \u{1F4DD} Debug logs \u2192 /tmp/agent-debug/"),o&&console.log(` \u{1F916} Model: ${o==="auto"?"Auto":o==="claude-opus-4-5-20251101"?"Opus 4.5":o==="claude-sonnet-4-5-20250929"?"Sonnet 4.5":o==="claude-haiku-4-5-20251001"?"Haiku 4.5":"Unknown"}`),e&&n&&console.log(" \u{1F50D} Auto-typecheck enabled (self-correcting mode)"),t&&s&&console.log(" \u{1F4E6} Auto-commit enabled"),console.log(` \u{1F4A1} Press Ctrl+C to stop the agent
1272
+ `)}function Tn(e,t){Ge("\u2705 Session Complete"),e&&console.log(" \u{1F4BE} Session saved - you can resume it next time"),t>0&&console.log(` \u{1F4B0} Total cost: $${t.toFixed(4)}`),console.log()}function En(e,t,n){e&&bt({sessionId:e,firstPrompt:t,createdAt:new Date().toISOString(),lastUsedAt:new Date().toISOString(),turnCount:n})}process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT=process.env.CLAUDE_CODE_STREAM_CLOSE_TIMEOUT||"60000";async function Pn(){let e=process.env.API_URL||process.env.MASTER_URL,t=process.env.PROJECT_ID,n=e,s=t;if(!e||!t){console.log(`
1273
1273
  \u{1F4CB} API Configuration Required
1274
- `);let f=await Ot();n=f.apiUrl,s=f.projectId}process.env.API_URL=n,process.env.PROJECT_ID=s;let o=process.env.WORKSPACE_DIR||process.cwd(),r=Te({workspaceDir:o}),i=Ee(o),l=te(o);pe(r),de(l),await Oe(void 0,{serviceManager:r,gitManager:i})}Tn().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
1274
+ `);let f=await Ft();n=f.apiUrl,s=f.projectId}process.env.API_URL=n,process.env.PROJECT_ID=s;let o=process.env.WORKSPACE_DIR||process.cwd(),r=Te({workspaceDir:o}),i=Ee(o),l=te(o);ge(r),ue(l),await Oe(void 0,{serviceManager:r,gitManager:i})}Pn().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glenn-code",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Glenn Code - Connect your local development environment to DNM Lab",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",