sweagent 0.0.5 → 0.0.6
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/README.md +31 -3
- package/dist/index.cjs +294 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +534 -116
- package/dist/index.d.ts +534 -116
- package/dist/index.js +294 -186
- package/dist/index.js.map +1 -1
- package/dist/stdio.js +224 -122
- package/dist/stdio.js.map +1 -1
- package/package.json +5 -6
package/dist/stdio.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import
|
|
3
|
-
Caused by: ${o.stack}`);}},
|
|
2
|
+
import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import ni from'openai';import {z}from'zod';import ii from'@anthropic-ai/sdk';import {GoogleGenAI}from'@google/genai';import'pino';import*as de from'path';import*as oe from'fs';import ie from'handlebars';var me=class extends Error{constructor(t,o){super(t,o===void 0?void 0:{cause:o}),this.name="LibraryError",o?.stack&&(this.stack=`${this.stack}
|
|
3
|
+
Caused by: ${o.stack}`);}},Q=class extends me{constructor(o,r,n){super(o,n);this.provider=r;this.name="ModelError";}},ge=class extends me{constructor(o,r,n){super(o,n);this.toolName=r;this.name="ToolError";}},yt=class extends me{constructor(o,r){super(o);this.errors=r;this.name="ValidationError";}},fe=class extends me{constructor(o,r,n){super(o,n);this.iteration=r;this.name="AgentError";}},we=class extends me{constructor(o,r,n){super(o,n);this.subagentName=r;this.name="SubagentError";}};function oi(e){let t=z.toJSONSchema(e),{$schema:o,definitions:r,...n}=t;return n}function Mn(e){let{description:t,inputSchema:o,execute:r}=e,n=oi(o);return {description:t,inputSchema:o,parameters:n,execute:r}}function y(e){let{name:t,description:o,input:r,handler:n}=e;return Mn({description:o,inputSchema:r,execute:async a=>{let s=r.safeParse(a);if(!s.success)throw new ge(`Invalid input: ${s.error.message}`,t,s.error);try{return await n(s.data,void 0)}catch(i){throw i instanceof ge?i:new ge(`Tool "${t}" failed: ${i instanceof Error?i.message:String(i)}`,t,i instanceof Error?i:void 0)}}})}async function On(e,t,o){let{logger:r}=o??{},n=o?.toolName??("name"in e&&typeof e.name=="string"?e.name:"unknown");if(!e.execute)return r?.error("Tool has no execute function",{toolName:n}),{success:false,error:"Tool has no execute function"};r?.debug("Executing tool",{toolName:n,toolCallId:o?.toolCallId});try{let a=await e.execute(t,{toolCallId:o?.toolCallId??"",messages:[],abortSignal:o?.abortSignal});return r?.info("Tool completed",{toolName:n,toolCallId:o?.toolCallId}),{success:!0,output:a}}catch(a){let s=a instanceof Error?a.message:String(a);return r?.error("Tool failed",{toolName:n,toolCallId:o?.toolCallId,error:s}),{success:false,error:s}}}async function Je(e,t,o,r){let n=e[t];if(!n)throw r?.logger?.error("Tool not found",{name:t,availableTools:Object.keys(e)}),new ge(`Tool not found: ${t}`);return On(n,o,{...r,toolName:t})}function he(e){let t=z.toJSONSchema(e),{$schema:o,definitions:r,...n}=t;return n}function Cn(e){if(e.role==="system")return {role:"system",content:e.content};if(e.role==="user"){let t=e.content;if(typeof t=="string")return {role:"user",content:t};let o=[];for(let r of t)r.type==="text"&&o.push({type:"text",text:r.text}),r.type==="image"&&o.push({type:"image_url",image_url:{url:r.image.startsWith("data:")?r.image:`data:${r.mimeType??"image/png"};base64,${r.image}`}});return {role:"user",content:o}}if(e.role==="assistant"){let t=e.content;if(typeof t=="string")return {role:"assistant",content:t};let o=[],r=[];for(let n of t)n.type==="text"&&o.push(n.text),n.type==="tool-call"&&r.push({id:n.toolCallId,type:"function",function:{name:n.toolName,arguments:JSON.stringify(n.input??{})}});return r.length>0?{role:"assistant",content:o.join("")||null,tool_calls:r}:{role:"assistant",content:o.join("")||""}}if(e.role==="tool"){let t=e.content[0];if(t&&"type"in t&&t.type==="tool-result")return {role:"tool",tool_call_id:t.toolCallId,content:(t.output.type==="text",t.output.value)}}return {role:"user",content:""}}function si(e){return Object.entries(e).map(([t,o])=>{let r=o.parameters??(o.inputSchema?he(o.inputSchema):{type:"object",properties:{}});return {type:"function",function:{name:t,description:o.description,parameters:r}}})}function Nn(e){return e?{inputTokens:e.prompt_tokens,outputTokens:e.completion_tokens,totalTokens:e.total_tokens??e.prompt_tokens+e.completion_tokens}:{inputTokens:0,outputTokens:0,totalTokens:0}}function ai(e){return e==="stop"||e==="length"||e==="tool_calls"||e==="content_filter"?e==="tool_calls"?"tool-calls":e:e??"stop"}function kn(e){let{model:t,apiKey:o,baseUrl:r}=e,n=new ni({apiKey:o??process.env.OPENAI_API_KEY,baseURL:r});return {provider:"openai",modelName:t,async invoke(a,s){try{let i=a.map(Cn),l=s?.tools?si(s.tools):void 0,p=await n.chat.completions.create({model:t,messages:i,tools:l?.length?l:void 0,tool_choice:l?.length?"auto":void 0,max_tokens:s?.maxOutputTokens,temperature:s?.temperature,stop:s?.stop?.length?s.stop:void 0}),c=p.choices?.[0],u=c?.message,d=typeof u?.content=="string"?u.content:"",m=(u?.tool_calls??[]).map(R=>{let w={};try{w=JSON.parse(R.function?.arguments??"{}");}catch{}return {toolCallId:R.id,toolName:R.function?.name??"",input:w}});return {text:d,toolCalls:m,usage:Nn(p.usage),finishReason:ai(c?.finish_reason)}}catch(i){let l=i instanceof Error?i:new Error(String(i));throw new Q("Failed to invoke OpenAI model","openai",l)}},async generateVision(a,s,i){let l=s.map(c=>({type:"image",image:`data:${c.mimeType};base64,${c.base64}`,mimeType:c.mimeType}));l.push({type:"text",text:a});let p=[];return i?.systemPrompt&&p.push({role:"system",content:i.systemPrompt}),p.push({role:"user",content:l}),this.invoke(p,{maxOutputTokens:i?.maxOutputTokens,temperature:i?.temperature})},async invokeObject(a,s,i){try{let l=s,p=a.map(Cn),c=await n.chat.completions.create({model:t,messages:[...p,{role:"system",content:"Respond with a single valid JSON object only. No markdown, no explanation, no code block."}],max_tokens:i?.maxOutputTokens,temperature:i?.temperature??0}),u=c.choices?.[0]?.message?.content;if(typeof u!="string")throw new Error("No content in response");let d=u.replace(/^```(?:json)?\s*|\s*```$/g,"").trim(),g=JSON.parse(d);return {data:l.parse(g),usage:Nn(c.usage)}}catch(l){let p=l instanceof Error?l:new Error(String(l));throw new Q("Failed to invokeObject OpenAI model","openai",p)}}}}function Dn(e){return kn({model:e.model,apiKey:e.apiKey,baseUrl:e.baseUrl})}function li(e){if(e.role==="system")return {system:e.content};if(e.role==="user"){let t=e.content,o=[];if(typeof t=="string")o.push({type:"text",text:t});else for(let r of t)r.type==="text"&&o.push({type:"text",text:r.text}),r.type==="image"&&o.push({type:"image",source:{type:"base64",media_type:r.mimeType??"image/png",data:r.image.replace(/^data:[^;]+;base64,/,"")}}),r.type==="tool-result"&&o.push({type:"tool_result",tool_use_id:r.toolCallId,content:(r.output.type==="text",r.output.value)});return o.length?{role:"user",content:o}:null}if(e.role==="assistant"){let t=e.content,o=[];if(typeof t=="string")o.push({type:"text",text:t});else for(let r of t)r.type==="text"&&o.push({type:"text",text:r.text}),r.type==="tool-call"&&o.push({type:"tool_use",id:r.toolCallId,name:r.toolName,input:r.input??{}});return o.length?{role:"assistant",content:o}:null}if(e.role==="tool"){let t=[];for(let o of e.content)o.type==="tool-result"&&t.push({type:"tool_result",tool_use_id:o.toolCallId,content:(o.output.type==="text",o.output.value)});return t.length?{role:"user",content:t}:null}return null}function _n(e){let t,o=[];for(let r of e){let n=li(r);n&&("system"in n?t=t?`${t}
|
|
4
|
+
|
|
5
|
+
${n.system}`:n.system:o.push(n));}return {system:t,messages:o}}function pi(e){return Object.entries(e).map(([t,o])=>{let r=o.parameters??(o.inputSchema?he(o.inputSchema):{type:"object",properties:{}});return {name:t,description:o.description,input_schema:{type:"object",properties:r.properties??{},...r}}})}function In(e,t){return {inputTokens:e,outputTokens:t,totalTokens:e+t}}function ci(e){return e==="end_turn"||e==="max_tokens"||e==="tool_use"||e==="stop_sequence"||e==="content_block_stop"?e==="tool_use"?"tool-calls":e==="max_tokens"?"length":"stop":e??"stop"}function jn(e){let{model:t,apiKey:o}=e,r=new ii({apiKey:o??process.env.ANTHROPIC_API_KEY});return {provider:"anthropic",modelName:t,async invoke(n,a){try{let{system:s,messages:i}=_n(n),l=a?.tools?pi(a.tools):void 0,p=await r.messages.create({model:t,max_tokens:a?.maxOutputTokens??4096,system:s,messages:i,tools:l?.length?l:void 0,temperature:a?.temperature,stop_sequences:a?.stop?.length?a.stop:void 0}),u=p.content?.find(g=>g.type==="text")?.text??"",d=(p.content??[]).filter(g=>g.type==="tool_use").map(g=>({toolCallId:g.id,toolName:g.name,input:g.input??{}}));return {text:u,toolCalls:d,usage:In(p.usage.input_tokens,p.usage.output_tokens),finishReason:ci(p.stop_reason)}}catch(s){let i=s instanceof Error?s:new Error(String(s));throw new Q("Failed to invoke Anthropic model","anthropic",i)}},async generateVision(n,a,s){let i=a.map(p=>({type:"image",image:p.base64,mimeType:p.mimeType}));i.push({type:"text",text:n});let l=[];return s?.systemPrompt&&l.push({role:"system",content:s.systemPrompt}),l.push({role:"user",content:i}),this.invoke(l,{maxOutputTokens:s?.maxOutputTokens,temperature:s?.temperature})},async invokeObject(n,a,s){try{let i=a,{system:l,messages:p}=_n(n),c=await r.messages.create({model:t,max_tokens:s?.maxOutputTokens??4096,system:l?`${l}
|
|
6
|
+
|
|
7
|
+
Respond with a single valid JSON object only. No markdown, no explanation, no code block.`:"Respond with a single valid JSON object only. No markdown, no explanation, no code block.",messages:p,temperature:s?.temperature??0}),g=(c.content?.find(w=>w.type==="text")?.text??"").replace(/^```(?:json)?\s*|\s*```$/g,"").trim(),m=JSON.parse(g);return {data:i.parse(m),usage:In(c.usage.input_tokens,c.usage.output_tokens)}}catch(i){let l=i instanceof Error?i:new Error(String(i));throw new Q("Failed to invokeObject Anthropic model","anthropic",l)}}}}function qn(e){return jn({model:e.model,apiKey:e.apiKey})}function di(e){if(e.role==="system")return {system:e.content};if(e.role==="user"){let t=e.content,o=[];if(typeof t=="string")o.push({text:t});else for(let r of t)r.type==="text"&&o.push({text:r.text}),r.type==="image"&&o.push({inlineData:{mimeType:r.mimeType??"image/png",data:r.image.replace(/^data:[^;]+;base64,/,"")}}),r.type==="tool-result"&&o.push({functionResponse:{name:r.toolName,response:(r.output.type==="text",r.output.value)}});return o.length?{role:"user",parts:o}:null}if(e.role==="assistant"){let t=e.content,o=[];if(typeof t=="string")o.push({text:t});else for(let r of t)r.type==="text"&&o.push({text:r.text}),r.type==="tool-call"&&o.push({functionCall:{name:r.toolName,args:r.input??{}}});return o.length?{role:"model",parts:o}:null}if(e.role==="tool"){let t=[];for(let o of e.content)o.type==="tool-result"&&t.push({functionResponse:{name:o.toolName,response:(o.output.type==="text",o.output.value)}});return t.length?{role:"user",parts:t}:null}return null}function Ln(e){let t,o=[];for(let r of e){let n=di(r);n&&("system"in n&&n.system!==void 0?t=t?`${t}
|
|
8
|
+
|
|
9
|
+
${n.system}`:n.system:"role"in n&&"parts"in n&&o.push(n));}return {systemInstruction:t,contents:o}}function mi(e){return [{functionDeclarations:Object.entries(e).map(([o,r])=>{let n=r.parameters??(r.inputSchema?he(r.inputSchema):{type:"object",properties:{}});return {name:o,description:r.description,parameters:n}})}]}function gi(e){return e==="STOP"||e==="MAX_TOKENS"||e==="SAFETY"||e==="RECITATION"||e==="OTHER"?e==="MAX_TOKENS"?"length":e==="STOP"?"stop":e==="SAFETY"?"content-filter":"stop":e??"stop"}function Fn(e){let{model:t,apiKey:o}=e,r=new GoogleGenAI({apiKey:o??process.env.GOOGLE_GENERATIVE_AI_API_KEY??process.env.GOOGLE_API_KEY});return {provider:"google",modelName:t,async invoke(n,a){try{let{systemInstruction:s,contents:i}=Ln(n),l=a?.tools?mi(a.tools):void 0,p=await r.models.generateContent({model:t,contents:i.length?i:[{role:"user",parts:[{text:""}]}],config:{systemInstruction:s,maxOutputTokens:a?.maxOutputTokens,temperature:a?.temperature,stopSequences:a?.stop,tools:l}}),c=p.text??"",d=(p.functionCalls??[]).map((R,w)=>({toolCallId:`call_${w}_${R.name??""}`,toolName:R.name??"",input:R.args??{}})),g=p.usageMetadata,m={inputTokens:g?.promptTokenCount??0,outputTokens:g?.candidatesTokenCount??g?.totalTokenCount??0,totalTokens:g?.totalTokenCount??0};return {text:c,toolCalls:d,usage:m,finishReason:gi(p.finishReason)}}catch(s){let i=s instanceof Error?s:new Error(String(s));throw new Q("Failed to invoke Google model","google",i)}},async generateVision(n,a,s){a.map(p=>({inlineData:{mimeType:p.mimeType,data:p.base64}})).push({text:n});let l=[];return s?.systemPrompt&&l.push({role:"system",content:s.systemPrompt}),l.push({role:"user",content:[{type:"text",text:n},...a.map(p=>({type:"image",image:p.base64,mimeType:p.mimeType}))]}),this.invoke(l,{maxOutputTokens:s?.maxOutputTokens,temperature:s?.temperature})},async invokeObject(n,a,s){try{let i=a,{systemInstruction:l,contents:p}=Ln(n),c=l?`${l}
|
|
10
|
+
|
|
11
|
+
Respond with a single valid JSON object only. No markdown, no explanation, no code block.`:"Respond with a single valid JSON object only. No markdown, no explanation, no code block.",u=await r.models.generateContent({model:t,contents:p.length?p:[{role:"user",parts:[{text:""}]}],config:{systemInstruction:c,maxOutputTokens:s?.maxOutputTokens,temperature:s?.temperature??0}}),g=(u.text??"").replace(/^```(?:json)?\s*|\s*```$/g,"").trim(),m=JSON.parse(g),R=i.parse(m),w=u.usageMetadata;return {data:R,usage:{inputTokens:w?.promptTokenCount??0,outputTokens:w?.candidatesTokenCount??0,totalTokens:w?.totalTokenCount??0}}}catch(i){let l=i instanceof Error?i:new Error(String(i));throw new Q("Failed to invokeObject Google model","google",l)}}}}function Un(e){return Fn({model:e.model,apiKey:e.apiKey})}function O(e){let{provider:t}=e;switch(t){case "openai":return Dn(e);case "anthropic":return qn(e);case "google":return Un(e);default:throw new Q(`Unsupported provider: ${t}. Supported providers: openai, anthropic, google`)}}var fi={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};function Gn(){return {stage:"discovery",projectDescription:null,sections:{...fi},history:[],pendingQuestions:[]}}function Bn(e,t){let{sections:o,projectDescription:r,pendingQuestions:n}=t,a={...e.sections};if(o)for(let s of Object.keys(o)){let i=o[s];i!=null&&(a[s]=i);}return {...e,...r!==void 0&&{projectDescription:r},sections:a,...n!==void 0&&{pendingQuestions:n}}}function St(e,t,o){let r={role:t,content:o};return {...e,history:[...e.history,r]}}function qo(e){let t=["discovery","requirements","design","complete"],o=t.indexOf(e.stage),n=(o>=0&&o<t.length-1?t[o+1]:void 0)??e.stage;return {...e,stage:n}}function bt(e){let t=e.trim().toLowerCase();return ["continue","yes","yeah","yep","looks good","good","ok","okay","next","proceed","sure"].some(r=>t===r||t.startsWith(r+" "))}var Z=`You are a senior software architect creating a single, implementation-ready plan that a developer can follow without ambiguity.
|
|
4
12
|
|
|
5
13
|
CRITICAL RULES:
|
|
6
14
|
- Output ONLY raw markdown text. Use code blocks ONLY for: request/response JSON examples, file/directory trees, and env or config snippets. No JSON or structured data outside those code blocks.
|
|
7
15
|
- Use consistent structure: ## for main sections, ### for subsections, #### for per-item headings (e.g. per route, per endpoint). Use **bold** for labels (e.g. **Purpose**, **Request Body**, **Response on Success**).
|
|
8
|
-
- Be concrete and actionable: include validation rules, HTTP status codes, redirects, field-level data model descriptions, and step-by-step auth flows. Every section should give enough detail to implement from the plan alone.`;var
|
|
16
|
+
- Be concrete and actionable: include validation rules, HTTP status codes, redirects, field-level data model descriptions, and step-by-step auth flows. Every section should give enough detail to implement from the plan alone.`;var Lo=`You are in the discovery stage. Your goal is to understand what the user wants to build.
|
|
9
17
|
|
|
10
18
|
Respond in natural language only. Do NOT output JSON.
|
|
11
19
|
|
|
@@ -15,21 +23,21 @@ Respond in natural language only. Do NOT output JSON.
|
|
|
15
23
|
- **## Core Features** \u2014 Numbered list: 1. **Feature Name** - Short description. (one line per feature)
|
|
16
24
|
- **## Tech Stack** \u2014 Bullet list with category labels: - **Frontend**: ... (versions if known), - **Database**: ..., - **Authentication**: ..., - **API**: ..., - **Backend**: ... Include versions and key libraries where relevant.
|
|
17
25
|
|
|
18
|
-
When the user says "continue", "yes", "looks good", or similar, treat it as confirmation to proceed. Do NOT keep asking questions. Make reasonable assumptions for any missing details (choose sensible defaults for tech stack, features, scope, etc.) and immediately output the project overview in the format above.`,
|
|
26
|
+
When the user says "continue", "yes", "looks good", or similar, treat it as confirmation to proceed. Do NOT keep asking questions. Make reasonable assumptions for any missing details (choose sensible defaults for tech stack, features, scope, etc.) and immediately output the project overview in the format above.`,Jn=`## Current user message:
|
|
19
27
|
{userMessage}
|
|
20
28
|
|
|
21
29
|
## Prior conversation (if any):
|
|
22
30
|
{history}
|
|
23
31
|
|
|
24
|
-
Respond in plain markdown. Either ask clarifying questions, or if you have enough information, output the project overview in pro format: ## Overview (one paragraph), ## Core Features (numbered list with **Feature Name** - description), ## Tech Stack (bullets with **Category**: detail). Do NOT output JSON.`;function
|
|
25
|
-
{context}`,
|
|
32
|
+
Respond in plain markdown. Either ask clarifying questions, or if you have enough information, output the project overview in pro format: ## Overview (one paragraph), ## Core Features (numbered list with **Feature Name** - description), ## Tech Stack (bullets with **Category**: detail). Do NOT output JSON.`;function Fo(e,t){return Jn.replace("{userMessage}",e).replace("{history}",t||"(No prior messages)")}var xt=`## Project description / context:
|
|
33
|
+
{context}`,zn=`${xt}
|
|
26
34
|
|
|
27
35
|
Using the project description above, write two markdown sections in this exact format:
|
|
28
36
|
|
|
29
37
|
1. **## Overview** \u2014 One paragraph only (2\u20134 sentences) summarizing the project and its purpose.
|
|
30
38
|
2. **## Tech Stack** \u2014 Bullet list with category labels: - **Frontend**: ... (include framework and versions if applicable, e.g. Next.js 16, React 19, TypeScript, Tailwind v4), - **Database**: ... (e.g. MongoDB with Mongoose), - **Authentication**: ... (e.g. JWT in HTTP-only cookies, bcrypt), - **API**: ... (REST or GraphQL), - **Backend**: ... Include versions and key libraries where applicable.
|
|
31
39
|
|
|
32
|
-
Output only these two sections in markdown. Do NOT output JSON
|
|
40
|
+
Output only these two sections in markdown. Do NOT output JSON.`,$n=`${xt}
|
|
33
41
|
|
|
34
42
|
## Already written (Overview + Tech Stack):
|
|
35
43
|
{overviewAndTechStack}
|
|
@@ -39,8 +47,8 @@ Write the next two markdown sections in this exact format:
|
|
|
39
47
|
1. **## Feature Decisions** \u2014 Use ### per feature/area (e.g. ### Workout Tracking, ### Nutrition Tracking). Under each, bullets for key product decisions; use sub-bullets for options where relevant (e.g. goal types: weight, strength, consistency, custom).
|
|
40
48
|
2. **## Data Models** \u2014 For each entity use ### EntityName. For each field use exactly one line: \`field_name\`: description (type, required/optional, unique if applicable). For references write "Reference to EntityName". Include User, profile/settings, and all domain entities.
|
|
41
49
|
|
|
42
|
-
Output only markdown. Do NOT output JSON.`;function
|
|
43
|
-
{priorSections}`,
|
|
50
|
+
Output only markdown. Do NOT output JSON.`;function Uo(e){return zn.replace("{context}",e)}function Go(e,t){return $n.replace("{context}",e).replace("{overviewAndTechStack}",t)}var Yn=`## Project context (all sections so far):
|
|
51
|
+
{priorSections}`,Hn=`${Yn}
|
|
44
52
|
|
|
45
53
|
## API Routes (already written):
|
|
46
54
|
{apiRoutes}
|
|
@@ -54,8 +62,8 @@ Write the next markdown section in this exact format:
|
|
|
54
62
|
- **### Key Setup** \u2014 One subsection per concern: **MongoDB connection** (file path, purpose, 3\u20135 bullets), **JWT utilities** (file path, purpose; cookie name, maxAge, httpOnly, secure; generateToken/verifyToken/setAuthCookie/clearAuthCookie), **Auth middleware** (file path, authenticateRequest behavior), **External API client** if any (file path, purpose).
|
|
55
63
|
- If the plan is UI-heavy, add **### UI Component Guidelines** (controlled inputs, validation, loading/error states) and **### Error Handling Standards** (API error JSON shape, HTTP status codes: 200, 201, 400, 401, 403, 404, 500).
|
|
56
64
|
|
|
57
|
-
Output only markdown. Do NOT output JSON.`;function
|
|
58
|
-
{priorSections}`,
|
|
65
|
+
Output only markdown. Do NOT output JSON.`;function Bo(e,t){return Hn.replace("{priorSections}",e).replace("{apiRoutes}",t)}var bi=`## Full plan so far (all sections):
|
|
66
|
+
{priorSections}`,Jo="You are in the complete stage. You have the full implementation plan. Output the final sections in markdown, in the exact order specified below, so they can be assembled into the plan.",Qn=`${bi}
|
|
59
67
|
|
|
60
68
|
Write the following sections in this exact order. Output only markdown. Do NOT output JSON.
|
|
61
69
|
|
|
@@ -81,10 +89,19 @@ Write the following sections in this exact order. Output only markdown. Do NOT o
|
|
|
81
89
|
|
|
82
90
|
8. **## Manual Testing Checklist** \u2014 ### per flow (e.g. ### Authentication Flow, ### Workout Flow, ### Nutrition Flow, ### Goals Flow, ### Profile Flow). Under each, checklist items: - [ ] Description of what to verify (e.g. "- [ ] Sign up with valid credentials creates account", "- [ ] Login with invalid credentials shows error").
|
|
83
91
|
|
|
84
|
-
Output all eight sections in the order above. Do NOT output JSON.`;function
|
|
85
|
-
`),
|
|
92
|
+
Output all eight sections in the order above. Do NOT output JSON.`;function zo(e){return Qn.replace("{priorSections}",e)}function Pi(e){let t=e.trim();if(t.length<100)return false;if(t.includes("## Overview")||t.includes("## Core Features"))return true;let o=t.toLowerCase();return !!((o.includes("overview")||o.includes("core features"))&&(o.includes("tech stack")||o.includes("technology")))}async function $o(e,t,o,r){r?.debug("Discovery stage started",{historyLength:t.history.length});let a=t.history.slice(0,-1).map(w=>`${w.role}: ${w.content}`).slice(-10).join(`
|
|
93
|
+
`),s=Fo(e,a),l=[{role:"system",content:`${Z}
|
|
94
|
+
|
|
95
|
+
${Lo}`},{role:"user",content:s}],c=(await o.invoke(l,{temperature:.4,maxOutputTokens:4096})).text?.trim()??"",u=Pi(c),d=bt(e),g=d&&t.history.length>=7&&c.length>50,m=u&&(t.projectDescription==null||d)||d&&t.projectDescription!=null||g,R=u||g&&c.length>50;return r?.debug("Discovery stage complete",{advance:m,hasOverview:u,userConfirmed:d,forceAdvance:g}),{message:c,advance:m,sections:{},...R&&{projectDescription:c}}}var Tt=class{stageName="discovery";async process(t,o){return $o(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "requirements"}};var Ri={noCacheTokens:void 0,cacheReadTokens:void 0,cacheWriteTokens:void 0},wi={textTokens:void 0,reasoningTokens:void 0};function ye(e){let t=0,o=0,r=0;for(let n of e)n&&(t+=n.inputTokens??0,o+=n.outputTokens??0,r+=n.totalTokens??0);return {inputTokens:t,outputTokens:o,totalTokens:r,inputTokenDetails:Ri,outputTokenDetails:wi}}function ve(e,t,o){e?.forEach(r=>r.onStep?.(t,o));}function Pt(e,t,o){e?.forEach(r=>r.onToolExecution?.(t,o));}function Rt(e,t){e?.forEach(o=>o.onError?.(t));}function Ae(e,t,o){e?.forEach(r=>r.onTokenBudgetWarning?.(t,o));}function j(e,t,o,r="json"){return y({name:e,description:o,input:z.object({[r]:z.string().describe("JSON string to validate")}),handler:async n=>{let a=n[r]??"";try{let s=JSON.parse(a);return t.parse(s),{valid:!0}}catch(s){return s instanceof z.ZodError?{valid:false,errors:s.issues.map(i=>`${i.path.join(".")}: ${i.message}`)}:s instanceof SyntaxError?{valid:false,errors:[`Invalid JSON: ${s.message}`]}:{valid:false,errors:[String(s)]}}}})}async function wt(e){let{tools:t,toolCalls:o,messages:r,logger:n,onToolResult:a,responseText:s}=e,i=[...s?[{type:"text",text:s}]:[],...o.map(p=>({type:"tool-call",toolCallId:p.toolCallId,toolName:p.toolName,input:p.input}))];r.push({role:"assistant",content:i});let l=[];for(let p of o){let c=await Je(t,p.toolName,p.input,{toolCallId:p.toolCallId,logger:n}),u={toolCallId:p.toolCallId,toolName:p.toolName,output:c.success?c.output:c.error,isError:!c.success};l.push(u),a?.(p.toolName,u.output);let d=u.isError?{type:"error-text",value:String(u.output)}:{type:"text",value:typeof u.output=="string"?u.output:JSON.stringify(u.output)};r.push({role:"tool",content:[{type:"tool-result",toolCallId:p.toolCallId,toolName:p.toolName,output:d}]});}return l}function Vn(e){if(e==null)return 0;let t=typeof e=="string"?e:JSON.stringify(e);return Math.ceil(t.length/3)}function vt(e){let t=0;for(let o of e)t+=Vn(o);return t}function ne(e,t){if(e.length<=t)return e;let o=t-50;if(o<=0)return e.slice(0,t);let r=Math.floor(o*.8),n=o-r,a=e.slice(0,r),s=e.slice(-n),i=e.length-r-n;return `${a}
|
|
86
96
|
|
|
87
|
-
|
|
97
|
+
[...truncated ${i} chars...]
|
|
98
|
+
|
|
99
|
+
${s}`}var vi=15e3,Wn=4e3,Ai=200,Ei=2e3;function Kn(e){let t=e.role,o=e.content;switch(t){case "system":return "[SYSTEM] (preserved)";case "user":return Mi(o);case "assistant":return Oi(o);case "tool":return Ci(o);default:return `[${t.toUpperCase()}]`}}function Mi(e){let t=Ni(e);return `[USER] ${ne(t,vi)}`}function Oi(e){if(typeof e=="string")return `[ASSISTANT] ${ne(e,Wn)}`;if(!Array.isArray(e))return "[ASSISTANT]";let t=[],o=[];for(let a of e)a.type==="text"&&a.text?t.push(ne(a.text,Wn)):a.type==="tool-call"&&a.toolName&&o.push(a.toolName);let r=t.join(" "),n=o.length?` | Tools: ${o.join(", ")}`:"";return `[ASSISTANT] ${r}${n}`}function Ci(e){if(!Array.isArray(e))return "[TOOL]";let t=[];for(let o of e){if(o.type!=="tool-result")continue;let r=o.toolName??"unknown",n=o.output?.type,a=o.output?.value??"";n==="error-text"?t.push(`[TOOL:${r}] ERROR: ${ne(a,Ai)}`):t.push(`[TOOL:${r}] ${ne(a,Ei)}`);}return t.join(`
|
|
100
|
+
`)||"[TOOL]"}function Ni(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(t=>t.type==="text"&&typeof t.text=="string").map(t=>t.text).join(" "):e==null?"":JSON.stringify(e)}function Ho(e,t=4){if(e.length<=t)return {summary:"",kept:e};let o=e.slice(0,-t),r=e.slice(-t);return {summary:o.map(Kn).join(`
|
|
101
|
+
`),kept:r}}var ki=1e3,Di=2e5,_i=.1,Ii=4;function ze(e,t){let o=t?.maxContextTokens??Di,r=t?.keepRecentCount??Ii,n=t?.logger,a=vt(e);if(a+ki<=o)return {pruned:false,beforeTokens:a,afterTokens:a};n?.info("Context pruning triggered",{beforeTokens:a,maxTokens:o});let s=e[0];if(!s)return {pruned:false,beforeTokens:a,afterTokens:a};let i=e.slice(1),{summary:l,kept:p}=Ho(i,r),u=Math.floor(o*_i)*3,d=ne(l,u),g={role:"user",content:ji(d)},m=[s,g,...p],R=vt(m);return e.length=0,e.push(...m),n?.info("Context pruned",{beforeTokens:a,afterTokens:R,summarizedCount:i.length-p.length,keptCount:p.length}),{pruned:true,beforeTokens:a,afterTokens:R}}function ji(e){return ["<conversation_summary>","This is a summary of the conversation so far.","The original messages have been condensed to save context space.","",e,"</conversation_summary>","","Please continue from here.","You may need to re-gather context before proceeding."].join(`
|
|
102
|
+
`)}async function _(e){let{model:t,tools:o,systemPrompt:r,input:n,maxIterations:a=10,onStep:s,observers:i,logger:l,maxContextTokens:p,tokenBudget:c}=e;l?.info("Starting agent",{maxIterations:a});let u=[{role:"system",content:r},{role:"user",content:n}],d=[];for(let m=0;m<a;m++){m>0&&m>=a-2&&l?.warn("Approaching max iterations",{iteration:m,maxIterations:a}),p&&m>0&&ze(u,{maxContextTokens:p,logger:l});let R=ye(d.map(Y=>Y.usage)),w=R.totalTokens??0;if(c){if(w>=c)return l?.warn("Token budget exhausted",{used:w,tokenBudget:c}),Ae(i,w,c),{output:d.at(-1)?.content??"",steps:d,totalUsage:R,messages:u};w>=c*.8&&Ae(i,w,c);}l?.debug("Agent iteration",{iteration:m});let z=await t.invoke(u,{tools:o}),G={iteration:m,content:z.text,toolCalls:z.toolCalls,usage:z.usage};if(!z.toolCalls?.length){G.cumulativeUsage=ye(d.map(re=>re.usage).concat(G.usage)),d.push(G),s?.(G),ve(i,G,G.cumulativeUsage);let Y=G.cumulativeUsage;return l?.info("Agent completed",{steps:d.length,totalUsage:Y}),{output:z.text,steps:d,totalUsage:Y,messages:u}}l?.debug("Tool calls",{iteration:m,toolCalls:z.toolCalls.map(Y=>({name:Y.toolName,toolCallId:Y.toolCallId}))});let Re=await wt({tools:o,toolCalls:z.toolCalls,messages:u,logger:l,responseText:z.text||void 0,onToolResult:(Y,re)=>{Pt(i,Y,re);}});G.toolResults=Re,G.cumulativeUsage=ye(d.map(Y=>Y.usage).concat(G.usage)),d.push(G),s?.(G),ve(i,G,G.cumulativeUsage);}let g=new fe(`Agent reached maximum iterations (${a}) without completing`,a-1);throw Rt(i,g),l?.error("Agent failed: max iterations reached",{maxIterations:a,error:g}),g}async function Qo(e){let{generator:t,tools:o,messages:r,steps:n,logger:a}=e,s={messages:r,toolResult:e.lastToolResult,stepsComplete:e.stepsComplete??false,nResponses:e.nResponses,steps:n},i=t.next(s);for(;!i.done;){let l=i.value;if(l==="STEP")return {type:"step"};if(l==="STEP_ALL")return {type:"step_all"};if(typeof l=="object"&&"type"in l&&l.type==="GENERATE_N")return {type:"generate_n",n:l.n};let p=l;a?.debug("Programmatic tool call",{toolName:p.toolName});let c=await Je(o,p.toolName,p.input,{logger:a}),u=c.success?c.output:c.error;i=t.next({messages:r,toolResult:u,stepsComplete:false,steps:n});}return {type:"done"}}async function Vo(e){let{model:t,messages:o,n:r,invokeOptions:n,logger:a}=e;a?.info("Generating N responses",{n:r});let s=Array.from({length:r},()=>t.invoke(o,n)),i=await Promise.all(s),l=i.map(p=>p.text);return a?.info("Generated N responses",{n:r,lengths:l.map(p=>p.length)}),{responses:i,texts:l}}async function Wo(e){let{model:t,tools:o,systemPrompt:r,input:n,maxIterations:a=10,observers:s,logger:i,maxContextTokens:l,tokenBudget:p,handleSteps:c,stepPrompt:u}=e;if(!c)throw new fe("runAgentWithSteps requires handleSteps in config");i?.info("Starting agent with handleSteps",{maxIterations:a});let d=[{role:"system",content:r},{role:"user",content:n}],g=[],m=c({input:n,logger:i}),R,w=false,z;for(let Re=0;Re<a;Re++){l&&Re>0&&ze(d,{maxContextTokens:l,logger:i});let Y=ye(g.map(ht=>ht.usage)),re=Y.totalTokens??0;if(p){if(re>=p)return i?.warn("Token budget exhausted",{used:re,tokenBudget:p}),Ae(s,re,p),{output:g.at(-1)?.content??"",steps:g,totalUsage:Y,messages:d};re>=p*.8&&Ae(s,re,p);}let ft=await Qo({generator:m,tools:o,messages:d,steps:g,logger:i,lastToolResult:R,stepsComplete:w,nResponses:z});if(ft.type==="done"){let ht=ye(g.map(ei=>ei.usage));return {output:g.at(-1)?.content??"",steps:g,totalUsage:ht,messages:d}}if(ft.type==="generate_n"){z=(await Vo({model:t,messages:d,n:ft.n,invokeOptions:{tools:o},logger:i})).texts,R=void 0,w=false;continue}let Xa=ft.type==="step_all",Za=await qi(e,d,g,Xa,Re,u);R=void 0,w=Za.stepsComplete,z=void 0;}let G=new fe(`Agent reached maximum iterations (${a})`,a-1);throw Rt(s,G),G}async function qi(e,t,o,r,n,a){let{model:s,tools:i,onStep:l,observers:p,logger:c}=e;a&&t.push({role:"user",content:a});let u=await s.invoke(t,{tools:i}),d={iteration:n,content:u.text,toolCalls:u.toolCalls,usage:u.usage};if(!u.toolCalls?.length)return o.push(d),l?.(d),ve(p,d),{stepsComplete:true};let g=await wt({tools:i,toolCalls:u.toolCalls,messages:t,logger:c,onToolResult:(m,R)=>{Pt(p,m,R);}});return d.toolResults=g,o.push(d),l?.(d),ve(p,d),{stepsComplete:!r}}var Li=/^[a-z0-9]+(-[a-z0-9]+)*$/;function h(e){if(!e.name.trim())throw new we("Subagent name is required",void 0);if(!Li.test(e.name))throw new we(`Subagent name must be kebab-case: ${e.name}`,e.name);return {...e}}function Fi(e,t){if(e.tools!=null&&Object.keys(e.tools).length>0)return e.tools;let o=t??{},r=new Set(e.disallowedTools??[]),n={};for(let[a,s]of Object.entries(o))a.startsWith("subagent_")||r.has(a)||(n[a]=s);return n}function Ui(e,t){return e.inheritParentSystemPrompt&&t?`${t}
|
|
103
|
+
|
|
104
|
+
${e.systemPrompt}`:e.systemPrompt}async function V(e,t,o){let{parentTools:r,parentModel:n,parentSystemPrompt:a}=o??{},s=Fi(e,r),i=e.model==null?n:O(e.model);if(!i)throw new we("Subagent has no model: set definition.model or pass parentModel in options",e.name);let l=Ui(e,a),p={model:i,tools:s,systemPrompt:l,input:t,maxIterations:e.maxIterations??10,onStep:e.onStep,observers:e.observers,stepPrompt:e.stepPrompt,maxContextTokens:e.maxContextTokens,tokenBudget:e.tokenBudget,handleSteps:e.handleSteps},c=e.handleSteps?await Wo(p):await _(p);if(e.outputSchema){let u=e.outputSchema.safeParse(c.output);if(!u.success)throw new yt(`Subagent "${e.name}" output schema validation failed: ${u.error.message}`,u.error.issues)}return {...c,subagentName:e.name}}function Zn(e,t){let o=e.spawnerPrompt??e.description;return y({name:`subagent_${e.name}`,description:o,input:z.object({prompt:z.string().describe("The task or question to delegate to this subagent")}),handler:async({prompt:r})=>(await V(e,r,{parentTools:t?.parentTools,parentModel:t?.parentModel,parentSystemPrompt:t?.parentSystemPrompt})).output})}function L(e,t){let o={};for(let r of e)o[`subagent_${r.name}`]=Zn(r,t);return o}var Gi=`You are an expert database entity analyst. Your job is to extract data model signals from requirements.
|
|
88
105
|
|
|
89
106
|
Perform these analyses:
|
|
90
107
|
|
|
@@ -103,7 +120,7 @@ Perform these analyses:
|
|
|
103
120
|
- Note ownership direction (which entity "belongs to" which).
|
|
104
121
|
- Identify potential M:N relationships that may need join tables.
|
|
105
122
|
|
|
106
|
-
Respond with a clear, structured analysis using headings and bullet points. Do NOT return JSON.`,
|
|
123
|
+
Respond with a clear, structured analysis using headings and bullet points. Do NOT return JSON.`,le=h({name:"entity-analyzer",description:"Analyzes requirements to extract entities, fields, relationships, and data model signals. Use when you need to understand the data before designing the schema.",systemPrompt:Gi,tools:{},maxIterations:2});var Bi=`You are a database relationship specialist. Given a list of entities and their fields, you determine:
|
|
107
124
|
|
|
108
125
|
## Cardinality Analysis
|
|
109
126
|
- For every entity pair that references each other, classify: 1:1, 1:N, or M:N.
|
|
@@ -121,7 +138,7 @@ Respond with a clear, structured analysis using headings and bullet points. Do N
|
|
|
121
138
|
- Suggest unique indexes for natural keys (email, slug, etc.).
|
|
122
139
|
- Note partial indexes where applicable (e.g. only active records).
|
|
123
140
|
|
|
124
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
141
|
+
Respond with structured analysis. Do NOT return JSON.`,At=h({name:"relationship-mapper",description:"Maps cardinality (1:1, 1:N, M:N), foreign keys, join tables, and index recommendations for entity relationships. Use after entity analysis.",systemPrompt:Bi,tools:{},maxIterations:2});var Ji=`You are an expert database schema reviewer. Your job is to:
|
|
125
142
|
|
|
126
143
|
1. Validate the schema structure: every entity has fields, indexes, and relations properly defined.
|
|
127
144
|
2. Check completeness: all entities from requirements are present, all relationships are bidirectional where needed.
|
|
@@ -135,7 +152,7 @@ If you have access to the validate_schema tool, use it first. Then provide a det
|
|
|
135
152
|
- Specific fixes for each issue
|
|
136
153
|
- Overall assessment (ready / needs work)
|
|
137
154
|
|
|
138
|
-
Respond with structured analysis. Do NOT return JSON.`;function
|
|
155
|
+
Respond with structured analysis. Do NOT return JSON.`;function Ee(){return h({name:"schema-refiner",description:"Reviews a data model schema for completeness, normalization, performance, and security. Has access to validate_schema tool.",systemPrompt:Ji,tools:{},maxIterations:3})}var zi=`You are a UX-focused frontend architect. You design detailed page specifications.
|
|
139
156
|
|
|
140
157
|
## Page Planning
|
|
141
158
|
For each page in the application:
|
|
@@ -157,7 +174,7 @@ For each page in the application:
|
|
|
157
174
|
- Group by access: public pages first, then protected.
|
|
158
175
|
- Order by user flow: signup -> login -> dashboard -> feature pages -> settings -> admin.
|
|
159
176
|
|
|
160
|
-
Respond with structured page specs. Do NOT return JSON.`,
|
|
177
|
+
Respond with structured page specs. Do NOT return JSON.`,Me=h({name:"page-planner",description:"Designs detailed page specifications with routes, form fields, actions, states, and UI elements. Use for frontend page design.",systemPrompt:zi,tools:{},maxIterations:2});var $i=`You are a component design specialist. Given page specifications, you identify reusable components and shared patterns.
|
|
161
178
|
|
|
162
179
|
## Component Identification
|
|
163
180
|
- **Layout components**: main layout (with nav, sidebar, content area), auth layout (centered form), admin layout.
|
|
@@ -179,7 +196,7 @@ For each component:
|
|
|
179
196
|
- Recommend server vs client state strategy.
|
|
180
197
|
- Identify data fetching patterns (on mount, on action, real-time).
|
|
181
198
|
|
|
182
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
199
|
+
Respond with structured analysis. Do NOT return JSON.`,Et=h({name:"component-analyzer",description:"Identifies reusable components, shared layouts, and state management patterns from page specifications. Use after page planning.",systemPrompt:$i,tools:{},maxIterations:2});var Yi=`You are a frontend technology advisor. Given project requirements, you recommend the best frontend framework.
|
|
183
200
|
|
|
184
201
|
## Decision Criteria
|
|
185
202
|
|
|
@@ -204,7 +221,7 @@ State your recommendation clearly:
|
|
|
204
221
|
- Reasoning: 2-3 sentences explaining why
|
|
205
222
|
- Trade-offs: what you would lose with the alternative
|
|
206
223
|
|
|
207
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
224
|
+
Respond with structured analysis. Do NOT return JSON.`,Ko=h({name:"framework-selector",description:"Analyzes project requirements and recommends React/Vite SPA or Next.js. Use to determine the frontend framework before delegating to a builder.",systemPrompt:Yi,tools:{},maxIterations:2});var Hi=`You are a web security specialist. You analyze project requirements for security concerns and design security policies.
|
|
208
225
|
|
|
209
226
|
## Authentication Analysis
|
|
210
227
|
- Determine the best auth strategy (JWT, session, OAuth) based on requirements.
|
|
@@ -228,7 +245,7 @@ Respond with structured analysis. Do NOT return JSON.`,Ao=f({name:"framework-sel
|
|
|
228
245
|
- Input sanitization: XSS prevention, SQL injection prevention.
|
|
229
246
|
- Brute force protection: account lockout, exponential backoff.
|
|
230
247
|
|
|
231
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
248
|
+
Respond with structured analysis. Do NOT return JSON.`,Mt=h({name:"security-analyzer",description:"Analyzes security requirements, threat vectors, and designs security policies. Use to understand auth needs before designing flows.",systemPrompt:Hi,tools:{},maxIterations:2});var Qi=`You are an authentication flow architect. You design detailed, numbered step-by-step auth flows.
|
|
232
249
|
|
|
233
250
|
For each flow (signup, login, logout, password reset, protected route middleware, API auth middleware):
|
|
234
251
|
|
|
@@ -258,32 +275,32 @@ For each flow (signup, login, logout, password reset, protected route middleware
|
|
|
258
275
|
- Protected route: check cookie/header, verify token, attach user to request, reject if invalid.
|
|
259
276
|
- API auth: same as above but for API routes, return 401 JSON.
|
|
260
277
|
|
|
261
|
-
Respond with structured numbered flows. Do NOT return JSON.`,
|
|
278
|
+
Respond with structured numbered flows. Do NOT return JSON.`,Oe=h({name:"flow-designer",description:"Designs detailed step-by-step authentication flows (signup, login, logout, password reset, middleware). Use after security analysis.",systemPrompt:Qi,tools:{},maxIterations:2});function es(e,t,o){let r=[{role:"system",content:t},{role:"user",content:o}];return e.invoke(r,{temperature:.3,maxOutputTokens:8192}).then(n=>n.text?.trim()??"")}function Vi(e){let t=e.indexOf("## Tech Stack");return t<0?{overview:e,techStack:""}:{overview:e.slice(0,t).trim(),techStack:e.slice(t).trim()}}function Wi(e){let t=e.indexOf("## Data Models");return t<0?{featureDecisions:e,dataModels:""}:{featureDecisions:e.slice(0,t).trim(),dataModels:e.slice(t).trim()}}async function Xo(e,t,o,r){r?.debug("Requirements stage started (specialist agents)");let n=t.projectDescription??"";if(!n)return {message:"No project description yet. Complete discovery first.",advance:false,sections:{}};let a=`${Z}
|
|
262
279
|
|
|
263
|
-
Output only markdown. Do NOT output JSON.`,
|
|
280
|
+
Output only markdown. Do NOT output JSON.`,s=await es(o,a,Uo(n)),{overview:i,techStack:l}=Vi(s),p=await es(o,a,Go(n,s)),{featureDecisions:c}=Wi(p);r?.info("Delegating to data-modeler specialist");let d=(await V(le,`Analyze the data model for this project:
|
|
264
281
|
|
|
265
282
|
${n}
|
|
266
283
|
|
|
267
284
|
Features:
|
|
268
|
-
${c}`,{parentModel:o})).output;r?.info("Delegating to frontend-architect specialist");let
|
|
285
|
+
${c}`,{parentModel:o})).output;r?.info("Delegating to frontend-architect specialist");let g=[s,c,d].join(`
|
|
269
286
|
|
|
270
287
|
---
|
|
271
288
|
|
|
272
|
-
`),
|
|
289
|
+
`),R=(await V(Me,`Design the pages and routes for this project:
|
|
273
290
|
|
|
274
291
|
${n}
|
|
275
292
|
|
|
276
293
|
Context:
|
|
277
|
-
${
|
|
294
|
+
${g}`,{parentModel:o})).output;r?.info("Delegating to auth-designer specialist");let w=[g,R].join(`
|
|
278
295
|
|
|
279
296
|
---
|
|
280
297
|
|
|
281
|
-
`),
|
|
298
|
+
`),G=(await V(Oe,`Design the authentication flows for this project:
|
|
282
299
|
|
|
283
300
|
${n}
|
|
284
301
|
|
|
285
302
|
Context:
|
|
286
|
-
${
|
|
303
|
+
${w}`,{parentModel:o})).output;return r?.info("Requirements stage complete (specialist agents)"),{message:"Requirements generated via specialist agents (Data Modeler, Frontend Architect, Auth Designer).",advance:true,sections:{overview:i,techStack:l,featureDecisions:c,dataModels:d,pagesAndRoutes:R,authFlow:G}}}var Ot=class{stageName="requirements";async process(t,o){return Xo(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "design"}};var Ki=`You are an API endpoint analyst. Given a data model and requirements, you derive the complete API surface.
|
|
287
304
|
|
|
288
305
|
## Endpoint Discovery
|
|
289
306
|
- For each entity in the data model, determine CRUD operations: create, read (by ID), list (with filters/pagination), update, delete.
|
|
@@ -300,7 +317,7 @@ ${L}`,{parentModel:o})).output;return r?.info("Requirements stage complete (spec
|
|
|
300
317
|
- Mark which endpoints require specific roles (admin, owner).
|
|
301
318
|
- Identify resource-ownership checks (user can only access their own data).
|
|
302
319
|
|
|
303
|
-
Respond with structured analysis using headings and bullet points. Do NOT return JSON.`,
|
|
320
|
+
Respond with structured analysis using headings and bullet points. Do NOT return JSON.`,Ce=h({name:"endpoint-analyzer",description:"Analyzes data model and requirements to derive API endpoints, routes, and auth annotations. Use before generating the API design.",systemPrompt:Ki,tools:{},maxIterations:2});var Xi=`You are an API contract specialist. Given endpoints and a data model, you design detailed request/response contracts.
|
|
304
321
|
|
|
305
322
|
## Request Design
|
|
306
323
|
- For each endpoint, define: required fields, optional fields, field types, validation rules.
|
|
@@ -324,25 +341,25 @@ Respond with structured analysis using headings and bullet points. Do NOT return
|
|
|
324
341
|
- Use consistent field naming (camelCase for JSON, snake_case for query params if preferred).
|
|
325
342
|
- Use ISO 8601 for dates in responses.
|
|
326
343
|
|
|
327
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
344
|
+
Respond with structured analysis. Do NOT return JSON.`,Ne=h({name:"contract-designer",description:"Designs detailed request/response contracts, validation rules, and error responses per API endpoint. Use after endpoint analysis.",systemPrompt:Xi,tools:{},maxIterations:2});function Zi(e){let t=[];e.projectDescription&&t.push(e.projectDescription);let o=e.sections;return o.overview&&t.push(o.overview),o.techStack&&t.push(o.techStack),o.featureDecisions&&t.push(o.featureDecisions),o.dataModels&&t.push(o.dataModels),o.pagesAndRoutes&&t.push(o.pagesAndRoutes),o.authFlow&&t.push(o.authFlow),t.join(`
|
|
328
345
|
|
|
329
346
|
---
|
|
330
347
|
|
|
331
|
-
`)}async function
|
|
348
|
+
`)}async function Zo(e,t,o,r){r?.debug("Design stage started (specialist agents)");let n=Zi(t);if(!n)return {message:"No prior sections. Complete discovery and requirements first.",advance:false,sections:{}};r?.info("Delegating to api-designer endpoint-analyzer specialist");let s=(await V(Ce,`Design the API routes for this project:
|
|
332
349
|
|
|
333
|
-
${n}`,{parentModel:o})).output;r?.info("Delegating to api-designer contract-designer specialist");let i=await
|
|
350
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to api-designer contract-designer specialist");let i=await V(Ne,`Design detailed request/response contracts for these API endpoints:
|
|
334
351
|
|
|
335
|
-
${
|
|
352
|
+
${s}
|
|
336
353
|
|
|
337
354
|
Project context:
|
|
338
|
-
${n}`,{parentModel:o}),l=`${
|
|
355
|
+
${n}`,{parentModel:o}),l=`${Z}
|
|
339
356
|
|
|
340
|
-
Output only markdown. Do NOT output JSON.`,p=await o.invoke([{role:"system",content:l},{role:"user",content:
|
|
357
|
+
Output only markdown. Do NOT output JSON.`,p=await o.invoke([{role:"system",content:l},{role:"user",content:Bo(n,s+`
|
|
341
358
|
|
|
342
|
-
`+i.output)}],{temperature:.3,maxOutputTokens:8192}).then(c=>c.text?.trim()??"");return r?.info("Design stage complete (specialist agents)"),{message:"Design generated via specialist agents (Endpoint Analyzer, Contract Designer).",advance:true,sections:{apiRoutes:
|
|
359
|
+
`+i.output)}],{temperature:.3,maxOutputTokens:8192}).then(c=>c.text?.trim()??"");return r?.info("Design stage complete (specialist agents)"),{message:"Design generated via specialist agents (Endpoint Analyzer, Contract Designer).",advance:true,sections:{apiRoutes:s,implementation:p}}}var Ct=class{stageName="design";async process(t,o){return Zo(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "complete"}};function er(e,t){return [`# ${e} Implementation Plan
|
|
343
360
|
`,t.overview,t.techStack,t.featureDecisions,"---",t.dataModels,"---",t.pagesAndRoutes,"---",t.authFlow,"---",t.apiRoutes,"---",t.implementation,"---",t.executionPlan,"---",t.edgeCases,"---",t.testingChecklist].filter(Boolean).join(`
|
|
344
361
|
|
|
345
|
-
`)}var
|
|
362
|
+
`)}var el=`You are a QA-minded tech lead. You identify edge cases that developers often miss.
|
|
346
363
|
|
|
347
364
|
For each domain area (Authentication, Data, API, Frontend, Integrations):
|
|
348
365
|
|
|
@@ -358,7 +375,7 @@ For each domain area (Authentication, Data, API, Frontend, Integrations):
|
|
|
358
375
|
- **Frontend**: empty states, loading states, network errors, form resubmission, back button behavior.
|
|
359
376
|
- **Integrations**: external API down, timeout, rate limited, invalid response format.
|
|
360
377
|
|
|
361
|
-
Respond with structured edge cases grouped by area. Do NOT return JSON.`,
|
|
378
|
+
Respond with structured edge cases grouped by area. Do NOT return JSON.`,ke=h({name:"edge-case-analyzer",description:"Identifies edge cases per domain area with scenarios, handling strategies, and severity levels. Use for comprehensive edge case analysis.",systemPrompt:el,tools:{},maxIterations:2});var tl=`You are a testing strategy specialist. You design comprehensive manual testing checklists.
|
|
362
379
|
|
|
363
380
|
## Testing Checklist Design
|
|
364
381
|
Group test items by flow (Authentication, CRUD operations, Edge cases, etc.).
|
|
@@ -381,20 +398,20 @@ Present as grouped checklist items using markdown checkboxes:
|
|
|
381
398
|
### Flow Name
|
|
382
399
|
- [ ] Test item description -> Expected result
|
|
383
400
|
|
|
384
|
-
Respond with structured checklist. Do NOT return JSON.`,
|
|
401
|
+
Respond with structured checklist. Do NOT return JSON.`,De=h({name:"testing-strategist",description:"Designs comprehensive manual testing checklists grouped by feature flow. Use for testing strategy and QA planning.",systemPrompt:tl,tools:{},maxIterations:2});function ol(e){let t=[];e.projectDescription&&t.push(e.projectDescription);let o=e.sections;return [o.overview,o.techStack,o.featureDecisions,o.dataModels,o.pagesAndRoutes,o.authFlow,o.apiRoutes,o.implementation].forEach(r=>{r&&t.push(r);}),t.join(`
|
|
385
402
|
|
|
386
403
|
---
|
|
387
404
|
|
|
388
|
-
`)}function
|
|
389
|
-
`)[0]?.trim()??"",n=/^#+\s*(.+?)(?:\s+Implementation Plan)?$/i.exec(o);return n?.[1]?n[1].trim():o.length>0&&o.length<80?o.replace(/^#+\s*/,"").trim():"Project Implementation Plan"}async function
|
|
405
|
+
`)}function rl(e){let o=(e.sections.overview??e.projectDescription??"").split(`
|
|
406
|
+
`)[0]?.trim()??"",n=/^#+\s*(.+?)(?:\s+Implementation Plan)?$/i.exec(o);return n?.[1]?n[1].trim():o.length>0&&o.length<80?o.replace(/^#+\s*/,"").trim():"Project Implementation Plan"}async function tr(e,t,o,r){r?.debug("Synthesis stage started (specialist agents)");let n=ol(t);if(!n)return {message:"No prior sections. Complete earlier stages first.",advance:false,sections:{}};let a=`${Z}
|
|
390
407
|
|
|
391
|
-
${
|
|
408
|
+
${Jo}
|
|
392
409
|
|
|
393
|
-
Output only markdown. Do NOT output JSON.`,
|
|
410
|
+
Output only markdown. Do NOT output JSON.`,s=await o.invoke([{role:"system",content:a},{role:"user",content:zo(n)}],{temperature:.3,maxOutputTokens:8192}).then(m=>m.text?.trim()??"");r?.info("Delegating to execution-planner edge-case-analyzer specialist");let l=(await V(ke,`Identify edge cases for this project:
|
|
394
411
|
|
|
395
|
-
${n}`,{parentModel:o})).output;r?.info("Delegating to execution-planner testing-strategist specialist");let c=(await
|
|
412
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to execution-planner testing-strategist specialist");let c=(await V(De,`Design the manual testing checklist for this project:
|
|
396
413
|
|
|
397
|
-
${n}`,{parentModel:o})).output,
|
|
414
|
+
${n}`,{parentModel:o})).output,u=rl(t),d={...t.sections,executionPlan:s||null,edgeCases:l||null,testingChecklist:c||null},g=er(u,d);return r?.info("Synthesis stage complete (specialist agents)",{projectName:u}),{message:`Plan complete: ${u}. Generated via specialist agents.`,advance:true,sections:{executionPlan:s,edgeCases:l,testingChecklist:c},planMarkdown:g}}var Nt=class{stageName="complete";async process(t,o){return tr(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return null}};var nl={discovery:new Tt,requirements:new Ot,design:new Ct,complete:new Nt};function or(e){return nl[e]}async function ts(e,t,o,r,n){n?.debug("Stage processor invoked",{stage:e});let s=await or(e).process(o,{userMessage:t,model:r,logger:n}),i=Bn(o,s),l={...i,pendingQuestions:s.pendingQuestions??i.pendingQuestions};return n?.debug("Stage result",{stage:e,advance:s.advance,hasPlanMarkdown:!!s.planMarkdown}),{message:s.message,pendingQuestions:s.pendingQuestions??i.pendingQuestions,advance:s.advance,data:l,planMarkdown:s.planMarkdown}}var rr=["discovery","requirements","design","complete"];async function $e(e,t,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=O(n),s=t??Gn();s=St(s,"user",e),r?.info("Planning chat turn",{stage:s.stage,messageLength:e.length});let i="",l=[],p=null,c=async g=>{let m=await ts(g,e,s,a,r);return i=m.message,l=m.pendingQuestions,s=m.data,m.planMarkdown&&(p=m.planMarkdown),{advance:m.advance,planMarkdown:m.planMarkdown}},u=s.stage;r?.info("Stage",{stage:u});let d=await c(u);for(;d.advance&&!p;){let g=rr.indexOf(u),m=g>=0&&g<rr.length-1?rr[g+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:u,to:m}),u=m,s=qo(s),s={...s,stage:u},r?.info("Stage",{stage:u}),d=await c(u);}return s=St(s,"assistant",i),r?.info("Planning chat turn done",{stage:u,hasPlanMarkdown:!!p}),{message:i,context:s,pendingQuestions:l,planMarkdown:p}}var os=10;async function nr(e){let{input:t,model:o,onStep:r,logger:n}=e;n?.info("Starting planning agent",{maxTurns:os});let a=null,s=await $e(t,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.planMarkdown&&i<os;){n?.debug("Planning agent turn",{turn:i});let c=`continue - proceed with the project: "${t}". Make reasonable assumptions for any unresolved details and produce the required output format.`;s=await $e(c,a,{model:o,logger:n}),a=s.context,i++;}let l=s.planMarkdown??s.message,p=a.history.map(c=>({role:c.role,content:c.content}));return n?.info("Planning agent completed",{turns:i,hasPlanMarkdown:!!s.planMarkdown}),{output:l,steps:[],totalUsage:void 0,messages:p}}var _e=z.object({id:z.string(),name:z.string(),description:z.string(),goals:z.array(z.string())}),kt=z.object({actors:z.array(_e),message:z.string()});var Ie=z.object({id:z.string(),actorId:z.string(),name:z.string(),description:z.string(),trigger:z.string(),outcome:z.string()}),Dt=z.object({flows:z.array(Ie),message:z.string()});var je=z.object({id:z.string(),flowId:z.string(),actor:z.string(),action:z.string(),benefit:z.string(),preconditions:z.array(z.string()),postconditions:z.array(z.string()),dataInvolved:z.array(z.string())}),_t=z.object({stories:z.array(je),message:z.string()});var rs=z.object({id:z.string(),name:z.string(),operation:z.enum(["create","read","readAll","update","delete"]),description:z.string(),inputs:z.array(z.string()),outputs:z.array(z.string())}),qe=z.object({id:z.string(),name:z.string(),description:z.string(),entity:z.string(),apis:z.array(rs)}),It=z.object({modules:z.array(qe),summary:z.object({totalModules:z.number(),totalApis:z.number()}),message:z.string()});var ns=z.object({name:z.string(),type:z.string(),required:z.boolean(),unique:z.boolean(),description:z.string(),default:z.string().optional()}),ss=z.object({name:z.string(),fields:z.array(z.string()),unique:z.boolean()}),as=z.object({field:z.string(),references:z.string(),description:z.string()}),is=z.object({name:z.string(),description:z.string(),fields:z.array(ns),indexes:z.array(ss),relations:z.array(as)}),Se=z.object({type:z.enum(["mongodb","postgresql"]),reasoning:z.string(),entities:z.array(is)});var Le=z.object({name:z.string(),goal:z.string(),features:z.array(z.string()),domain:z.string(),database:z.enum(["mongodb","postgresql"]),backendRuntime:z.literal("nodejs"),apiStyle:z.enum(["rest","graphql"])}),jt=z.object({id:z.string(),question:z.string(),context:z.string(),suggestions:z.array(z.string()),multiSelect:z.boolean(),required:z.boolean()}),ls=z.object({role:z.enum(["user","assistant"]),content:z.string()});z.object({stage:z.enum(["discovery","requirements","design","complete"]),projectBrief:Le.nullable(),actors:z.array(_e),flows:z.array(Ie),stories:z.array(je),modules:z.array(qe),database:Se.nullable(),history:z.array(ls),pendingQuestions:z.array(jt)});var ps=z.object({totalActors:z.number(),totalFlows:z.number(),totalStories:z.number(),totalModules:z.number(),totalEntities:z.number(),overview:z.string()}),sr=z.object({project:Le,actors:z.array(_e),flows:z.array(Ie),stories:z.array(je),modules:z.array(qe),database:Se,summary:ps});var be=`You are a senior fullstack developer helping scope and plan a project. Your role is to understand what the user wants to build and produce a clear, actionable requirement document.
|
|
398
415
|
|
|
399
416
|
You work in stages: discovery (understand the project and tech preferences), requirements (actors, flows, stories, modules), design (database + APIs), and complete (final document).
|
|
400
417
|
|
|
@@ -406,7 +423,7 @@ Guidelines:
|
|
|
406
423
|
- Never repeat a question already answered in the conversation history.
|
|
407
424
|
- When the user says "continue", "yes", "looks good", or similar, treat it as confirmation and advance.
|
|
408
425
|
- Return valid JSON only when the prompt asks for JSON (no markdown code fences unless specified).
|
|
409
|
-
- Backend is Node.js only; database is MongoDB or PostgreSQL per user preference.`;var
|
|
426
|
+
- Backend is Node.js only; database is MongoDB or PostgreSQL per user preference.`;var ar=`You are in the discovery stage. Parse the user's message (and prior context) into a structured project brief. Ask clarifying questions only when something genuinely blocks design decisions.
|
|
410
427
|
|
|
411
428
|
Determine from the user's words:
|
|
412
429
|
- Project name and goal
|
|
@@ -421,7 +438,7 @@ Question rules:
|
|
|
421
438
|
- All other questions: Use "suggestions": []. Ask open-ended, specific to what the user described (e.g. file uploads, real-time features, auth provider, core user action).
|
|
422
439
|
- Never ask: scale, "how many users?", "what's the complexity?", or generic intake-form questions.
|
|
423
440
|
- Before asking, check conversation history \u2014 never repeat something already answered.
|
|
424
|
-
- If the user's message is clear enough (e.g. "Instagram clone with photo sharing, messaging, stories"), infer the obvious and ask only about genuine gaps. If you have enough for the brief, set needsClarification to false and empty questions.`,
|
|
441
|
+
- If the user's message is clear enough (e.g. "Instagram clone with photo sharing, messaging, stories"), infer the obvious and ask only about genuine gaps. If you have enough for the brief, set needsClarification to false and empty questions.`,cs=`## Current user message:
|
|
425
442
|
{userMessage}
|
|
426
443
|
|
|
427
444
|
## Prior conversation (if any):
|
|
@@ -455,10 +472,10 @@ Return ONLY valid JSON (no markdown, no explanation) in this shape:
|
|
|
455
472
|
}
|
|
456
473
|
|
|
457
474
|
For tech choices (API style, database), populate "suggestions" with the predefined options. For all other questions, use "suggestions": [].
|
|
458
|
-
If needsClarification is true, projectBrief can have empty/default values. If false, projectBrief must be complete.`;function
|
|
475
|
+
If needsClarification is true, projectBrief can have empty/default values. If false, projectBrief must be complete.`;function ir(e,t){return cs.replace("{userMessage}",e).replace("{history}",t||"(No prior messages)")}var qt=`## Project:
|
|
459
476
|
- **Name**: {projectName}
|
|
460
477
|
- **Goal**: {projectGoal}
|
|
461
|
-
- **Features**: {projectFeatures}`,
|
|
478
|
+
- **Features**: {projectFeatures}`,us=`${qt}
|
|
462
479
|
|
|
463
480
|
Identify ALL distinct user types (actors) who will use this system. 2-5 actors. Include unauthenticated and admin roles if applicable.
|
|
464
481
|
|
|
@@ -468,7 +485,7 @@ Return ONLY valid JSON:
|
|
|
468
485
|
{ "id": "actor-1", "name": "Name", "description": "Who they are", "goals": ["goal1", "goal2"] }
|
|
469
486
|
],
|
|
470
487
|
"message": "Brief explanation"
|
|
471
|
-
}`,
|
|
488
|
+
}`,ds=`${qt}
|
|
472
489
|
|
|
473
490
|
## Actors (JSON):
|
|
474
491
|
{actors}
|
|
@@ -481,7 +498,7 @@ Return ONLY valid JSON:
|
|
|
481
498
|
{ "id": "flow-1", "actorId": "actor-1", "name": "Flow Name", "description": "...", "trigger": "...", "outcome": "..." }
|
|
482
499
|
],
|
|
483
500
|
"message": "Brief explanation"
|
|
484
|
-
}`,
|
|
501
|
+
}`,ms=`${qt}
|
|
485
502
|
|
|
486
503
|
## Actors: {actors}
|
|
487
504
|
|
|
@@ -496,7 +513,7 @@ Return ONLY valid JSON:
|
|
|
496
513
|
{ "id": "story-1", "flowId": "flow-1", "actor": "ActorName", "action": "...", "benefit": "...", "preconditions": [], "postconditions": [], "dataInvolved": ["User.email", "Order.total"] }
|
|
497
514
|
],
|
|
498
515
|
"message": "Brief explanation"
|
|
499
|
-
}`,
|
|
516
|
+
}`,gs=`${qt}
|
|
500
517
|
|
|
501
518
|
## Actors: {actors}
|
|
502
519
|
## Flows: {flows}
|
|
@@ -512,7 +529,7 @@ Return ONLY valid JSON:
|
|
|
512
529
|
],
|
|
513
530
|
"summary": { "totalModules": 0, "totalApis": 0 },
|
|
514
531
|
"message": "Brief explanation"
|
|
515
|
-
}`;function
|
|
532
|
+
}`;function lr(e,t,o){return us.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o)}function pr(e,t,o,r){return ds.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r)}function cr(e,t,o,r,n){return ms.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n)}function ur(e,t,o,r,n,a){return gs.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n).replace("{stories}",a)}var al=`You are a database architect. The project brief includes a "database" field (mongodb or postgresql)\u2014use that database. Do not choose a different one. Output a single JSON object.
|
|
516
533
|
|
|
517
534
|
## Project brief (includes database: "mongodb" | "postgresql"):
|
|
518
535
|
{projectBrief}
|
|
@@ -540,7 +557,7 @@ Return ONLY valid JSON (no markdown) in this exact shape. Set "type" to the data
|
|
|
540
557
|
"relations": [ { "field": "refField", "references": "OtherEntity", "description": "..." } ]
|
|
541
558
|
}
|
|
542
559
|
]
|
|
543
|
-
}`;var
|
|
560
|
+
}`;var dr="You output only valid JSON. No markdown, no explanation.";function mr(e,t,o){return al.replace("{projectBrief}",e).replace("{modules}",t).replace("{stories}",o)}var gr="You are in the complete stage. You have the full context: project brief, actors, flows, stories, modules, and database design. Your job is to produce a single final requirement document (JSON) that matches the FinalRequirement schema, with a summary that includes totalActors, totalFlows, totalStories, totalModules, totalEntities, and a short overview paragraph.",fs=`## Project brief (JSON):
|
|
544
561
|
{projectBrief}
|
|
545
562
|
|
|
546
563
|
## Actors (JSON):
|
|
@@ -576,14 +593,14 @@ Return ONLY valid JSON in this shape (no markdown, no extra text):
|
|
|
576
593
|
"totalEntities": 0,
|
|
577
594
|
"overview": "string"
|
|
578
595
|
}
|
|
579
|
-
}`;function
|
|
580
|
-
`)}function
|
|
581
|
-
`)}function
|
|
582
|
-
`),
|
|
596
|
+
}`;function fr(e,t,o,r,n,a){return fs.replace("{projectBrief}",e).replace("{actors}",t).replace("{flows}",o).replace("{stories}",r).replace("{modules}",n).replace("{database}",a)}function hr(){return {stage:"discovery",projectBrief:null,actors:[],flows:[],stories:[],modules:[],database:null,history:[],pendingQuestions:[]}}function yr(e,t){let o=t.data;return {...e,...o.stage!==void 0&&{stage:o.stage},...o.projectBrief!==void 0&&{projectBrief:o.projectBrief},...o.actors!==void 0&&{actors:o.actors},...o.flows!==void 0&&{flows:o.flows},...o.stories!==void 0&&{stories:o.stories},...o.modules!==void 0&&{modules:o.modules},...o.database!==void 0&&{database:o.database},...o.pendingQuestions!==void 0&&{pendingQuestions:o.pendingQuestions}}}function Ye(e,t,o){let r={role:t,content:o};return {...e,history:[...e.history,r]}}function Lt(e){let t=["discovery","requirements","design","complete"],o=t.indexOf(e.stage),n=(o>=0&&o<t.length-1?t[o+1]:void 0)??e.stage;return {...e,stage:n}}function hs(e){return e.map(t=>`${t.name}: ${t.entity} (${t.apis.length} APIs)`).join(`
|
|
597
|
+
`)}function ys(e){return e.map(t=>`- ${t.actor}: ${t.action}`).join(`
|
|
598
|
+
`)}function K(e){let t=e.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(t);return o?.[1]?o[1].trim():t}function X(e){try{return {success:!0,data:JSON.parse(e)}}catch(t){return {success:false,error:t instanceof Error?t.message:String(t)}}}async function Ft(e,t,o,r){r?.debug("Discovery stage started",{historyLength:t.history.length});let n=t.history.map(w=>`${w.role}: ${w.content}`).slice(-10).join(`
|
|
599
|
+
`),a=ir(e,n),i=[{role:"system",content:`${be}
|
|
583
600
|
|
|
584
|
-
${
|
|
601
|
+
${ar}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.4,maxOutputTokens:4096}),p=K(l.text),c=X(p);if(!c.success)return r?.warn("Discovery response was not valid JSON",{error:c.error}),{message:"I couldn't parse that. Could you describe your project in a few sentences?",advance:false,data:{}};let u=c.data,d=u.conversationalMessage??l.text?.slice(0,500)??"Thanks for the details.",g=u.needsClarification===true,m=[];if(Array.isArray(u.questions))for(let w of u.questions){let z=jt.safeParse(w);z.success&&m.push(z.data);}let R=null;if(u.projectBrief&&!g){let w=Le.safeParse(u.projectBrief);w.success&&(R=w.data);}return r?.debug("Discovery stage complete",{advance:!g&&R!==null,hasProjectBrief:!!R,questionsCount:m.length}),{message:d,questions:m.length?m:void 0,advance:!g&&R!==null,data:{...R&&{projectBrief:R},pendingQuestions:m}}}async function Ss(e,t,o){if(e.invokeObject)return (await e.invokeObject(t,kt,{temperature:.4,maxOutputTokens:4096})).data;let r=await e.invoke(t,{temperature:.4,maxOutputTokens:4096}),n=X(K(r.text));if(!n.success)throw new Error(`Actors: ${n.error}`);let a=kt.safeParse(n.data);if(!a.success)throw new Error(`Actors schema: ${a.error.message}`);return a.data}async function bs(e,t,o,r){if(e.invokeObject)return (await e.invokeObject(t,Dt,{temperature:.4,maxOutputTokens:8192})).data;let n=await e.invoke(t,{temperature:.4,maxOutputTokens:8192}),a=X(K(n.text));if(!a.success)throw new Error(`Flows: ${a.error}`);let s=Dt.safeParse(a.data);if(!s.success)throw new Error(`Flows schema: ${s.error.message}`);return s.data}async function xs(e,t,o,r,n){if(e.invokeObject)return (await e.invokeObject(t,_t,{temperature:.4,maxOutputTokens:16384})).data;let a=await e.invoke(t,{temperature:.4,maxOutputTokens:16384}),s=X(K(a.text));if(!s.success)throw new Error(`Stories: ${s.error}`);let i=_t.safeParse(s.data);if(!i.success)throw new Error(`Stories schema: ${i.error.message}`);return i.data}async function Ts(e,t,o,r,n,a){if(e.invokeObject)return (await e.invokeObject(t,It,{temperature:.4,maxOutputTokens:16384})).data;let s=await e.invoke(t,{temperature:.4,maxOutputTokens:16384}),i=X(K(s.text));if(!i.success)throw new Error(`Modules: ${i.error}`);let l=It.safeParse(i.data);if(!l.success)throw new Error(`Modules schema: ${l.error.message}`);return l.data}async function Ut(e,t,o,r){r?.debug("Requirements stage started");let n=t.projectBrief;if(!n)return {message:"Project brief is missing. Complete discovery first.",advance:false,data:{}};let a=n.name,s=n.goal,i=n.features.join(". "),l=[{role:"system",content:be}];try{l.push({role:"user",content:lr(a,s,i)});let c=(await Ss(o,l,r)).actors;r?.debug("Requirements: actors",{count:c.length}),l.push({role:"assistant",content:`[Extracted ${c.length} actors]`}),l.push({role:"user",content:pr(a,s,i,JSON.stringify(c))});let d=(await bs(o,l,c,r)).flows;r?.debug("Requirements: flows",{count:d.length}),l.push({role:"assistant",content:`[Generated ${d.length} flows]`}),l.push({role:"user",content:cr(a,s,i,JSON.stringify(c),JSON.stringify(d))});let m=(await xs(o,l,c,d,r)).stories;r?.debug("Requirements: stories",{count:m.length}),l.push({role:"assistant",content:`[Generated ${m.length} stories]`}),l.push({role:"user",content:ur(a,s,i,JSON.stringify(c),JSON.stringify(d),JSON.stringify(m))});let w=(await Ts(o,l,c,d,m,r)).modules;return r?.debug("Requirements stage complete",{actors:c.length,flows:d.length,stories:m.length,modules:w.length}),{message:`I've identified ${c.length} actors, ${d.length} flows, ${m.length} stories, and ${w.length} modules. Proceeding to technical design.`,advance:!0,data:{actors:c,flows:d,stories:m,modules:w,pendingQuestions:[]}}}catch(p){let c=p instanceof Error?p.message:String(p);return r?.warn("Requirements stage failed",{error:c}),{message:`Requirements step failed: ${c}. Please try again.`,advance:false,data:{}}}}async function Gt(e,t,o,r){let n=t.projectBrief;if(!n)return {message:"Project brief is missing.",advance:false,data:{}};if(!t.modules.length||!t.stories.length)return {message:"Requirements (modules and stories) are missing. Run requirements stage first.",advance:false,data:{}};r?.info("Design stage: database design",{modules:t.modules.length,stories:t.stories.length});let a=JSON.stringify(n),s=hs(t.modules),i=ys(t.stories),l=mr(a,s,i),p=[{role:"system",content:dr},{role:"user",content:l}],c=await o.invoke(p,{temperature:.3,maxOutputTokens:8192}),u=K(c.text),d=X(u);if(!d.success)return r?.warn("Database design response was not valid JSON",{error:d.error}),{message:"Failed to parse database design response. Please try again.",advance:false,data:{}};let g=Se.safeParse(d.data);if(!g.success){let R=g.error;return r?.warn("Database design schema validation failed",{error:z.treeifyError(R)}),{message:"Failed to produce database design. Please try again.",advance:false,data:{}}}let m=g.data;return {message:`Database design complete: ${m.type}. API design will be handled by the api-designer module.`,advance:true,data:{database:m,pendingQuestions:[]}}}async function Bt(e,t,o,r){r?.debug("Synthesis stage started");let n=t.projectBrief;if(!n||!t.database)return {message:"Missing project brief or database design. Complete earlier stages first.",advance:false,data:{}};let a=fr(JSON.stringify(n),JSON.stringify(t.actors),JSON.stringify(t.flows),JSON.stringify(t.stories),JSON.stringify(t.modules),JSON.stringify(t.database)),i=[{role:"system",content:`${be}
|
|
585
602
|
|
|
586
|
-
${
|
|
603
|
+
${gr}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.3,maxOutputTokens:16384}),p=K(l.text),c=X(p);if(!c.success)return r?.warn("Synthesis response was not valid JSON",{error:c.error}),{message:"Failed to compile final requirement document. Please try again.",advance:false,data:{}};let u=sr.safeParse(c.data);if(!u.success)return r?.warn("Synthesis: final requirement schema validation failed",{error:u.error.message}),{message:"Final document did not match schema. "+(l.text?.slice(0,300)??""),advance:false,data:{}};let d=u.data;return r?.info("Synthesis stage complete",{overview:d.summary?.overview}),{message:`Requirement document ready. ${d.summary.overview}`,advance:true,data:{finalRequirement:d}}}var Jt=class{stageName="discovery";async process(t,o){return Ft(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "requirements"}};var zt=class{stageName="requirements";async process(t,o){return Ut(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "design"}};var $t=class{stageName="design";async process(t,o){return Gt(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "complete"}};var Yt=class{stageName="complete";async process(t,o){return Bt(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return null}};var ll={discovery:new Jt,requirements:new zt,design:new $t,complete:new Yt};function Sr(e){return ll[e]}async function Ps(e,t,o,r,n){n?.debug("Stage processor invoked",{stage:e});let s=await Sr(e).process(o,{userMessage:t,model:r,logger:n}),i=yr(o,s),l="finalRequirement"in s.data?s.data.finalRequirement:void 0;n?.debug("Stage result",{stage:e,advance:s.advance,hasFinalRequirement:!!l});let p={...i,pendingQuestions:s.questions??i.pendingQuestions};return {message:s.message,questions:s.questions??i.pendingQuestions,advance:s.advance,data:p,finalRequirement:l}}var br=["discovery","requirements","design","complete"];async function Ht(e,t,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=O(n),s=t??hr();s=Ye(s,"user",e),r?.info("Chat turn",{stage:s.stage,messageLength:e.length});let i="",l=[],p=null,c=async g=>{let m=await Ps(g,e,s,a,r);return i=m.message,l=m.questions,s=m.data,m.finalRequirement&&(p=m.finalRequirement),{advance:m.advance,finalReq:m.finalRequirement}},u=s.stage;r?.info("Stage",{stage:u});let d=await c(u);for(s={...s,pendingQuestions:l};d.advance&&!p;){let g=br.indexOf(u),m=g>=0&&g<br.length-1?br[g+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:u,to:m}),u=m,s=Lt(s),s={...s,stage:u},r?.info("Stage",{stage:u}),d=await c(u),s={...s,pendingQuestions:l};}return s=Ye(s,"assistant",i),r?.info("Chat turn done",{stage:u,hasFinalRequirement:!!p}),{message:i,context:s,questions:l,finalRequirement:p}}var Rs=10;async function He(e){let{input:t,model:o,onStep:r,logger:n}=e;n?.info("Starting requirement gatherer agent",{maxTurns:Rs});let a=null,s=await Ht(t,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.finalRequirement&&i<Rs;)n?.debug("Requirement gatherer turn",{turn:i}),s=await Ht("continue",a,{model:o,logger:n}),a=s.context,i++;let l=s.finalRequirement?JSON.stringify(s.finalRequirement,null,2):s.message,p=a.history.map(c=>({role:c.role,content:c.content}));return n?.info("Requirement gatherer agent completed",{turns:i,hasFinalRequirement:!!s.finalRequirement}),{output:l,steps:[],totalUsage:void 0,messages:p}}var xr=z.object({name:z.string(),type:z.string(),required:z.coerce.boolean().default(false),unique:z.coerce.boolean().default(false),description:z.string().default(""),default:z.string().optional()}),ws=z.object({name:z.string().default(""),fields:z.array(z.string()).default([]),unique:z.coerce.boolean().default(false)}),cl=z.string().transform(e=>{let t=e.toLowerCase().replace(/[\s_-]+/g,"");return ["1:1","onetoone"].includes(t)?"1:1":["1:n","1:m","n:1","onetomany","manytoone"].includes(t)?"1:N":["m:n","n:m","manytomany"].includes(t)?"M:N":e}).pipe(z.enum(["1:1","1:N","M:N"])),vs=z.object({field:z.string(),references:z.string(),type:cl,description:z.string().default("")}),Tr=z.object({name:z.string(),description:z.string().default(""),fields:z.union([z.array(xr),z.record(z.string(),z.unknown())]).transform((e,t)=>{if(Array.isArray(e))return e;let o=[];for(let[r,n]of Object.entries(e)){let a=typeof n=="object"&&n!==null?{...n}:{};a.name||(a.name=r);let s=xr.safeParse(a);if(s.success)o.push(s.data);else for(let i of s.error.issues)t.addIssue({...i,path:[r,...i.path]});}return o}),indexes:z.array(ws).default([]),relations:z.array(vs).default([])}),ul=z.string().transform(e=>e.toLowerCase().trim()).pipe(z.enum(["mongodb","postgresql"])),te=z.object({type:ul,reasoning:z.string().default(""),entities:z.array(Tr).default([])});var Fe=z.object({fieldName:z.string().describe("fieldName must be in camelCase"),fieldType:z.string().default("string").transform(e=>{let t=e.toLowerCase().trim();return ["string","text","varchar"].includes(t)?"string":["number","int","integer","float","double","decimal"].includes(t)?"number":["boolean","bool"].includes(t)?"boolean":["types.objectid","objectid","ref","reference"].includes(t)?"Types.ObjectId":["date","datetime","timestamp"].includes(t)?"Date":["object","json","mixed"].includes(t)?"object":["email"].includes(t)?"email":["password","hash"].includes(t)?"password":["enum","select"].includes(t)?"enum":("string")}).pipe(z.enum(["string","number","boolean","Types.ObjectId","Date","object","email","password","enum"])),isArray:z.coerce.boolean().default(false),isRequired:z.coerce.boolean().default(true),isUnique:z.coerce.boolean().default(false),values:z.array(z.string()).default([]).describe("Enum values if fieldType is enum, else empty array"),defaultVal:z.union([z.string(),z.boolean(),z.number(),z.null()]).optional(),relationTo:z.string().optional().describe("Module name for relations"),relationType:z.string().transform(e=>{let t=e.toLowerCase().replace(/[\s_]+/g,"-");return ["one-to-one","1:1","1-to-1"].includes(t)?"one-to-one":["many-to-one","n:1","n-to-1","many-to-1","*:1"].includes(t)?"many-to-one":""}).pipe(z.enum(["one-to-one","many-to-one",""])).optional(),isPrivate:z.coerce.boolean().default(false).describe("True if password field, else false")});var Ue=z.object({moduleName:z.string().describe("camelCase, single word, never auth/authentication"),isUserModule:z.coerce.boolean().default(false),authMethod:z.string().transform(e=>{let t=e.toUpperCase().replace(/[\s-]+/g,"_");return ["EMAIL_AND_PASSWORD","EMAIL_PASSWORD","EMAIL"].includes(t)?"EMAIL_AND_PASSWORD":["PHONE_AND_OTP","PHONE_OTP","PHONE","SMS"].includes(t)?"PHONE_AND_OTP":""}).pipe(z.enum(["EMAIL_AND_PASSWORD","PHONE_AND_OTP",""])).optional(),emailField:z.string().optional(),passwordField:z.string().optional(),phoneField:z.string().optional(),roleField:z.string().optional(),permissions:z.record(z.string(),z.array(z.enum(["CREATE","READ","UPDATE","DELETE"]))).optional().describe("Permissions per role"),fields:z.union([z.array(Fe),z.record(z.string(),z.unknown())]).transform((e,t)=>{if(Array.isArray(e))return e;let o=[];for(let[r,n]of Object.entries(e)){let a=typeof n=="object"&&n!==null?{...n}:{};a.fieldName||(a.fieldName=r);let s=Fe.safeParse(a);if(s.success)o.push(s.data);else for(let i of s.error.issues)t.addIssue({...i,path:[r,...i.path]});}return o})});var pe=z.object({projectName:z.string().default("project").describe("projectName must be in kebab-case"),projectDescription:z.string().default(""),modules:z.union([z.array(Ue),z.record(z.string(),z.unknown())]).transform((e,t)=>{if(Array.isArray(e))return e;let o=[];for(let[r,n]of Object.entries(e)){let a=typeof n=="object"&&n!==null?{...n}:{};a.moduleName||(a.moduleName=r);let s=Ue.safeParse(a);if(s.success)o.push(s.data);else for(let i of s.error.issues)t.addIssue({...i,path:[r,...i.path]});}return o}),author:z.string().default("sijeeshmiziha")});var Qt=`You are a senior database architect specializing in both MongoDB and PostgreSQL schema design.
|
|
587
604
|
|
|
588
605
|
You analyze requirements and produce enterprise-quality data models with:
|
|
589
606
|
- Properly typed fields (MongoDB: ObjectId, string, number, date, array; PostgreSQL: uuid, varchar, text, integer, timestamp, jsonb)
|
|
@@ -592,7 +609,7 @@ You analyze requirements and produce enterprise-quality data models with:
|
|
|
592
609
|
- Validation constraints and default values
|
|
593
610
|
- Security considerations (hashed passwords, encrypted fields)
|
|
594
611
|
|
|
595
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
612
|
+
Output only valid JSON unless instructed otherwise.`;var As=`## Requirements:
|
|
596
613
|
{requirement}
|
|
597
614
|
|
|
598
615
|
Design the database schema. Determine the best database type (mongodb or postgresql) based on the requirements, or use the one specified.
|
|
@@ -615,13 +632,13 @@ Return ONLY valid JSON:
|
|
|
615
632
|
"relations": [ { "field": "refField", "references": "OtherEntity", "type": "1:N", "description": "..." } ]
|
|
616
633
|
}
|
|
617
634
|
]
|
|
618
|
-
}`,
|
|
635
|
+
}`,Es=`## Current Schema (JSON):
|
|
619
636
|
{existingSchema}
|
|
620
637
|
|
|
621
638
|
## Feedback:
|
|
622
639
|
{feedback}
|
|
623
640
|
|
|
624
|
-
Update the schema based on the feedback. Return the complete updated schema as valid JSON in the same format.`;function
|
|
641
|
+
Update the schema based on the feedback. Return the complete updated schema as valid JSON in the same format.`;function Pr(e){return As.replace("{requirement}",e)}function Rr(e,t){return Es.replace("{existingSchema}",e).replace("{feedback}",t)}var Ms=`## Project: {projectName}
|
|
625
642
|
## Goal: {projectGoal}
|
|
626
643
|
## Database: {databaseType}
|
|
627
644
|
|
|
@@ -651,9 +668,9 @@ Apply the 5-phase enterprise data modeling process:
|
|
|
651
668
|
- Verify every entity referenced in relations exists.
|
|
652
669
|
- Verify no orphan fields or missing indexes.
|
|
653
670
|
|
|
654
|
-
Return ONLY valid JSON in the DataModelDesign format.`;function
|
|
671
|
+
Return ONLY valid JSON in the DataModelDesign format.`;function wr(e,t,o,r){return Ms.replace("{projectName}",e).replace("{projectGoal}",t).replace("{databaseType}",o).replace("{context}",r)}var Vt=j("validate_data_model",te,"Validates a data model JSON string against the DataModelDesign schema. Returns valid: true or valid: false with errors.","schema");function hl(e){let t=e.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(t);return o?.[1]?o[1].trim():t}function C(e,t){let o=hl(e),r;try{r=JSON.parse(o);}catch(a){let s=o.length>300?o.slice(0,300)+"...":o;throw new Error(`Failed to parse model response as JSON: ${a instanceof Error?a.message:String(a)}. Preview: ${s}`)}let n=t.safeParse(r);if(!n.success){let a=n.error.issues.slice(0,5).map(s=>` ${s.path.join(".")}: ${s.message}`).join(`
|
|
655
672
|
`);throw new Error(`Model JSON does not match expected schema:
|
|
656
|
-
${
|
|
673
|
+
${a}`)}return n.data}function Ge(e,t){try{return JSON.parse(e)}catch(o){let r=e.length>200?e.slice(0,200)+"...":e;throw new Error(`Invalid JSON${t?` for ${t}`:""}: ${o instanceof Error?o.message:String(o)}. Preview: ${r}`)}}function Wt(e){return y({name:"design_schema",description:"Generate a database schema (MongoDB or PostgreSQL) from plain text requirements. Returns the full data model as JSON.",input:z.object({requirement:z.string().describe("Plain text description of the data modeling requirements")}),handler:async({requirement:t})=>{let o=Pr(t),r=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:8192});return C(n.text,te)}})}function Kt(e){return y({name:"design_schema_pro",description:"Generate an enterprise-quality database schema using 5-phase analysis (Entity Discovery, Relationship Mapping, Permission Derivation, Schema Generation, Validation). Use when structured context is available.",input:z.object({projectName:z.string().describe("Project name"),projectGoal:z.string().describe("Project goal / purpose"),databaseType:z.enum(["mongodb","postgresql"]).describe("Target database type"),context:z.string().describe("Full project context: features, actors, flows, stories")}),handler:async({projectName:t,projectGoal:o,databaseType:r,context:n})=>{let a=wr(t,o,r,n),s=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:a}],i=await e.invoke(s,{temperature:.2,maxOutputTokens:16384});return C(i.text,te)}})}function Xt(e){return y({name:"refine_schema",description:"Update an existing data model schema based on user feedback. Provide the current schema JSON and feedback describing desired changes.",input:z.object({existingSchema:z.string().describe("Current data model schema as JSON string"),feedback:z.string().describe("Feedback describing desired changes")}),handler:async({existingSchema:t,feedback:o})=>{let r=Rr(t,o),n=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:r}],a=await e.invoke(n,{temperature:.3,maxOutputTokens:8192});return C(a.text,te)}})}j("validate_schema",pe,"Validates a MongoDB project schema JSON string against the expected schema. Returns valid: true or valid: false with errors.","schema");z.object({projectName:z.string(),projectGoal:z.string(),projectDescription:z.string().optional(),actors:z.array(z.object({id:z.string(),name:z.string(),description:z.string(),goals:z.array(z.string())})),flows:z.array(z.object({id:z.string(),actorId:z.string(),name:z.string(),description:z.string(),trigger:z.string(),outcome:z.string()})),stories:z.array(z.object({id:z.string(),flowId:z.string(),actor:z.string(),action:z.string(),benefit:z.string(),preconditions:z.array(z.string()),postconditions:z.array(z.string()),dataInvolved:z.array(z.string())})),technicalRequirements:z.object({authentication:z.string().transform(e=>{let t=e.toLowerCase().replace(/[\s_-]+/g,"");return ["none","no",""].includes(t)?"none":["email","emailpassword","emailandpassword"].includes(t)?"email":["oauth","oauth2","social"].includes(t)?"oauth":["phone","phoneotp","sms"].includes(t)?"phone":["emailandphone","emailphone","both"].includes(t)?"email_and_phone":"email"}).pipe(z.enum(["none","email","oauth","phone","email_and_phone"])),authorization:z.coerce.boolean().default(false),roles:z.array(z.string()).optional(),integrations:z.array(z.string()).optional(),realtime:z.boolean().optional(),fileUpload:z.boolean().optional(),search:z.boolean().optional()}).optional()});function Cr(e){return {validate_data_model:Vt,design_schema:Wt(e),design_schema_pro:Kt(e),refine_schema:Xt(e)}}var yl=`${Qt}
|
|
657
674
|
|
|
658
675
|
You are the data modeling orchestrator. When the user asks for a data model:
|
|
659
676
|
|
|
@@ -663,7 +680,7 @@ You are the data modeling orchestrator. When the user asks for a data model:
|
|
|
663
680
|
4. **Refine (optional)**: Use subagent_schema-refiner to validate and suggest improvements to the generated schema.
|
|
664
681
|
5. **Validate**: Use validate_data_model to check the final schema JSON before returning.
|
|
665
682
|
|
|
666
|
-
Respond with the final data model schema as JSON.`;async function
|
|
683
|
+
Respond with the final data model schema as JSON.`;async function Ve(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=Cr(s),l=Ee(),p=L([le,At,l],{parentModel:s}),c={...i,...p};return _({model:s,tools:c,systemPrompt:yl,input:t,maxIterations:r,onStep:n,logger:a})}var bl=z.union([z.enum(["GET","POST","PUT","PATCH","DELETE"]),z.string()]).transform(e=>typeof e=="string"?e.toUpperCase():e).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),Nr=z.record(z.string(),z.unknown()).optional().default({}).transform(e=>Object.fromEntries(Object.entries(e??{}).map(([t,o])=>[t,typeof o=="string"?o:String(o)]))),js=z.array(z.unknown()).default([]).transform(e=>e.map(t=>typeof t=="string"?t:JSON.stringify(t))),kr=z.object({id:z.string(),resource:z.string(),method:bl,path:z.string(),description:z.string(),auth:z.coerce.boolean(),roles:z.array(z.string()).default([]),requestBody:Nr,responseBody:Nr,queryParams:Nr,validation:js,errorResponses:js}),Dr=z.object({name:z.string(),type:z.enum(["query","mutation","subscription"]),description:z.string(),auth:z.coerce.boolean(),roles:z.array(z.string()).default([]),args:z.array(z.object({name:z.string(),type:z.string(),required:z.coerce.boolean()})),returnType:z.string()}),xl=z.unknown().transform(e=>(typeof e=="string"?e.toLowerCase().trim():"rest").includes("graphql")?"graphql":"rest"),ue=z.object({style:xl,baseUrl:z.string().default("/api/v1"),endpoints:z.array(kr).optional().default([]),graphqlOperations:z.array(Dr).optional().default([])}).refine(e=>e.endpoints.length>0||e.graphqlOperations.length>0,{message:"API design must include at least one REST endpoint or GraphQL operation. The endpoints array and graphqlOperations array cannot both be empty."});var Zt=`You are a senior API architect specializing in REST and GraphQL API design.
|
|
667
684
|
|
|
668
685
|
You analyze data models and requirements to produce enterprise-quality API designs with:
|
|
669
686
|
- RESTful endpoints grouped by resource with proper HTTP methods
|
|
@@ -673,43 +690,78 @@ You analyze data models and requirements to produce enterprise-quality API desig
|
|
|
673
690
|
- Authentication and authorization annotations per endpoint
|
|
674
691
|
- GraphQL types, queries, mutations, and subscriptions when applicable
|
|
675
692
|
|
|
676
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
693
|
+
Output only valid JSON unless instructed otherwise.`;var qs=`## Requirements:
|
|
677
694
|
{requirement}
|
|
678
695
|
|
|
679
|
-
Design the API. Determine the best API style (rest or graphql) based on the requirements, or use the one specified.
|
|
696
|
+
Design the API. Determine the best API style ("rest" or "graphql") based on the requirements, or use the one specified.
|
|
680
697
|
|
|
681
|
-
|
|
698
|
+
IMPORTANT: You MUST generate ALL CRUD endpoints (Create, Read, List, Update, Delete) for EVERY resource identified in the requirements. The "endpoints" array MUST NOT be empty for REST APIs.
|
|
699
|
+
|
|
700
|
+
For REST: group endpoints by resource. Each endpoint needs: id, resource, method, path, description, auth, roles, requestBody, responseBody, queryParams, validation, and errorResponses.
|
|
682
701
|
For GraphQL: define operations (queries, mutations, subscriptions) with args and return types.
|
|
683
702
|
|
|
684
|
-
Return ONLY valid JSON:
|
|
703
|
+
Return ONLY valid JSON matching this exact structure:
|
|
685
704
|
{
|
|
686
|
-
"style": "rest"
|
|
705
|
+
"style": "rest",
|
|
687
706
|
"baseUrl": "/api/v1",
|
|
688
707
|
"endpoints": [
|
|
689
|
-
{
|
|
708
|
+
{
|
|
709
|
+
"id": "ep-1",
|
|
710
|
+
"resource": "users",
|
|
711
|
+
"method": "POST",
|
|
712
|
+
"path": "/api/v1/users",
|
|
713
|
+
"description": "Register a new user",
|
|
714
|
+
"auth": false,
|
|
715
|
+
"roles": [],
|
|
716
|
+
"requestBody": { "name": "string", "email": "string", "password": "string" },
|
|
717
|
+
"responseBody": { "id": "string", "name": "string", "email": "string" },
|
|
718
|
+
"queryParams": {},
|
|
719
|
+
"validation": ["name is required", "email must be valid format"],
|
|
720
|
+
"errorResponses": ["400 Validation error", "409 Email already exists"]
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
"id": "ep-2",
|
|
724
|
+
"resource": "users",
|
|
725
|
+
"method": "GET",
|
|
726
|
+
"path": "/api/v1/users/:id",
|
|
727
|
+
"description": "Get user by ID",
|
|
728
|
+
"auth": true,
|
|
729
|
+
"roles": ["user", "admin"],
|
|
730
|
+
"requestBody": {},
|
|
731
|
+
"responseBody": { "id": "string", "name": "string", "email": "string" },
|
|
732
|
+
"queryParams": {},
|
|
733
|
+
"validation": [],
|
|
734
|
+
"errorResponses": ["401 Unauthenticated", "404 User not found"]
|
|
735
|
+
}
|
|
690
736
|
],
|
|
691
737
|
"graphqlOperations": []
|
|
692
|
-
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
Generate endpoints for ALL resources. Do NOT return an empty endpoints array.`,Ls=`## Project: {projectName}
|
|
693
741
|
## API Style: {apiStyle}
|
|
694
742
|
## Data Model:
|
|
695
743
|
{dataModel}
|
|
696
744
|
## Requirements:
|
|
697
745
|
{context}
|
|
698
746
|
|
|
699
|
-
Design a comprehensive API surface from the data model and requirements. For
|
|
747
|
+
Design a comprehensive API surface from the data model and requirements. For EVERY entity in the data model, generate CRUD endpoints (Create, Read by ID, List with pagination, Update, Delete) plus any custom operations implied by the requirements.
|
|
748
|
+
|
|
749
|
+
IMPORTANT: The "endpoints" array MUST NOT be empty. You MUST include endpoints for ALL entities.
|
|
700
750
|
|
|
701
|
-
Include per-endpoint:
|
|
751
|
+
Include per-endpoint: id (unique like "ep-1"), resource, method, path, description, auth flag, roles array, requestBody (field-to-type map), responseBody (field-to-type map), queryParams (field-to-type map), validation rules (string array), and error responses (string array with status codes like "400 Validation error", "401 Unauthenticated", "404 Not found").
|
|
702
752
|
|
|
703
|
-
Return ONLY valid JSON in the ApiDesign format.`;function
|
|
753
|
+
Return ONLY valid JSON in the ApiDesign format.`;function _r(e){return qs.replace("{requirement}",e)}function Ir(e,t,o,r){return Ls.replace("{projectName}",e).replace("{apiStyle}",t).replace("{dataModel}",o).replace("{context}",r)}var eo=j("validate_api",ue,"Validates an API design JSON string against the ApiDesign schema. Returns valid: true or valid: false with errors.","design");function to(e){return y({name:"design_api",description:"Generate an API design (REST or GraphQL) from plain text requirements. Returns the full API design as JSON.",input:z.object({requirement:z.string().describe("Plain text description of the API requirements")}),handler:async({requirement:t})=>{let o=_r(t),r=[{role:"system",content:"You are an API architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,ue)}})}function oo(e){return y({name:"design_api_pro",description:"Generate a comprehensive API design from a data model and project context. Produces detailed endpoints with validation, error responses, and auth annotations.",input:z.object({projectName:z.string().describe("Project name"),apiStyle:z.enum(["rest","graphql"]).describe("Target API style"),dataModel:z.string().describe("Data model JSON or description"),context:z.string().describe("Project context: features, actors, stories")}),handler:async({projectName:t,apiStyle:o,dataModel:r,context:n})=>{let a=Ir(t,o,r,n),s=[{role:"system",content:"You are an API architect. Return only valid JSON."},{role:"user",content:a}],i=await e.invoke(s,{temperature:.2,maxOutputTokens:16384});return C(i.text,ue)}})}function jr(e){return {validate_api:eo,design_api:to(e),design_api_pro:oo(e)}}var Tl=`${Zt}
|
|
704
754
|
|
|
705
|
-
You are the API design orchestrator.
|
|
755
|
+
You are the API design orchestrator. You MUST use tools to generate the API design. Do NOT respond with a text-only answer or skip tool calls.
|
|
756
|
+
|
|
757
|
+
Follow these steps:
|
|
706
758
|
|
|
707
759
|
1. **Analyze endpoints**: Use subagent_endpoint-analyzer to derive endpoints from the data model and requirements.
|
|
708
760
|
2. **Design contracts**: Use subagent_contract-designer to design request/response contracts, validation rules, and error responses.
|
|
709
|
-
3. **Generate design**:
|
|
761
|
+
3. **Generate design**: You MUST call design_api (for plain text requirements) or design_api_pro (when data model and structured context are available) to produce the API design. This step is mandatory \u2014 never skip it.
|
|
710
762
|
4. **Validate**: Use validate_api to check the final API design JSON before returning.
|
|
711
763
|
|
|
712
|
-
|
|
764
|
+
CRITICAL: You MUST always call the design_api or design_api_pro tool. If a tool call fails, retry with adjusted input. Never fall back to a text-only response. The final output must be valid API design JSON with a non-empty endpoints array.`;async function Ke(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=jr(s),l=L([Ce,Ne],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:Tl,input:t,maxIterations:r,onStep:n,logger:a})}var Us=z.object({order:z.number(),side:z.enum(["frontend","backend"]),action:z.string(),details:z.string()}),Gs=z.object({name:z.string(),description:z.string(),steps:z.array(Us)}),Bs=z.object({name:z.string(),purpose:z.string(),behavior:z.array(z.string())}),Js=z.object({name:z.string(),description:z.string(),permissions:z.array(z.string())}),zs=z.object({area:z.string(),rules:z.array(z.string())}),Xe=z.object({strategy:z.enum(["jwt","session","oauth"]),flows:z.array(Gs),middleware:z.array(Bs),roles:z.array(Js),policies:z.array(zs)});var qr=`You are a senior security engineer specializing in authentication, authorization, and web security.
|
|
713
765
|
|
|
714
766
|
You design enterprise-quality auth systems with:
|
|
715
767
|
- Step-by-step auth flows (signup, login, logout, password reset) with both frontend and backend steps
|
|
@@ -719,7 +771,7 @@ You design enterprise-quality auth systems with:
|
|
|
719
771
|
- Security policies: password hashing (bcrypt), rate limiting, CORS, input sanitization, brute force protection
|
|
720
772
|
- OAuth integration patterns when needed
|
|
721
773
|
|
|
722
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
774
|
+
Output only valid JSON unless instructed otherwise.`;var $s=`## Requirements:
|
|
723
775
|
{requirement}
|
|
724
776
|
|
|
725
777
|
Design the authentication and authorization system. Include:
|
|
@@ -737,7 +789,7 @@ Return ONLY valid JSON:
|
|
|
737
789
|
"middleware": [{ "name": "authenticateRequest", "purpose": "...", "behavior": ["..."] }],
|
|
738
790
|
"roles": [{ "name": "user", "description": "...", "permissions": ["..."] }],
|
|
739
791
|
"policies": [{ "area": "passwords", "rules": ["..."] }]
|
|
740
|
-
}`;function
|
|
792
|
+
}`;function Lr(e){return $s.replace("{requirement}",e)}var ro=j("validate_auth",Xe,"Validates an auth design JSON string against the AuthDesign schema. Returns valid: true or valid: false with errors.","design");function no(e){return y({name:"design_auth",description:"Generate a complete authentication and authorization design from project requirements. Returns auth flows, middleware, roles, and security policies as JSON.",input:z.object({requirement:z.string().describe("Project context and auth requirements")}),handler:async({requirement:t})=>{let o=Lr(t),r=[{role:"system",content:"You are a security engineer. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:8192});return C(n.text,Xe)}})}function Fr(e){return {validate_auth:ro,design_auth:no(e)}}var Pl=`${qr}
|
|
741
793
|
|
|
742
794
|
You are the auth design orchestrator. When the user asks for an auth design:
|
|
743
795
|
|
|
@@ -746,7 +798,7 @@ You are the auth design orchestrator. When the user asks for an auth design:
|
|
|
746
798
|
3. **Generate design**: Use design_auth to produce the complete auth design with flows, middleware, roles, and security policies.
|
|
747
799
|
4. **Validate**: Use validate_auth to check the final auth design JSON before returning.
|
|
748
800
|
|
|
749
|
-
Respond with the final auth design as JSON.`;async function
|
|
801
|
+
Respond with the final auth design as JSON.`;async function Ze(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=Fr(s),l=L([Mt,Oe],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:Pl,input:t,maxIterations:r,onStep:n,logger:a})}var Hs=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),Qs=z.object({name:z.string(),purpose:z.string(),appliesTo:z.string().default("global").transform(e=>{let t=e.toLowerCase().trim();return ["global","all","app","application","every","server"].includes(t)?"global":["route","routes","specific","specific routes","endpoint","endpoints","path"].includes(t)?"route":["resource","entity","module","controller","model"].includes(t)?"resource":"global"}).pipe(z.enum(["global","route","resource"])),config:z.record(z.string(),z.unknown()).default({})}),Vs=z.object({name:z.string(),entity:z.string(),operations:z.array(z.string()).default([]),dependencies:z.array(z.string()).default([])}),Rl=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),Ws=z.object({resource:z.string(),basePath:z.string(),endpoints:z.array(z.object({method:Rl,path:z.string(),handler:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([])})).default([])}),et=z.object({framework:Hs(["express","apollo","both"]),language:Hs(["typescript","javascript"]).default("typescript"),database:z.string().default("mongodb"),services:z.array(Vs).default([]),middleware:z.array(Qs).default([]),routes:z.array(Ws).default([]),folderStructure:z.array(z.string()).default([]),envVars:z.array(z.string()).default([]),notes:z.string().default("")});var Ur=`You are a senior backend architect specializing in Node.js server design.
|
|
750
802
|
|
|
751
803
|
You analyze data models, API designs, and auth requirements to produce enterprise-quality backend architectures with:
|
|
752
804
|
- Framework selection (Express REST, Apollo GraphQL, or both)
|
|
@@ -764,7 +816,7 @@ When "both" is selected (Express + Apollo), use the Apollo Gateway pattern:
|
|
|
764
816
|
- Express for webhooks, file uploads, and health checks only
|
|
765
817
|
- Gateway has no business logic, all logic lives in subgraphs
|
|
766
818
|
|
|
767
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
819
|
+
Output only valid JSON unless instructed otherwise.`;var Ks=`## Requirements:
|
|
768
820
|
{requirement}
|
|
769
821
|
|
|
770
822
|
Design the backend architecture. Include:
|
|
@@ -787,7 +839,7 @@ Return ONLY valid JSON:
|
|
|
787
839
|
"folderStructure": ["src/", "src/routes/", "src/services/", "src/middleware/", "src/models/", "src/config/"],
|
|
788
840
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET"],
|
|
789
841
|
"notes": ""
|
|
790
|
-
}`;function
|
|
842
|
+
}`;function Gr(e){return Ks.replace("{requirement}",e)}var so=j("validate_backend",et,"Validates a backend design JSON string against the BackendDesign schema. Returns valid: true or valid: false with errors.","design");function ao(e){return y({name:"design_backend",description:"Generate a complete backend architecture design from requirements. Returns framework, services, middleware, routes, and folder structure as JSON.",input:z.object({requirement:z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:t})=>{let o=Gr(t),r=[{role:"system",content:"You are a backend architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,et)}})}function Br(e){return {validate_backend:so,design_backend:ao(e)}}var wl=`You are a backend service architect. Given a data model and API design, you plan the service layer.
|
|
791
843
|
|
|
792
844
|
## Service Design
|
|
793
845
|
For each entity:
|
|
@@ -814,7 +866,7 @@ Recommend a clean folder layout:
|
|
|
814
866
|
- src/config/ (env, database, auth config)
|
|
815
867
|
- src/utils/ (shared helpers)
|
|
816
868
|
|
|
817
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
869
|
+
Respond with structured analysis. Do NOT return JSON.`,io=h({name:"service-planner",description:"Plans service layer, middleware stack, and folder structure for a backend project. Use before generating the backend design.",systemPrompt:wl,tools:{},maxIterations:2});var vl=`You are a backend technology advisor. Given project requirements, you recommend the best backend framework.
|
|
818
870
|
|
|
819
871
|
## Decision Criteria
|
|
820
872
|
|
|
@@ -849,7 +901,7 @@ State your recommendation clearly:
|
|
|
849
901
|
- Trade-offs: what you'd lose with the alternative
|
|
850
902
|
- If "both": describe which concerns go to Express vs Apollo Gateway vs subgraphs
|
|
851
903
|
|
|
852
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
904
|
+
Respond with structured analysis. Do NOT return JSON.`,lo=h({name:"framework-selector",description:"Analyzes project requirements and recommends Express, Apollo, or both. Use to determine the backend framework before designing.",systemPrompt:vl,tools:{},maxIterations:2});var Al=`${Ur}
|
|
853
905
|
|
|
854
906
|
You are the backend architecture orchestrator. When the user provides requirements:
|
|
855
907
|
|
|
@@ -863,7 +915,7 @@ After generating the design, note the "framework" field in the result:
|
|
|
863
915
|
- If "apollo": the downstream apollo-builder should be used to scaffold the project.
|
|
864
916
|
- If "both": both builders should be invoked sequentially.
|
|
865
917
|
|
|
866
|
-
Respond with the final backend design as JSON.`;async function
|
|
918
|
+
Respond with the final backend design as JSON.`;async function tt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=Br(s),l=L([io,lo],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:Al,input:t,maxIterations:r,onStep:n,logger:a})}var Zs=z.object({name:z.string(),type:z.string(),required:z.coerce.boolean(),validation:z.string()}),ea=z.object({path:z.string(),name:z.string(),access:z.string().transform(e=>e.toLowerCase().trim()).pipe(z.enum(["public","protected"])),purpose:z.string(),formFields:z.array(Zs).default([]),actions:z.array(z.string()).default([]),emptyState:z.string().default(""),errorState:z.string().default(""),redirectOnSuccess:z.string().default(""),keyUiElements:z.array(z.string()).default([])}),ta=z.object({name:z.string(),type:z.string().transform(e=>e.toLowerCase().trim()).pipe(z.enum(["layout","shared","form","display","navigation"])),purpose:z.string(),props:z.array(z.string()).default([]),usedIn:z.array(z.string()).default([])}),ot=z.object({pages:z.array(ea).default([]),components:z.array(ta).default([]),stateManagement:z.string().default(""),routingNotes:z.string().default("")});var Jr=`You are a senior frontend architect specializing in page design, routing, and component architecture.
|
|
867
919
|
|
|
868
920
|
You design enterprise-quality frontend architectures targeting a Vite + React 19 + TypeScript stack with:
|
|
869
921
|
- **UI Library**: ShadCN UI (Radix-based components in src/components/ui/)
|
|
@@ -879,7 +931,7 @@ Architecture outputs:
|
|
|
879
931
|
- Component taxonomy: layout (sidebar, navbar), shared (data tables, dialogs), form (inputs, selects), display (cards, badges), navigation (breadcrumbs, tabs)
|
|
880
932
|
- State management strategy (per-page vs global, Apollo cache vs local state)
|
|
881
933
|
|
|
882
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
934
|
+
Output only valid JSON unless instructed otherwise.`;var oa=`## Requirements:
|
|
883
935
|
{requirement}
|
|
884
936
|
|
|
885
937
|
Design the frontend architecture. Include:
|
|
@@ -895,7 +947,7 @@ Return ONLY valid JSON:
|
|
|
895
947
|
"components": [{ "name": "Navbar", "type": "navigation", "purpose": "...", "props": ["user"], "usedIn": ["/dashboard", "/profile"] }],
|
|
896
948
|
"stateManagement": "...",
|
|
897
949
|
"routingNotes": "..."
|
|
898
|
-
}`;function
|
|
950
|
+
}`;function zr(e){return oa.replace("{requirement}",e)}var po=j("validate_frontend",ot,"Validates a frontend design JSON string against the FrontendDesign schema. Returns valid: true or valid: false with errors.","design");function co(e){return y({name:"design_frontend",description:"Generate a complete frontend architecture design from project requirements. Returns pages, components, state management, and routing as JSON.",input:z.object({requirement:z.string().describe("Project context, API surface, and frontend requirements")}),handler:async({requirement:t})=>{let o=zr(t),r=[{role:"system",content:"You are a frontend architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,ot)}})}function $r(e){return {validate_frontend:po,design_frontend:co(e)}}var El=h({name:"react-builder",description:"Generates a Vite + React SPA configuration from a frontend design and GraphQL schema. Use when the framework-selector recommends react-vite.",systemPrompt:"You are a React/Vite frontend builder. Generate a complete frontend config JSON from the requirements.",tools:{},maxIterations:5}),Ml=h({name:"nextjs-builder",description:"Generates a Next.js App Router configuration from a frontend design. Use when the framework-selector recommends nextjs.",systemPrompt:"You are a Next.js App Router builder. Generate a complete Next.js config JSON from the requirements.",tools:{},maxIterations:5}),Ol=`${Jr}
|
|
899
951
|
|
|
900
952
|
You are the frontend architecture routing orchestrator. When the user asks for a frontend design:
|
|
901
953
|
|
|
@@ -908,7 +960,7 @@ You are the frontend architecture routing orchestrator. When the user asks for a
|
|
|
908
960
|
- If "react-vite": use subagent_react-builder with the design to generate a Vite + React SPA config.
|
|
909
961
|
- If "nextjs": use subagent_nextjs-builder with the design to generate a Next.js App Router config.
|
|
910
962
|
|
|
911
|
-
Respond with the final frontend design as JSON, including the builder output.`;async function
|
|
963
|
+
Respond with the final frontend design as JSON, including the builder output.`;async function rt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=$r(s),l=L([Me,Et,Ko,El,Ml],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:Ol,input:t,maxIterations:r,onStep:n,logger:a})}var Cl=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),na=z.object({name:z.string(),httpMethod:Cl,path:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([]),validation:z.string().default(""),description:z.string().default("")}),sa=z.object({name:z.string(),resource:z.string(),basePath:z.string(),methods:z.array(na).default([])}),aa=z.object({name:z.string(),type:z.string(),required:z.coerce.boolean().default(false),unique:z.coerce.boolean().default(false),ref:z.string().optional(),default:z.string().optional()}),ia=z.object({name:z.string(),collection:z.string(),fields:z.array(aa).default([]),timestamps:z.coerce.boolean().default(true),indexes:z.array(z.string()).default([])}),la=z.object({name:z.string(),type:z.string().transform(e=>{let t=e.toLowerCase().replace(/[\s_-]+/g,"");return ["auth","authentication","jwt","token"].includes(t)?"auth":["validation","validate","validator","input"].includes(t)?"validation":["errorhandler","error","errorhandling","errors"].includes(t)?"errorHandler":["cors","crossorigin"].includes(t)?"cors":["ratelimit","ratelimiter","ratelimiting","throttle"].includes(t)?"rateLimit":["logging","logger","log","morgan"].includes(t)?"logging":"custom"}).pipe(z.enum(["auth","validation","errorHandler","cors","rateLimit","logging","custom"])),config:z.record(z.string(),z.unknown()).default({})}),nt=z.object({appName:z.string().default("app"),port:z.number().default(3e3),database:z.string().default("mongodb"),routers:z.array(sa).default([]),models:z.array(ia).default([]),middleware:z.array(la).default([]),envVars:z.array(z.string()).default([])});var Yr=`You are an expert Express.js backend architect.
|
|
912
964
|
|
|
913
965
|
You generate production-ready Express application configurations from data models and API designs:
|
|
914
966
|
- Co-located router pattern: each feature lives in src/routers/{name}/ with {name}.controller.ts, {name}.router.ts, and {name}.spec.ts
|
|
@@ -919,7 +971,7 @@ You generate production-ready Express application configurations from data model
|
|
|
919
971
|
- Jest tests per router using supertest
|
|
920
972
|
- Environment variable inventory
|
|
921
973
|
|
|
922
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
974
|
+
Output only valid JSON unless instructed otherwise.`;var pa=`## Requirements:
|
|
923
975
|
{requirement}
|
|
924
976
|
|
|
925
977
|
Generate an Express.js application configuration. Include:
|
|
@@ -959,7 +1011,7 @@ Return ONLY valid JSON:
|
|
|
959
1011
|
}],
|
|
960
1012
|
"middleware": [{ "name": "authMiddleware", "type": "auth", "config": {} }],
|
|
961
1013
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "NODE_ENV"]
|
|
962
|
-
}`;function
|
|
1014
|
+
}`;function Hr(e){return pa.replace("{requirement}",e)}var uo=j("validate_express",nt,"Validates an Express config JSON string against the ExpressConfig schema. Returns valid: true or valid: false with errors.","config");function mo(e){return y({name:"generate_express",description:"Generate a complete Express.js application configuration from data model and API design. Returns routers, models, middleware, and env vars as JSON.",input:z.object({requirement:z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:t})=>{let o=Hr(t),r=[{role:"system",content:"You are an Express.js architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,nt)}})}function ua(e,t){return ie.compile(e,{noEscape:true})(t)}function da(e,t=e){let o=[];if(!oe.existsSync(e))return o;let r=oe.readdirSync(e,{withFileTypes:true});for(let n of r){let a=de.join(e,n.name);n.isDirectory()?o.push(...da(a,t)):n.name.endsWith(".hbs")&&o.push(de.relative(t,a));}return o}function Nl(e){return e.replace(/\.hbs$/,"")}function kl(e,t){for(let o of t)if(new RegExp("^"+o.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/<<GLOBSTAR>>/g,".*")+"$").test(e))return true;return false}async function xe(e){let{templateDir:t,outputDir:o,context:r,skipPatterns:n=[]}=e,a=da(t),s=[],i=[];for(let l of a){if(kl(l,n))continue;let p=Nl(l),c=de.join(t,l),u=de.join(o,p);try{let d=oe.readFileSync(c,"utf-8"),g=ua(d,r);oe.mkdirSync(de.dirname(u),{recursive:!0}),oe.writeFileSync(u,g,"utf-8"),s.push(p);}catch(d){i.push({file:l,message:d instanceof Error?d.message:String(d)});}}return {fileCount:s.length,files:s,errors:i}}function ma(){ie.registerHelper("eq",(e,t)=>e===t),ie.registerHelper("neq",(e,t)=>e!==t),ie.registerHelper("json",e=>JSON.stringify(e,null,2)),ie.registerHelper("uppercase",e=>typeof e=="string"?e.toUpperCase():""),ie.registerHelper("lowercase",e=>typeof e=="string"?e.toLowerCase():""),ie.registerHelper("capitalize",e=>typeof e=="string"?e.charAt(0).toUpperCase()+e.slice(1):""),ie.registerHelper("camelCase",e=>typeof e!="string"?"":e.replace(/[-_\s]+(.)?/g,(t,o)=>o?o.toUpperCase():"").replace(/^(.)/,t=>t.toLowerCase())),ie.registerHelper("pascalCase",e=>typeof e!="string"?"":e.replace(/[-_\s]+(.)?/g,(t,o)=>o?o.toUpperCase():"").replace(/^(.)/,t=>t.toUpperCase()));}ma();function Dl(e){return {appName:e.appName,port:e.port,database:e.database,routers:e.routers,models:e.models,middleware:e.middleware,envVars:e.envVars,modules:e.routers.map(t=>({name:t.resource,pascalName:t.name.charAt(0).toUpperCase()+t.name.slice(1),camelName:t.resource,methods:t.methods}))}}y({name:"scaffold_express",description:"Scaffold an Express.js project from a validated config. Compiles Handlebars templates and writes the project to the output directory.",input:z.object({config:z.string().describe("JSON string of the validated Express config"),outputDir:z.string().describe("Absolute path to the output directory")}),handler:async({config:e,outputDir:t})=>{let o=Ge(e,"express config"),r=de.resolve(process.cwd(),".ref/templates/express"),n=Dl(o);return xe({templateDir:r,outputDir:t,context:n})}});function Vr(e,t){let o={validate_express:uo,generate_express:mo(e)};return o}var _l=`You are an Express.js route specialist. Given an API design, you generate route definitions using a co-located router pattern.
|
|
963
1015
|
|
|
964
1016
|
## Co-located Router Pattern
|
|
965
1017
|
Each feature lives in src/routers/{name}/ with three files:
|
|
@@ -997,7 +1049,7 @@ Every app includes a /health router in src/routers/health/:
|
|
|
997
1049
|
- Param validation (e.g. valid ObjectId)
|
|
998
1050
|
- Query param parsing and defaults
|
|
999
1051
|
|
|
1000
|
-
Respond with structured route definitions. Do NOT return JSON.`,
|
|
1052
|
+
Respond with structured route definitions. Do NOT return JSON.`,fo=h({name:"route-generator",description:"Generates Express route definitions from API design using the co-located router pattern ({name}.router.ts, {name}.controller.ts, {name}.spec.ts). Use before generating the Express config.",systemPrompt:_l,tools:{},maxIterations:2});var Il=`You are an Express.js middleware specialist. You design the complete middleware stack.
|
|
1001
1053
|
|
|
1002
1054
|
## Core Middleware
|
|
1003
1055
|
1. **CORS**: Configure allowed origins, methods, headers, credentials
|
|
@@ -1023,7 +1075,7 @@ Respond with structured route definitions. Do NOT return JSON.`,zt=f({name:"rout
|
|
|
1023
1075
|
1. **Global**: Limit requests per IP per time window
|
|
1024
1076
|
2. **Auth routes**: Stricter limits on login/signup
|
|
1025
1077
|
|
|
1026
|
-
Respond with structured middleware analysis. Do NOT return JSON
|
|
1078
|
+
Respond with structured middleware analysis. Do NOT return JSON.`,ho=h({name:"middleware-configurator",description:"Designs the Express middleware stack including auth, validation, error handling, CORS, and rate limiting. Use before generating the Express config.",systemPrompt:Il,tools:{},maxIterations:2});function ql(e){return `${Yr}
|
|
1027
1079
|
|
|
1028
1080
|
You are the Express builder orchestrator. When the user provides requirements:
|
|
1029
1081
|
|
|
@@ -1032,7 +1084,7 @@ You are the Express builder orchestrator. When the user provides requirements:
|
|
|
1032
1084
|
3. **Generate config**: Use generate_express to produce the complete Express configuration as JSON.
|
|
1033
1085
|
4. **Validate**: Use validate_express to check the config JSON before returning.${""}
|
|
1034
1086
|
|
|
1035
|
-
Respond with the final Express config as JSON.`}async function
|
|
1087
|
+
Respond with the final Express config as JSON.`}async function Wr(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,i=O(o??{provider:"openai",model:"gpt-4o-mini"}),l=Vr(i),p=L([fo,ho],{parentModel:i}),c={...l,...p};return _({model:i,tools:c,systemPrompt:ql(),input:t,maxIterations:r,onStep:n,logger:a})}var fa=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),Kr=z.object({name:z.string(),type:z.string(),nullable:z.coerce.boolean().default(false),isList:z.coerce.boolean().default(false),description:z.string().default("")}),Xr=z.object({name:z.string(),kind:fa(["type","input","enum","interface","union"]),fields:z.array(Kr).default([]),values:z.array(z.string()).default([]),description:z.string().default(""),isEntity:z.coerce.boolean().default(false),keyFields:z.array(z.string()).default([])}),ha=z.object({name:z.string(),type:fa(["query","mutation","subscription"]),args:z.array(Kr).default([]),returnType:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([]),description:z.string().default("")}),ya=z.object({name:z.string(),entity:z.string(),types:z.array(Xr).default([]),operations:z.array(ha).default([]),datasource:z.string().default(""),loader:z.string().default("")}),st=z.object({appName:z.string().default("app"),port:z.number().default(4e3),database:z.string().default("mongodb"),modules:z.array(ya).default([]),sharedTypes:z.array(Xr).default([]),authDirective:z.coerce.boolean().default(true),cacheDirective:z.coerce.boolean().default(false),envVars:z.array(z.string()).default([])});var Zr=`You are an expert Apollo GraphQL subgraph architect using Apollo Federation v2.
|
|
1036
1088
|
|
|
1037
1089
|
You generate production-ready Apollo subgraph configurations from data models and API designs:
|
|
1038
1090
|
- 4-file module pattern per entity: {module}.graphql, {module}.resolver.ts, {module}.datasource.ts, {module}.loader.ts
|
|
@@ -1049,7 +1101,7 @@ You generate production-ready Apollo subgraph configurations from data models an
|
|
|
1049
1101
|
- GraphQL CodeGen for TypeScript types (generates base-types.ts)
|
|
1050
1102
|
- Module-based organization (one module per entity/domain)
|
|
1051
1103
|
|
|
1052
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1104
|
+
Output only valid JSON unless instructed otherwise.`;var Sa=`## Requirements:
|
|
1053
1105
|
{requirement}
|
|
1054
1106
|
|
|
1055
1107
|
Generate an Apollo GraphQL subgraph configuration (Federation v2). Include:
|
|
@@ -1080,7 +1132,7 @@ Return ONLY valid JSON:
|
|
|
1080
1132
|
"authDirective": true,
|
|
1081
1133
|
"cacheDirective": false,
|
|
1082
1134
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "REDIS_URL"]
|
|
1083
|
-
}`;function
|
|
1135
|
+
}`;function en(e){return Sa.replace("{requirement}",e)}var yo=j("validate_subgraph",st,"Validates a subgraph config JSON string against the SubgraphConfig schema. Returns valid: true or valid: false with errors.","config");function So(e){return y({name:"generate_subgraph",description:"Generate a complete Apollo GraphQL subgraph configuration from data model and API design. Returns modules, types, operations, and datasources as JSON.",input:z.object({requirement:z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:t})=>{let o=en(t),r=[{role:"system",content:"You are an Apollo GraphQL architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,st)}})}function Ll(e){return {appName:e.appName,port:e.port,database:e.database,modules:e.modules.map(t=>({name:t.name,pascalName:t.name.charAt(0).toUpperCase()+t.name.slice(1),camelName:t.name.charAt(0).toLowerCase()+t.name.slice(1),entity:t.entity,datasource:t.datasource,types:t.types,operations:t.operations})),authDirective:e.authDirective,envVars:e.envVars,sharedTypes:e.sharedTypes}}y({name:"scaffold_subgraph",description:"Scaffold an Apollo GraphQL subgraph project from a validated config. Compiles Handlebars templates and writes the project to the output directory.",input:z.object({config:z.string().describe("JSON string of the validated subgraph config"),outputDir:z.string().describe("Absolute path to the output directory")}),handler:async({config:e,outputDir:t})=>{let o=Ge(e,"subgraph config"),r=de.resolve(process.cwd(),".ref/templates/subgraph"),n=Ll(o);return xe({templateDir:r,outputDir:t,context:n})}});function on(e,t){let o={validate_subgraph:yo,generate_subgraph:So(e)};return o}var Fl=`You are a GraphQL schema specialist for Apollo Federation v2 subgraphs. Given a data model, you generate GraphQL type definitions using buildSubgraphSchema.
|
|
1084
1136
|
|
|
1085
1137
|
## Type Generation
|
|
1086
1138
|
For each entity in the data model:
|
|
@@ -1111,7 +1163,7 @@ For each entity in the data model:
|
|
|
1111
1163
|
- Inputs: PascalCase + Input suffix (CreateUserInput, UpdateUserInput)
|
|
1112
1164
|
- Enums: SCREAMING_SNAKE_CASE values (ADMIN, ACTIVE)
|
|
1113
1165
|
|
|
1114
|
-
Respond with the full GraphQL SDL. Do NOT return JSON.`,
|
|
1166
|
+
Respond with the full GraphQL SDL. Do NOT return JSON.`,xo=h({name:"schema-generator",description:"Generates GraphQL type definitions, input types, and enums from a data model. Use before generating the subgraph config.",systemPrompt:Fl,tools:{},maxIterations:2});var Ul=`You are a GraphQL resolver architect for Apollo Federation v2 subgraphs. Given types and operations, you plan resolver implementations.
|
|
1115
1167
|
|
|
1116
1168
|
## 4-File Module Pattern
|
|
1117
1169
|
Each module has four files:
|
|
@@ -1158,7 +1210,7 @@ Each module has a loader file that creates DataLoader instances:
|
|
|
1158
1210
|
- Verify role permissions per operation
|
|
1159
1211
|
- Resource ownership checks for user-specific data
|
|
1160
1212
|
|
|
1161
|
-
Respond with structured analysis per module. Do NOT return JSON.`,
|
|
1213
|
+
Respond with structured analysis per module. Do NOT return JSON.`,To=h({name:"resolver-planner",description:"Plans resolver implementations, datasource methods, and auth integration per GraphQL module. Use after schema generation.",systemPrompt:Ul,tools:{},maxIterations:2});function Bl(e){return `${Zr}
|
|
1162
1214
|
|
|
1163
1215
|
You are the Apollo subgraph builder orchestrator. When the user provides requirements:
|
|
1164
1216
|
|
|
@@ -1167,7 +1219,7 @@ You are the Apollo subgraph builder orchestrator. When the user provides require
|
|
|
1167
1219
|
3. **Generate config**: Use generate_subgraph to produce the complete subgraph configuration as JSON.
|
|
1168
1220
|
4. **Validate**: Use validate_subgraph to check the config JSON before returning.${""}
|
|
1169
1221
|
|
|
1170
|
-
Respond with the final subgraph config as JSON.`}async function
|
|
1222
|
+
Respond with the final subgraph config as JSON.`}async function rn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,i=O(o??{provider:"openai",model:"gpt-4o-mini"}),l=on(i),p=L([xo,To],{parentModel:i}),c={...l,...p};return _({model:i,tools:c,systemPrompt:Bl(),input:t,maxIterations:r,onStep:n,logger:a})}var nn=z.object({brandName:z.string().describe("The brand's display name"),primaryColor:z.string().describe("The brand's primary color code (e.g., #FFFFFF)"),secondaryColor:z.string().describe("The brand's secondary color code (e.g., #000000)"),logo:z.url().describe("URL pointing to the brand's logo")});var sn=z.object({name:z.string().describe("Application name"),description:z.string().describe("Brief description of the application"),author:z.string().describe("Author or owner of the application").default("sijeeshmiziha (HubSpire)"),branding:nn.describe("Branding information for the application"),apiEndpoint:z.url().describe("URL endpoint for the app's API calls")});var Ta=z.object({minLength:z.number().optional().describe("Minimum length requirement"),zodString:z.string().describe("Raw Zod string validation (e.g. regex)")}),Pa=z.object({hookName:z.string().optional().describe("Name of the hook for dynamic field options"),queryString:z.string().optional().describe("Optional query string for fetching field options"),labelKey:z.string().optional().describe("Key used as label when displaying options"),valueKey:z.string().optional().describe("Key used as value for a field when selecting options"),values:z.array(z.string()).optional().describe("Static list of possible field values")}),Po=z.object({name:z.string().describe("The field's key or identifier"),type:z.enum(["text","email","password","number","multiSelect","textarea","hidden","select","date","image"]).describe('Type of input field. If it has options, it should not be "hidden". If the field is required, it should not be hidden unless it serves as the current user.'),required:z.boolean().optional().describe("Whether this field must be filled"),validation:Ta.optional().describe("Optional field validation requirements"),defaultValue:z.union([z.string(),z.number(),z.boolean()]).optional().describe("Default value can be string, number, or boolean"),options:Pa.optional().describe("Additional dynamic or static options for this field")}),an=z.object({field:z.string().describe("Key or name of the data field in the table"),label:z.string().describe("User-friendly label to show on the table header")});var pn=z.object({type:z.string().describe("Indicates the response type (e.g., 'object')"),properties:z.record(z.string(),z.object({type:z.string().describe("Property type as returned by the API")})).describe("Key-value record describing each field in the response")}).optional().describe("Describes the expected structure of an API response"),Ra=z.object({type:z.enum(["list","create","update","delete","getById"]).describe("Type of API call for CRUD operations"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useGetAllUserQuery, useCreateUserMutation)"),queryString:z.string().describe("Actual GraphQL query string"),responseType:pn.describe("Optional schema describing shape of the API response")}),wa=z.object({type:z.enum(["login","currentUser","forgotPassword","resetPassword"]).describe("Type of API call"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useLoginMutation)"),queryString:z.string().describe("Actual GraphQL query string"),responseType:pn.describe("Optional schema describing shape of the API response")}),ln=z.object({title:z.string().describe("Title displayed on the drawer"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useCreateUserMutation, useDeleteOneUserMutation)"),fields:z.array(Po).describe("List of fields displayed within the drawer")}),va=z.object({name:z.enum(["LoginPage","ForgotPasswordPage","ResetPasswordPage"]).describe("Internal name of the auth page"),type:z.enum(["EmailPassword","ForgotPassword","ResetPassword"]).describe("Type of authentication page"),route:z.string().describe("URL route for this page (e.g., '/login')"),isPrivate:z.boolean().describe("Whether this page requires an authenticated session"),api:z.array(wa).describe("List of API calls involved in this page"),fields:z.array(Po).optional().describe("Optional form fields needed on this auth page")}),Aa=z.object({type:z.literal("Listing").describe("Indicates that this page is a listing-type page"),name:z.string().describe("Internal name of the listing page"),route:z.string().describe("URL route for this listing page"),isPrivate:z.boolean().describe("Whether this page is private (requires auth)"),api:z.array(Ra).describe("List of API calls that power this listing page"),columns:z.array(an).describe("Table columns displayed on the listing page"),actions:z.array(z.string()).describe("List of possible actions on each row (e.g., create, edit, delete, view)"),drawerCreate:ln.describe("Drawer configuration for creating new records"),drawerUpdate:ln.describe("Drawer configuration for editing existing records")}),cn=z.discriminatedUnion("type",[va,Aa]);var Ea=z.object({name:z.string().describe("Name of the module"),pages:z.array(cn).describe("Pages included within this module")}),pt=z.object({app:sn.describe("Overall application configuration"),modules:z.array(Ea).describe("List of modules that make up the application. Ensure all modules use every available CRUD GraphQL query and mutation from the schema.")});z.object({email:z.email().describe("User's email address, must be valid format"),password:z.string().min(8).describe("User's password, minimum length of 8")});var Ma=z.object({_id:z.string().describe("Unique identifier of the specialization, type: string"),title:z.string().describe("Display title for the specialization, type: string")});z.object({_id:z.string().describe("Unique ID of the user, type: string"),firstName:z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:z.email().describe("Email address in valid format, type: string"),phoneNumber:z.string().min(10).describe("User's phone number, at least 10 digits, type: string"),profileImage:z.string().optional().describe("Optional URL to user's profile image, type: string, optional"),role:z.enum(["ADMIN","TRAINER","CLIENT"]).describe("User's role in the system (ADMIN, TRAINER, CLIENT)"),rate:z.number().min(1).optional().describe("User's rate (e.g., hourly, etc.), type: number, optional"),specializations:z.array(Ma).optional().describe("Array of specialization objects, optional"),languages:z.array(z.string()).optional().describe("Array of languages the user speaks, type: string[], optional"),about:z.string().min(20).max(500).optional().describe("Brief bio or description (20-500 chars), type: string, optional"),gender:z.string().optional().describe("User's gender, type: string, optional"),timezone:z.string().optional().describe("User's timezone, type: string, optional"),averageRating:z.number().optional().describe("Average rating for this user, type: number, optional")});z.object({firstName:z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:z.email().describe("Valid email for the new user, type: string"),phoneNumber:z.string().min(10).describe("Phone number (at least 10 digits), type: string"),password:z.string().min(8).describe("Password with min length 8, type: string"),role:z.enum(["ADMIN","TRAINER","CLIENT"]).describe("Role of the new user (ADMIN, TRAINER, CLIENT)"),rate:z.number().min(1).optional().describe("Rate for the new user, type: number, optional"),specializationIds:z.array(z.string()).min(1).optional().describe("Array of specialization IDs, optional"),languages:z.array(z.string()).min(1).optional().describe("List of languages user speaks, optional"),about:z.string().min(20).max(500).optional().describe("User's about/bio field, 20-500 chars, optional")});z.object({_id:z.string().describe("ID of the user to be updated, type: string"),firstName:z.string().min(2).max(30).optional().describe("Updated first name, type: string, optional"),lastName:z.string().min(2).max(30).optional().describe("Updated last name, type: string, optional"),email:z.email().optional().describe("Updated email, type: string, optional"),phoneNumber:z.string().min(10).optional().describe("Updated phone number, at least 10 digits, optional"),rate:z.number().min(1).optional().describe("Updated rate, type: number, optional"),specializationIds:z.array(z.string()).min(1).optional().describe("Updated array of specialization IDs, optional"),languages:z.array(z.string()).min(1).optional().describe("Updated list of languages, optional"),about:z.string().min(20).max(500).optional().describe("Updated about/bio (20-500 chars), optional")});z.object({email:z.email().describe("Email to initiate the password reset process, type: string")});z.object({type:z.enum(["EMAIL","SMS"]).describe("How the reset code was sent (EMAIL or SMS)"),resetTicket:z.string().describe("Token/ticket to validate the reset request, type: string"),newPassword:z.string().min(8).describe("The new password, min length 8, type: string")});var ct=`You are an expert GraphQL-to-frontend configuration converter. Transform the provided GraphQL schema into a structured JSON configuration for a React + Vite frontend application.
|
|
1171
1223
|
|
|
1172
1224
|
## Target Tech Stack
|
|
1173
1225
|
The generated configuration will be consumed by a Vite + React 19 + TypeScript template with:
|
|
@@ -1187,7 +1239,7 @@ Strict guidelines:
|
|
|
1187
1239
|
- Relationships \u2192 multiSelect with query-based options where appropriate.
|
|
1188
1240
|
- Add isPrivate: true for authenticated operations (route guarded by React Router).
|
|
1189
1241
|
- Form fields should map to React Hook Form + Zod validation schemas.
|
|
1190
|
-
- Maintain camelCase. Ensure valid JSON syntax.`;var
|
|
1242
|
+
- Maintain camelCase. Ensure valid JSON syntax.`;var Ro=`
|
|
1191
1243
|
Act as an expert GraphQL-to-frontend configuration converter. Transform the provided schema into a structured JSON configuration for rapid app development.
|
|
1192
1244
|
|
|
1193
1245
|
**Conversion Process**
|
|
@@ -1219,7 +1271,7 @@ Act as an expert GraphQL-to-frontend configuration converter. Transform the prov
|
|
|
1219
1271
|
6. Output:
|
|
1220
1272
|
- Generate complete CRUD pages with table column mappings, validated Create/Update forms, API hooks
|
|
1221
1273
|
- Include Zod validation strings, maintain camelCase, valid JSON only
|
|
1222
|
-
`.trim();function
|
|
1274
|
+
`.trim();function un(){return Ro}var Oa=`
|
|
1223
1275
|
type Query {
|
|
1224
1276
|
getCurrentUser: User
|
|
1225
1277
|
getAllUser(limit: Int, offset: Int): [User]!
|
|
@@ -1238,7 +1290,7 @@ type User {
|
|
|
1238
1290
|
enum Role { ADMIN TRAINER CLIENT }
|
|
1239
1291
|
input LoginInput { email: String! password: String! }
|
|
1240
1292
|
input CreateUserInput { firstName: String! lastName: String! email: String! role: Role! }
|
|
1241
|
-
`.trim(),
|
|
1293
|
+
`.trim(),Ca=`{
|
|
1242
1294
|
"app": {
|
|
1243
1295
|
"name": "my-app",
|
|
1244
1296
|
"description": "App description",
|
|
@@ -1286,19 +1338,19 @@ input CreateUserInput { firstName: String! lastName: String! email: String! role
|
|
|
1286
1338
|
]
|
|
1287
1339
|
}
|
|
1288
1340
|
]
|
|
1289
|
-
}`;function
|
|
1341
|
+
}`;function dn(){return `
|
|
1290
1342
|
**Reference Conversion Example**
|
|
1291
1343
|
|
|
1292
1344
|
EXAMPLE GRAPHQL INPUT:
|
|
1293
1345
|
\`\`\`graphql
|
|
1294
|
-
${
|
|
1346
|
+
${Oa}
|
|
1295
1347
|
\`\`\`
|
|
1296
1348
|
|
|
1297
1349
|
EXPECTED JSON OUTPUT:
|
|
1298
1350
|
\`\`\`json
|
|
1299
|
-
${
|
|
1351
|
+
${Ca}
|
|
1300
1352
|
\`\`\`
|
|
1301
|
-
`.trim()}var
|
|
1353
|
+
`.trim()}var Be=j("validate_frontend_config",pt,"Validates a frontend configuration JSON string against the ApplicationSchema. Returns valid: true or valid: false with errors array.","config");function Vl(e,t){let o=un(),r=dn(),n=t?`
|
|
1302
1354
|
**Project context:**
|
|
1303
1355
|
- name: ${t.projectName??"project"}
|
|
1304
1356
|
- description: ${t.projectDescription??""}
|
|
@@ -1314,14 +1366,14 @@ ${n}
|
|
|
1314
1366
|
${e}
|
|
1315
1367
|
\`\`\`
|
|
1316
1368
|
|
|
1317
|
-
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function
|
|
1369
|
+
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function wo(e){return y({name:"generate_frontend",description:"Convert a GraphQL schema into a frontend configuration JSON (app, modules, pages, fields, API hooks). Optionally provide app info (project name, description, apiEndpoint). Returns the full application config as JSON.",input:z.object({graphqlSchema:z.string().describe("The GraphQL schema string to convert"),appInfo:z.object({projectName:z.string().optional(),projectDescription:z.string().optional(),modules:z.string().optional(),apiEndpoint:z.string().optional()}).optional().describe("Optional project/app context")}),handler:async({graphqlSchema:t,appInfo:o})=>{let r=Vl(t,o),n=[{role:"system",content:ct},{role:"user",content:r}],a=await e.invoke(n,{temperature:.2,maxOutputTokens:16384});return C(a.text,pt)}})}function vo(e){return y({name:"generate_feature_breakdown",description:"Analyze a GraphQL schema and produce a feature/component breakdown: list of modules, CRUD operations, and suggested pages. Returns a structured summary (not the full frontend JSON).",input:z.object({graphqlSchema:z.string().describe("The GraphQL schema string to analyze")}),handler:async({graphqlSchema:t})=>{let o=`${Ro}
|
|
1318
1370
|
|
|
1319
1371
|
**Schema to analyze:**
|
|
1320
1372
|
\`\`\`graphql
|
|
1321
1373
|
${t}
|
|
1322
1374
|
\`\`\`
|
|
1323
1375
|
|
|
1324
|
-
Respond with a structured breakdown only (no full JSON config): list modules, list Query/Mutation operations, and suggested pages for each module. Use clear headings and bullet points.`,r=[{role:"system",content:"You are a GraphQL schema analyst. Return a clear, structured text breakdown."},{role:"user",content:o}];return {summary:(await e.invoke(r,{temperature:.3,maxOutputTokens:4096})).text,modules:[],operations:[],suggestedPages:[]}}})}function
|
|
1376
|
+
Respond with a structured breakdown only (no full JSON config): list modules, list Query/Mutation operations, and suggested pages for each module. Use clear headings and bullet points.`,r=[{role:"system",content:"You are a GraphQL schema analyst. Return a clear, structured text breakdown."},{role:"user",content:o}];return {summary:(await e.invoke(r,{temperature:.3,maxOutputTokens:4096})).text,modules:[],operations:[],suggestedPages:[]}}})}function Wl(e){return {appName:e.app.name,description:e.app.description,apiEndpoint:e.app.apiEndpoint,branding:{brandName:e.app.branding.brandName,primaryColor:e.app.branding.primaryColor,secondaryColor:e.app.branding.secondaryColor,logo:e.app.branding.logo},modules:e.modules.map(t=>({name:t.name,pascalName:t.name.charAt(0).toUpperCase()+t.name.slice(1),camelName:t.name.charAt(0).toLowerCase()+t.name.slice(1)})),author:e.app.author,pages:e.modules.flatMap(t=>t.pages)}}y({name:"scaffold_vite",description:"Scaffold a Vite + React project from a validated ApplicationSchema config. Compiles Handlebars templates from .ref/templates/vite/ and writes the project to the output directory.",input:z.object({config:z.string().describe("JSON string of the validated ApplicationSchema config"),outputDir:z.string().describe("Absolute path to the output directory")}),handler:async({config:e,outputDir:t})=>{let o=Ge(e,"application schema config"),r=de.resolve(process.cwd(),".ref/templates/vite"),n=Wl(o);return xe({templateDir:r,outputDir:t,context:n})}});function fn(e,t){let o={validate_frontend_config:Be,generate_frontend:wo(e),generate_feature_breakdown:vo(e)};return o}var Kl=`You are an expert at analyzing GraphQL schemas. Your job is to:
|
|
1325
1377
|
|
|
1326
1378
|
1. **Types**: List all object types, enums, scalars, and input types.
|
|
1327
1379
|
2. **Queries**: List every Query field with arguments and return type.
|
|
@@ -1329,13 +1381,13 @@ Respond with a structured breakdown only (no full JSON config): list modules, li
|
|
|
1329
1381
|
4. **Relationships**: Identify types that reference other types (e.g. User has role: Role, or Order has customer: User).
|
|
1330
1382
|
5. **Auth/directives**: Note any @auth, @directive usage that affects access control.
|
|
1331
1383
|
|
|
1332
|
-
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,
|
|
1384
|
+
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,Ao=h({name:"graphql-analyzer",description:"Analyzes a GraphQL schema to extract types, queries, mutations, and relationships. Use when you need to understand the schema before generating frontend config. Returns structured analysis (no JSON).",systemPrompt:Kl,tools:{},maxIterations:2});var Xl=`You are a frontend configuration validator. Your job is to:
|
|
1333
1385
|
|
|
1334
1386
|
1. Validate the provided frontend config JSON using the validate_frontend_config tool.
|
|
1335
1387
|
2. Compare the config against the GraphQL schema (if provided) and check that all CRUD operations are covered.
|
|
1336
1388
|
3. Report any missing modules, pages, or API hooks.
|
|
1337
1389
|
|
|
1338
|
-
When the user gives you a config (as JSON string) and optionally the GraphQL schema, first call validate_frontend_config to check structure. Then summarize completeness.`;function
|
|
1390
|
+
When the user gives you a config (as JSON string) and optionally the GraphQL schema, first call validate_frontend_config to check structure. Then summarize completeness.`;function Eo(){return h({name:"config-validator",description:"Validates a frontend configuration JSON and checks completeness against the GraphQL schema. Use when you have a draft config and want to validate it. Has access to validate_frontend_config tool.",systemPrompt:Xl,tools:{validate_frontend_config:Be},maxIterations:5})}var Zl=`${ct}
|
|
1339
1391
|
|
|
1340
1392
|
You are the React frontend builder orchestrator. When the user provides a GraphQL schema and asks for a frontend configuration:
|
|
1341
1393
|
|
|
@@ -1345,7 +1397,7 @@ You are the React frontend builder orchestrator. When the user provides a GraphQ
|
|
|
1345
1397
|
4. **Validate directly**: You can use validate_frontend_config to check any config JSON.
|
|
1346
1398
|
5. **Feature breakdown**: Use generate_feature_breakdown to get a module/operation breakdown before generating.
|
|
1347
1399
|
|
|
1348
|
-
Respond with the final frontend config (as JSON) or a clear summary and the config. If the user gives feedback, use generate_frontend again with the same schema and consider their feedback in your instructions.`;async function
|
|
1400
|
+
Respond with the final frontend config (as JSON) or a clear summary and the config. If the user gives feedback, use generate_frontend again with the same schema and consider their feedback in your instructions.`;async function hn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,i=O(o??{provider:"openai",model:"gpt-4o-mini"}),l=fn(i),p=Eo(),c=L([Ao,p],{parentModel:i}),u={...l,...c};return _({model:i,tools:u,systemPrompt:Zl,input:t,maxIterations:r,onStep:n,logger:a})}var Da=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),ep=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),_a=z.object({path:z.string(),name:z.string(),access:Da(["public","protected"]),routeGroup:z.string().default(""),purpose:z.string(),hasForm:z.coerce.boolean().default(false),formFields:z.array(z.string()).default([]),dataFetching:Da(["server","client","hybrid"]).default("server"),actions:z.array(z.string()).default([])}),Ia=z.object({name:z.string(),path:z.string(),routeGroup:z.string().default(""),components:z.array(z.string()).default([]),purpose:z.string()}),ja=z.object({path:z.string(),methods:z.array(ep).default([]),auth:z.coerce.boolean().default(true),description:z.string()}),qa=z.object({name:z.string(),module:z.string(),description:z.string(),revalidates:z.array(z.string()).default([])}),ut=z.object({appName:z.string().default("app"),pages:z.array(_a).default([]),layouts:z.array(Ia).default([]),apiRoutes:z.array(ja).default([]),serverActions:z.array(qa).default([]),middleware:z.array(z.string()).default([]),envVars:z.array(z.string()).default([]),packages:z.array(z.string()).default([])});var yn=`You are an expert Next.js application architect using the App Router.
|
|
1349
1401
|
|
|
1350
1402
|
You generate production-ready Next.js configurations from frontend designs and API designs:
|
|
1351
1403
|
- App Router file structure with route groups, layouts, pages, loading, and error boundaries
|
|
@@ -1356,7 +1408,7 @@ You generate production-ready Next.js configurations from frontend designs and A
|
|
|
1356
1408
|
- Data fetching strategy (server vs client vs hybrid per page)
|
|
1357
1409
|
- Package recommendations (next-auth, prisma, tailwindcss, shadcn/ui)
|
|
1358
1410
|
|
|
1359
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1411
|
+
Output only valid JSON unless instructed otherwise.`;var La=`## Requirements:
|
|
1360
1412
|
{requirement}
|
|
1361
1413
|
|
|
1362
1414
|
Generate a Next.js App Router application configuration. Include:
|
|
@@ -1405,7 +1457,7 @@ Return ONLY valid JSON:
|
|
|
1405
1457
|
"middleware": ["Redirect unauthenticated users to /login"],
|
|
1406
1458
|
"envVars": ["DATABASE_URL", "NEXTAUTH_SECRET"],
|
|
1407
1459
|
"packages": ["next-auth", "prisma", "@prisma/client", "tailwindcss"]
|
|
1408
|
-
}`;function
|
|
1460
|
+
}`;function Sn(e){return La.replace("{requirement}",e)}var Mo=j("validate_nextjs",ut,"Validates a Next.js config JSON string against the NextjsConfig schema. Returns valid: true or valid: false with errors.","config");function Oo(e){return y({name:"generate_nextjs",description:"Generate a complete Next.js App Router configuration from frontend design and requirements. Returns pages, layouts, API routes, server actions, and middleware as JSON.",input:z.object({requirement:z.string().describe("Frontend design, API design, and project requirements")}),handler:async({requirement:t})=>{let o=Sn(t),r=[{role:"system",content:"You are a Next.js architect. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,ut)}})}function bn(e){return {validate_nextjs:Mo,generate_nextjs:Oo(e)}}var tp=`You are a Next.js App Router specialist. Given page specs, you plan the file structure.
|
|
1409
1461
|
|
|
1410
1462
|
## Route Groups
|
|
1411
1463
|
- (auth) for public auth pages: login, signup, forgot-password
|
|
@@ -1431,7 +1483,7 @@ Return ONLY valid JSON:
|
|
|
1431
1483
|
- Parallel routes: @modal, @sidebar
|
|
1432
1484
|
- Intercepting routes: (.)photo, (..)details
|
|
1433
1485
|
|
|
1434
|
-
Respond with the full file tree and route structure. Do NOT return JSON.`,
|
|
1486
|
+
Respond with the full file tree and route structure. Do NOT return JSON.`,Co=h({name:"route-planner",description:"Plans Next.js App Router file structure with route groups, layouts, and page files. Use before generating the Next.js config.",systemPrompt:tp,tools:{},maxIterations:2});var op=`You are a Next.js API specialist. Given an API design, you plan route handlers and server actions.
|
|
1435
1487
|
|
|
1436
1488
|
## API Route Handlers (app/api/)
|
|
1437
1489
|
For external integrations, webhooks, and file uploads:
|
|
@@ -1456,7 +1508,7 @@ For form submissions and data writes:
|
|
|
1456
1508
|
- Server Actions: check session at the start of each action
|
|
1457
1509
|
- Middleware: protect route groups with matcher patterns
|
|
1458
1510
|
|
|
1459
|
-
Respond with structured analysis per module. Do NOT return JSON.`,
|
|
1511
|
+
Respond with structured analysis per module. Do NOT return JSON.`,No=h({name:"api-route-generator",description:"Generates Next.js API route handlers and server actions from API design. Use after route planning.",systemPrompt:op,tools:{},maxIterations:2});var rp=`${yn}
|
|
1460
1512
|
|
|
1461
1513
|
You are the Next.js builder orchestrator. When the user provides requirements:
|
|
1462
1514
|
|
|
@@ -1465,7 +1517,7 @@ You are the Next.js builder orchestrator. When the user provides requirements:
|
|
|
1465
1517
|
3. **Generate config**: Use generate_nextjs to produce the complete Next.js configuration as JSON.
|
|
1466
1518
|
4. **Validate**: Use validate_nextjs to check the config JSON before returning.
|
|
1467
1519
|
|
|
1468
|
-
Respond with the final Next.js config as JSON.`;async function
|
|
1520
|
+
Respond with the final Next.js config as JSON.`;async function xn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=bn(s),l=L([Co,No],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:rp,input:t,maxIterations:r,onStep:n,logger:a})}var Ua=z.object({order:z.number(),action:z.string(),details:z.string()}),Ga=z.object({name:z.string(),description:z.string(),steps:z.array(Ua)}),Ba=z.object({area:z.string(),scenario:z.string(),handling:z.string(),severity:z.string().transform(e=>e.toLowerCase().trim()).pipe(z.enum(["critical","warning","info"]))}),Ja=z.object({flow:z.string(),item:z.string(),expectedResult:z.string()}),dt=z.object({phases:z.array(Ga).default([]),currentState:z.string().default(""),desiredEndState:z.string().default(""),edgeCases:z.array(Ba).default([]),securityNotes:z.array(z.string()).default([]),performanceNotes:z.array(z.string()).default([]),testingChecklist:z.array(Ja).default([])});var Tn=`You are a senior tech lead specializing in implementation strategy and project execution planning.
|
|
1469
1521
|
|
|
1470
1522
|
You create enterprise-quality execution plans with:
|
|
1471
1523
|
- Phased implementation order with concrete, numbered steps per phase
|
|
@@ -1475,7 +1527,7 @@ You create enterprise-quality execution plans with:
|
|
|
1475
1527
|
- Performance considerations (indexing, caching, lazy loading, N+1 prevention)
|
|
1476
1528
|
- Manual testing checklists grouped by feature flow
|
|
1477
1529
|
|
|
1478
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1530
|
+
Output only valid JSON unless instructed otherwise.`;var za=`## Full Plan Context:
|
|
1479
1531
|
{context}
|
|
1480
1532
|
|
|
1481
1533
|
Create a comprehensive execution plan. Include:
|
|
@@ -1497,7 +1549,7 @@ Return ONLY valid JSON:
|
|
|
1497
1549
|
"securityNotes": ["..."],
|
|
1498
1550
|
"performanceNotes": ["..."],
|
|
1499
1551
|
"testingChecklist": [{ "flow": "Auth Flow", "item": "Sign up with valid credentials", "expectedResult": "Account created, redirected to dashboard" }]
|
|
1500
|
-
}`;function
|
|
1552
|
+
}`;function Pn(e){return za.replace("{context}",e)}var ko=j("validate_execution_plan",dt,"Validates an execution plan JSON string against the ExecutionPlan schema. Returns valid: true or valid: false with errors.","plan");function Do(e){return y({name:"create_execution_plan",description:"Generate a comprehensive execution plan with phases, edge cases, and testing checklist from the full plan context.",input:z.object({context:z.string().describe("Full plan context: all sections generated so far")}),handler:async({context:t})=>{let o=Pn(t),r=[{role:"system",content:"You are a tech lead. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:16384});return C(n.text,dt)}})}function Rn(e){return {validate_execution_plan:ko,create_execution_plan:Do(e)}}var np=`${Tn}
|
|
1501
1553
|
|
|
1502
1554
|
You are the execution planning orchestrator. When the user provides plan sections:
|
|
1503
1555
|
|
|
@@ -1506,7 +1558,57 @@ You are the execution planning orchestrator. When the user provides plan section
|
|
|
1506
1558
|
3. **Generate plan**: Use create_execution_plan to produce the complete execution plan with phases, edge cases, and testing checklist.
|
|
1507
1559
|
4. **Validate**: Use validate_execution_plan to check the final plan JSON before returning.
|
|
1508
1560
|
|
|
1509
|
-
Respond with the final execution plan as JSON.`;async function
|
|
1510
|
-
|
|
1511
|
-
|
|
1561
|
+
Respond with the final execution plan as JSON.`;async function mt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=O(o??{provider:"openai",model:"gpt-4o-mini"}),i=Rn(s),l=L([ke,De],{parentModel:s}),p={...i,...l};return _({model:s,tools:p,systemPrompt:np,input:t,maxIterations:r,onStep:n,logger:a})}var wn=y({name:"hello_world",description:"Returns a greeting message for the given name",input:z.object({name:z.string().describe("Name to greet")}),handler:async({name:e})=>({greeting:`Hello, ${e}! Welcome to sweagent.`})});var sp="You are a friendly greeter. Use the hello_world tool to greet users.";async function vn(e){let{input:t,model:o,systemPrompt:r=sp,maxIterations:n=3,onStep:a,logger:s}=e,i=O(o??{provider:"openai",model:"gpt-4o-mini"});return _({model:i,tools:{hello_world:wn},systemPrompt:r,input:t,maxIterations:n,onStep:a,logger:s})}function Pe(e,t){return {input:e,model:t.model,maxIterations:t.maxIterations,onStep:t.onStep,logger:t.logger}}var _o=[{name:"Requirement Gatherer",key:"requirements",heading:"Requirements",run:(e,t)=>He(Pe(e.userInput??"",t)).then(o=>o.output)},{name:"Data Modeler",key:"dataModel",heading:"Data Model",run:(e,t)=>Ve(Pe(`Design a data model based on these requirements:
|
|
1562
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"API Designer",key:"apiDesign",heading:"API Design",run:(e,t)=>Ke(Pe(`Design the API based on this data model and requirements:
|
|
1563
|
+
Data Model:
|
|
1564
|
+
${e.dataModel}
|
|
1565
|
+
|
|
1566
|
+
Requirements:
|
|
1567
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"Auth Designer",key:"authDesign",heading:"Auth Design",run:(e,t)=>Ze(Pe(`Design auth for this project:
|
|
1568
|
+
Requirements:
|
|
1569
|
+
${e.requirements}
|
|
1570
|
+
|
|
1571
|
+
API Design:
|
|
1572
|
+
${e.apiDesign}`,t)).then(o=>o.output)},{name:"Backend Architect",key:"backendDesign",heading:"Backend Architecture",run:(e,t)=>tt(Pe(`Design backend architecture:
|
|
1573
|
+
Data Model:
|
|
1574
|
+
${e.dataModel}
|
|
1575
|
+
|
|
1576
|
+
API Design:
|
|
1577
|
+
${e.apiDesign}
|
|
1578
|
+
|
|
1579
|
+
Auth Design:
|
|
1580
|
+
${e.authDesign}`,t)).then(o=>o.output)},{name:"Frontend Architect",key:"frontendDesign",heading:"Frontend Architecture",run:(e,t)=>rt(Pe(`Design frontend architecture:
|
|
1581
|
+
API Design:
|
|
1582
|
+
${e.apiDesign}
|
|
1583
|
+
|
|
1584
|
+
Requirements:
|
|
1585
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"Execution Planner",key:"executionPlan",heading:"Execution Plan",run:(e,t)=>mt(Pe(`Create an execution plan for this project:
|
|
1586
|
+
Requirements:
|
|
1587
|
+
${e.requirements}
|
|
1588
|
+
|
|
1589
|
+
Data Model:
|
|
1590
|
+
${e.dataModel}
|
|
1591
|
+
|
|
1592
|
+
API Design:
|
|
1593
|
+
${e.apiDesign}
|
|
1594
|
+
|
|
1595
|
+
Auth Design:
|
|
1596
|
+
${e.authDesign}
|
|
1597
|
+
|
|
1598
|
+
Backend Design:
|
|
1599
|
+
${e.backendDesign}
|
|
1600
|
+
|
|
1601
|
+
Frontend Design:
|
|
1602
|
+
${e.frontendDesign}`,t)).then(o=>o.output)}];var An=e=>{process.stderr.write(`[full-pipeline] ${e}
|
|
1603
|
+
`);};function ap(e){return `# Full Application Specification
|
|
1604
|
+
|
|
1605
|
+
${e.map(o=>`## ${_o.find(a=>a.key===o.key)?.heading??o.name}
|
|
1606
|
+
|
|
1607
|
+
${o.output}`).join(`
|
|
1608
|
+
|
|
1609
|
+
---
|
|
1610
|
+
|
|
1611
|
+
`)}`}async function En(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s={model:o,maxIterations:r,onStep:n,logger:a},i={userInput:t},l=[],p=_o.length;for(let[c,u]of _o.entries()){An(`[${c+1}/${p}] ${u.name}...`);let d=await u.run(i,s);i[u.key]=d,l.push({name:u.name,key:u.key,output:d}),An(`[${c+1}/${p}] ${u.name} \u2014 done`);}return An("Pipeline complete"),{output:ap(l),steps:[],messages:[]}}function H(e,t,o){return {name:e,description:t,handler:(r,n,a)=>o({input:r,model:n,onStep:a})}}var Io=[H("create_app",'Run the full pipeline (requirements, data model, API, auth, backend, frontend, execution plan) from a single project description. Returns a combined specification document with all layers. Input: A natural-language project description. Example: "Project management SaaS with teams, Kanban boards, time tracking, and billing". No prior context needed -- this tool chains all 7 agents automatically, passing each output as context to the next.',En),H("plan",'Generate a full software plan (discovery, requirements, design, synthesis) from a project description. Returns an 11-section markdown blueprint covering tech stack, data models, API routes, auth, implementation order, edge cases, and testing. Input: A natural-language project description. Example: "E-commerce site with users, products, cart, checkout, and admin dashboard". No prior context needed -- lighter and faster than create_app when you only need a high-level plan.',nr),H("gather_requirements",'Extract structured requirements (actors, flows, stories, modules) from a project description. Returns JSON with actors and permissions, user flows with steps, user stories with acceptance criteria, modules with CRUD operations, and database/API outlines. Input: A natural-language project description. Example: "Task manager with teams, Kanban boards, and time tracking". No prior context needed -- use this as a standalone first step before calling specialist tools.',He),H("design_data_model",'Design a database schema (MongoDB or PostgreSQL) with entities, fields, indexes, relationships, and validation rules. Input: Requirements or a project description that lists the entities and relationships to model. Best results when you include the output from gather_requirements. Example input: "Design a data model based on these requirements: {paste requirements JSON here}".',Ve),H("design_api",'Design REST or GraphQL API contracts with endpoints, methods, request/response schemas, and auth requirements. Input: A data model and/or requirements describing the resources and operations. Best results when you include both the data model output and the requirements output. Example input: "Design the API -- Data Model: {data model JSON} -- Requirements: {requirements JSON}".',Ke),H("design_auth",'Design authentication and authorization strategy including providers, roles, permissions, flows, middleware, and security policies. Input: Project requirements and/or API design describing the users, roles, and protected resources. Best results when you include the requirements and API design outputs. Example input: "Design auth -- Requirements: {requirements JSON} -- API Design: {api design JSON}".',Ze),H("architect_backend",'Design backend architecture including framework selection, folder structure, services, middleware, routes, and deployment config. Input: The data model, API design, and auth design for the project. Best results when you include all three. Example input: "Design backend -- Data Model: {data model JSON} -- API Design: {api JSON} -- Auth Design: {auth JSON}".',tt),H("architect_frontend",'Design frontend architecture including pages, components, routing, state management, and styling approach. Input: The API design and requirements for the project. Best results when you include both. Example input: "Design frontend -- API Design: {api JSON} -- Requirements: {requirements JSON}".',rt),H("build_express",'Generate Express.js REST API configuration with routers, models, middleware, and environment variables. Input: The data model and API design describing the endpoints and schemas to generate. Example input: "Generate Express API config -- Data Model: {data model JSON} -- API Design: {api JSON}".',e=>Wr({...e})),H("build_apollo",'Generate Apollo GraphQL subgraph configuration with modules, types, resolvers, and datasources (Federation v2). Input: The data model and API design (GraphQL style) describing the types and operations. Example input: "Generate Apollo subgraph config -- Data Model: {data model JSON} -- API Design: {api JSON}".',e=>rn({...e})),H("build_react",'Generate React + Vite application configuration with pages, components, fields, API hooks, and branding from a GraphQL schema. Input: A GraphQL schema or frontend design describing the types and operations to build UI for. Example input: "Generate React config -- Frontend Design: {frontend JSON} -- API Design: {api JSON}".',e=>hn({...e})),H("build_nextjs",'Generate Next.js App Router configuration with pages, layouts, API routes, server actions, and middleware. Input: The frontend design and API design describing the pages and data fetching requirements. Example input: "Generate Next.js config -- Frontend Design: {frontend JSON} -- API Design: {api JSON}".',xn),H("plan_execution",'Create a phased execution plan with implementation order, edge-case analysis, security/performance notes, and testing strategy. Input: All prior design outputs (requirements, data model, API, auth, backend, frontend). Best results when you include as much context as possible. Example input: "Create execution plan -- Requirements: {requirements} -- Data Model: {data model} -- API: {api} -- Auth: {auth} -- Backend: {backend} -- Frontend: {frontend}".',mt),H("hello_world",'Test agent that greets users. Use to verify the MCP server is working. Input: Any greeting or test message. Example: "Say hello".',vn)];var Ha={input:z.string().describe("Natural language description of what to build or design"),provider:z.enum(["openai","anthropic","google"]).optional().describe("LLM provider (defaults to openai)"),model:z.string().optional().describe("Model name, e.g. gpt-4o-mini, claude-3-5-sonnet-20241022"),temperature:z.number().min(0).max(1).optional().describe("Sampling temperature (0-1)")};function Qa(e){if(!(!e.provider&&!e.model))return {provider:e.provider??"openai",model:e.model??"gpt-4o-mini",temperature:e.temperature}}var lp="sweagent",pp="0.0.3",gt=e=>{process.stderr.write(`[sweagent] ${e}
|
|
1612
|
+
`);},Va=200;function cp(e){return t=>{let o=`${e} \u2014 step ${t.iteration+1}`;if(t.content){let r=t.content.length>Va?t.content.slice(0,Va)+"\u2026":t.content;gt(`${o}: ${r}`);}else {let r=t.toolCalls?.map(n=>n.toolName).join(", ");gt(`${o}${r?` (tools: ${r})`:""}`);}}}function Wa(){let e=new McpServer({name:lp,version:pp},{capabilities:{tools:{}}});for(let t of Io)e.registerTool(t.name,{description:t.description,inputSchema:Ha},async o=>{gt(`${t.name} \u2014 started`);try{let r=Qa(o),n=cp(t.name),a=await t.handler(o.input,r,n);return gt(`${t.name} \u2014 completed`),{content:[{type:"text",text:a.output}]}}catch(r){let n=r instanceof Error?r.message:String(r);return gt(`${t.name} \u2014 error: ${n}`),{content:[{type:"text",text:n}],isError:true}}});return e}var Ka=e=>{process.stderr.write(`[sweagent] ${e}
|
|
1613
|
+
`);};try{let e=Wa(),t=new StdioServerTransport;await e.connect(t),Ka(`MCP server running (stdio) \u2014 ${Io.length} tools registered`);}catch(e){Ka(`Failed to start: ${e}`),process.exit(1);}//# sourceMappingURL=stdio.js.map
|
|
1512
1614
|
//# sourceMappingURL=stdio.js.map
|