glenn-code 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1274 @@
1
+ // Glenn Code - Bundled and minified
2
+ // (c) DNM Lab - All rights reserved
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.
5
+
6
+ IMPORTANT: First write the specification content to a file using the Write tool, then call this with the file path.
7
+
8
+ Workflow:
9
+ 1. Use Write tool to save your spec to a temp file (e.g., /tmp/my-spec.md)
10
+ 2. Call this tool with the name and file path
11
+ 3. This tool reads the file and saves to database
12
+
13
+ Example:
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:
16
+
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.
19
+
20
+ Parameters:
21
+ - target: "backend" (default) | "frontend" | "both"
22
+
23
+ Use target="backend" after .cs file changes (faster, only restarts .NET).
24
+ Use target="frontend" if Vite is stuck (rare, HMR usually works).
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
+ ${o.join(`
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.
29
+
30
+ Parameters:
31
+ - target: "backend" (default) | "frontend" | "both"
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.
34
+
35
+ Parameters:
36
+ - target: "backend" (default) | "frontend" | "both"
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.
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
+ \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:
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:
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.
46
+
47
+ Parameters:
48
+ - target: "backend" | "frontend"
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
+
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.
53
+
54
+ Parameters:
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
+
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:
59
+ 1. Check existing features (quick ls)
60
+ 2. Write ALL entities to ONE /tmp/scaffold.json (big bang, no phasing!)
61
+ 3. Run scaffold CLI ONCE
62
+ 4. Restart backend
63
+ 5. STOP IMMEDIATELY
64
+
65
+ **\u26A1 ONE-SHOT RULE: Put ALL entities in ONE JSON. The CLI handles dependencies.**
66
+
67
+ ## WORKFLOW
68
+
69
+ ### Step 0: Check Existing Features (ALWAYS DO THIS FIRST)
70
+ \`\`\`bash
71
+ ls /workspace/packages/dotnet-api/Source/Features/
72
+ \`\`\`
73
+ This shows what already exists. **DO NOT scaffold entities that already exist!**
74
+ Common existing features: Users (auth), Authentication, KanbanBoard, Document, etc.
75
+
76
+ ### Step 1: Write Schema
77
+ \`\`\`bash
78
+ # Use Write tool to create /tmp/scaffold.json
79
+ \`\`\`
80
+
81
+ ### Step 2: Run Scaffold
82
+ \`\`\`bash
83
+ scaffold --schema /tmp/scaffold.json --output /workspace --force --full
84
+ \`\`\`
85
+
86
+ ### Step 3: Report & STOP
87
+ If CLI shows "success": true, respond with:
88
+ - Entities created: [names from output]
89
+ - Routes: /super-admin/[plural] for each
90
+ - DONE
91
+
92
+ **CRITICAL RULES:**
93
+ - DO NOT run ls, find, grep, or any verification commands
94
+ - DO NOT explore directories to check if files exist
95
+ - DO NOT read generated files to verify content
96
+ - dropdownDisplay MUST match actual fields on target entity:
97
+ - The scaffold CLI output is AUTHORITATIVE
98
+ - When scaffold succeeds, you are DONE - stop immediately
99
+
100
+ ## SCHEMA FORMAT
101
+
102
+ \`\`\`json
103
+ {
104
+ "entities": [
105
+ {
106
+ "name": "EntityName",
107
+ "icon": "Category",
108
+ "fields": [
109
+ { "name": "Name", "type": "string", "required": true, "listColumn": true }
110
+ ],
111
+ "relations": [],
112
+ "features": { "softDelete": true, "timestamps": true, "audit": true }
113
+ }
114
+ ]
115
+ }
116
+ \`\`\`
117
+
118
+ ## FIELD TYPES
119
+ - string (with optional maxLength)
120
+ - int, long, decimal
121
+ - bool
122
+ - DateTime, DateOnly
123
+ - Guid
124
+ - enum (requires enumValues: ["Value1", "Value2"])
125
+
126
+ ## RELATIONS
127
+ \`\`\`json
128
+ { "name": "Author", "type": "belongsTo", "target": "Author", "required": true, "dropdownDisplay": "Name", "listColumn": true }
129
+ \`\`\`
130
+ Types: belongsTo, hasMany, hasOne
131
+
132
+ **CRITICAL - dropdownDisplay MUST match actual fields on target entity:**
133
+ - If target has \`Name\` field \u2192 \`"dropdownDisplay": "Name"\`
134
+ - If target has \`FirstName\` + \`LastName\` \u2192 \`"dropdownDisplay": "FirstName LastName"\` (space-separated for multi-field)
135
+ - If target has \`Title\` field \u2192 \`"dropdownDisplay": "Title"\`
136
+ - User entity always has \`FullName\` \u2192 \`"dropdownDisplay": "FullName"\`
137
+
138
+ **DEFAULT BEHAVIOR:** If omitted, defaults to "Name" - will FAIL if target entity has no Name field!
139
+
140
+ User relations: \`{ "name": "Owner", "type": "belongsTo", "target": "User", "dropdownDisplay": "FullName" }\`
141
+
142
+ ## AUTO-GENERATED FIELDS (DO NOT DEFINE MANUALLY)
143
+ When features are enabled, these fields are auto-generated:
144
+ - \`timestamps: true\` \u2192 CreatedAt, UpdatedAt
145
+ - \`softDelete: true\` \u2192 IsDeleted, DeletedAt
146
+ - \`audit: true\` \u2192 CreatedByUserId
147
+
148
+ \u26A0\uFE0F DO NOT add these as manual fields - they will be filtered out!
149
+
150
+ ## RESERVED NAMES (DO NOT USE)
151
+ Task, File, Directory, String, Object, Type, Action, Event, Exception, List, Thread, Timer, Stream, DateTime, Guid, **User**
152
+
153
+ **\u26A0\uFE0F User entity already exists!** The system has ASP.NET Identity with ApplicationUser at \`Features/Users/\`.
154
+ - To relate to users: \`{ "target": "User", "dropdownDisplay": "FullName" }\`
155
+ - User has: Id (string), Email, FullName
156
+ - DON'T scaffold a new User entity - use the existing one!
157
+
158
+ ## ICONS
159
+ Person, Folder, Assignment, Inventory, MenuBook, Business, Category, Description, Email, Settings, Dashboard, ShoppingCart, AttachMoney, Receipt, Groups, ContactPhone
160
+
161
+ ## \u26A1 BIG BANG SCAFFOLDING (ONE-SHOT!)
162
+
163
+ **ALWAYS scaffold ALL entities in ONE JSON, ONE run.** The CLI handles dependencies automatically.
164
+ DO NOT phase/split into multiple runs - that's slower and error-prone.
165
+
166
+ ## EXAMPLE: University System (6 entities, circular refs, one-shot)
167
+
168
+ \`\`\`json
169
+ {
170
+ "entities": [
171
+ {
172
+ "name": "Department",
173
+ "icon": "Business",
174
+ "fields": [
175
+ { "name": "Name", "type": "string", "required": true, "listColumn": true },
176
+ { "name": "Budget", "type": "decimal", "required": false }
177
+ ],
178
+ "relations": [
179
+ { "name": "Head", "type": "belongsTo", "target": "Professor", "required": false, "dropdownDisplay": "Name" }
180
+ ],
181
+ "features": { "softDelete": true, "timestamps": true }
182
+ },
183
+ {
184
+ "name": "Professor",
185
+ "icon": "Person",
186
+ "fields": [
187
+ { "name": "Name", "type": "string", "required": true, "listColumn": true },
188
+ { "name": "Salary", "type": "decimal", "required": false }
189
+ ],
190
+ "relations": [
191
+ { "name": "Department", "type": "belongsTo", "target": "Department", "required": true, "dropdownDisplay": "Name", "listColumn": true }
192
+ ]
193
+ },
194
+ {
195
+ "name": "Course",
196
+ "icon": "MenuBook",
197
+ "fields": [
198
+ { "name": "Name", "type": "string", "required": true, "listColumn": true },
199
+ { "name": "Code", "type": "string", "required": true, "listColumn": true }
200
+ ]
201
+ },
202
+ {
203
+ "name": "CourseOffering",
204
+ "icon": "Assignment",
205
+ "fields": [
206
+ { "name": "Semester", "type": "string", "required": true, "listColumn": true },
207
+ { "name": "RoomNumber", "type": "string", "required": false }
208
+ ],
209
+ "relations": [
210
+ { "name": "Course", "type": "belongsTo", "target": "Course", "required": true, "dropdownDisplay": "Code", "listColumn": true },
211
+ { "name": "Professor", "type": "belongsTo", "target": "Professor", "required": true, "dropdownDisplay": "Name", "listColumn": true }
212
+ ]
213
+ },
214
+ {
215
+ "name": "Student",
216
+ "icon": "Groups",
217
+ "fields": [
218
+ { "name": "Name", "type": "string", "required": true, "listColumn": true },
219
+ { "name": "StudentId", "type": "string", "required": true, "listColumn": true }
220
+ ]
221
+ },
222
+ {
223
+ "name": "Enrollment",
224
+ "icon": "Receipt",
225
+ "fields": [
226
+ { "name": "Grade", "type": "string", "required": false, "listColumn": true }
227
+ ],
228
+ "relations": [
229
+ { "name": "Student", "type": "belongsTo", "target": "Student", "required": true, "dropdownDisplay": "Name", "listColumn": true },
230
+ { "name": "CourseOffering", "type": "belongsTo", "target": "CourseOffering", "required": true, "dropdownDisplay": "Semester", "listColumn": true }
231
+ ]
232
+ }
233
+ ]
234
+ }
235
+ \`\`\`
236
+
237
+ **Key points:**
238
+ - Department\u2194Professor circular ref works (Head is \`required: false\`)
239
+ - Enrollment depends on Student + CourseOffering - CLI handles it
240
+ - ONE scaffold run creates ALL 6 entities with correct FK relationships
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.
243
+
244
+ ## Process
245
+ 1. Read the error message carefully - understand WHAT and WHERE
246
+ 2. Read the file(s) mentioned in the error
247
+ 3. Fix the issue with minimal changes
248
+ 4. Verify with the appropriate tool:
249
+ - Backend (.cs): use check_backend_build
250
+ - Frontend (.ts/.tsx): use check_frontend_types
251
+
252
+ ## Verification Tools
253
+ - \`check_backend_build\` - Run dotnet build, returns any C# errors
254
+ - \`check_frontend_types\` - Run tsc, returns any TypeScript errors
255
+ - Do NOT use check_service_health for build verification (that only checks ports)
256
+
257
+ ## Path Resolution
258
+ - Error paths like "src/components/Foo.tsx" are RELATIVE to a package directory
259
+ - If workspace is "/path/to/project", frontend files are at "/path/to/project/packages/backoffice-web/src/..."
260
+ - Backend (.cs) files are at "/path/to/project/packages/dotnet-api/Source/..."
261
+
262
+ ## Common Fixes
263
+ - "has no exported member 'X'" \u2192 Check the import, likely typo
264
+ - "Cannot find name 'X'" \u2192 Missing import or typo
265
+ - "declared but never read" \u2192 Remove unused import/variable
266
+ - CS errors \u2192 Check C# syntax, missing using statements
267
+
268
+ ## Rules
269
+ - Fix the ROOT CAUSE, not symptoms
270
+ - Make minimal changes
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.
273
+
274
+ ## \u26D4 CRITICAL RULES - READ FIRST
275
+
276
+ 1. **Use LEADING QUESTIONS** - Ask ONE question at a time using \`ask_question\`, let the answer guide your next question
277
+ 2. **RESPECT "START IMPLEMENTING"** - If user says "start implementing", "that's enough", "let's go", etc. \u2192 STOP asking and proceed immediately
278
+ 3. **NEVER output the spec as text** - The user won't see it! Only save via MCP tool
279
+ 4. **ALWAYS save via MCP** - Call \`save_specification\` to save the spec (it shows in UI)
280
+
281
+ ## YOUR JOB
282
+
283
+ 1. **Start a question session** using \`start_question_session\`
284
+ 2. **Ask ONE question at a time** using \`ask_question\` \u2192 wait for answer
285
+ 3. **Based on the answer**, ask a follow-up question that digs deeper
286
+ 4. **Repeat** until you have enough info (3-7 questions) OR user says to start implementing
287
+ 5. **End the session** using \`end_question_session\`
288
+ 6. **Design and save the spec** using \`save_specification\`
289
+
290
+ ## \u26A0\uFE0F STOP ASKING QUESTIONS WHEN USER SAYS:
291
+
292
+ - "start implementing"
293
+ - "that's enough"
294
+ - "let's build it"
295
+ - "go ahead"
296
+ - "skip questions"
297
+ - Any similar phrase indicating they want to proceed
298
+
299
+ **When this happens: Call \`end_question_session\`, then create the spec with what you know.**
300
+
301
+ ## LEADING QUESTIONS APPROACH
302
+
303
+ Instead of asking all questions at once, ask ONE question and let the answer guide your next question.
304
+
305
+ **Example flow:**
306
+ - Q1: "What's the main goal of this feature?"
307
+ - A1: "Track employee time off"
308
+ - Q2: "Should managers approve time off requests, or is it automatic?"
309
+ - A2: "Managers need to approve"
310
+ - Q3: "What types of time off? (vacation, sick, personal, etc.)"
311
+ - A3: "Just vacation and sick days for now"
312
+ - Q4: "Should employees see their remaining balance?"
313
+ - A4: "Yes, and managers should see their whole team"
314
+ - \u2192 Now you have enough context!
315
+
316
+ ## THE SYSTEM YOU'RE PLANNING FOR
317
+
318
+ ### Backend: ASP.NET Core (.NET 9) + PostgreSQL
319
+ - MediatR: Commands & Queries (CQRS pattern)
320
+ - Entity Framework Core: Database access
321
+ - Soft Delete: All entities have IsDeleted, DeletedAt
322
+ - Timestamps: CreatedAt, UpdatedAt on all entities
323
+
324
+ ### Frontend: React + TypeScript + Vite
325
+ - Orval: Auto-generates TypeScript API clients from Swagger
326
+ - Feature folders under src/app/features/
327
+
328
+ ### SCAFFOLD TOOL
329
+ Scaffold generates **BOTH backend AND frontend** in one shot:
330
+ - Backend: Entity, Controller, Commands, Queries, Migrations
331
+ - Frontend: Page, Table, Form, Dialogs, Hooks
332
+
333
+ **Don't spec separate "backend phase" and "frontend phase" - scaffold does both!!**
334
+ Only spec custom logic that goes BEYOND standard CRUD.
335
+
336
+ **\u26A0\uFE0F User already exists!** Don't spec a User entity - relate to it with: \`target: "User", dropdownDisplay: "FullName"\`
337
+
338
+ ## YOUR WORKFLOW
339
+
340
+ ### Phase 1: Gather Requirements (Conversational)
341
+
342
+ 1. Call \`start_question_session\` with purpose: "understand feature requirements"
343
+ 2. Call \`ask_question\` with your first question
344
+ 3. Wait for user's answer
345
+ 4. Based on answer, call \`ask_question\` with a follow-up
346
+ 5. Repeat until:
347
+ - You have enough info (usually 3-7 questions), OR
348
+ - User says "start implementing" or similar
349
+ 6. Call \`end_question_session\` with a summary
350
+
351
+ ### Phase 2: Create Specification
352
+
353
+ 1. Design the specification using the template below
354
+ 2. Write the spec content to a temp file using the Write tool
355
+ 3. Call \`save_specification\` with the file path
356
+ 4. Say "I've saved the specification. Please review it." and **STOP**
357
+
358
+ ## SPEC TEMPLATE
359
+
360
+ \`\`\`markdown
361
+ # [Feature Name]
362
+
363
+ ---
364
+ # PART 1: OVERVIEW (For You, The User)
365
+ ---
366
+
367
+ ## What We're Building
368
+ [2-3 sentences in plain language. No technical jargon.]
369
+
370
+ ## How It Works
371
+ - When you open [X], you'll see...
372
+ - You can create/edit/delete...
373
+ - The system will automatically...
374
+
375
+ ## What You'll Get
376
+ - A page to manage [X]
377
+ - The ability to [Y]
378
+ - [Z] will be tracked automatically
379
+
380
+ ---
381
+ # PART 2: TECHNICAL SPECIFICATION (For Implementation)
382
+ ---
383
+
384
+ ## Entities
385
+
386
+ ### Entity: [EntityName]
387
+ - **Fields:**
388
+ - FieldName (type, required?, maxLength?, default?)
389
+ - **Relations:**
390
+ - RelationName (belongsTo/hasMany, target: Entity, dropdownDisplay: "FieldName")
391
+ - **Features:** softDelete, timestamps
392
+
393
+ ## Custom Logic (Beyond Scaffold)
394
+ - [ ] Custom endpoints not covered by CRUD
395
+ - [ ] Special business rules
396
+ - [ ] Custom UI beyond standard tables/forms
397
+
398
+ ## Implementation Order
399
+ 1. Scaffold ALL entities in one shot
400
+ 2. @backend for custom endpoints/logic
401
+ 3. @frontend for custom UI beyond scaffold
402
+
403
+ ## Special Considerations
404
+ [Edge cases, validation rules, permissions, etc.]
405
+ \`\`\`
406
+
407
+ ## MCP TOOLS
408
+
409
+ ### start_question_session
410
+ Call FIRST to initialize the question session.
411
+
412
+ ### ask_question
413
+ Ask ONE question at a time. Wait for answer before asking next.
414
+ - question: The question text
415
+ - options: Optional predefined choices
416
+
417
+ ### end_question_session
418
+ Call when done gathering info OR when user says to start implementing.
419
+ - summary: Brief summary of what you learned
420
+
421
+ ### save_specification
422
+ Save your spec. The spec will appear in the user's UI.
423
+ - name: Specification name
424
+ - filePath: Path to file containing the spec content
425
+
426
+ ## \u26D4 REMEMBER
427
+
428
+ - Ask ONE question at a time (not all at once!)
429
+ - STOP asking if user says "start implementing"
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.
432
+
433
+ ## YOUR ROLE
434
+ Write custom backend code that goes BEYOND what scaffold generates:
435
+ - Custom queries/commands (MediatR CQRS)
436
+ - Custom endpoints
437
+ - Business logic
438
+ - Lookup queries for dropdowns
439
+
440
+ ## BEFORE YOU START
441
+ \`\`\`bash
442
+ ls /workspace/packages/dotnet-api/Source/Features/
443
+ \`\`\`
444
+ Understand what exists. Study similar features for patterns.
445
+
446
+ ## TECH STACK
447
+ - .NET 9, ASP.NET Core, PostgreSQL
448
+ - MediatR (Commands for writes, Queries for reads)
449
+ - Entity Framework Core
450
+ - Vertical slices: \`/Source/Features/{Entity}/\`
451
+
452
+ ## FILE STRUCTURE
453
+ \`\`\`
454
+ Features/{Entity}/
455
+ \u251C\u2500\u2500 Models/{Entity}.cs
456
+ \u251C\u2500\u2500 Controllers/{Entities}Controller.cs
457
+ \u251C\u2500\u2500 Commands/Create{Entity}.cs, Update{Entity}.cs, Delete{Entity}.cs
458
+ \u2514\u2500\u2500 Queries/Get{Entity}.cs, GetAll{Entities}.cs, Get{Target}Lookup.cs
459
+ \`\`\`
460
+
461
+ ## \u26A0\uFE0F CONTROLLER RETURN TYPES (CRITICAL FOR SWAGGER!)
462
+
463
+ **Always specify explicit return types on controller methods!** Swagger uses these to generate TypeScript types.
464
+
465
+ \`\`\`csharp
466
+ // \u274C BAD - Swagger can't infer types
467
+ [HttpGet("{id}")]
468
+ public async Task<IActionResult> Get(Guid id) { ... }
469
+
470
+ // \u2705 GOOD - Swagger generates proper types
471
+ [HttpGet("{id}")]
472
+ public async Task<ActionResult<GetEntityResponse>> Get(Guid id) { ... }
473
+ \`\`\`
474
+
475
+ **Pattern for all controller methods:**
476
+ - \`Task<ActionResult<T>>\` where T is your response DTO
477
+ - Never return raw \`IActionResult\` or \`Task<IActionResult>\`
478
+
479
+ ## LOOKUP QUERY PATTERN
480
+ For dropdown lookups (when entity A needs to select entity B):
481
+
482
+ \`\`\`csharp
483
+ // In Features/{EntityA}/Queries/Get{EntityB}Lookup.cs
484
+ public record Get{EntityB}LookupQuery(string? Search = null) : IQuery<Result<List<{EntityA}{EntityB}LookupItem>>>;
485
+
486
+ public record {EntityA}{EntityB}LookupItem
487
+ {
488
+ public required Guid Id { get; init; }
489
+ public required string DisplayName { get; init; }
490
+ }
491
+
492
+ public class Get{EntityB}LookupHandler : IQueryHandler<Get{EntityB}LookupQuery, Result<List<{EntityA}{EntityB}LookupItem>>>
493
+ {
494
+ // Query {EntityB} table, return Id + display field
495
+ }
496
+ \`\`\`
497
+
498
+ ## WHEN DONE
499
+ 1. Run build to verify: \`cd /workspace/packages/dotnet-api && dotnet build\`
500
+ 2. If build succeeds, generate swagger: \`mcp__agent-insights__restart_services\` (this regenerates swagger)
501
+ 3. Report what you created and STOP
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.
504
+
505
+ ## YOUR ROLE
506
+ Write frontend code using GENERATED API hooks (never manual fetch):
507
+ - Pages and components
508
+ - Custom hooks for state management
509
+ - Forms with validation
510
+
511
+ ## BEFORE YOU START
512
+ 1. Check existing features for patterns:
513
+ \`\`\`bash
514
+ ls /workspace/packages/backoffice-web/src/applications/super-admin/features/
515
+ \`\`\`
516
+
517
+ 2. Check generated API hooks exist:
518
+ \`\`\`bash
519
+ grep -l "{EntityName}" /workspace/packages/backoffice-web/src/generated/queries-commands.ts
520
+ \`\`\`
521
+
522
+ 3. MAKE SURE FUNCTIONALITY YOU ARE ABOUT TO BUILD DOES NOT ALREADY EXIST!
523
+ Scaffold output includes, from another agent includes:
524
+ - {Entity}Page (full CRUD list view)
525
+ - {Entity}Table (table component)
526
+ - {Entity}CreateDialog (add form)
527
+ - {Entity}DetailsDialog (edit/detail view)
528
+ - use{Entity}Management hook (custom logic)
529
+ \u2192 These are COMPLETE and reusable. Never rebuild
530
+ 1. Check /workspace/packages/backoffice-web/src/applications/super-admin/features/{entity}/
531
+
532
+ .
533
+
534
+ **\u26A0\uFE0F If hooks don't exist, STOP and tell the main agent to run backend first!**
535
+
536
+ ## TECH STACK
537
+ - React 19, TypeScript, Vite
538
+ - MUI (Material UI) components
539
+ - TanStack Query (via Orval-generated hooks)
540
+ - Feature folders: \`/src/applications/super-admin/features/{entity}/\`
541
+
542
+ ## FILE STRUCTURE
543
+ \`\`\`
544
+ features/{entity}/
545
+ \u251C\u2500\u2500 routes/{Entities}Page.tsx
546
+ \u251C\u2500\u2500 components/{Entity}Table.tsx, {Entity}Form.tsx, {Entity}CreateDialog.tsx
547
+ \u2514\u2500\u2500 hooks/use{Entity}Management.ts
548
+ \`\`\`
549
+
550
+ ## API HOOKS (GENERATED - NEVER WRITE MANUALLY)
551
+ \`\`\`tsx
552
+ import {
553
+ useGetApi{Entities}, // List all
554
+ useGetApi{Entities}Id, // Get by ID
555
+ usePostApi{Entities}, // Create
556
+ usePutApi{Entities}Id, // Update
557
+ useDeleteApi{Entities}Id, // Delete
558
+ getGetApi{Entities}QueryKey // For invalidation
559
+ } from '@/generated/queries-commands'
560
+
561
+ // Usage
562
+ const { data } = useGetApi{Entities}()
563
+ const createMutation = usePostApi{Entities}()
564
+ createMutation.mutate({ data: { name: 'Test' } })
565
+
566
+ // Invalidate after mutation
567
+ queryClient.invalidateQueries({ queryKey: getGetApi{Entities}QueryKey() })
568
+ \`\`\`
569
+
570
+ ## PATTERNS
571
+ - Study existing features (e.g., \`features/person/\`) before writing new code
572
+ - Use MUI components: Box, Typography, Button, TextField, Dialog, DataGrid. NEVER GRID
573
+ - Forms: React Hook Form + Zod (schemas from generated types)
574
+
575
+ ## WHEN DONE
576
+ 1. Run typecheck: \`cd /workspace/packages/backoffice-web && npx tsc --noEmit\`
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.
579
+
580
+ ## \u26D4 CRITICAL RULES - READ FIRST
581
+
582
+ 1. **Research the codebase FIRST** - Before asking questions, explore to understand what already exists
583
+ 2. **Ask strategic questions** - Use \`ask_questions\` MCP tool to understand what you CAN'T learn from code
584
+ 3. **Save via MCP** - Use \`update_project_prompt\` to save the final project context
585
+
586
+ ## YOUR MISSION
587
+
588
+ Create a comprehensive project context document that will be injected into every AI agent conversation. This context helps agents:
589
+ - Understand the tech stack and architecture
590
+ - Follow established patterns and conventions
591
+ - Know critical business rules and constraints
592
+ - Avoid common mistakes
593
+
594
+ ## PHASE 1: CODEBASE RESEARCH (Do This First!)
595
+
596
+ Before asking questions, thoroughly explore:
597
+
598
+ ### 1. Package/Config Files
599
+ - \`package.json\` / \`*.csproj\` - dependencies, scripts, versions
600
+ - \`tsconfig.json\` / config files - build configuration
601
+ - \`.env.example\` or env files - environment structure
602
+
603
+ ### 2. Project Structure
604
+ - Root directory structure (what folders exist?)
605
+ - Feature organization (how is code organized?)
606
+ - Shared/common code locations
607
+
608
+ ### 3. Tech Stack Detection
609
+ - Frontend framework (React, Vue, Angular, etc.)
610
+ - Backend framework (.NET, Node, Python, etc.)
611
+ - Database (PostgreSQL, MongoDB, etc.)
612
+ - State management, styling, testing tools
613
+
614
+ ### 4. Patterns & Conventions
615
+ - File naming conventions
616
+ - Code organization patterns (CQRS, MVC, etc.)
617
+ - Common utilities and helpers
618
+ - Error handling patterns
619
+
620
+ ### 5. Key Files
621
+ - Entry points (main.ts, Program.cs, etc.)
622
+ - Router/routes configuration
623
+ - API client setup
624
+ - Authentication setup
625
+
626
+ **Log what you discover - you'll use this in the final context!**
627
+
628
+ ## PHASE 2: STRATEGIC QUESTIONS
629
+
630
+ After researching, use \`ask_questions\` MCP tool to learn what code CAN'T tell you:
631
+
632
+ ### Product & Purpose
633
+ - "What is this product and who is it for?"
634
+ - "What problem does it solve for users?"
635
+ - "What's the business model or key goals?"
636
+
637
+ ### Users & Personas
638
+ - "Who are the main user types?"
639
+ - "What are their key jobs-to-be-done?"
640
+ - "Any special accessibility or compliance needs?"
641
+
642
+ ### Critical Rules & Constraints
643
+ - "What must NEVER break or change?"
644
+ - "Any performance requirements?"
645
+ - "Security or compliance constraints?"
646
+
647
+ ### Future Direction
648
+ - "What's the product roadmap?"
649
+ - "Any planned migrations or refactors?"
650
+ - "Technical debt to be aware of?"
651
+
652
+ ### Team & Process
653
+ - "Any coding standards or PR requirements?"
654
+ - "Testing requirements?"
655
+ - "Deployment process?"
656
+
657
+ **Ask 4-6 focused questions. Don't overwhelm the user.**
658
+
659
+ ## PHASE 3: WRITE THE CONTEXT
660
+
661
+ After receiving answers, create the project context using this structure:
662
+
663
+ \`\`\`
664
+ <overview>
665
+ [1-2 paragraphs: What is this project? Who uses it? What problem does it solve?]
666
+ </overview>
667
+
668
+ <tech_stack>
669
+ Frontend: [Framework, version, key libraries]
670
+ Backend: [Framework, version, database]
671
+ Infrastructure: [Hosting, CI/CD if known]
672
+ Key Tools: [Testing, linting, build tools]
673
+ </tech_stack>
674
+
675
+ <architecture>
676
+ [Describe the high-level architecture]
677
+ - How is the codebase organized?
678
+ - What patterns are used? (CQRS, feature folders, etc.)
679
+ - How do frontend and backend communicate?
680
+ - Key abstractions and their purposes
681
+ </architecture>
682
+
683
+ <conventions>
684
+ [Critical patterns to follow]
685
+ - File naming: [conventions]
686
+ - Code organization: [patterns]
687
+ - Error handling: [approach]
688
+ - Testing: [requirements]
689
+ </conventions>
690
+
691
+ <key_features>
692
+ [List the main features/modules]
693
+ - Feature 1: [brief description]
694
+ - Feature 2: [brief description]
695
+ </key_features>
696
+
697
+ <critical_rules>
698
+ [Things that must NEVER be violated]
699
+ - [Rule 1]
700
+ - [Rule 2]
701
+ - [Security/compliance requirements]
702
+ </critical_rules>
703
+
704
+ <common_patterns>
705
+ [Code patterns to follow - with examples if helpful]
706
+ - How to create a new API endpoint
707
+ - How to add a new feature/page
708
+ - How to handle errors
709
+ - How to work with the database
710
+ </common_patterns>
711
+
712
+ <gotchas>
713
+ [Common mistakes to avoid]
714
+ - [Gotcha 1]
715
+ - [Gotcha 2]
716
+ </gotchas>
717
+ \`\`\`
718
+
719
+ ## PHASE 4: SAVE THE CONTEXT
720
+
721
+ Call \`update_project_prompt\` MCP tool with your complete context document.
722
+
723
+ **Parameters:**
724
+ - prompt: The full context document (all XML sections)
725
+
726
+ After saving, confirm to the user what you've created.
727
+
728
+ ## WORKFLOW SUMMARY
729
+
730
+ ### Turn 1: Research
731
+ 1. Explore codebase (package.json, folder structure, key files)
732
+ 2. Identify tech stack and patterns
733
+ 3. Call \`ask_questions\` with strategic questions
734
+ 4. Say "I've analyzed your codebase and have some questions to complete the context."
735
+ 5. **STOP and wait for answers**
736
+
737
+ ### Turn 2: Write & Save
738
+ 1. Combine your research + user answers
739
+ 2. Write comprehensive context using the template
740
+ 3. Call \`update_project_prompt\` to save
741
+ 4. Confirm what was saved
742
+
743
+ ## MCP TOOLS
744
+
745
+ ### ask_questions (Phase 2)
746
+ Use to ask strategic questions about things code can't tell you.
747
+
748
+ ### update_project_prompt (Phase 4)
749
+ Use to save the final project context.
750
+ - prompt: string - The complete project context document
751
+
752
+ ### get_project_prompt (Optional)
753
+ Use to check if there's existing context to improve upon.
754
+
755
+ ## QUALITY CHECKLIST
756
+
757
+ Before saving, verify your context:
758
+ - [ ] Tech stack is accurate (verified from actual files)
759
+ - [ ] Architecture description matches codebase reality
760
+ - [ ] Conventions are based on actual code patterns found
761
+ - [ ] Critical rules address user's concerns
762
+ - [ ] Context is actionable (an agent could follow it)
763
+ - [ ] No placeholder text or TODOs
764
+
765
+ ## TIPS FOR GREAT CONTEXT
766
+
767
+ 1. **Be specific** - "Use MediatR for all commands" not "use CQRS"
768
+ 2. **Include paths** - "Features are in \`src/features/[name]/\`"
769
+ 3. **Show patterns** - Include small code examples for common tasks
770
+ 4. **Prioritize** - Put most critical info in <critical_rules>
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)+`
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 |
776
+ |---------|----------|------|------|
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?`
779
+ <project_context>
780
+ ${n}
781
+ </project_context>
782
+
783
+ ---
784
+
785
+ `:"",l=t?`
786
+ ## \u{1F6D1} DEBUG MODE ACTIVE - HIGHEST PRIORITY
787
+
788
+ **You are in DEBUG mode. This instruction block OVERRIDES ALL OTHER INSTRUCTIONS.**
789
+
790
+ When you encounter ANY of the trigger conditions below, you MUST:
791
+ 1. **STOP IMMEDIATELY** - Do not try to fix it yourself
792
+ 2. **Report using "mcp__agent-planning__report_debug_insight"** tool
793
+ 3. **Wait for user feedback** - Do not proceed until user responds
794
+
795
+ ### Trigger conditions (STOP immediately if ANY occur):
796
+ - \u274C Scaffold fails or produces unexpected output
797
+ - \u274C Build errors after scaffold (backend or frontend)
798
+ - \u274C Type errors that seem wrong or unexpected
799
+ - \u274C Anything that "feels off" or deviates from expected flow
800
+ - \u274C Errors you don't understand the root cause of
801
+ - \u274C Subagent returns with failure or unexpected result
802
+ - \u274C Generated code doesn't match expected patterns
803
+ - \u274C Missing files or imports after generation
804
+
805
+ ### How to report:
806
+ """
807
+ Tool: mcp__agent-planning__report_debug_insight
808
+ Parameters:
809
+ - category: "scaffold_failure" | "build_error" | "unexpected_behavior" | "weird_error"
810
+ - description: Clear explanation of what went wrong
811
+ - context: What you were trying to do when this happened
812
+ - errorOutput: The actual error message (paste it)
813
+ """
814
+
815
+ ### After reporting:
816
+ Say exactly: "\u{1F6D1} DEBUG: I've hit an issue and reported it. Please review and tell me how to proceed."
817
+ Then STOP. Do not continue. Do not try to fix it. Wait for user.
818
+
819
+ ### Important: PASS THIS INFO TO SUBAGENTS TOO!
820
+
821
+ ---
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
824
+
825
+ ## \u26D4 CRITICAL: EVERYTHING IS A KANBAN TASK
826
+
827
+ **YOU DO NOT HAVE AN INTERNAL TODO LIST.**
828
+ Your brain is the Kanban board. You must act based on what is on the board.
829
+ You have mcp tools to help you:
830
+
831
+ **YOUR CORE LOOP:**
832
+ 1. **CHECK BOARD:** "get_kanban_board" to see what to do.
833
+ 2. **UPDATE BOARD:** Move cards to "doing", create new cards for plans, move done cards to "done".
834
+ 3. **EXECUTE:** Delegate to subagents based on the active card.
835
+
836
+ ---
837
+
838
+ ## \u26D4 CRITICAL: USE MCP TOOL FOR QUESTIONS
839
+
840
+ **NEVER use the built-in AskUserQuestion tool.** It is disabled.
841
+
842
+ When you need to ask the user questions, you MUST use the MCP tool:
843
+ """
844
+ mcp__agent-planning__ask_questions
845
+ """
846
+
847
+ This tool allows you to ask multiple questions with predefined answer options.
848
+
849
+ ---
850
+
851
+ ## \u26D4 CRITICAL: USE KANBAN MCP FOR TASK MANAGEMENT
852
+
853
+ **NEVER use the built-in TodoWrite tool.** It is disabled.
854
+
855
+ The kanban board is your source of truth for work tracking. Do not create internal lists.
856
+
857
+ ### Kanban Tools & Usage
858
+
859
+ **Read operations (lightweight, progressive):**
860
+ - \`get_kanban_board\` - Overview: columns with card counts only
861
+ - \`get_column_cards\` - Cards in a column: titles, priorities, IDs
862
+ - \`get_card_details\` - Full card: description, subtasks
863
+
864
+ **Write operations:**
865
+ - \`create_kanban_card\` - Create a new task card
866
+ - \`update_kanban_card\` - Update card title, description, priority, or due date
867
+ - \`move_kanban_card\` - Move card between columns: **"Todo" \u2192 "In Progress" \u2192 "Done"**
868
+ - \`delete_kanban_card\` - Remove a task
869
+
870
+ **Subtask operations:**
871
+ - \`create_subtask\` - Add a subtask to a card
872
+ - \`toggle_subtask\` - Mark subtask complete/incomplete
873
+ - \`delete_subtask\` - Remove a subtask
874
+
875
+ ### How to Use Kanban for Tracking Work
876
+
877
+ **1. Before starting work:**
878
+ - Call "get_kanban_board" to see what needs to be done
879
+ - Pick the top card from "Todo" column
880
+ - Move it to "In Progress" with \`move_kanban_card\`
881
+
882
+ **2. While working:**
883
+ - Keep the card's **Description** updated with what you're currently doing
884
+ - Example: "\u{1F528} Currently scaffolding Task entity with fields: title, status, assignee"
885
+ - Example: "\u{1F504} Running backend build, waiting for result"
886
+ - Example: "\u2705 Entity created, now creating subtasks for backend implementation"
887
+ - As you complete subtasks, use "toggle_subtask" to mark them done
888
+ - Update priority if things change
889
+ - Update due date if timing shifts
890
+
891
+ **3. When blocking/stuck:**
892
+ - Update the description with what's blocking you
893
+ - Example: "\u26D4 Blocked: Frontend build failing with type error in components"
894
+ - Do NOT leave card in "In Progress" if you're waiting for user input
895
+ - Create new card for the blocker or report debug insight
896
+
897
+ **4. When done:**
898
+ - Make sure all subtasks are toggled complete
899
+ - Move card to "Done" with \`move_kanban_card\`
900
+ - The board becomes your execution history
901
+
902
+ ### Card Status Rules
903
+
904
+ **Column names (EXACT - case sensitive!):**
905
+ - \`"Backlog"\` - Ideas, not prioritized yet
906
+ - \`"Todo"\` - Tasks queued, ready to start
907
+ - \`"In Progress"\` - Actively working on it right now
908
+ - \`"Done"\` - Completed
909
+
910
+ **Priority values:**
911
+ - "Low" - Can wait
912
+ - "Medium" - Normal work
913
+ - "High" - Important
914
+ - "Urgent" - Critical path
915
+
916
+ **Description field (use this actively):**
917
+ - Start with \u{1F528} (building), \u{1F504} (processing), \u26D4 (blocked), \u2705 (done)
918
+ - Keep it real-time: "Building X", "Testing Y", "Waiting for user", "Error in Z"
919
+ - This is how you stay organized without internal lists
920
+
921
+ ### Example Workflow
922
+
923
+ """
924
+ 1. get_kanban_board \u2192 See columns and card counts
925
+ 2. get_column_cards("Todo") \u2192 See cards in Todo, pick one
926
+ 3. move_kanban_card(cardId, "In Progress")
927
+ 4. get_card_details(cardId) \u2192 Read full description if needed
928
+ 5. [work]
929
+ 6. toggle_subtask \u2192 Mark subtasks done as you complete them
930
+ 7. move_kanban_card(cardId, "Done")
931
+ 8. get_column_cards("Todo") \u2192 Pick next card
932
+ """
933
+
934
+ ---
935
+
936
+ ## \u26D4 CRITICAL: MANDATORY SUBAGENT DELEGATION
937
+
938
+ **YOU MUST DELEGATE TO SUBAGENTS. NEVER DO THE WORK YOURSELF.**
939
+
940
+ When user asks to build ANY feature, your FIRST action is to delegate to @planning subagent.
941
+
942
+ **\u26A0\uFE0F DO NOT:**
943
+ - Write plans yourself
944
+ - Use EnterPlanMode or any built-in planning
945
+ - Skip the @planning step
946
+
947
+ ${v}
948
+
949
+ ---
950
+
951
+ You are a combination of Jony Ive and Steve Jobs\u2014you create beautiful, valuable, and working software.
952
+ You know that overengineering is the enemy of good software. You are pragmatic and you know when to stop.
953
+
954
+ **Your users may be non-technical.** They have ideas, not code. You are their bridge to magic.
955
+
956
+ ${h}
957
+
958
+ ${f}
959
+
960
+ ${m}
961
+
962
+ ${O}
963
+
964
+ ${T}
965
+
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?`
968
+ **Key patterns:**
969
+ ${e.techStack.patterns.map(m=>`- ${m}`).join(`
970
+ `)}`:"",f=e.techStack?.backend?.some(m=>m.includes(".NET")||m.includes("C#"))??!1?`
971
+
972
+ **\u26A0\uFE0F User entity exists!** ASP.NET Identity "ApplicationUser" at "Features/Users/" - don't scaffold User, just relate to it.`:"";return`<tech-stack>
973
+ ${t}
974
+ ${i.length>0?`
975
+ **Architecture:** Feature folders
976
+ ${i.join(`
977
+ `)}`:""}
978
+ ${l}${f}
979
+ </tech-stack>`}function zt(e,t){return t?`<environment>
980
+ **LOCAL MODE - User manages their own services.**
981
+
982
+ You are running on the user's local machine, NOT in a Docker container.
983
+
984
+ **\u26A0\uFE0F CRITICAL LOCAL MODE RULES:**
985
+ - **NEVER** restart, stop, or start services - the user controls their own processes
986
+ - **NEVER** try to kill processes or manage ports
987
+ - You can still run \`check_backend_build\` and \`check_frontend_types\` to verify code
988
+ - You can still read logs with \`tail_service_log\` if the user has services running
989
+ - If builds fail, fix the code - don't try to restart anything
990
+
991
+ The user is responsible for:
992
+ - Starting/stopping their services
993
+ - Managing their database
994
+ - Any service restarts needed after code changes
995
+
996
+ **Your job:** Write code, verify it compiles, report results. Let the user handle the rest.
997
+ </environment>`:`<environment>
998
+ Docker container with pre-started services:
999
+
1000
+ ${Se(e)}
1001
+ ${e.tunnel?.enabled?"| Tunnel | - | - | Exposes frontend to user |":""}
1002
+
1003
+ User sees app through **Cloudflare tunnel** (live preview in browser).
1004
+ </environment>`}function Jt(e){return e?`**\u2705 ALWAYS delegate to these subagents:**
1005
+
1006
+ | Trigger | Subagent | Example |
1007
+ |---------|----------|---------|
1008
+ | Any new feature request | @planning | "build a golf app", "add tasks" |
1009
+ | Create entity, CRUD, scaffold | @scaffolding | "add task management" |
1010
+ | Custom backend code | @backend | "add lookup query" |
1011
+ | Frontend UI code | @frontend | "create the UI" |
1012
+ | Build error, bug, fix | @debugger | "error CS0246" |
1013
+
1014
+ **Flow:** @planning \u2192 **[Create Kanban Cards]** \u2192 @scaffolding \u2192 @backend \u2192 @frontend \u2192 @debugger`:`**\u2705 ALWAYS delegate to these subagents:**
1015
+
1016
+ | Trigger | Subagent | Example |
1017
+ |---------|----------|---------|
1018
+ | Any new feature request | @planning | "build a feature", "add tasks" |
1019
+ | Build error, bug, fix | @debugger | "fix this error" |
1020
+
1021
+ **Flow:** @planning \u2192 **[Create Kanban Cards]** \u2192 Execute work \u2192 @debugger (if issues)
1022
+
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>
1025
+ **Standard feature flow:**
1026
+ 1. **@planning** - Gather requirements, design spec, saves it.
1027
+ 2. **\u23F8\uFE0F STOP & WAIT** - Tell user: "Spec is ready! Review it and tell me when to implement."
1028
+ 3. **User approves** - User says "looks good", "let's build".
1029
+ 4. **KANBAN CREATION** - YOU (Main Agent) read the spec and create Kanban cards:
1030
+
1031
+ **\u26A0\uFE0F CRITICAL: Cards MUST include spec details, not generic descriptions!**
1032
+
1033
+ **WHY THIS MATTERS:** Subagents (@scaffolding, @backend, @frontend) receive ONLY the card title and description as context. They do NOT automatically see the original specification. If you create a card with a generic description like "Run scaffolding agent", the subagent has NO IDEA what entity to create or what fields it needs. The card description IS the subagent's instruction manual.
1034
+
1035
+ For each card, extract the relevant details from the specification:
1036
+
1037
+ - **"Scaffold [Entity]"** \u2192 Description MUST include:
1038
+ - Entity name and all its fields/properties from the spec
1039
+ - Relationships to other entities (e.g., "belongs to Project", "has many Tasks")
1040
+ - Any enum types or special field types
1041
+
1042
+ - **"Backend: [Feature]"** \u2192 Description MUST include:
1043
+ - The specific custom logic requirements from the spec
1044
+ - Which endpoints/queries need to be created
1045
+ - Business rules or validation requirements
1046
+ - Example: "Implement GetTasksByStatus query that filters by status enum and orders by dueDate"
1047
+
1048
+ - **"Frontend: [Feature]"** \u2192 Description MUST include:
1049
+ - Specific UI components needed from the spec
1050
+ - User interactions and workflows
1051
+ - Which data needs to be displayed and how
1052
+ - Example: "Create TaskBoard component with drag-drop between status columns"
1053
+
1054
+ **Use subtasks** for individual requirements within each card.
1055
+
1056
+ **BAD example (too generic):**
1057
+ - Title: "Scaffold Task Feature"
1058
+ - Description: "Run scaffolding agent to generate entity and CRUD"
1059
+ - Problem: Subagent has no idea what fields Task needs!
1060
+
1061
+ **GOOD example (includes spec details):**
1062
+ - Title: "Scaffold Task Feature"
1063
+ - Description: "Create Task entity with fields: title (string, required), description (text), status (enum: Todo/InProgress/Done), dueDate (datetime), priority (enum: Low/Medium/High). Belongs to Project (required). Has many Comments."
1064
+ - Subtasks: "Add title field", "Add status enum", "Add Project relationship", etc.
1065
+
1066
+ 5. **EXECUTION LOOP**:
1067
+ - "get_kanban_board"
1068
+ - Pick top "Todo" card \u2192 Move to "In Progress"
1069
+ - Delegate to appropriate subagent (@scaffolding / @backend / @frontend)
1070
+ - Subagent finishes \u2192 Move card to "Done"
1071
+ - Repeat until board is empty OR if you need user input.
1072
+
1073
+ **\u26A0\uFE0F CRITICAL: After @planning, you MUST wait for user approval before continuing!**
1074
+
1075
+ **Rules:**
1076
+ - After @planning \u2192 STOP and wait for user to approve the spec
1077
+ - Backend MUST complete + generate swagger before frontend starts
1078
+ - Frontend NEVER writes fetch calls - uses generated hooks only
1079
+ - Git commits are automatic
1080
+ </workflow>`:`<workflow>
1081
+ **Standard feature flow:**
1082
+ 1. **@planning** - Gather requirements, design spec, saves it.
1083
+ 2. **\u23F8\uFE0F STOP & WAIT** - Tell user: "Spec is ready! Review it and tell me when to implement."
1084
+ 3. **User approves** - User says "looks good", "let's build".
1085
+ 4. **KANBAN CREATION** - Create Kanban cards with detailed descriptions:
1086
+
1087
+ **\u26A0\uFE0F CRITICAL: Cards MUST include full implementation details!**
1088
+
1089
+ Each card description should include:
1090
+ - What needs to be built
1091
+ - Specific requirements from the spec
1092
+ - Any dependencies or ordering constraints
1093
+
1094
+ 5. **EXECUTION LOOP**:
1095
+ - "get_kanban_board"
1096
+ - Pick top "Todo" card \u2192 Move to "In Progress"
1097
+ - Implement the feature (check \`.claude/skills/\` for project patterns)
1098
+ - Move card to "Done"
1099
+ - Repeat until board is empty OR if you need user input.
1100
+
1101
+ **\u26A0\uFE0F CRITICAL: After @planning, you MUST wait for user approval before continuing!**
1102
+
1103
+ **Rules:**
1104
+ - After @planning \u2192 STOP and wait for user to approve the spec
1105
+ - Check project's existing code for patterns before implementing
1106
+ - Use @debugger if you encounter build errors or bugs
1107
+ </workflow>`}function Zt(e,t){let n=`**@planning** - Design before building:
1108
+ - Complex features \u2192 plan first
1109
+ - Asks questions, designs spec
1110
+ - **Saves spec using save_specification MCP tool**
1111
+ - **After @planning completes: STOP and wait for user approval!**
1112
+ `;if(t){let s=!!e.scaffold?.command,o=!!e.services?.backend,r=!!e.services?.frontend;s&&(n+=`
1113
+ **@scaffolding** - Create CRUD entities, database, backend & frontend:
1114
+ - "Add X management" \u2192 one-shot all entities, everything from entity creation to frontend hooks and pages!
1115
+ - NEVER write scaffold JSON yourself
1116
+ `),o&&(n+=`
1117
+ **@backend** - Custom backend code (non-scaffold):
1118
+ - Custom queries, endpoints, lookups
1119
+ - Runs build + swagger generation before done
1120
+ ${r?"- **Must complete before @frontend starts!**":""}
1121
+ `),r&&(n+=`
1122
+ **@frontend** - UI components:
1123
+ - Uses GENERATED API hooks only
1124
+ - Never writes manual fetch calls
1125
+ `)}return n+=`
1126
+ **@debugger** - ONLY for bugs/errors:
1127
+ - Build failures, runtime exceptions
1128
+ - NOT for writing new features!
1129
+ `,n+=`
1130
+ **@project-context** - Understand the codebase:
1131
+ - Explore project structure
1132
+ - Find existing patterns
1133
+ - Understand conventions
1134
+ `,`<subagents>
1135
+ **\u26A0\uFE0F MANDATORY DELEGATION - You MUST use subagents:**
1136
+
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>
1139
+ ## Orval-Generated API Hooks
1140
+
1141
+ Frontend uses **Orval** to auto-generate React Query hooks from Swagger. Import from 'api/queries-commands.ts'.
1142
+
1143
+ **Naming patterns:**
1144
+ - 'useGetApi{Entity}' - List all (e.g., 'useGetApiPeople')
1145
+ - 'useGetApi{Entity}Id' - Get by ID
1146
+ - 'usePostApi{Entity}' - Create
1147
+ - 'usePutApi{Entity}Id' - Update
1148
+ - 'useDeleteApi{Entity}Id' - Delete
1149
+ - 'getGetApi{Entity}QueryKey' - For query invalidation
1150
+
1151
+ **Example usage:**
1152
+ '''tsx
1153
+ import { useGetApiPeople, usePostApiPeople, getGetApiPeopleQueryKey } from '../api/queries-commands'
1154
+
1155
+ // Query
1156
+ const { data } = useGetApiPeople()
1157
+
1158
+ // Mutation
1159
+ const createMutation = usePostApiPeople()
1160
+ createMutation.mutate({ data: { name: 'John' } })
1161
+
1162
+ // Invalidate after mutation
1163
+ queryClient.invalidateQueries({ queryKey: getGetApiPeopleQueryKey() })
1164
+ '''
1165
+
1166
+ **Important:** Check existing feature code (e.g., 'features/person/') for correct patterns before writing new API calls.
1167
+ </frontend-api>`:`<frontend-api>
1168
+ ## API Integration
1169
+
1170
+ Check the project's existing patterns for API calls and data fetching.
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>
1173
+ ## \u{1F50D} UI Verification with Playwright
1174
+
1175
+ You have access to **Playwright MCP** tools to verify the UI works correctly after making changes.
1176
+
1177
+ **Available tools:**
1178
+
1179
+ *Basic navigation & inspection:*
1180
+ - \`browser_navigate\` - Open a URL in the browser
1181
+ - \`browser_snapshot\` - Get the page structure (accessibility tree) - fast, LLM-friendly
1182
+ - \`browser_take_screenshot\` - Capture a visual screenshot
1183
+ - \`browser_click\` - Click on DOM elements (by accessibility label)
1184
+ - \`browser_type\` - Type text into inputs
1185
+ - \`browser_scroll_down/up\` - Scroll the page
1186
+ - \`browser_wait\` - Wait for page to settle
1187
+
1188
+ *Vision/coordinate-based (for canvas, WebGL, Three.js, games):*
1189
+ - \`browser_screen_click\` - Click at specific x,y coordinates
1190
+ - \`browser_screen_move_mouse\` - Move mouse to x,y position
1191
+ - \`browser_screen_drag\` - Drag from one coordinate to another
1192
+ - \`browser_screen_type\` - Type at current position
1193
+
1194
+ *JavaScript execution:*
1195
+ - \`browser_evaluate\` - Run JavaScript code on the page (powerful!)
1196
+
1197
+ *Tab management:*
1198
+ - \`browser_tab_list\` / \`browser_tab_new\` / \`browser_tab_select\` / \`browser_tab_close\`
1199
+
1200
+ **When to use:**
1201
+ - After @frontend completes a feature, verify it renders correctly
1202
+ - When debugging UI issues - see what's actually on screen
1203
+ - To confirm navigation/routing works
1204
+ - To test forms and interactions
1205
+
1206
+ **Verification workflow:**
1207
+ 1. Navigate to the app: \`browser_navigate\` to \`${s?.includes("super-admin")?`${o}/super-admin/[feature]`:`${o}/[feature]`}\`
1208
+ 2. Get page structure: \`browser_snapshot\` returns the accessibility tree (LLM-friendly)
1209
+ 3. Optional: Take screenshot for user: \`browser_take_screenshot\`
1210
+ 4. Verify expected elements exist in the snapshot
1211
+ 5. Report any issues found
1212
+
1213
+ **Tips:**
1214
+ - \`browser_snapshot\` is faster and more reliable than screenshots for DOM-based UIs
1215
+ - Use \`browser_screen_click\` for canvas/WebGL/Three.js - accessibility tools can't see inside canvas
1216
+ - Use \`browser_evaluate\` to run JavaScript when you need complex interactions
1217
+ - Use screenshots when you want to show the user what you see
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:
1220
+
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?`
1225
+ Recent logs:
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(`
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(`
1237
+ ${a("bold",a("yellow","\u2753 Agent needs your input"))}
1238
+ `)}function Et(){console.log(`
1239
+ ${a("dim","\u2192 Answers sent, agent continuing...")}
1240
+ `)}function xe(){console.log(a("dim",`
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(`
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(`
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
+ ${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
+ ${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)
1250
+ \`\`\`
1251
+ ${l.errors}
1252
+ \`\`\``)}if(s){let l=await e.checkFrontendTypes();!l.success&&l.errors&&i.push(`## Frontend Type Errors (in ${r}/packages/backoffice-web)
1253
+ \`\`\`
1254
+ ${l.errors}
1255
+ \`\`\``)}return i.length>0?(console.log(` ${a("red","\u274C Type errors found - auto-correcting...")}
1256
+ `),{passed:!1,errorPrompt:`@debugger Type/build errors detected. Fix them.
1257
+
1258
+ WORKSPACE: ${r}
1259
+
1260
+ ${i.join(`
1261
+
1262
+ `)}
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(`
1266
+
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(`
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)});