sweagent 0.0.4 → 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 +52 -109
- package/dist/index.cjs +294 -186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +567 -119
- package/dist/index.d.ts +567 -119
- package/dist/index.js +294 -186
- package/dist/index.js.map +1 -1
- package/dist/stdio.js +226 -126
- package/dist/stdio.js.map +1 -1
- package/package.json +5 -6
package/dist/index.js
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
Caused by: ${o.stack}`);}},
|
|
1
|
+
import cr from'pino';import {z}from'zod';import sl from'openai';import ll from'@anthropic-ai/sdk';import {GoogleGenAI}from'@google/genai';import*as re from'fs';import*as De from'path';import De__default from'path';import le from'handlebars';import {Client}from'@modelcontextprotocol/sdk/client';import {createRequire}from'module';import {pathToFileURL}from'url';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {writeFile}from'fs/promises';var he=class extends Error{constructor(t,o){super(t,o===void 0?void 0:{cause:o}),this.name="LibraryError",o?.stack&&(this.stack=`${this.stack}
|
|
2
|
+
Caused by: ${o.stack}`);}},Q=class extends he{constructor(o,r,n){super(o,n);this.provider=r;this.name="ModelError";}},W=class extends he{constructor(o,r,n){super(o,n);this.toolName=r;this.name="ToolError";}},vt=class extends he{constructor(o,r){super(o);this.errors=r;this.name="ValidationError";}},ye=class extends he{constructor(o,r,n){super(o,n);this.iteration=r;this.name="AgentError";}},Me=class extends he{constructor(o,r,n){super(o,n);this.subagentName=r;this.name="SubagentError";}};function Fi(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=Fi(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(`
|
|
3
3
|
`);throw new Error(`Model JSON does not match expected schema:
|
|
4
|
-
${a}`)}return n.data}function xe(t,e){try{return JSON.parse(t)}catch(o){let r=t.length>200?t.slice(0,200)+"...":t;throw new Error(`Invalid JSON${e?` for ${e}`:""}: ${o instanceof Error?o.message:String(o)}. Preview: ${r}`)}}var Un={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{},child:()=>Un};function tc(t={}){if(t.enabled===false)return Un;let{name:e,level:o="info",pretty:r=false,file:n,stream:a,destination:s}=t,i=a==="stderr"?2:a==="stdout"?1:r?2:1,l;if(s)l=No({name:e,level:o},s);else {let c=[];r?c.push({target:"pino-pretty",options:{colorize:true,destination:i,singleLine:true,ignore:"time,pid,hostname",translateTime:false},level:o}):c.push({target:"pino/file",options:{destination:i},level:o}),n&&c.push({target:"pino/file",options:{destination:n,mkdir:true},level:o});let p=No.transport({targets:c});l=No({name:e,level:o},p);}return Ln(l)}function oc(t={}){let e=process.env,o=(e.SWE_LOG_ENABLED??"true").trim().toLowerCase(),r=o!=="0"&&o!=="false"&&o!=="no"&&o!=="disabled",n=(e.SWE_LOG_LEVEL??"info").trim().toLowerCase(),a=n==="debug"||n==="info"||n==="warn"||n==="error"?n:"info",s=(e.SWE_LOG_STREAM??"").trim().toLowerCase(),i=(e.SWE_LOG_PRETTY??"0").trim().toLowerCase(),l=i==="1"||i==="true"||i==="yes",c=s==="stdout"?"stdout":s==="stderr"||l?"stderr":"stdout",p=e.SWE_LOG_FILE?.trim()||void 0,d=e.SWE_LOG_NAME?.trim()||void 0;return {enabled:r,level:a,stream:c,pretty:l,...p&&{file:p},...d&&{name:d},...t}}function Ln(t){return {debug:(e,o)=>{t.debug(o??{},e);},info:(e,o)=>{t.info(o??{},e);},warn:(e,o)=>{t.warn(o??{},e);},error:(e,o)=>{o instanceof Error?t.error({err:o},e):t.error(o??{},e);},child:e=>Ln(t.child(e))}}var Xa={noCacheTokens:void 0,cacheReadTokens:void 0,cacheWriteTokens:void 0},Ka={textTokens:void 0,reasoningTokens:void 0};function Do(t){let e=0,o=0,r=0;for(let n of t)n&&(e+=n.inputTokens??0,o+=n.outputTokens??0,r+=n.totalTokens??0);return {inputTokens:e,outputTokens:o,totalTokens:r,inputTokenDetails:Xa,outputTokenDetails:Ka}}function h(t){let{name:e,description:o,input:r,handler:n}=t;return tool({description:o,inputSchema:r,execute:async a=>{let s=r.safeParse(a);if(!s.success)throw new H(`Invalid input: ${s.error.message}`,e,s.error);try{return await n(s.data,void 0)}catch(i){throw i instanceof H?i:new H(`Tool "${e}" failed: ${i instanceof Error?i.message:String(i)}`,e,i instanceof Error?i:void 0)}}})}function k(t){return t}function Gn(t){return Object.values(t)}function Bn(t,e){return t[e]}async function _o(t,e,o){let{logger:r}=o??{},n=o?.toolName??("name"in t&&typeof t.name=="string"?t.name:"unknown");if(!t.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 t.execute(e,{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 nt(t,e,o,r){let n=t[e];if(!n)throw r?.logger?.error("Tool not found",{name:e,availableTools:Object.keys(t)}),new H(`Tool not found: ${e}`);return _o(n,o,{...r,toolName:e})}function q(t,e,o,r="json"){return h({name:t,description:o,input:z$1.object({[r]:z$1.string().describe("JSON string to validate")}),handler:async n=>{let a=n[r]??"";try{let s=JSON.parse(a);return e.parse(s),{valid:!0}}catch(s){return s instanceof z$1.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)]}}}})}function Io(t,e){t?.forEach(o=>o.onStep?.(e));}function Jn(t,e,o){t?.forEach(r=>r.onToolExecution?.(e,o));}function Yn(t,e){t?.forEach(o=>o.onError?.(e));}async function C(t){let{model:e,tools:o,systemPrompt:r,input:n,maxIterations:a=10,onStep:s,observers:i,logger:l}=t;l?.info("Starting agent",{maxIterations:a});let c=[{role:"system",content:r},{role:"user",content:n}],p=[];for(let u=0;u<a;u++){u>0&&u>=a-2&&l?.warn("Approaching max iterations",{iteration:u,maxIterations:a}),l?.debug("Agent iteration",{iteration:u});let y=await e.invoke(c,{tools:o}),m={iteration:u,content:y.text,toolCalls:y.toolCalls,usage:y.usage};if(y.text&&l?.debug("Model response",{iteration:u,textLength:y.text.length}),!y.toolCalls?.length)return p.push(m),s?.(m),Io(i,m),l?.info("Agent completed",{steps:p.length,totalUsage:Do(p.map(j=>j.usage))}),{output:y.text,steps:p,totalUsage:Do(p.map(j=>j.usage)),messages:c};l?.debug("Tool calls",{iteration:u,toolCalls:y.toolCalls.map(j=>({name:j.toolName,toolCallId:j.toolCallId}))});let J=[...y.text?[{type:"text",text:y.text}]:[],...y.toolCalls.map(j=>({type:"tool-call",toolCallId:j.toolCallId,toolName:j.toolName,input:j.input}))];c.push({role:"assistant",content:J});let L=[];for(let j of y.toolCalls){let Se=await nt(o,j.toolName,j.input,{toolCallId:j.toolCallId,logger:l}),de={toolCallId:j.toolCallId,toolName:j.toolName,output:Se.success?Se.output:Se.error,isError:!Se.success};L.push(de),Jn(i,j.toolName,de.output);let Va=de.isError?{type:"error-text",value:String(de.output)}:{type:"text",value:typeof de.output=="string"?de.output:JSON.stringify(de.output)};c.push({role:"tool",content:[{type:"tool-result",toolCallId:j.toolCallId,toolName:j.toolName,output:Va}]});}m.toolResults=L,p.push(m),s?.(m),Io(i,m);}let d=new rt(`Agent reached maximum iterations (${a}) without completing`,a-1);throw Yn(i,d),l?.error("Agent failed: max iterations reached",{maxIterations:a,error:d}),d}function Te(t){let{provider:e,modelName:o,getModel:r}=t;return {provider:e,modelName:o,async invoke(n,a){try{let s=await r(),i=a?.tools?Object.fromEntries(Object.entries(a.tools).map(([p,d])=>{let{execute:u,...y}=d;return [p,y]})):void 0,l=await generateText({model:s,messages:n,tools:i,maxOutputTokens:a?.maxOutputTokens,temperature:a?.temperature,stopSequences:a?.stop}),c=l.toolCalls.map(p=>({toolCallId:p.toolCallId,toolName:p.toolName,input:p.input}));return {text:l.text,toolCalls:c,usage:l.usage,finishReason:l.finishReason}}catch(s){let i=s instanceof Error?s:new Error(String(s));throw new ie(`Failed to invoke ${e} model`,e,i)}},async generateVision(n,a,s){try{let i=await r(),l=[];for(let d of a)l.push({type:"image",image:`data:${d.mimeType};base64,${d.base64}`,mimeType:d.mimeType});l.push({type:"text",text:n});let c=[];s?.systemPrompt&&c.push({role:"system",content:s.systemPrompt}),c.push({role:"user",content:l});let p=await generateText({model:i,messages:c,maxOutputTokens:s?.maxOutputTokens,temperature:s?.temperature});return {text:p.text,toolCalls:[],usage:p.usage,finishReason:p.finishReason}}catch(i){let l=i instanceof Error?i:new Error(String(i));throw new ie("Failed to generate vision response",e,l)}},async invokeObject(n,a,s){try{let i=await r(),l=zodSchema(a),c=await generateObject({model:i,messages:n,schema:l,temperature:s?.temperature,maxOutputTokens:s?.maxOutputTokens});return {data:c.object,usage:c.usage}}catch(i){let l=i instanceof Error?i:new Error(String(i));throw new ie(`Failed to invokeObject ${e} model`,e,l)}}}}function st(t){let{model:e,apiKey:o,baseUrl:r}=t,n=createOpenAI({apiKey:o??process.env.OPENAI_API_KEY,baseURL:r});return Te({provider:"openai",modelName:e,getModel:()=>n.chat(e)})}function at(t){let{model:e,apiKey:o}=t,r=createAnthropic({apiKey:o??process.env.ANTHROPIC_API_KEY});return Te({provider:"anthropic",modelName:e,getModel:()=>r(e)})}function it(t){let{model:e,apiKey:o}=t,r=createGoogleGenerativeAI({apiKey:o??process.env.GOOGLE_GENERATIVE_AI_API_KEY});return Te({provider:"google",modelName:e,getModel:()=>r(e)})}function v(t){let{provider:e}=t;switch(e){case "openai":return st(t);case "anthropic":return at(t);case "google":return it(t);default:throw new ie(`Unsupported provider: ${e}. Supported providers: openai, anthropic, google`)}}var ii=/^[a-z0-9]+(-[a-z0-9]+)*$/;function f(t){if(!t.name.trim())throw new be("Subagent name is required",void 0);if(!ii.test(t.name))throw new be(`Subagent name must be kebab-case (lowercase letters, numbers, hyphens): ${t.name}`,t.name);return {...t}}function li(t,e){if(t.tools!=null&&Object.keys(t.tools).length>0)return t.tools;let o=e??{},r=new Set(t.disallowedTools??[]),n={};for(let[a,s]of Object.entries(o))a.startsWith("subagent_")||r.has(a)||(n[a]=s);return n}async function z(t,e,o){let{parentTools:r,parentModel:n}=o??{},a=li(t,r),s=t.model==null?n:v(t.model);if(!s)throw new be("Subagent has no model: set definition.model or pass parentModel in options",t.name);return {...await C({model:s,tools:a,systemPrompt:t.systemPrompt,input:e,maxIterations:t.maxIterations??10,onStep:t.onStep}),subagentName:t.name}}function jo(t,e){let o=`subagent_${t.name}`;return h({name:o,description:t.description,input:z$1.object({prompt:z$1.string().describe("The task or question to delegate to this subagent")}),handler:async({prompt:r})=>(await z(t,r,{parentTools:e?.parentTools,parentModel:e?.parentModel})).output})}function I(t,e){let o={};for(let r of t){let n=jo(r,e);o[`subagent_${r.name}`]=n;}return o}function qo(t,e){return re.compile(t,{noEscape:true})(e)}function Hn(t,e=t){let o=[];if(!Z.existsSync(t))return o;let r=Z.readdirSync(t,{withFileTypes:true});for(let n of r){let a=Pe.join(t,n.name);n.isDirectory()?o.push(...Hn(a,e)):n.name.endsWith(".hbs")&&o.push(Pe.relative(e,a));}return o}function ci(t){return t.replace(/\.hbs$/,"")}function pi(t,e){for(let o of e)if(new RegExp("^"+o.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/<<GLOBSTAR>>/g,".*")+"$").test(t))return true;return false}async function ce(t){let{templateDir:e,outputDir:o,context:r,skipPatterns:n=[]}=t,a=Hn(e),s=[],i=[];for(let l of a){if(pi(l,n))continue;let c=ci(l),p=Pe.join(e,l),d=Pe.join(o,c);try{let u=Z.readFileSync(p,"utf-8"),y=qo(u,r);Z.mkdirSync(Pe.dirname(d),{recursive:!0}),Z.writeFileSync(d,y,"utf-8"),s.push(c);}catch(u){i.push({file:l,message:u instanceof Error?u.message:String(u)});}}return {fileCount:s.length,files:s,errors:i}}function Fo(){re.registerHelper("eq",(t,e)=>t===e),re.registerHelper("neq",(t,e)=>t!==e),re.registerHelper("json",t=>JSON.stringify(t,null,2)),re.registerHelper("uppercase",t=>typeof t=="string"?t.toUpperCase():""),re.registerHelper("lowercase",t=>typeof t=="string"?t.toLowerCase():""),re.registerHelper("capitalize",t=>typeof t=="string"?t.charAt(0).toUpperCase()+t.slice(1):""),re.registerHelper("camelCase",t=>typeof t!="string"?"":t.replace(/[-_\s]+(.)?/g,(e,o)=>o?o.toUpperCase():"").replace(/^(.)/,e=>e.toLowerCase())),re.registerHelper("pascalCase",t=>typeof t!="string"?"":t.replace(/[-_\s]+(.)?/g,(e,o)=>o?o.toUpperCase():"").replace(/^(.)/,e=>e.toUpperCase()));}Fo();function ui(){let e=createRequire(import.meta.url).resolve("@modelcontextprotocol/sdk/client");return Pe__default.dirname(Pe__default.dirname(Pe__default.dirname(Pe__default.dirname(e))))}var Vn=ui();function Wn(t){let e=t.content;if(!e?.length)return {};let o=e[0];if(o?.type==="text"&&typeof o.text=="string"){let r=o.text.trim();if(r.startsWith("{")||r.startsWith("["))try{return JSON.parse(r)}catch{return {raw:r}}return {text:r}}return t}async function Xn(t,e){let o=Pe__default.join(Vn,"dist","esm","client","streamableHttp.js"),r=await import(pathToFileURL(o).href),n=e?{headers:new Headers(e)}:void 0;return new r.StreamableHTTPClientTransport(new URL(t),n?{requestInit:n}:void 0)}async function Kn(t,e){let o=Pe__default.join(Vn,"dist","esm","client","stdio.js"),r=await import(pathToFileURL(o).href);return new r.StdioClientTransport({command:t,args:e})}var lt=class{info;config;client=null;transport=null;connectPromise=null;constructor(e,o){this.info=e,this.config=o;}static resolveConfig(e,o={envPrefix:"MCP"}){let{envPrefix:r,serverLabel:n,apiKeyHeader:a}=o,s=e?.url??process.env[`${r}_URL`],i=process.env[`${r}_API_KEY`],l=e?.command??process.env[`${r}_COMMAND`],c=process.env[`${r}_ARGS`],p=e?.args??(c?c.split(",").map(u=>u.trim()):void 0),d=e?.headers?{...e.headers}:void 0;if(i){let u=a??"Authorization";d=d??{},d[u]=u==="Authorization"?`Bearer ${i}`:i;}if(s)return {url:s,headers:d};if(l)return {command:l,args:p?.length?p:[]};throw new H(`${n??r} uses MCP only. Set ${r}_URL or ${r}_COMMAND (and optionally ${r}_ARGS).`,"mcp_client")}async ensureConnected(){if(this.client)return this.client;if(this.connectPromise){if(await this.connectPromise,!this.client)throw new H("MCP connection failed.","mcp_client");return this.client}if(this.connectPromise=this.doConnect(),await this.connectPromise,this.connectPromise=null,!this.client)throw new H("MCP connection failed.","mcp_client");return this.client}async doConnect(){let e=new Client({name:this.info.name,version:this.info.version},{capabilities:{}});if(this.config.url)this.transport=await Xn(this.config.url,this.config.headers);else if(this.config.command)this.transport=await Kn(this.config.command,this.config.args??[]);else throw new H("MCP config missing: provide url or command.","mcp_client");await e.connect(this.transport),this.client=e;}async callTool(e,o={}){let n=await(await this.ensureConnected()).callTool({name:e,arguments:o});return n&&typeof n=="object"&&"content"in n?Wn(n):n}async close(){this.transport&&(await this.transport.close(),this.transport=null),this.client=null,this.connectPromise=null;}};var gi={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};function Zn(){return {stage:"discovery",projectDescription:null,sections:{...gi},history:[],pendingQuestions:[]}}function es(t,e){let{sections:o,projectDescription:r,pendingQuestions:n}=e,a={...t.sections};if(o)for(let s of Object.keys(o)){let i=o[s];i!=null&&(a[s]=i);}return {...t,...r!==void 0&&{projectDescription:r},sections:a,...n!==void 0&&{pendingQuestions:n}}}function ct(t,e,o){let r={role:e,content:o};return {...t,history:[...t.history,r]}}function Uo(t){let e=["discovery","requirements","design","complete"],o=e.indexOf(t.stage),n=(o>=0&&o<e.length-1?e[o+1]:void 0)??t.stage;return {...t,stage:n}}function pt(t){let e=t.trim().toLowerCase();return ["continue","yes","yeah","yep","looks good","good","ok","okay","next","proceed","sure"].some(r=>e===r||e.startsWith(r+" "))}var ee=`You are a senior software architect creating a single, implementation-ready plan that a developer can follow without ambiguity.
|
|
4
|
+
${a}`)}return n.data}function Ee(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}`)}}var gs={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{},child:()=>gs};function gc(e={}){if(e.enabled===false)return gs;let{name:t,level:o="info",pretty:r=false,file:n,stream:a,destination:s}=e,i=a==="stderr"?2:a==="stdout"?1:r?2:1,l;if(s)l=cr({name:t,level:o},s);else {let p=[];r?p.push({target:"pino-pretty",options:{colorize:true,destination:i,singleLine:true,ignore:"time,pid,hostname",translateTime:false},level:o}):p.push({target:"pino/file",options:{destination:i},level:o}),n&&p.push({target:"pino/file",options:{destination:n,mkdir:true},level:o});let c=cr.transport({targets:p});l=cr({name:t,level:o},c);}return fs(l)}function fc(e={}){let t=process.env,o=(t.SWE_LOG_ENABLED??"true").trim().toLowerCase(),r=o!=="0"&&o!=="false"&&o!=="no"&&o!=="disabled",n=(t.SWE_LOG_LEVEL??"info").trim().toLowerCase(),a=n==="debug"||n==="info"||n==="warn"||n==="error"?n:"info",s=(t.SWE_LOG_STREAM??"").trim().toLowerCase(),i=(t.SWE_LOG_PRETTY??"0").trim().toLowerCase(),l=i==="1"||i==="true"||i==="yes",p=s==="stdout"?"stdout":s==="stderr"||l?"stderr":"stdout",c=t.SWE_LOG_FILE?.trim()||void 0,u=t.SWE_LOG_NAME?.trim()||void 0;return {enabled:r,level:a,stream:p,pretty:l,...c&&{file:c},...u&&{name:u},...e}}function fs(e){return {debug:(t,o)=>{e.debug(o??{},t);},info:(t,o)=>{e.info(o??{},t);},warn:(t,o)=>{e.warn(o??{},t);},error:(t,o)=>{o instanceof Error?e.error({err:o},t):e.error(o??{},t);},child:t=>fs(e.child(t))}}var Gi={noCacheTokens:void 0,cacheReadTokens:void 0,cacheWriteTokens:void 0},Bi={textTokens:void 0,reasoningTokens:void 0};function Se(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:Gi,outputTokenDetails:Bi}}function Oe(e,t,o){e?.forEach(r=>r.onStep?.(t,o));}function At(e,t,o){e?.forEach(r=>r.onToolExecution?.(t,o));}function Mt(e,t){e?.forEach(o=>o.onError?.(t));}function Ce(e,t,o){e?.forEach(r=>r.onTokenBudgetWarning?.(t,o));}function hs(e){let t=z.toJSONSchema(e),{$schema:o,definitions:r,...n}=t;return n}function ur(e){let{description:t,inputSchema:o,execute:r}=e,n=hs(o);return {description:t,inputSchema:o,parameters:n,execute:r}}function zi(e){return {schema:e,jsonSchema:hs(e)}}function f(e){let{name:t,description:o,input:r,handler:n}=e;return ur({description:o,inputSchema:r,execute:async a=>{let s=r.safeParse(a);if(!s.success)throw new W(`Invalid input: ${s.error.message}`,t,s.error);try{return await n(s.data,void 0)}catch(i){throw i instanceof W?i:new W(`Tool "${t}" failed: ${i instanceof Error?i.message:String(i)}`,t,i instanceof Error?i:void 0)}}})}function j(e){return e}function ys(e){return Object.values(e)}function Ss(e,t){return e[t]}async function dr(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 Ne(e,t,o,r){let n=e[t];if(!n)throw r?.logger?.error("Tool not found",{name:t,availableTools:Object.keys(e)}),new W(`Tool not found: ${t}`);return dr(n,o,{...r,toolName:t})}function be(e){let t=z.toJSONSchema(e),{$schema:o,definitions:r,...n}=t;return n}function L(e,t,o,r="json"){return f({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)]}}}})}var gr=new Map;function Ve(e){let t=gr.get(e);return t||(t=new Map,gr.set(e,t)),t}function Et(e,t,o){let r={artifact:t,data:o,proposedAt:Date.now()};return Ve(e).set(t,r),r}function Ot(e,t){return Ve(e).get(t)}function Ct(e){return Array.from(Ve(e).values())}function Nt(e,t){let o=Ve(e),r=o.get(t);return r&&o.delete(t),r?.data}function bs(e,t){return Ve(e).delete(t)}function xs(e){gr.delete(e);}function Ts(e){let t=f({name:"propose_output",description:"Propose an output artifact for review before finalizing. Returns the proposal.",input:z.object({artifact:z.string().describe('Name/key for this artifact (e.g. "data-model", "api-spec")'),data:z.any().describe("The proposed content (JSON, string, etc.)")}),handler:async({artifact:a,data:s})=>{let i=Et(e,a,s);return {status:"proposed",artifact:i.artifact,proposedAt:i.proposedAt,preview:typeof s=="string"?s.slice(0,500):JSON.stringify(s).slice(0,500)}}}),o=f({name:"finalize_output",description:"Finalize a previously proposed artifact, committing it as the final output.",input:z.object({artifact:z.string().describe("The artifact name to finalize")}),handler:async({artifact:a})=>{let s=Nt(e,a);return s===void 0?{status:"error",message:`No proposal found for "${a}"`}:{status:"finalized",artifact:a,data:s}}}),r=f({name:"list_proposals",description:"List all pending proposed artifacts for the current run.",input:z.object({}),handler:async()=>Ct(e).map(s=>({artifact:s.artifact,proposedAt:s.proposedAt,preview:typeof s.data=="string"?s.data.slice(0,200):JSON.stringify(s.data).slice(0,200)}))}),n=f({name:"review_proposal",description:"View the full content of a proposed artifact for review.",input:z.object({artifact:z.string().describe("The artifact name to review")}),handler:async({artifact:a})=>{let s=Ot(e,a);return s?{status:"found",artifact:s.artifact,data:s.data}:{status:"error",message:`No proposal found for "${a}"`}}});return {propose_output:t,finalize_output:o,list_proposals:r,review_proposal:n}}async function kt(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 Ne(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 fr(e){if(e==null)return 0;let t=typeof e=="string"?e:JSON.stringify(e);return Math.ceil(t.length/3)}function We(e){let t=0;for(let o of e)t+=fr(o);return t}function Z(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}
|
|
5
|
+
|
|
6
|
+
[...truncated ${i} chars...]
|
|
7
|
+
|
|
8
|
+
${s}`}function Ps(e,t){let o=t*3;return Z(e,o)}var Yi=15e3,Rs=4e3,Hi=200,Qi=2e3;function hr(e){let t=e.role,o=e.content;switch(t){case "system":return "[SYSTEM] (preserved)";case "user":return Vi(o);case "assistant":return Wi(o);case "tool":return Ki(o);default:return `[${t.toUpperCase()}]`}}function Vi(e){let t=Xi(e);return `[USER] ${Z(t,Yi)}`}function Wi(e){if(typeof e=="string")return `[ASSISTANT] ${Z(e,Rs)}`;if(!Array.isArray(e))return "[ASSISTANT]";let t=[],o=[];for(let a of e)a.type==="text"&&a.text?t.push(Z(a.text,Rs)):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 Ki(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: ${Z(a,Hi)}`):t.push(`[TOOL:${r}] ${Z(a,Qi)}`);}return t.join(`
|
|
9
|
+
`)||"[TOOL]"}function Xi(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 Dt(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(hr).join(`
|
|
10
|
+
`),kept:r}}var Zi=1e3,el=2e5,tl=.1,ol=4;function ke(e,t){let o=t?.maxContextTokens??el,r=t?.keepRecentCount??ol,n=t?.logger,a=We(e);if(a+Zi<=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}=Dt(i,r),u=Math.floor(o*tl)*3,d=Z(l,u),g={role:"user",content:rl(d)},m=[s,g,...p],R=We(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 rl(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(`
|
|
11
|
+
`)}async function k(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&&ke(u,{maxContextTokens:p,logger:l});let R=Se(d.map(Y=>Y.usage)),w=R.totalTokens??0;if(c){if(w>=c)return l?.warn("Token budget exhausted",{used:w,tokenBudget:c}),Ce(i,w,c),{output:d.at(-1)?.content??"",steps:d,totalUsage:R,messages:u};w>=c*.8&&Ce(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=Se(d.map(ie=>ie.usage).concat(G.usage)),d.push(G),s?.(G),Oe(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 Ae=await kt({tools:o,toolCalls:z.toolCalls,messages:u,logger:l,responseText:z.text||void 0,onToolResult:(Y,ie)=>{At(i,Y,ie);}});G.toolResults=Ae,G.cumulativeUsage=Se(d.map(Y=>Y.usage).concat(G.usage)),d.push(G),s?.(G),Oe(i,G,G.cumulativeUsage);}let g=new ye(`Agent reached maximum iterations (${a}) without completing`,a-1);throw Mt(i,g),l?.error("Agent failed: max iterations reached",{maxIterations:a,error:g}),g}async function _t(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 Ne(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 It(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 jt(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 ye("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 Ae=0;Ae<a;Ae++){l&&Ae>0&&ke(d,{maxContextTokens:l,logger:i});let Y=Se(g.map(wt=>wt.usage)),ie=Y.totalTokens??0;if(p){if(ie>=p)return i?.warn("Token budget exhausted",{used:ie,tokenBudget:p}),Ce(s,ie,p),{output:g.at(-1)?.content??"",steps:g,totalUsage:Y,messages:d};ie>=p*.8&&Ce(s,ie,p);}let Rt=await _t({generator:m,tools:o,messages:d,steps:g,logger:i,lastToolResult:R,stepsComplete:w,nResponses:z});if(Rt.type==="done"){let wt=Se(g.map(Ui=>Ui.usage));return {output:g.at(-1)?.content??"",steps:g,totalUsage:wt,messages:d}}if(Rt.type==="generate_n"){z=(await It({model:t,messages:d,n:Rt.n,invokeOptions:{tools:o},logger:i})).texts,R=void 0,w=false;continue}let qi=Rt.type==="step_all",Li=await nl(e,d,g,qi,Ae,u);R=void 0,w=Li.stepsComplete,z=void 0;}let G=new ye(`Agent reached maximum iterations (${a})`,a-1);throw Mt(s,G),G}async function nl(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),Oe(p,d),{stepsComplete:true};let g=await kt({tools:i,toolCalls:u.toolCalls,messages:t,logger:c,onToolResult:(m,R)=>{At(p,m,R);}});return d.toolResults=g,o.push(d),l?.(d),Oe(p,d),{stepsComplete:!r}}function ws(e){if(e.length===0)return {selectedIndex:0,selectedText:"",reason:"no responses"};let t=0;for(let o=1;o<e.length;o++)(e[o]?.length??0)>(e[t]?.length??0)&&(t=o);return {selectedIndex:t,selectedText:e[t]??"",reason:"longest response"}}async function vs(e){let{model:t,responses:o,criteria:r,logger:n}=e,a=o.map((c,u)=>`--- Candidate ${u} ---
|
|
12
|
+
${c}`).join(`
|
|
13
|
+
|
|
14
|
+
`),s=[{role:"system",content:["You are a judge selecting the best response.",`Criteria: ${r}`,"Reply with ONLY the candidate number (0-indexed) of the best response."].join(`
|
|
15
|
+
`)},{role:"user",content:`Select the best candidate:
|
|
16
|
+
|
|
17
|
+
${a}`}];n?.debug("Running LLM judge",{candidateCount:o.length});let i=await t.invoke(s,{}),l=parseInt(i.text.trim(),10),p=isNaN(l)||l<0||l>=o.length?0:l;return {selectedIndex:p,selectedText:o[p]??"",reason:`judge selected candidate ${p}`}}function As(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 al(e){return Object.entries(e).map(([t,o])=>{let r=o.parameters??(o.inputSchema?be(o.inputSchema):{type:"object",properties:{}});return {type:"function",function:{name:t,description:o.description,parameters:r}}})}function Ms(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 il(e){return e==="stop"||e==="length"||e==="tool_calls"||e==="content_filter"?e==="tool_calls"?"tool-calls":e:e??"stop"}function Es(e){let{model:t,apiKey:o,baseUrl:r}=e,n=new sl({apiKey:o??process.env.OPENAI_API_KEY,baseURL:r});return {provider:"openai",modelName:t,async invoke(a,s){try{let i=a.map(As),l=s?.tools?al(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:Ms(p.usage),finishReason:il(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(As),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:Ms(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 qt(e){return Es({model:e.model,apiKey:e.apiKey,baseUrl:e.baseUrl})}function pl(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 Os(e){let t,o=[];for(let r of e){let n=pl(r);n&&("system"in n?t=t?`${t}
|
|
18
|
+
|
|
19
|
+
${n.system}`:n.system:o.push(n));}return {system:t,messages:o}}function cl(e){return Object.entries(e).map(([t,o])=>{let r=o.parameters??(o.inputSchema?be(o.inputSchema):{type:"object",properties:{}});return {name:t,description:o.description,input_schema:{type:"object",properties:r.properties??{},...r}}})}function Cs(e,t){return {inputTokens:e,outputTokens:t,totalTokens:e+t}}function ul(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 Ns(e){let{model:t,apiKey:o}=e,r=new ll({apiKey:o??process.env.ANTHROPIC_API_KEY});return {provider:"anthropic",modelName:t,async invoke(n,a){try{let{system:s,messages:i}=Os(n),l=a?.tools?cl(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:Cs(p.usage.input_tokens,p.usage.output_tokens),finishReason:ul(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}=Os(n),c=await r.messages.create({model:t,max_tokens:s?.maxOutputTokens??4096,system:l?`${l}
|
|
20
|
+
|
|
21
|
+
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:Cs(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 Lt(e){return Ns({model:e.model,apiKey:e.apiKey})}function ml(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 ks(e){let t,o=[];for(let r of e){let n=ml(r);n&&("system"in n&&n.system!==void 0?t=t?`${t}
|
|
22
|
+
|
|
23
|
+
${n.system}`:n.system:"role"in n&&"parts"in n&&o.push(n));}return {systemInstruction:t,contents:o}}function gl(e){return [{functionDeclarations:Object.entries(e).map(([o,r])=>{let n=r.parameters??(r.inputSchema?be(r.inputSchema):{type:"object",properties:{}});return {name:o,description:r.description,parameters:n}})}]}function fl(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 Ds(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}=ks(n),l=a?.tools?gl(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:fl(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}=ks(n),c=l?`${l}
|
|
24
|
+
|
|
25
|
+
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 Ut(e){return Ds({model:e.model,apiKey:e.apiKey})}function M(e){let{provider:t}=e;switch(t){case "openai":return qt(e);case "anthropic":return Lt(e);case "google":return Ut(e);default:throw new Q(`Unsupported provider: ${t}. Supported providers: openai, anthropic, google`)}}var hl=/^[a-z0-9]+(-[a-z0-9]+)*$/;function y(e){if(!e.name.trim())throw new Me("Subagent name is required",void 0);if(!hl.test(e.name))throw new Me(`Subagent name must be kebab-case: ${e.name}`,e.name);return {...e}}function yl(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 Sl(e,t){return e.inheritParentSystemPrompt&&t?`${t}
|
|
26
|
+
|
|
27
|
+
${e.systemPrompt}`:e.systemPrompt}async function V(e,t,o){let{parentTools:r,parentModel:n,parentSystemPrompt:a}=o??{},s=yl(e,r),i=e.model==null?n:M(e.model);if(!i)throw new Me("Subagent has no model: set definition.model or pass parentModel in options",e.name);let l=Sl(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 jt(p):await k(p);if(e.outputSchema){let u=e.outputSchema.safeParse(c.output);if(!u.success)throw new vt(`Subagent "${e.name}" output schema validation failed: ${u.error.message}`,u.error.issues)}return {...c,subagentName:e.name}}function yr(e,t){let o=e.spawnerPrompt??e.description;return f({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 q(e,t){let o={};for(let r of e)o[`subagent_${r.name}`]=yr(r,t);return o}function Sr(e,t){return le.compile(e,{noEscape:true})(t)}function Is(e,t=e){let o=[];if(!re.existsSync(e))return o;let r=re.readdirSync(e,{withFileTypes:true});for(let n of r){let a=De.join(e,n.name);n.isDirectory()?o.push(...Is(a,t)):n.name.endsWith(".hbs")&&o.push(De.relative(t,a));}return o}function bl(e){return e.replace(/\.hbs$/,"")}function xl(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 ge(e){let{templateDir:t,outputDir:o,context:r,skipPatterns:n=[]}=e,a=Is(t),s=[],i=[];for(let l of a){if(xl(l,n))continue;let p=bl(l),c=De.join(t,l),u=De.join(o,p);try{let d=re.readFileSync(c,"utf-8"),g=Sr(d,r);re.mkdirSync(De.dirname(u),{recursive:!0}),re.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 br(){le.registerHelper("eq",(e,t)=>e===t),le.registerHelper("neq",(e,t)=>e!==t),le.registerHelper("json",e=>JSON.stringify(e,null,2)),le.registerHelper("uppercase",e=>typeof e=="string"?e.toUpperCase():""),le.registerHelper("lowercase",e=>typeof e=="string"?e.toLowerCase():""),le.registerHelper("capitalize",e=>typeof e=="string"?e.charAt(0).toUpperCase()+e.slice(1):""),le.registerHelper("camelCase",e=>typeof e!="string"?"":e.replace(/[-_\s]+(.)?/g,(t,o)=>o?o.toUpperCase():"").replace(/^(.)/,t=>t.toLowerCase())),le.registerHelper("pascalCase",e=>typeof e!="string"?"":e.replace(/[-_\s]+(.)?/g,(t,o)=>o?o.toUpperCase():"").replace(/^(.)/,t=>t.toUpperCase()));}br();function Pl(){let t=createRequire(import.meta.url).resolve("@modelcontextprotocol/sdk/client");return De__default.dirname(De__default.dirname(De__default.dirname(De__default.dirname(t))))}var qs=Pl();function Ls(e){let t=e.content;if(!t?.length)return {};let o=t[0];if(o?.type==="text"&&typeof o.text=="string"){let r=o.text.trim();if(r.startsWith("{")||r.startsWith("["))try{return JSON.parse(r)}catch{return {raw:r}}return {text:r}}return e}async function Us(e,t){let o=De__default.join(qs,"dist","esm","client","streamableHttp.js"),r=await import(pathToFileURL(o).href),n=t?{headers:new Headers(t)}:void 0;return new r.StreamableHTTPClientTransport(new URL(e),n?{requestInit:n}:void 0)}async function Fs(e,t){let o=De__default.join(qs,"dist","esm","client","stdio.js"),r=await import(pathToFileURL(o).href);return new r.StdioClientTransport({command:e,args:t})}var Ft=class{info;config;client=null;transport=null;connectPromise=null;constructor(t,o){this.info=t,this.config=o;}static resolveConfig(t,o={envPrefix:"MCP"}){let{envPrefix:r,serverLabel:n,apiKeyHeader:a}=o,s=t?.url??process.env[`${r}_URL`],i=process.env[`${r}_API_KEY`],l=t?.command??process.env[`${r}_COMMAND`],p=process.env[`${r}_ARGS`],c=t?.args??(p?p.split(",").map(d=>d.trim()):void 0),u=t?.headers?{...t.headers}:void 0;if(i){let d=a??"Authorization";u=u??{},u[d]=d==="Authorization"?`Bearer ${i}`:i;}if(s)return {url:s,headers:u};if(l)return {command:l,args:c?.length?c:[]};throw new W(`${n??r} uses MCP only. Set ${r}_URL or ${r}_COMMAND (and optionally ${r}_ARGS).`,"mcp_client")}async ensureConnected(){if(this.client)return this.client;if(this.connectPromise){if(await this.connectPromise,!this.client)throw new W("MCP connection failed.","mcp_client");return this.client}if(this.connectPromise=this.doConnect(),await this.connectPromise,this.connectPromise=null,!this.client)throw new W("MCP connection failed.","mcp_client");return this.client}async doConnect(){let t=new Client({name:this.info.name,version:this.info.version},{capabilities:{}});if(this.config.url)this.transport=await Us(this.config.url,this.config.headers);else if(this.config.command)this.transport=await Fs(this.config.command,this.config.args??[]);else throw new W("MCP config missing: provide url or command.","mcp_client");await t.connect(this.transport),this.client=t;}async callTool(t,o={}){let n=await(await this.ensureConnected()).callTool({name:t,arguments:o});return n&&typeof n=="object"&&"content"in n?Ls(n):n}async close(){this.transport&&(await this.transport.close(),this.transport=null),this.client=null,this.connectPromise=null;}};var wl={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};function Gs(){return {stage:"discovery",projectDescription:null,sections:{...wl},history:[],pendingQuestions:[]}}function Bs(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 Gt(e,t,o){let r={role:t,content:o};return {...e,history:[...e.history,r]}}function xr(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 ne=`You are a senior software architect creating a single, implementation-ready plan that a developer can follow without ambiguity.
|
|
5
28
|
|
|
6
29
|
CRITICAL RULES:
|
|
7
30
|
- 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.
|
|
8
31
|
- 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**).
|
|
9
|
-
- 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
|
|
32
|
+
- 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 Tr=`You are in the discovery stage. Your goal is to understand what the user wants to build.
|
|
10
33
|
|
|
11
34
|
Respond in natural language only. Do NOT output JSON.
|
|
12
35
|
|
|
@@ -16,21 +39,21 @@ Respond in natural language only. Do NOT output JSON.
|
|
|
16
39
|
- **## Core Features** \u2014 Numbered list: 1. **Feature Name** - Short description. (one line per feature)
|
|
17
40
|
- **## Tech Stack** \u2014 Bullet list with category labels: - **Frontend**: ... (versions if known), - **Database**: ..., - **Authentication**: ..., - **API**: ..., - **Backend**: ... Include versions and key libraries where relevant.
|
|
18
41
|
|
|
19
|
-
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.`,
|
|
42
|
+
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.`,Js=`## Current user message:
|
|
20
43
|
{userMessage}
|
|
21
44
|
|
|
22
45
|
## Prior conversation (if any):
|
|
23
46
|
{history}
|
|
24
47
|
|
|
25
|
-
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
|
|
26
|
-
{context}`,
|
|
48
|
+
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 Pr(e,t){return Js.replace("{userMessage}",e).replace("{history}",t||"(No prior messages)")}var Jt=`## Project description / context:
|
|
49
|
+
{context}`,zs=`${Jt}
|
|
27
50
|
|
|
28
51
|
Using the project description above, write two markdown sections in this exact format:
|
|
29
52
|
|
|
30
53
|
1. **## Overview** \u2014 One paragraph only (2\u20134 sentences) summarizing the project and its purpose.
|
|
31
54
|
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.
|
|
32
55
|
|
|
33
|
-
Output only these two sections in markdown. Do NOT output JSON
|
|
56
|
+
Output only these two sections in markdown. Do NOT output JSON.`,$s=`${Jt}
|
|
34
57
|
|
|
35
58
|
## Already written (Overview + Tech Stack):
|
|
36
59
|
{overviewAndTechStack}
|
|
@@ -40,8 +63,8 @@ Write the next two markdown sections in this exact format:
|
|
|
40
63
|
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).
|
|
41
64
|
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.
|
|
42
65
|
|
|
43
|
-
Output only markdown. Do NOT output JSON.`;function
|
|
44
|
-
{priorSections}`,
|
|
66
|
+
Output only markdown. Do NOT output JSON.`;function Rr(e){return zs.replace("{context}",e)}function wr(e,t){return $s.replace("{context}",e).replace("{overviewAndTechStack}",t)}var Ys=`## Project context (all sections so far):
|
|
67
|
+
{priorSections}`,Hs=`${Ys}
|
|
45
68
|
|
|
46
69
|
## API Routes (already written):
|
|
47
70
|
{apiRoutes}
|
|
@@ -55,8 +78,8 @@ Write the next markdown section in this exact format:
|
|
|
55
78
|
- **### 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).
|
|
56
79
|
- 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).
|
|
57
80
|
|
|
58
|
-
Output only markdown. Do NOT output JSON.`;function
|
|
59
|
-
{priorSections}`,
|
|
81
|
+
Output only markdown. Do NOT output JSON.`;function vr(e,t){return Hs.replace("{priorSections}",e).replace("{apiRoutes}",t)}var El=`## Full plan so far (all sections):
|
|
82
|
+
{priorSections}`,Ar="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.",Qs=`${El}
|
|
60
83
|
|
|
61
84
|
Write the following sections in this exact order. Output only markdown. Do NOT output JSON.
|
|
62
85
|
|
|
@@ -82,7 +105,7 @@ Write the following sections in this exact order. Output only markdown. Do NOT o
|
|
|
82
105
|
|
|
83
106
|
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").
|
|
84
107
|
|
|
85
|
-
Output all eight sections in the order above. Do NOT output JSON.`;function
|
|
108
|
+
Output all eight sections in the order above. Do NOT output JSON.`;function Mr(e){return Qs.replace("{priorSections}",e)}var Er=`You are a senior software architect revising an existing implementation plan.
|
|
86
109
|
|
|
87
110
|
CRITICAL RULES:
|
|
88
111
|
- You will receive the FULL existing plan and the user's feedback or edit instructions.
|
|
@@ -91,18 +114,18 @@ CRITICAL RULES:
|
|
|
91
114
|
- Only modify sections that are affected by the feedback. Leave unrelated sections intact.
|
|
92
115
|
- Use code blocks ONLY for: request/response JSON examples, file/directory trees, and env or config snippets.
|
|
93
116
|
- Be concrete and actionable: include validation rules, HTTP status codes, redirects, field-level data model descriptions, and step-by-step auth flows.
|
|
94
|
-
- If the feedback adds new requirements, integrate them into the appropriate existing sections rather than appending a separate section (unless a new section is clearly needed).`;function
|
|
117
|
+
- If the feedback adds new requirements, integrate them into the appropriate existing sections rather than appending a separate section (unless a new section is clearly needed).`;function Or(e,t){return `## Existing Plan
|
|
95
118
|
|
|
96
|
-
${
|
|
119
|
+
${e}
|
|
97
120
|
|
|
98
121
|
---
|
|
99
122
|
|
|
100
123
|
## Edit Instructions
|
|
101
124
|
|
|
102
|
-
${
|
|
103
|
-
`),s=
|
|
125
|
+
${t}`}function Ol(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 Cr(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(`
|
|
126
|
+
`),s=Pr(e,a),l=[{role:"system",content:`${ne}
|
|
104
127
|
|
|
105
|
-
${
|
|
128
|
+
${Tr}`},{role:"user",content:s}],c=(await o.invoke(l,{temperature:.4,maxOutputTokens:4096})).text?.trim()??"",u=Ol(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 zt=class{stageName="discovery";async process(t,o){return Cr(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "requirements"}};var Cl=`You are an expert database entity analyst. Your job is to extract data model signals from requirements.
|
|
106
129
|
|
|
107
130
|
Perform these analyses:
|
|
108
131
|
|
|
@@ -121,7 +144,7 @@ Perform these analyses:
|
|
|
121
144
|
- Note ownership direction (which entity "belongs to" which).
|
|
122
145
|
- Identify potential M:N relationships that may need join tables.
|
|
123
146
|
|
|
124
|
-
Respond with a clear, structured analysis using headings and bullet points. Do NOT return JSON.`,
|
|
147
|
+
Respond with a clear, structured analysis using headings and bullet points. Do NOT return JSON.`,pe=y({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:Cl,tools:{},maxIterations:2});var Nl=`You are a database relationship specialist. Given a list of entities and their fields, you determine:
|
|
125
148
|
|
|
126
149
|
## Cardinality Analysis
|
|
127
150
|
- For every entity pair that references each other, classify: 1:1, 1:N, or M:N.
|
|
@@ -139,7 +162,7 @@ Respond with a clear, structured analysis using headings and bullet points. Do N
|
|
|
139
162
|
- Suggest unique indexes for natural keys (email, slug, etc.).
|
|
140
163
|
- Note partial indexes where applicable (e.g. only active records).
|
|
141
164
|
|
|
142
|
-
Respond with structured analysis. Do NOT return JSON
|
|
165
|
+
Respond with structured analysis. Do NOT return JSON.`,$t=y({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:Nl,tools:{},maxIterations:2});var kl=`You are an expert database schema reviewer. Your job is to:
|
|
143
166
|
|
|
144
167
|
1. Validate the schema structure: every entity has fields, indexes, and relations properly defined.
|
|
145
168
|
2. Check completeness: all entities from requirements are present, all relationships are bidirectional where needed.
|
|
@@ -153,7 +176,7 @@ If you have access to the validate_schema tool, use it first. Then provide a det
|
|
|
153
176
|
- Specific fixes for each issue
|
|
154
177
|
- Overall assessment (ready / needs work)
|
|
155
178
|
|
|
156
|
-
Respond with structured analysis. Do NOT return JSON.`;function
|
|
179
|
+
Respond with structured analysis. Do NOT return JSON.`;function xe(){return y({name:"schema-refiner",description:"Reviews a data model schema for completeness, normalization, performance, and security. Has access to validate_schema tool.",systemPrompt:kl,tools:{},maxIterations:3})}var Dl=`You are a UX-focused frontend architect. You design detailed page specifications.
|
|
157
180
|
|
|
158
181
|
## Page Planning
|
|
159
182
|
For each page in the application:
|
|
@@ -175,7 +198,7 @@ For each page in the application:
|
|
|
175
198
|
- Group by access: public pages first, then protected.
|
|
176
199
|
- Order by user flow: signup -> login -> dashboard -> feature pages -> settings -> admin.
|
|
177
200
|
|
|
178
|
-
Respond with structured page specs. Do NOT return JSON.`,
|
|
201
|
+
Respond with structured page specs. Do NOT return JSON.`,_e=y({name:"page-planner",description:"Designs detailed page specifications with routes, form fields, actions, states, and UI elements. Use for frontend page design.",systemPrompt:Dl,tools:{},maxIterations:2});var _l=`You are a component design specialist. Given page specifications, you identify reusable components and shared patterns.
|
|
179
202
|
|
|
180
203
|
## Component Identification
|
|
181
204
|
- **Layout components**: main layout (with nav, sidebar, content area), auth layout (centered form), admin layout.
|
|
@@ -197,7 +220,7 @@ For each component:
|
|
|
197
220
|
- Recommend server vs client state strategy.
|
|
198
221
|
- Identify data fetching patterns (on mount, on action, real-time).
|
|
199
222
|
|
|
200
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
223
|
+
Respond with structured analysis. Do NOT return JSON.`,Yt=y({name:"component-analyzer",description:"Identifies reusable components, shared layouts, and state management patterns from page specifications. Use after page planning.",systemPrompt:_l,tools:{},maxIterations:2});var Il=`You are a frontend technology advisor. Given project requirements, you recommend the best frontend framework.
|
|
201
224
|
|
|
202
225
|
## Decision Criteria
|
|
203
226
|
|
|
@@ -222,7 +245,7 @@ State your recommendation clearly:
|
|
|
222
245
|
- Reasoning: 2-3 sentences explaining why
|
|
223
246
|
- Trade-offs: what you would lose with the alternative
|
|
224
247
|
|
|
225
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
248
|
+
Respond with structured analysis. Do NOT return JSON.`,Nr=y({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:Il,tools:{},maxIterations:2});var jl=`You are a web security specialist. You analyze project requirements for security concerns and design security policies.
|
|
226
249
|
|
|
227
250
|
## Authentication Analysis
|
|
228
251
|
- Determine the best auth strategy (JWT, session, OAuth) based on requirements.
|
|
@@ -246,7 +269,7 @@ Respond with structured analysis. Do NOT return JSON.`,Wo=f({name:"framework-sel
|
|
|
246
269
|
- Input sanitization: XSS prevention, SQL injection prevention.
|
|
247
270
|
- Brute force protection: account lockout, exponential backoff.
|
|
248
271
|
|
|
249
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
272
|
+
Respond with structured analysis. Do NOT return JSON.`,Ht=y({name:"security-analyzer",description:"Analyzes security requirements, threat vectors, and designs security policies. Use to understand auth needs before designing flows.",systemPrompt:jl,tools:{},maxIterations:2});var ql=`You are an authentication flow architect. You design detailed, numbered step-by-step auth flows.
|
|
250
273
|
|
|
251
274
|
For each flow (signup, login, logout, password reset, protected route middleware, API auth middleware):
|
|
252
275
|
|
|
@@ -276,32 +299,32 @@ For each flow (signup, login, logout, password reset, protected route middleware
|
|
|
276
299
|
- Protected route: check cookie/header, verify token, attach user to request, reject if invalid.
|
|
277
300
|
- API auth: same as above but for API routes, return 401 JSON.
|
|
278
301
|
|
|
279
|
-
Respond with structured numbered flows. Do NOT return JSON.`,
|
|
302
|
+
Respond with structured numbered flows. Do NOT return JSON.`,Ie=y({name:"flow-designer",description:"Designs detailed step-by-step authentication flows (signup, login, logout, password reset, middleware). Use after security analysis.",systemPrompt:ql,tools:{},maxIterations:2});function Vs(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 Ll(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 Ul(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 kr(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=`${ne}
|
|
280
303
|
|
|
281
|
-
Output only markdown. Do NOT output JSON.`,s=await
|
|
304
|
+
Output only markdown. Do NOT output JSON.`,s=await Vs(o,a,Rr(n)),{overview:i,techStack:l}=Ll(s),p=await Vs(o,a,wr(n,s)),{featureDecisions:c}=Ul(p);r?.info("Delegating to data-modeler specialist");let d=(await V(pe,`Analyze the data model for this project:
|
|
282
305
|
|
|
283
306
|
${n}
|
|
284
307
|
|
|
285
308
|
Features:
|
|
286
|
-
${
|
|
309
|
+
${c}`,{parentModel:o})).output;r?.info("Delegating to frontend-architect specialist");let g=[s,c,d].join(`
|
|
287
310
|
|
|
288
311
|
---
|
|
289
312
|
|
|
290
|
-
`),
|
|
313
|
+
`),R=(await V(_e,`Design the pages and routes for this project:
|
|
291
314
|
|
|
292
315
|
${n}
|
|
293
316
|
|
|
294
317
|
Context:
|
|
295
|
-
${
|
|
318
|
+
${g}`,{parentModel:o})).output;r?.info("Delegating to auth-designer specialist");let w=[g,R].join(`
|
|
296
319
|
|
|
297
320
|
---
|
|
298
321
|
|
|
299
|
-
`),
|
|
322
|
+
`),G=(await V(Ie,`Design the authentication flows for this project:
|
|
300
323
|
|
|
301
324
|
${n}
|
|
302
325
|
|
|
303
326
|
Context:
|
|
304
|
-
${
|
|
327
|
+
${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 Qt=class{stageName="requirements";async process(t,o){return kr(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "design"}};var Fl=`You are an API endpoint analyst. Given a data model and requirements, you derive the complete API surface.
|
|
305
328
|
|
|
306
329
|
## Endpoint Discovery
|
|
307
330
|
- For each entity in the data model, determine CRUD operations: create, read (by ID), list (with filters/pagination), update, delete.
|
|
@@ -318,7 +341,7 @@ ${L}`,{parentModel:o})).output;return r?.info("Requirements stage complete (spec
|
|
|
318
341
|
- Mark which endpoints require specific roles (admin, owner).
|
|
319
342
|
- Identify resource-ownership checks (user can only access their own data).
|
|
320
343
|
|
|
321
|
-
Respond with structured analysis using headings and bullet points. Do NOT return JSON.`,
|
|
344
|
+
Respond with structured analysis using headings and bullet points. Do NOT return JSON.`,je=y({name:"endpoint-analyzer",description:"Analyzes data model and requirements to derive API endpoints, routes, and auth annotations. Use before generating the API design.",systemPrompt:Fl,tools:{},maxIterations:2});var Gl=`You are an API contract specialist. Given endpoints and a data model, you design detailed request/response contracts.
|
|
322
345
|
|
|
323
346
|
## Request Design
|
|
324
347
|
- For each endpoint, define: required fields, optional fields, field types, validation rules.
|
|
@@ -342,25 +365,25 @@ Respond with structured analysis using headings and bullet points. Do NOT return
|
|
|
342
365
|
- Use consistent field naming (camelCase for JSON, snake_case for query params if preferred).
|
|
343
366
|
- Use ISO 8601 for dates in responses.
|
|
344
367
|
|
|
345
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
368
|
+
Respond with structured analysis. Do NOT return JSON.`,qe=y({name:"contract-designer",description:"Designs detailed request/response contracts, validation rules, and error responses per API endpoint. Use after endpoint analysis.",systemPrompt:Gl,tools:{},maxIterations:2});function Bl(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(`
|
|
346
369
|
|
|
347
370
|
---
|
|
348
371
|
|
|
349
|
-
`)}async function
|
|
372
|
+
`)}async function Dr(e,t,o,r){r?.debug("Design stage started (specialist agents)");let n=Bl(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(je,`Design the API routes for this project:
|
|
350
373
|
|
|
351
|
-
${n}`,{parentModel:o})).output;r?.info("Delegating to api-designer contract-designer specialist");let i=await
|
|
374
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to api-designer contract-designer specialist");let i=await V(qe,`Design detailed request/response contracts for these API endpoints:
|
|
352
375
|
|
|
353
376
|
${s}
|
|
354
377
|
|
|
355
378
|
Project context:
|
|
356
|
-
${n}`,{parentModel:o}),l=`${
|
|
379
|
+
${n}`,{parentModel:o}),l=`${ne}
|
|
357
380
|
|
|
358
|
-
Output only markdown. Do NOT output JSON.`,
|
|
381
|
+
Output only markdown. Do NOT output JSON.`,p=await o.invoke([{role:"system",content:l},{role:"user",content:vr(n,s+`
|
|
359
382
|
|
|
360
|
-
`+i.output)}],{temperature:.3,maxOutputTokens:8192}).then(
|
|
361
|
-
`,
|
|
383
|
+
`+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 Vt=class{stageName="design";async process(t,o){return Dr(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "complete"}};function _r(e,t){return [`# ${e} Implementation Plan
|
|
384
|
+
`,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(`
|
|
362
385
|
|
|
363
|
-
`)}async function
|
|
386
|
+
`)}async function zl(e,t){await writeFile(t,e,"utf-8");}var $l=`You are a QA-minded tech lead. You identify edge cases that developers often miss.
|
|
364
387
|
|
|
365
388
|
For each domain area (Authentication, Data, API, Frontend, Integrations):
|
|
366
389
|
|
|
@@ -376,7 +399,7 @@ For each domain area (Authentication, Data, API, Frontend, Integrations):
|
|
|
376
399
|
- **Frontend**: empty states, loading states, network errors, form resubmission, back button behavior.
|
|
377
400
|
- **Integrations**: external API down, timeout, rate limited, invalid response format.
|
|
378
401
|
|
|
379
|
-
Respond with structured edge cases grouped by area. Do NOT return JSON.`,
|
|
402
|
+
Respond with structured edge cases grouped by area. Do NOT return JSON.`,Le=y({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:$l,tools:{},maxIterations:2});var Yl=`You are a testing strategy specialist. You design comprehensive manual testing checklists.
|
|
380
403
|
|
|
381
404
|
## Testing Checklist Design
|
|
382
405
|
Group test items by flow (Authentication, CRUD operations, Edge cases, etc.).
|
|
@@ -399,38 +422,38 @@ Present as grouped checklist items using markdown checkboxes:
|
|
|
399
422
|
### Flow Name
|
|
400
423
|
- [ ] Test item description -> Expected result
|
|
401
424
|
|
|
402
|
-
Respond with structured checklist. Do NOT return JSON.`,
|
|
425
|
+
Respond with structured checklist. Do NOT return JSON.`,Ue=y({name:"testing-strategist",description:"Designs comprehensive manual testing checklists grouped by feature flow. Use for testing strategy and QA planning.",systemPrompt:Yl,tools:{},maxIterations:2});function Hl(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(`
|
|
403
426
|
|
|
404
427
|
---
|
|
405
428
|
|
|
406
|
-
`)}function
|
|
407
|
-
`)[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
|
|
429
|
+
`)}function Ql(e){let o=(e.sections.overview??e.projectDescription??"").split(`
|
|
430
|
+
`)[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 Ir(e,t,o,r){r?.debug("Synthesis stage started (specialist agents)");let n=Hl(t);if(!n)return {message:"No prior sections. Complete earlier stages first.",advance:false,sections:{}};let a=`${ne}
|
|
408
431
|
|
|
409
|
-
${
|
|
432
|
+
${Ar}
|
|
410
433
|
|
|
411
|
-
Output only markdown. Do NOT output JSON.`,s=await o.invoke([{role:"system",content:a},{role:"user",content
|
|
434
|
+
Output only markdown. Do NOT output JSON.`,s=await o.invoke([{role:"system",content:a},{role:"user",content:Mr(n)}],{temperature:.3,maxOutputTokens:8192}).then(m=>m.text?.trim()??"");r?.info("Delegating to execution-planner edge-case-analyzer specialist");let l=(await V(Le,`Identify edge cases for this project:
|
|
412
435
|
|
|
413
|
-
${n}`,{parentModel:o})).output;r?.info("Delegating to execution-planner testing-strategist specialist");let
|
|
436
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to execution-planner testing-strategist specialist");let c=(await V(Ue,`Design the manual testing checklist for this project:
|
|
414
437
|
|
|
415
|
-
${n}`,{parentModel:o})).output,
|
|
438
|
+
${n}`,{parentModel:o})).output,u=Ql(t),d={...t.sections,executionPlan:s||null,edgeCases:l||null,testingChecklist:c||null},g=_r(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 Wt=class{stageName="complete";async process(t,o){return Ir(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return null}};var Vl={discovery:new zt,requirements:new Qt,design:new Vt,complete:new Wt};function jr(e){return Vl[e]}async function Ws(e,t,o,r,n){n?.debug("Stage processor invoked",{stage:e});let s=await jr(e).process(o,{userMessage:t,model:r,logger:n}),i=Bs(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 qr=["discovery","requirements","design","complete"];async function Te(e,t,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=M(n),s=t??Gs();s=Gt(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 Ws(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=qr.indexOf(u),m=g>=0&&g<qr.length-1?qr[g+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:u,to:m}),u=m,s=xr(s),s={...s,stage:u},r?.info("Stage",{stage:u}),d=await c(u);}return s=Gt(s,"assistant",i),r?.info("Planning chat turn done",{stage:u,hasPlanMarkdown:!!p}),{message:i,context:s,pendingQuestions:l,planMarkdown:p}}var Ks=10;async function Lr(e){let{input:t,model:o,onStep:r,logger:n}=e;n?.info("Starting planning agent",{maxTurns:Ks});let a=null,s=await Te(t,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.planMarkdown&&i<Ks;){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 Te(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}}async function Wl(e){let{existingPlan:t,feedback:o,logger:r}=e;if(r?.info("Editing plan",{feedbackLength:o.length}),!t||t.trim().length<50)throw new Error("existingPlan is too short or empty. Provide a valid plan to edit.");if(!o||o.trim().length===0)throw new Error("feedback is empty. Provide edit instructions.");let n=e.model??{provider:"openai",model:"gpt-4o-mini"},i=(await M(n).invoke([{role:"system",content:Er},{role:"user",content:Or(t,o)}],{temperature:.3,maxOutputTokens:16384})).text?.trim()??"";if(!i)throw new Error("Model returned empty response when editing plan.");return r?.info("Plan edited successfully",{outputLength:i.length}),i}function Kl(e){return e.fields.length?`| Field | Type | Constraints | Description |
|
|
416
439
|
| --- | --- | --- | --- |
|
|
417
|
-
${
|
|
418
|
-
`)}`:""}function
|
|
440
|
+
${e.fields.map(o=>{let r=[o.required?"required":"",o.unique?"unique":""].filter(Boolean).join(", ");return `| ${o.name} | ${o.type} | ${r||"-"} | ${o.description} |`}).join(`
|
|
441
|
+
`)}`:""}function Xl(e){let t=`## Data Models
|
|
419
442
|
|
|
420
|
-
**Database:** ${
|
|
421
|
-
**Reasoning:** ${
|
|
422
|
-
`,o=
|
|
423
|
-
**Relations:** `+a.join("; "):"",i=r.indexes.map(
|
|
443
|
+
**Database:** ${e.type}
|
|
444
|
+
**Reasoning:** ${e.reasoning}
|
|
445
|
+
`,o=e.entities.map(r=>{let n=Kl(r),a=r.relations.map(p=>p.field+" \u2192 "+p.references+" ("+p.description+")"),s=a.length?`
|
|
446
|
+
**Relations:** `+a.join("; "):"",i=r.indexes.map(p=>p.name+" ["+p.fields.join(", ")+"]"+(p.unique?" (unique)":"")),l=i.length?`
|
|
424
447
|
**Indexes:** `+i.join("; "):"";return `### ${r.name}
|
|
425
448
|
|
|
426
449
|
${r.description}
|
|
427
450
|
|
|
428
451
|
${n}${s}${l}`}).join(`
|
|
429
452
|
|
|
430
|
-
`);return `${
|
|
431
|
-
${o}`}function
|
|
453
|
+
`);return `${t}
|
|
454
|
+
${o}`}function Zl(e){return `## Feature Decisions
|
|
432
455
|
|
|
433
|
-
${
|
|
456
|
+
${e.map(o=>{let r=o.apis.map(n=>` - \`${n.operation}\` ${n.name}: ${n.description}`).join(`
|
|
434
457
|
`);return `### ${o.name}
|
|
435
458
|
|
|
436
459
|
${o.description} (entity: ${o.entity})
|
|
@@ -438,25 +461,25 @@ ${o.description} (entity: ${o.entity})
|
|
|
438
461
|
**APIs:**
|
|
439
462
|
${r}`}).join(`
|
|
440
463
|
|
|
441
|
-
`)}`}function
|
|
442
|
-
`);return `# ${
|
|
464
|
+
`)}`}function ep(e){let t=e.project,o=t.features.map(r=>`- ${r}`).join(`
|
|
465
|
+
`);return `# ${t.name}
|
|
443
466
|
|
|
444
|
-
**Goal:** ${
|
|
445
|
-
**Domain:** ${
|
|
467
|
+
**Goal:** ${t.goal}
|
|
468
|
+
**Domain:** ${t.domain}
|
|
446
469
|
|
|
447
|
-
${
|
|
470
|
+
${e.summary.overview}
|
|
448
471
|
|
|
449
472
|
**Key Features:**
|
|
450
|
-
${o}`}function
|
|
451
|
-
`)}function
|
|
473
|
+
${o}`}function tp(e){let t=e.project;return ["## Tech Stack","",`- **Database:** ${t.database}`,`- **Backend Runtime:** ${t.backendRuntime}`,`- **API Style:** ${t.apiStyle}`].join(`
|
|
474
|
+
`)}function op(e,t,o){let r=["## Actors and Flows"];for(let n of e){r.push(`
|
|
452
475
|
### ${n.name}
|
|
453
|
-
${n.description}`);let a=
|
|
476
|
+
${n.description}`);let a=t.filter(s=>s.actorId===n.id);if(a.length){r.push("**Flows:**");for(let s of a)r.push(`- ${s.name}: ${s.description} (trigger: ${s.trigger}, outcome: ${s.outcome})`);}}if(o.length){r.push(`
|
|
454
477
|
### Key User Stories`);for(let n of o.slice(0,10))r.push(`- As **${n.actor}**, I want to **${n.action}**, so that **${n.benefit}**`);o.length>10&&r.push(`- ... and ${o.length-10} more stories`);}return r.join(`
|
|
455
|
-
`)}function
|
|
478
|
+
`)}function Xs(e){let t={overview:`## Overview
|
|
456
479
|
|
|
457
|
-
${
|
|
480
|
+
${e.summary.overview}`,techStack:tp(e),featureDecisions:Zl(e.modules),dataModels:Xl(e.database),pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};return {stage:"design",projectDescription:ep(e)+`
|
|
458
481
|
|
|
459
|
-
|
|
482
|
+
`+op(e.actors,e.flows,e.stories),sections:t,history:[],pendingQuestions:[]}}var rp=8;async function np(e){let{requirement:t,model:o,onStep:r,logger:n}=e;n?.info("Starting planning from requirements (fast path)",{project:t.project.name});let a=Xs(t),s=`Generate the implementation plan for "${t.project.name}". The project description, tech stack, features, and data models are already provided in context. Proceed with API routes, implementation details, execution plan, edge cases, and testing checklist.`,i=await Te(s,a,{model:o,logger:n}),l=1;for(;!i.planMarkdown&&l<rp;)n?.debug("Planning from requirements turn",{turn:l}),i=await Te("continue - produce the complete implementation plan.",i.context,{model:o,logger:n}),l++;let p=i.planMarkdown??i.message,c=i.context.history.map(u=>({role:u.role,content:u.content}));return n?.info("Planning from requirements completed",{turns:l,hasPlanMarkdown:!!i.planMarkdown}),{output:p,steps:[],totalUsage:void 0,messages:c}}var sp="discovery",Zs={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null},Kt=class{data={};withStage(t){return this.data.stage=t,this}withProjectDescription(t){return this.data.projectDescription=t,this}withSections(t){return this.data.sections={...this.data.sections??Zs,...t},this}withHistory(t){return this.data.history=t,this}withPendingQuestions(t){return this.data.pendingQuestions=t,this}reset(){return this.data={},this}build(){return {stage:this.data.stage??sp,projectDescription:this.data.projectDescription??null,sections:this.data.sections??{...Zs},history:this.data.history??[],pendingQuestions:this.data.pendingQuestions??[]}}};function ap(){return new Kt}var Fe=z.object({id:z.string(),name:z.string(),description:z.string(),goals:z.array(z.string())}),Xt=z.object({actors:z.array(Fe),message:z.string()});var Ge=z.object({id:z.string(),actorId:z.string(),name:z.string(),description:z.string(),trigger:z.string(),outcome:z.string()}),Zt=z.object({flows:z.array(Ge),message:z.string()});var Be=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())}),eo=z.object({stories:z.array(Be),message:z.string()});var ea=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())}),Je=z.object({id:z.string(),name:z.string(),description:z.string(),entity:z.string(),apis:z.array(ea)}),to=z.object({modules:z.array(Je),summary:z.object({totalModules:z.number(),totalApis:z.number()}),message:z.string()});var ta=z.object({name:z.string(),type:z.string(),required:z.boolean(),unique:z.boolean(),description:z.string(),default:z.string().optional()}),oa=z.object({name:z.string(),fields:z.array(z.string()),unique:z.boolean()}),ra=z.object({field:z.string(),references:z.string(),description:z.string()}),na=z.object({name:z.string(),description:z.string(),fields:z.array(ta),indexes:z.array(oa),relations:z.array(ra)}),Pe=z.object({type:z.enum(["mongodb","postgresql"]),reasoning:z.string(),entities:z.array(na)});var ze=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"])}),oo=z.object({id:z.string(),question:z.string(),context:z.string(),suggestions:z.array(z.string()),multiSelect:z.boolean(),required:z.boolean()}),sa=z.object({role:z.enum(["user","assistant"]),content:z.string()}),ip=z.object({stage:z.enum(["discovery","requirements","design","complete"]),projectBrief:ze.nullable(),actors:z.array(Fe),flows:z.array(Ge),stories:z.array(Be),modules:z.array(Je),database:Pe.nullable(),history:z.array(sa),pendingQuestions:z.array(oo)});var aa=z.object({totalActors:z.number(),totalFlows:z.number(),totalStories:z.number(),totalModules:z.number(),totalEntities:z.number(),overview:z.string()}),Ur=z.object({project:ze,actors:z.array(Fe),flows:z.array(Ge),stories:z.array(Be),modules:z.array(Je),database:Pe,summary:aa});var Re=`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.
|
|
460
483
|
|
|
461
484
|
You work in stages: discovery (understand the project and tech preferences), requirements (actors, flows, stories, modules), design (database + APIs), and complete (final document).
|
|
462
485
|
|
|
@@ -468,7 +491,7 @@ Guidelines:
|
|
|
468
491
|
- Never repeat a question already answered in the conversation history.
|
|
469
492
|
- When the user says "continue", "yes", "looks good", or similar, treat it as confirmation and advance.
|
|
470
493
|
- Return valid JSON only when the prompt asks for JSON (no markdown code fences unless specified).
|
|
471
|
-
- Backend is Node.js only; database is MongoDB or PostgreSQL per user preference.`;var
|
|
494
|
+
- Backend is Node.js only; database is MongoDB or PostgreSQL per user preference.`;var Fr=`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.
|
|
472
495
|
|
|
473
496
|
Determine from the user's words:
|
|
474
497
|
- Project name and goal
|
|
@@ -483,7 +506,7 @@ Question rules:
|
|
|
483
506
|
- 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).
|
|
484
507
|
- Never ask: scale, "how many users?", "what's the complexity?", or generic intake-form questions.
|
|
485
508
|
- Before asking, check conversation history \u2014 never repeat something already answered.
|
|
486
|
-
- 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.`,
|
|
509
|
+
- 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.`,ia=`## Current user message:
|
|
487
510
|
{userMessage}
|
|
488
511
|
|
|
489
512
|
## Prior conversation (if any):
|
|
@@ -517,10 +540,10 @@ Return ONLY valid JSON (no markdown, no explanation) in this shape:
|
|
|
517
540
|
}
|
|
518
541
|
|
|
519
542
|
For tech choices (API style, database), populate "suggestions" with the predefined options. For all other questions, use "suggestions": [].
|
|
520
|
-
If needsClarification is true, projectBrief can have empty/default values. If false, projectBrief must be complete.`;function
|
|
543
|
+
If needsClarification is true, projectBrief can have empty/default values. If false, projectBrief must be complete.`;function Gr(e,t){return ia.replace("{userMessage}",e).replace("{history}",t||"(No prior messages)")}var ro=`## Project:
|
|
521
544
|
- **Name**: {projectName}
|
|
522
545
|
- **Goal**: {projectGoal}
|
|
523
|
-
- **Features**: {projectFeatures}`,
|
|
546
|
+
- **Features**: {projectFeatures}`,la=`${ro}
|
|
524
547
|
|
|
525
548
|
Identify ALL distinct user types (actors) who will use this system. 2-5 actors. Include unauthenticated and admin roles if applicable.
|
|
526
549
|
|
|
@@ -530,7 +553,7 @@ Return ONLY valid JSON:
|
|
|
530
553
|
{ "id": "actor-1", "name": "Name", "description": "Who they are", "goals": ["goal1", "goal2"] }
|
|
531
554
|
],
|
|
532
555
|
"message": "Brief explanation"
|
|
533
|
-
}`,
|
|
556
|
+
}`,pa=`${ro}
|
|
534
557
|
|
|
535
558
|
## Actors (JSON):
|
|
536
559
|
{actors}
|
|
@@ -543,7 +566,7 @@ Return ONLY valid JSON:
|
|
|
543
566
|
{ "id": "flow-1", "actorId": "actor-1", "name": "Flow Name", "description": "...", "trigger": "...", "outcome": "..." }
|
|
544
567
|
],
|
|
545
568
|
"message": "Brief explanation"
|
|
546
|
-
}`,
|
|
569
|
+
}`,ca=`${ro}
|
|
547
570
|
|
|
548
571
|
## Actors: {actors}
|
|
549
572
|
|
|
@@ -558,7 +581,7 @@ Return ONLY valid JSON:
|
|
|
558
581
|
{ "id": "story-1", "flowId": "flow-1", "actor": "ActorName", "action": "...", "benefit": "...", "preconditions": [], "postconditions": [], "dataInvolved": ["User.email", "Order.total"] }
|
|
559
582
|
],
|
|
560
583
|
"message": "Brief explanation"
|
|
561
|
-
}`,
|
|
584
|
+
}`,ua=`${ro}
|
|
562
585
|
|
|
563
586
|
## Actors: {actors}
|
|
564
587
|
## Flows: {flows}
|
|
@@ -574,7 +597,7 @@ Return ONLY valid JSON:
|
|
|
574
597
|
],
|
|
575
598
|
"summary": { "totalModules": 0, "totalApis": 0 },
|
|
576
599
|
"message": "Brief explanation"
|
|
577
|
-
}`;function
|
|
600
|
+
}`;function Br(e,t,o){return la.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o)}function Jr(e,t,o,r){return pa.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r)}function zr(e,t,o,r,n){return ca.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n)}function $r(e,t,o,r,n,a){return ua.replace("{projectName}",e).replace("{projectGoal}",t).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n).replace("{stories}",a)}var lp=`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.
|
|
578
601
|
|
|
579
602
|
## Project brief (includes database: "mongodb" | "postgresql"):
|
|
580
603
|
{projectBrief}
|
|
@@ -602,7 +625,7 @@ Return ONLY valid JSON (no markdown) in this exact shape. Set "type" to the data
|
|
|
602
625
|
"relations": [ { "field": "refField", "references": "OtherEntity", "description": "..." } ]
|
|
603
626
|
}
|
|
604
627
|
]
|
|
605
|
-
}`;var
|
|
628
|
+
}`;var Yr="You output only valid JSON. No markdown, no explanation.";function Hr(e,t,o){return lp.replace("{projectBrief}",e).replace("{modules}",t).replace("{stories}",o)}var Qr="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.",da=`## Project brief (JSON):
|
|
606
629
|
{projectBrief}
|
|
607
630
|
|
|
608
631
|
## Actors (JSON):
|
|
@@ -638,14 +661,14 @@ Return ONLY valid JSON in this shape (no markdown, no extra text):
|
|
|
638
661
|
"totalEntities": 0,
|
|
639
662
|
"overview": "string"
|
|
640
663
|
}
|
|
641
|
-
}`;function
|
|
642
|
-
`)}function
|
|
643
|
-
`)}function
|
|
644
|
-
`),a=
|
|
664
|
+
}`;function Vr(e,t,o,r,n,a){return da.replace("{projectBrief}",e).replace("{actors}",t).replace("{flows}",o).replace("{stories}",r).replace("{modules}",n).replace("{database}",a)}function Wr(){return {stage:"discovery",projectBrief:null,actors:[],flows:[],stories:[],modules:[],database:null,history:[],pendingQuestions:[]}}function Kr(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 Ke(e,t,o){let r={role:t,content:o};return {...e,history:[...e.history,r]}}function no(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 ma(e){return e.map(t=>`${t.name}: ${t.entity} (${t.apis.length} APIs)`).join(`
|
|
665
|
+
`)}function ga(e){return e.map(t=>`- ${t.actor}: ${t.action}`).join(`
|
|
666
|
+
`)}function X(e){let t=e.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(t);return o?.[1]?o[1].trim():t}function ee(e){try{return {success:!0,data:JSON.parse(e)}}catch(t){return {success:false,error:t instanceof Error?t.message:String(t)}}}async function so(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(`
|
|
667
|
+
`),a=Gr(e,n),i=[{role:"system",content:`${Re}
|
|
645
668
|
|
|
646
|
-
${
|
|
669
|
+
${Fr}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.4,maxOutputTokens:4096}),p=X(l.text),c=ee(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=oo.safeParse(w);z.success&&m.push(z.data);}let R=null;if(u.projectBrief&&!g){let w=ze.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 fa(e,t,o){if(e.invokeObject)return (await e.invokeObject(t,Xt,{temperature:.4,maxOutputTokens:4096})).data;let r=await e.invoke(t,{temperature:.4,maxOutputTokens:4096}),n=ee(X(r.text));if(!n.success)throw new Error(`Actors: ${n.error}`);let a=Xt.safeParse(n.data);if(!a.success)throw new Error(`Actors schema: ${a.error.message}`);return a.data}async function ha(e,t,o,r){if(e.invokeObject)return (await e.invokeObject(t,Zt,{temperature:.4,maxOutputTokens:8192})).data;let n=await e.invoke(t,{temperature:.4,maxOutputTokens:8192}),a=ee(X(n.text));if(!a.success)throw new Error(`Flows: ${a.error}`);let s=Zt.safeParse(a.data);if(!s.success)throw new Error(`Flows schema: ${s.error.message}`);return s.data}async function ya(e,t,o,r,n){if(e.invokeObject)return (await e.invokeObject(t,eo,{temperature:.4,maxOutputTokens:16384})).data;let a=await e.invoke(t,{temperature:.4,maxOutputTokens:16384}),s=ee(X(a.text));if(!s.success)throw new Error(`Stories: ${s.error}`);let i=eo.safeParse(s.data);if(!i.success)throw new Error(`Stories schema: ${i.error.message}`);return i.data}async function Sa(e,t,o,r,n,a){if(e.invokeObject)return (await e.invokeObject(t,to,{temperature:.4,maxOutputTokens:16384})).data;let s=await e.invoke(t,{temperature:.4,maxOutputTokens:16384}),i=ee(X(s.text));if(!i.success)throw new Error(`Modules: ${i.error}`);let l=to.safeParse(i.data);if(!l.success)throw new Error(`Modules schema: ${l.error.message}`);return l.data}async function ao(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:Re}];try{l.push({role:"user",content:Br(a,s,i)});let c=(await fa(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:Jr(a,s,i,JSON.stringify(c))});let d=(await ha(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:zr(a,s,i,JSON.stringify(c),JSON.stringify(d))});let m=(await ya(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:$r(a,s,i,JSON.stringify(c),JSON.stringify(d),JSON.stringify(m))});let w=(await Sa(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 io(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=ma(t.modules),i=ga(t.stories),l=Hr(a,s,i),p=[{role:"system",content:Yr},{role:"user",content:l}],c=await o.invoke(p,{temperature:.3,maxOutputTokens:8192}),u=X(c.text),d=ee(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=Pe.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 lo(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=Vr(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:`${Re}
|
|
647
670
|
|
|
648
|
-
${
|
|
671
|
+
${Qr}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.3,maxOutputTokens:16384}),p=X(l.text),c=ee(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=Ur.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 po=class{stageName="discovery";async process(t,o){return so(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "requirements"}};var co=class{stageName="requirements";async process(t,o){return ao(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "design"}};var uo=class{stageName="design";async process(t,o){return io(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return "complete"}};var mo=class{stageName="complete";async process(t,o){return lo(o.userMessage,t,o.model,o.logger)}canAdvance(t){return t.advance}getNextStageName(){return null}};var cp={discovery:new po,requirements:new co,design:new uo,complete:new mo};function Xr(e){return cp[e]}async function ba(e,t,o,r,n){n?.debug("Stage processor invoked",{stage:e});let s=await Xr(e).process(o,{userMessage:t,model:r,logger:n}),i=Kr(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 Zr=["discovery","requirements","design","complete"];async function go(e,t,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=M(n),s=t??Wr();s=Ke(s,"user",e),r?.info("Chat turn",{stage:s.stage,messageLength:e.length});let i="",l=[],p=null,c=async g=>{let m=await ba(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=Zr.indexOf(u),m=g>=0&&g<Zr.length-1?Zr[g+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:u,to:m}),u=m,s=no(s),s={...s,stage:u},r?.info("Stage",{stage:u}),d=await c(u),s={...s,pendingQuestions:l};}return s=Ke(s,"assistant",i),r?.info("Chat turn done",{stage:u,hasFinalRequirement:!!p}),{message:i,context:s,questions:l,finalRequirement:p}}var xa=10;async function Xe(e){let{input:t,model:o,onStep:r,logger:n}=e;n?.info("Starting requirement gatherer agent",{maxTurns:xa});let a=null,s=await go(t,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.finalRequirement&&i<xa;)n?.debug("Requirement gatherer turn",{turn:i}),s=await go("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 dp="discovery",fo=class{data={};withStage(t){return this.data.stage=t,this}withProjectBrief(t){return this.data.projectBrief=t,this}withActors(t){return this.data.actors=t,this}withFlows(t){return this.data.flows=t,this}withStories(t){return this.data.stories=t,this}withModules(t){return this.data.modules=t,this}withDatabase(t){return this.data.database=t,this}withHistory(t){return this.data.history=t,this}withPendingQuestions(t){return this.data.pendingQuestions=t,this}reset(){return this.data={},this}build(){return {stage:this.data.stage??dp,projectBrief:this.data.projectBrief??null,actors:this.data.actors??[],flows:this.data.flows??[],stories:this.data.stories??[],modules:this.data.modules??[],database:this.data.database??null,history:this.data.history??[],pendingQuestions:this.data.pendingQuestions??[]}}};function mp(){return new fo}var en=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()}),Ta=z.object({name:z.string().default(""),fields:z.array(z.string()).default([]),unique:z.coerce.boolean().default(false)}),gp=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"])),Pa=z.object({field:z.string(),references:z.string(),type:gp,description:z.string().default("")}),tn=z.object({name:z.string(),description:z.string().default(""),fields:z.union([z.array(en),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=en.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(Ta).default([]),relations:z.array(Pa).default([])}),fp=z.string().transform(e=>e.toLowerCase().trim()).pipe(z.enum(["mongodb","postgresql"])),ae=z.object({type:fp,reasoning:z.string().default(""),entities:z.array(tn).default([])});var $e=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 Ye=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($e),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=$e.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 te=z.object({projectName:z.string().default("project").describe("projectName must be in kebab-case"),projectDescription:z.string().default(""),modules:z.union([z.array(Ye),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=Ye.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 ho=`You are a senior database architect specializing in both MongoDB and PostgreSQL schema design.
|
|
649
672
|
|
|
650
673
|
You analyze requirements and produce enterprise-quality data models with:
|
|
651
674
|
- Properly typed fields (MongoDB: ObjectId, string, number, date, array; PostgreSQL: uuid, varchar, text, integer, timestamp, jsonb)
|
|
@@ -654,7 +677,7 @@ You analyze requirements and produce enterprise-quality data models with:
|
|
|
654
677
|
- Validation constraints and default values
|
|
655
678
|
- Security considerations (hashed passwords, encrypted fields)
|
|
656
679
|
|
|
657
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
680
|
+
Output only valid JSON unless instructed otherwise.`;var Ra=`## Requirements:
|
|
658
681
|
{requirement}
|
|
659
682
|
|
|
660
683
|
Design the database schema. Determine the best database type (mongodb or postgresql) based on the requirements, or use the one specified.
|
|
@@ -677,13 +700,13 @@ Return ONLY valid JSON:
|
|
|
677
700
|
"relations": [ { "field": "refField", "references": "OtherEntity", "type": "1:N", "description": "..." } ]
|
|
678
701
|
}
|
|
679
702
|
]
|
|
680
|
-
}`,
|
|
703
|
+
}`,wa=`## Current Schema (JSON):
|
|
681
704
|
{existingSchema}
|
|
682
705
|
|
|
683
706
|
## Feedback:
|
|
684
707
|
{feedback}
|
|
685
708
|
|
|
686
|
-
Update the schema based on the feedback. Return the complete updated schema as valid JSON in the same format.`;function
|
|
709
|
+
Update the schema based on the feedback. Return the complete updated schema as valid JSON in the same format.`;function on(e){return Ra.replace("{requirement}",e)}function rn(e,t){return wa.replace("{existingSchema}",e).replace("{feedback}",t)}var va=`## Project: {projectName}
|
|
687
710
|
## Goal: {projectGoal}
|
|
688
711
|
## Database: {databaseType}
|
|
689
712
|
|
|
@@ -713,7 +736,7 @@ Apply the 5-phase enterprise data modeling process:
|
|
|
713
736
|
- Verify every entity referenced in relations exists.
|
|
714
737
|
- Verify no orphan fields or missing indexes.
|
|
715
738
|
|
|
716
|
-
Return ONLY valid JSON in the DataModelDesign format.`;function
|
|
739
|
+
Return ONLY valid JSON in the DataModelDesign format.`;function nn(e,t,o,r){return va.replace("{projectName}",e).replace("{projectGoal}",t).replace("{databaseType}",o).replace("{context}",r)}var oe=`You are an expert MongoDB database architect with deep expertise in schema design, performance optimization, scalability, and domain-driven design. You analyze requirements systematically using a multi-phase approach to create production-ready database schemas.
|
|
717
740
|
|
|
718
741
|
## ANALYSIS FRAMEWORK
|
|
719
742
|
|
|
@@ -763,44 +786,44 @@ Synthesize all analyses into the final schema:
|
|
|
763
786
|
2. **Relationships**: One-to-One: reference in BOTH collections; Many-to-One: reference in "many" side; One-to-Many: FORBIDDEN - invert to many-to-one
|
|
764
787
|
3. **Data Types**: NO arrays of ObjectIds; Timestamps: createdAt, updatedAt in EVERY collection; Enums: fieldType: 'enum' with values array
|
|
765
788
|
4. **Security**: NO separate "Auth" collection; NO token storage; Password fields: isPrivate: true
|
|
766
|
-
5. **Authorization (RBAC)**: Define permissions per role on user modules`;function
|
|
767
|
-
- `);return `### ${o+1}. ${
|
|
768
|
-
**Description:** ${
|
|
789
|
+
5. **Authorization (RBAC)**: Define permissions per role on user modules`;function sn(e){return !e||e.length===0?'No specific user types defined. Assume a general "User" role.':e.map((t,o)=>{let r=t.goals.filter(n=>n.trim()).join(`
|
|
790
|
+
- `);return `### ${o+1}. ${t.name}
|
|
791
|
+
**Description:** ${t.description}
|
|
769
792
|
**Goals:**
|
|
770
793
|
- ${r||"No specific goals defined"}`}).join(`
|
|
771
794
|
|
|
772
|
-
`)}function
|
|
795
|
+
`)}function an(e,t){return !e||e.length===0?"No specific user flows defined.":e.map((o,r)=>{let n=t.find(a=>a.id===o.actorId);return `### ${r+1}. ${o.name}
|
|
773
796
|
**Actor:** ${n?.name||"User"}
|
|
774
797
|
**Description:** ${o.description}
|
|
775
798
|
**Trigger:** ${o.trigger||"User initiates action"}
|
|
776
799
|
**Outcome:** ${o.outcome||"Action completed"}`}).join(`
|
|
777
800
|
|
|
778
|
-
`)}function
|
|
779
|
-
`);for(let i of s){let l=i.preconditions.filter(
|
|
780
|
-
`;l.length&&(
|
|
801
|
+
`)}function ln(e,t){if(!e||e.length===0)return "No specific user stories defined.";let o=new Map;for(let a of e){let s=o.get(a.flowId)||[];s.push(a),o.set(a.flowId,s);}let r=[];for(let a of t){let s=o.get(a.id)||[];if(s.length!==0){r.push(`### Flow: ${a.name}
|
|
802
|
+
`);for(let i of s){let l=i.preconditions.filter(d=>d.trim()),p=i.postconditions.filter(d=>d.trim()),c=i.dataInvolved.filter(d=>d.trim()),u=`**As a** ${i.actor}, **I want to** ${i.action}, **so that** ${i.benefit}
|
|
803
|
+
`;l.length&&(u+=`
|
|
781
804
|
**Preconditions:**
|
|
782
|
-
${l.map(
|
|
805
|
+
${l.map(d=>`- ${d}`).join(`
|
|
783
806
|
`)}
|
|
784
|
-
`),
|
|
807
|
+
`),p.length&&(u+=`
|
|
785
808
|
**Postconditions:**
|
|
786
|
-
${
|
|
809
|
+
${p.map(d=>`- ${d}`).join(`
|
|
787
810
|
`)}
|
|
788
|
-
`),
|
|
811
|
+
`),c.length&&(u+=`
|
|
789
812
|
**Data Involved (IMPORTANT):**
|
|
790
|
-
${
|
|
813
|
+
${c.map(d=>`- ${d}`).join(`
|
|
791
814
|
`)}
|
|
792
|
-
`),r.push(
|
|
815
|
+
`),r.push(u);}}}let n=e.filter(a=>!t.some(s=>s.id===a.flowId));if(n.length){r.push(`### Other Stories
|
|
793
816
|
`);for(let a of n){let s=a.dataInvolved.filter(l=>l.trim()),i=`**As a** ${a.actor}, **I want to** ${a.action}, **so that** ${a.benefit}
|
|
794
817
|
`;s.length&&(i+=`
|
|
795
818
|
**Data Involved:** ${s.join(", ")}
|
|
796
819
|
`),r.push(i);}}return r.join(`
|
|
797
|
-
`)}function
|
|
798
|
-
`)}function
|
|
820
|
+
`)}function pn(e){if(!e)return "No specific technical requirements. Use defaults.";let t=[`**Authentication:** ${e.authentication||"none"}`];return e.authorization?(t.push("**Authorization (RBAC):** Enabled"),e.roles?.length&&t.push(`**Defined Roles:** ${e.roles.join(", ")}`)):t.push("**Authorization:** Disabled"),e.realtime&&t.push("**Realtime Features:** Required"),e.fileUpload&&t.push("**File Upload:** Required"),e.search&&t.push("**Search Functionality:** Required"),e.integrations?.length&&t.push(`**Integrations:** ${e.integrations.join(", ")}`),t.join(`
|
|
821
|
+
`)}function yo(e){let t=new Set;for(let o of e)for(let r of o.dataInvolved)r.trim()&&t.add(r.trim());return Array.from(t)}function So(e){return e.map(t=>t.name.toLowerCase().replaceAll(/\s+/g,"_"))}function bo(e){return {projectName:e.projectName,projectGoal:e.projectGoal,projectDescription:e.projectDescription||e.projectGoal,userTypes:sn(e.actors),userFlows:an(e.flows,e.actors),userStories:ln(e.stories,e.flows),technicalRequirements:pn(e.technicalRequirements)}}function Ze(e){return `${oe}
|
|
799
822
|
|
|
800
823
|
Design a robust and efficient MongoDB database schema based on the following requirements:
|
|
801
824
|
|
|
802
825
|
## Requirements
|
|
803
|
-
${
|
|
826
|
+
${e}
|
|
804
827
|
|
|
805
828
|
## Guidelines
|
|
806
829
|
1. Use camelCase for module names and field names
|
|
@@ -808,39 +831,39 @@ ${t}
|
|
|
808
831
|
3. Define proper relationships between modules
|
|
809
832
|
4. Set appropriate permissions for user modules
|
|
810
833
|
|
|
811
|
-
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function
|
|
834
|
+
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function et(e){let t=bo(e);return `${oe}
|
|
812
835
|
|
|
813
836
|
---
|
|
814
837
|
|
|
815
838
|
## PROJECT CONTEXT
|
|
816
839
|
|
|
817
|
-
**Project Name:** ${
|
|
818
|
-
**Project Goal:** ${
|
|
819
|
-
**Description:** ${
|
|
840
|
+
**Project Name:** ${t.projectName}
|
|
841
|
+
**Project Goal:** ${t.projectGoal}
|
|
842
|
+
**Description:** ${t.projectDescription}
|
|
820
843
|
|
|
821
844
|
---
|
|
822
845
|
|
|
823
846
|
## USER TYPES (ACTORS)
|
|
824
847
|
|
|
825
|
-
${
|
|
848
|
+
${t.userTypes}
|
|
826
849
|
|
|
827
850
|
---
|
|
828
851
|
|
|
829
852
|
## USER FLOWS
|
|
830
853
|
|
|
831
|
-
${
|
|
854
|
+
${t.userFlows}
|
|
832
855
|
|
|
833
856
|
---
|
|
834
857
|
|
|
835
858
|
## USER STORIES WITH DATA REQUIREMENTS
|
|
836
859
|
|
|
837
|
-
${
|
|
860
|
+
${t.userStories}
|
|
838
861
|
|
|
839
862
|
---
|
|
840
863
|
|
|
841
864
|
## TECHNICAL REQUIREMENTS
|
|
842
865
|
|
|
843
|
-
${
|
|
866
|
+
${t.technicalRequirements}
|
|
844
867
|
|
|
845
868
|
---
|
|
846
869
|
|
|
@@ -868,7 +891,7 @@ Follow the 5-phase analysis framework:
|
|
|
868
891
|
### Step 5: Schema Construction
|
|
869
892
|
Generate the final schema with complete module definitions, fields, relationships, RBAC permissions, and timestamps.
|
|
870
893
|
|
|
871
|
-
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function
|
|
894
|
+
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function tt(e,t){return `${oe}
|
|
872
895
|
|
|
873
896
|
Update the existing MongoDB schema based on user feedback.
|
|
874
897
|
|
|
@@ -878,13 +901,13 @@ Update the existing MongoDB schema based on user feedback.
|
|
|
878
901
|
3. Update the schema to incorporate the requested changes while adhering to best practices
|
|
879
902
|
|
|
880
903
|
## Existing Schema
|
|
881
|
-
${
|
|
904
|
+
${e}
|
|
882
905
|
|
|
883
906
|
## User Feedback
|
|
884
|
-
${
|
|
907
|
+
${t}
|
|
885
908
|
|
|
886
909
|
Return the updated schema as a valid JSON object matching the original schema format.
|
|
887
|
-
IMPORTANT: Return ONLY the JSON object, no markdown code blocks, no explanations.`}var
|
|
910
|
+
IMPORTANT: Return ONLY the JSON object, no markdown code blocks, no explanations.`}var xo=L("validate_data_model",ae,"Validates a data model JSON string against the DataModelDesign schema. Returns valid: true or valid: false with errors.","schema");function To(e){return f({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=on(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,ae)}})}function Po(e){return f({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=nn(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,ae)}})}function Ro(e){return f({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=rn(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,ae)}})}var wo=L("validate_schema",te,"Validates a MongoDB project schema JSON string against the expected schema. Returns valid: true or valid: false with errors.","schema");function vo(e){return f({name:"design_database",description:"Generate a MongoDB database schema from plain text requirements. Returns the full project schema as JSON.",input:z.object({requirement:z.string().describe("Plain text description of the database requirements")}),handler:async({requirement:t})=>{let o=Ze(t),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.3,maxOutputTokens:8192});return C(n.text,te)}})}var hp=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 Ao(e){return f({name:"design_database_pro",description:"Generate a MongoDB schema from structured requirements (actors, flows, stories, technical requirements). Returns dbDesign and metadata.",input:hp,handler:async t=>{let o=et(t),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],n=await e.invoke(r,{temperature:.2,maxOutputTokens:16384}),a=C(n.text,te),s={entitiesDetected:yo(t.stories),rolesExtracted:So(t.actors)};return {dbDesign:a,metadata:s}}})}function Mo(e){return f({name:"redesign_database",description:"Update an existing MongoDB project schema based on user feedback. Provide the current schema JSON string and the feedback.",input:z.object({existingSchema:z.string().describe("Current project schema as JSON string"),feedback:z.string().describe("User feedback describing desired changes")}),handler:async({existingSchema:t,feedback:o})=>{let r=tt(t,o),n=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:r}],a=await e.invoke(n,{temperature:.3,maxOutputTokens:8192});return C(a.text,te)}})}function dn(e){return {validate_data_model:xo,design_schema:To(e),design_schema_pro:Po(e),refine_schema:Ro(e)}}function mn(e){return {validate_schema:wo,design_database:vo(e),design_database_pro:Ao(e),redesign_database:Mo(e)}}var yp=`${ho}
|
|
888
911
|
|
|
889
912
|
You are the data modeling orchestrator. When the user asks for a data model:
|
|
890
913
|
|
|
@@ -894,7 +917,7 @@ You are the data modeling orchestrator. When the user asks for a data model:
|
|
|
894
917
|
4. **Refine (optional)**: Use subagent_schema-refiner to validate and suggest improvements to the generated schema.
|
|
895
918
|
5. **Validate**: Use validate_data_model to check the final schema JSON before returning.
|
|
896
919
|
|
|
897
|
-
Respond with the final data model schema as JSON.`;async function
|
|
920
|
+
Respond with the final data model schema as JSON.`;async function rt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=dn(s),l=xe(),p=q([pe,$t,l],{parentModel:s}),c={...i,...p};return k({model:s,tools:c,systemPrompt:yp,input:t,maxIterations:r,onStep:n,logger:a})}var Sp=`${oe}
|
|
898
921
|
|
|
899
922
|
You are the MongoDB database design orchestrator. When the user asks for a database design:
|
|
900
923
|
|
|
@@ -904,7 +927,7 @@ You are the MongoDB database design orchestrator. When the user asks for a datab
|
|
|
904
927
|
4. **Validate**: Use validate_schema to check the final schema JSON.
|
|
905
928
|
5. **Redesign**: If changes are requested, use redesign_database with existing schema and feedback.
|
|
906
929
|
|
|
907
|
-
Respond with the final schema as JSON.`;async function
|
|
930
|
+
Respond with the final schema as JSON.`;async function bp(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=mn(s),l=xe(),p=q([pe,l],{parentModel:s}),c={...i,...p};return k({model:s,tools:c,systemPrompt:Sp,input:t,maxIterations:r,onStep:n,logger:a})}var xp=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"])),gn=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)]))),Ea=z.array(z.unknown()).default([]).transform(e=>e.map(t=>typeof t=="string"?t:JSON.stringify(t))),fn=z.object({id:z.string(),resource:z.string(),method:xp,path:z.string(),description:z.string(),auth:z.coerce.boolean(),roles:z.array(z.string()).default([]),requestBody:gn,responseBody:gn,queryParams:gn,validation:Ea,errorResponses:Ea}),hn=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()}),Tp=z.unknown().transform(e=>(typeof e=="string"?e.toLowerCase().trim():"rest").includes("graphql")?"graphql":"rest"),fe=z.object({style:Tp,baseUrl:z.string().default("/api/v1"),endpoints:z.array(fn).optional().default([]),graphqlOperations:z.array(hn).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 Eo=`You are a senior API architect specializing in REST and GraphQL API design.
|
|
908
931
|
|
|
909
932
|
You analyze data models and requirements to produce enterprise-quality API designs with:
|
|
910
933
|
- RESTful endpoints grouped by resource with proper HTTP methods
|
|
@@ -914,43 +937,78 @@ You analyze data models and requirements to produce enterprise-quality API desig
|
|
|
914
937
|
- Authentication and authorization annotations per endpoint
|
|
915
938
|
- GraphQL types, queries, mutations, and subscriptions when applicable
|
|
916
939
|
|
|
917
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
940
|
+
Output only valid JSON unless instructed otherwise.`;var Oa=`## Requirements:
|
|
918
941
|
{requirement}
|
|
919
942
|
|
|
920
|
-
Design the API. Determine the best API style (rest or graphql) based on the requirements, or use the one specified.
|
|
943
|
+
Design the API. Determine the best API style ("rest" or "graphql") based on the requirements, or use the one specified.
|
|
921
944
|
|
|
922
|
-
|
|
945
|
+
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.
|
|
946
|
+
|
|
947
|
+
For REST: group endpoints by resource. Each endpoint needs: id, resource, method, path, description, auth, roles, requestBody, responseBody, queryParams, validation, and errorResponses.
|
|
923
948
|
For GraphQL: define operations (queries, mutations, subscriptions) with args and return types.
|
|
924
949
|
|
|
925
|
-
Return ONLY valid JSON:
|
|
950
|
+
Return ONLY valid JSON matching this exact structure:
|
|
926
951
|
{
|
|
927
|
-
"style": "rest"
|
|
952
|
+
"style": "rest",
|
|
928
953
|
"baseUrl": "/api/v1",
|
|
929
954
|
"endpoints": [
|
|
930
|
-
{
|
|
955
|
+
{
|
|
956
|
+
"id": "ep-1",
|
|
957
|
+
"resource": "users",
|
|
958
|
+
"method": "POST",
|
|
959
|
+
"path": "/api/v1/users",
|
|
960
|
+
"description": "Register a new user",
|
|
961
|
+
"auth": false,
|
|
962
|
+
"roles": [],
|
|
963
|
+
"requestBody": { "name": "string", "email": "string", "password": "string" },
|
|
964
|
+
"responseBody": { "id": "string", "name": "string", "email": "string" },
|
|
965
|
+
"queryParams": {},
|
|
966
|
+
"validation": ["name is required", "email must be valid format"],
|
|
967
|
+
"errorResponses": ["400 Validation error", "409 Email already exists"]
|
|
968
|
+
},
|
|
969
|
+
{
|
|
970
|
+
"id": "ep-2",
|
|
971
|
+
"resource": "users",
|
|
972
|
+
"method": "GET",
|
|
973
|
+
"path": "/api/v1/users/:id",
|
|
974
|
+
"description": "Get user by ID",
|
|
975
|
+
"auth": true,
|
|
976
|
+
"roles": ["user", "admin"],
|
|
977
|
+
"requestBody": {},
|
|
978
|
+
"responseBody": { "id": "string", "name": "string", "email": "string" },
|
|
979
|
+
"queryParams": {},
|
|
980
|
+
"validation": [],
|
|
981
|
+
"errorResponses": ["401 Unauthenticated", "404 User not found"]
|
|
982
|
+
}
|
|
931
983
|
],
|
|
932
984
|
"graphqlOperations": []
|
|
933
|
-
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
Generate endpoints for ALL resources. Do NOT return an empty endpoints array.`,Ca=`## Project: {projectName}
|
|
934
988
|
## API Style: {apiStyle}
|
|
935
989
|
## Data Model:
|
|
936
990
|
{dataModel}
|
|
937
991
|
## Requirements:
|
|
938
992
|
{context}
|
|
939
993
|
|
|
940
|
-
Design a comprehensive API surface from the data model and requirements. For
|
|
994
|
+
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.
|
|
941
995
|
|
|
942
|
-
|
|
996
|
+
IMPORTANT: The "endpoints" array MUST NOT be empty. You MUST include endpoints for ALL entities.
|
|
943
997
|
|
|
944
|
-
|
|
998
|
+
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").
|
|
945
999
|
|
|
946
|
-
|
|
1000
|
+
Return ONLY valid JSON in the ApiDesign format.`;function yn(e){return Oa.replace("{requirement}",e)}function Sn(e,t,o,r){return Ca.replace("{projectName}",e).replace("{apiStyle}",t).replace("{dataModel}",o).replace("{context}",r)}var Oo=L("validate_api",fe,"Validates an API design JSON string against the ApiDesign schema. Returns valid: true or valid: false with errors.","design");function Co(e){return f({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=yn(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,fe)}})}function No(e){return f({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=Sn(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,fe)}})}function bn(e){return {validate_api:Oo,design_api:Co(e),design_api_pro:No(e)}}var Pp=`${Eo}
|
|
1001
|
+
|
|
1002
|
+
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.
|
|
1003
|
+
|
|
1004
|
+
Follow these steps:
|
|
947
1005
|
|
|
948
1006
|
1. **Analyze endpoints**: Use subagent_endpoint-analyzer to derive endpoints from the data model and requirements.
|
|
949
1007
|
2. **Design contracts**: Use subagent_contract-designer to design request/response contracts, validation rules, and error responses.
|
|
950
|
-
3. **Generate design**:
|
|
1008
|
+
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.
|
|
951
1009
|
4. **Validate**: Use validate_api to check the final API design JSON before returning.
|
|
952
1010
|
|
|
953
|
-
|
|
1011
|
+
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 st(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=bn(s),l=q([je,qe],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:Pp,input:t,maxIterations:r,onStep:n,logger:a})}var ka=z.object({order:z.number(),side:z.enum(["frontend","backend"]),action:z.string(),details:z.string()}),Da=z.object({name:z.string(),description:z.string(),steps:z.array(ka)}),_a=z.object({name:z.string(),purpose:z.string(),behavior:z.array(z.string())}),Ia=z.object({name:z.string(),description:z.string(),permissions:z.array(z.string())}),ja=z.object({area:z.string(),rules:z.array(z.string())}),at=z.object({strategy:z.enum(["jwt","session","oauth"]),flows:z.array(Da),middleware:z.array(_a),roles:z.array(Ia),policies:z.array(ja)});var xn=`You are a senior security engineer specializing in authentication, authorization, and web security.
|
|
954
1012
|
|
|
955
1013
|
You design enterprise-quality auth systems with:
|
|
956
1014
|
- Step-by-step auth flows (signup, login, logout, password reset) with both frontend and backend steps
|
|
@@ -960,7 +1018,7 @@ You design enterprise-quality auth systems with:
|
|
|
960
1018
|
- Security policies: password hashing (bcrypt), rate limiting, CORS, input sanitization, brute force protection
|
|
961
1019
|
- OAuth integration patterns when needed
|
|
962
1020
|
|
|
963
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1021
|
+
Output only valid JSON unless instructed otherwise.`;var qa=`## Requirements:
|
|
964
1022
|
{requirement}
|
|
965
1023
|
|
|
966
1024
|
Design the authentication and authorization system. Include:
|
|
@@ -978,7 +1036,7 @@ Return ONLY valid JSON:
|
|
|
978
1036
|
"middleware": [{ "name": "authenticateRequest", "purpose": "...", "behavior": ["..."] }],
|
|
979
1037
|
"roles": [{ "name": "user", "description": "...", "permissions": ["..."] }],
|
|
980
1038
|
"policies": [{ "area": "passwords", "rules": ["..."] }]
|
|
981
|
-
}`;function
|
|
1039
|
+
}`;function Tn(e){return qa.replace("{requirement}",e)}var ko=L("validate_auth",at,"Validates an auth design JSON string against the AuthDesign schema. Returns valid: true or valid: false with errors.","design");function Do(e){return f({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=Tn(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,at)}})}function Pn(e){return {validate_auth:ko,design_auth:Do(e)}}var Rp=`${xn}
|
|
982
1040
|
|
|
983
1041
|
You are the auth design orchestrator. When the user asks for an auth design:
|
|
984
1042
|
|
|
@@ -987,7 +1045,7 @@ You are the auth design orchestrator. When the user asks for an auth design:
|
|
|
987
1045
|
3. **Generate design**: Use design_auth to produce the complete auth design with flows, middleware, roles, and security policies.
|
|
988
1046
|
4. **Validate**: Use validate_auth to check the final auth design JSON before returning.
|
|
989
1047
|
|
|
990
|
-
Respond with the final auth design as JSON.`;async function
|
|
1048
|
+
Respond with the final auth design as JSON.`;async function it(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=Pn(s),l=q([Ht,Ie],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:Rp,input:t,maxIterations:r,onStep:n,logger:a})}var Ua=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),Fa=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({})}),Ga=z.object({name:z.string(),entity:z.string(),operations:z.array(z.string()).default([]),dependencies:z.array(z.string()).default([])}),wp=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),Ba=z.object({resource:z.string(),basePath:z.string(),endpoints:z.array(z.object({method:wp,path:z.string(),handler:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([])})).default([])}),lt=z.object({framework:Ua(["express","apollo","both"]),language:Ua(["typescript","javascript"]).default("typescript"),database:z.string().default("mongodb"),services:z.array(Ga).default([]),middleware:z.array(Fa).default([]),routes:z.array(Ba).default([]),folderStructure:z.array(z.string()).default([]),envVars:z.array(z.string()).default([]),notes:z.string().default("")});var Rn=`You are a senior backend architect specializing in Node.js server design.
|
|
991
1049
|
|
|
992
1050
|
You analyze data models, API designs, and auth requirements to produce enterprise-quality backend architectures with:
|
|
993
1051
|
- Framework selection (Express REST, Apollo GraphQL, or both)
|
|
@@ -1005,7 +1063,7 @@ When "both" is selected (Express + Apollo), use the Apollo Gateway pattern:
|
|
|
1005
1063
|
- Express for webhooks, file uploads, and health checks only
|
|
1006
1064
|
- Gateway has no business logic, all logic lives in subgraphs
|
|
1007
1065
|
|
|
1008
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1066
|
+
Output only valid JSON unless instructed otherwise.`;var Ja=`## Requirements:
|
|
1009
1067
|
{requirement}
|
|
1010
1068
|
|
|
1011
1069
|
Design the backend architecture. Include:
|
|
@@ -1028,7 +1086,7 @@ Return ONLY valid JSON:
|
|
|
1028
1086
|
"folderStructure": ["src/", "src/routes/", "src/services/", "src/middleware/", "src/models/", "src/config/"],
|
|
1029
1087
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET"],
|
|
1030
1088
|
"notes": ""
|
|
1031
|
-
}`;function
|
|
1089
|
+
}`;function wn(e){return Ja.replace("{requirement}",e)}var _o=L("validate_backend",lt,"Validates a backend design JSON string against the BackendDesign schema. Returns valid: true or valid: false with errors.","design");function Io(e){return f({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=wn(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,lt)}})}function vn(e){return {validate_backend:_o,design_backend:Io(e)}}var vp=`You are a backend service architect. Given a data model and API design, you plan the service layer.
|
|
1032
1090
|
|
|
1033
1091
|
## Service Design
|
|
1034
1092
|
For each entity:
|
|
@@ -1055,7 +1113,7 @@ Recommend a clean folder layout:
|
|
|
1055
1113
|
- src/config/ (env, database, auth config)
|
|
1056
1114
|
- src/utils/ (shared helpers)
|
|
1057
1115
|
|
|
1058
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
1116
|
+
Respond with structured analysis. Do NOT return JSON.`,jo=y({name:"service-planner",description:"Plans service layer, middleware stack, and folder structure for a backend project. Use before generating the backend design.",systemPrompt:vp,tools:{},maxIterations:2});var Ap=`You are a backend technology advisor. Given project requirements, you recommend the best backend framework.
|
|
1059
1117
|
|
|
1060
1118
|
## Decision Criteria
|
|
1061
1119
|
|
|
@@ -1090,7 +1148,7 @@ State your recommendation clearly:
|
|
|
1090
1148
|
- Trade-offs: what you'd lose with the alternative
|
|
1091
1149
|
- If "both": describe which concerns go to Express vs Apollo Gateway vs subgraphs
|
|
1092
1150
|
|
|
1093
|
-
Respond with structured analysis. Do NOT return JSON.`,
|
|
1151
|
+
Respond with structured analysis. Do NOT return JSON.`,qo=y({name:"framework-selector",description:"Analyzes project requirements and recommends Express, Apollo, or both. Use to determine the backend framework before designing.",systemPrompt:Ap,tools:{},maxIterations:2});var Mp=`${Rn}
|
|
1094
1152
|
|
|
1095
1153
|
You are the backend architecture orchestrator. When the user provides requirements:
|
|
1096
1154
|
|
|
@@ -1104,7 +1162,7 @@ After generating the design, note the "framework" field in the result:
|
|
|
1104
1162
|
- If "apollo": the downstream apollo-builder should be used to scaffold the project.
|
|
1105
1163
|
- If "both": both builders should be invoked sequentially.
|
|
1106
1164
|
|
|
1107
|
-
Respond with the final backend design as JSON.`;async function
|
|
1165
|
+
Respond with the final backend design as JSON.`;async function pt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=vn(s),l=q([jo,qo],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:Mp,input:t,maxIterations:r,onStep:n,logger:a})}var $a=z.object({name:z.string(),type:z.string(),required:z.coerce.boolean(),validation:z.string()}),Ya=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($a).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([])}),Ha=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([])}),ct=z.object({pages:z.array(Ya).default([]),components:z.array(Ha).default([]),stateManagement:z.string().default(""),routingNotes:z.string().default("")});var An=`You are a senior frontend architect specializing in page design, routing, and component architecture.
|
|
1108
1166
|
|
|
1109
1167
|
You design enterprise-quality frontend architectures targeting a Vite + React 19 + TypeScript stack with:
|
|
1110
1168
|
- **UI Library**: ShadCN UI (Radix-based components in src/components/ui/)
|
|
@@ -1120,7 +1178,7 @@ Architecture outputs:
|
|
|
1120
1178
|
- Component taxonomy: layout (sidebar, navbar), shared (data tables, dialogs), form (inputs, selects), display (cards, badges), navigation (breadcrumbs, tabs)
|
|
1121
1179
|
- State management strategy (per-page vs global, Apollo cache vs local state)
|
|
1122
1180
|
|
|
1123
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1181
|
+
Output only valid JSON unless instructed otherwise.`;var Qa=`## Requirements:
|
|
1124
1182
|
{requirement}
|
|
1125
1183
|
|
|
1126
1184
|
Design the frontend architecture. Include:
|
|
@@ -1136,7 +1194,7 @@ Return ONLY valid JSON:
|
|
|
1136
1194
|
"components": [{ "name": "Navbar", "type": "navigation", "purpose": "...", "props": ["user"], "usedIn": ["/dashboard", "/profile"] }],
|
|
1137
1195
|
"stateManagement": "...",
|
|
1138
1196
|
"routingNotes": "..."
|
|
1139
|
-
}`;function
|
|
1197
|
+
}`;function Mn(e){return Qa.replace("{requirement}",e)}var Lo=L("validate_frontend",ct,"Validates a frontend design JSON string against the FrontendDesign schema. Returns valid: true or valid: false with errors.","design");function Uo(e){return f({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=Mn(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,ct)}})}function En(e){return {validate_frontend:Lo,design_frontend:Uo(e)}}var Ep=y({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}),Op=y({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}),Cp=`${An}
|
|
1140
1198
|
|
|
1141
1199
|
You are the frontend architecture routing orchestrator. When the user asks for a frontend design:
|
|
1142
1200
|
|
|
@@ -1149,7 +1207,7 @@ You are the frontend architecture routing orchestrator. When the user asks for a
|
|
|
1149
1207
|
- If "react-vite": use subagent_react-builder with the design to generate a Vite + React SPA config.
|
|
1150
1208
|
- If "nextjs": use subagent_nextjs-builder with the design to generate a Next.js App Router config.
|
|
1151
1209
|
|
|
1152
|
-
Respond with the final frontend design as JSON, including the builder output.`;async function
|
|
1210
|
+
Respond with the final frontend design as JSON, including the builder output.`;async function ut(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=En(s),l=q([_e,Yt,Nr,Ep,Op],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:Cp,input:t,maxIterations:r,onStep:n,logger:a})}var Np=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),Wa=z.object({name:z.string(),httpMethod:Np,path:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([]),validation:z.string().default(""),description:z.string().default("")}),Ka=z.object({name:z.string(),resource:z.string(),basePath:z.string(),methods:z.array(Wa).default([])}),Xa=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()}),Za=z.object({name:z.string(),collection:z.string(),fields:z.array(Xa).default([]),timestamps:z.coerce.boolean().default(true),indexes:z.array(z.string()).default([])}),ei=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({})}),dt=z.object({appName:z.string().default("app"),port:z.number().default(3e3),database:z.string().default("mongodb"),routers:z.array(Ka).default([]),models:z.array(Za).default([]),middleware:z.array(ei).default([]),envVars:z.array(z.string()).default([])});var On=`You are an expert Express.js backend architect.
|
|
1153
1211
|
|
|
1154
1212
|
You generate production-ready Express application configurations from data models and API designs:
|
|
1155
1213
|
- Co-located router pattern: each feature lives in src/routers/{name}/ with {name}.controller.ts, {name}.router.ts, and {name}.spec.ts
|
|
@@ -1160,7 +1218,7 @@ You generate production-ready Express application configurations from data model
|
|
|
1160
1218
|
- Jest tests per router using supertest
|
|
1161
1219
|
- Environment variable inventory
|
|
1162
1220
|
|
|
1163
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1221
|
+
Output only valid JSON unless instructed otherwise.`;var ti=`## Requirements:
|
|
1164
1222
|
{requirement}
|
|
1165
1223
|
|
|
1166
1224
|
Generate an Express.js application configuration. Include:
|
|
@@ -1200,7 +1258,7 @@ Return ONLY valid JSON:
|
|
|
1200
1258
|
}],
|
|
1201
1259
|
"middleware": [{ "name": "authMiddleware", "type": "auth", "config": {} }],
|
|
1202
1260
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "NODE_ENV"]
|
|
1203
|
-
}`;function
|
|
1261
|
+
}`;function Cn(e){return ti.replace("{requirement}",e)}var Fo=L("validate_express",dt,"Validates an Express config JSON string against the ExpressConfig schema. Returns valid: true or valid: false with errors.","config");function Go(e){return f({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=Cn(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,dt)}})}function kp(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}))}}var Bo=f({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=Ee(e,"express config"),r=De.resolve(process.cwd(),".ref/templates/express"),n=kp(o);return ge({templateDir:r,outputDir:t,context:n})}});function kn(e,t){let o={validate_express:Fo,generate_express:Go(e)};return t?.disableScaffold||(o.scaffold_express=Bo),o}var Dp=`You are an Express.js route specialist. Given an API design, you generate route definitions using a co-located router pattern.
|
|
1204
1262
|
|
|
1205
1263
|
## Co-located Router Pattern
|
|
1206
1264
|
Each feature lives in src/routers/{name}/ with three files:
|
|
@@ -1238,7 +1296,7 @@ Every app includes a /health router in src/routers/health/:
|
|
|
1238
1296
|
- Param validation (e.g. valid ObjectId)
|
|
1239
1297
|
- Query param parsing and defaults
|
|
1240
1298
|
|
|
1241
|
-
Respond with structured route definitions. Do NOT return JSON.`,
|
|
1299
|
+
Respond with structured route definitions. Do NOT return JSON.`,Jo=y({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:Dp,tools:{},maxIterations:2});var _p=`You are an Express.js middleware specialist. You design the complete middleware stack.
|
|
1242
1300
|
|
|
1243
1301
|
## Core Middleware
|
|
1244
1302
|
1. **CORS**: Configure allowed origins, methods, headers, credentials
|
|
@@ -1264,17 +1322,17 @@ Respond with structured route definitions. Do NOT return JSON.`,po=f({name:"rout
|
|
|
1264
1322
|
1. **Global**: Limit requests per IP per time window
|
|
1265
1323
|
2. **Auth routes**: Stricter limits on login/signup
|
|
1266
1324
|
|
|
1267
|
-
Respond with structured middleware analysis. Do NOT return JSON.`,
|
|
1325
|
+
Respond with structured middleware analysis. Do NOT return JSON.`,zo=y({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:_p,tools:{},maxIterations:2});var Ip=`
|
|
1326
|
+
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_express to compile templates.`;function jp(e){return `${On}
|
|
1268
1327
|
|
|
1269
1328
|
You are the Express builder orchestrator. When the user provides requirements:
|
|
1270
1329
|
|
|
1271
1330
|
1. **Generate routes**: Use subagent_route-generator to design route definitions from the API design.
|
|
1272
1331
|
2. **Configure middleware**: Use subagent_middleware-configurator to design the middleware stack.
|
|
1273
1332
|
3. **Generate config**: Use generate_express to produce the complete Express configuration as JSON.
|
|
1274
|
-
4. **Validate**: Use validate_express to check the config JSON before returning
|
|
1275
|
-
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_express to compile templates.
|
|
1333
|
+
4. **Validate**: Use validate_express to check the config JSON before returning.${e?"":Ip}
|
|
1276
1334
|
|
|
1277
|
-
Respond with the final Express config as JSON
|
|
1335
|
+
Respond with the final Express config as JSON.`}async function Dn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a,disableScaffold:s}=e,i=M(o??{provider:"openai",model:"gpt-4o-mini"}),l=kn(i,{disableScaffold:s}),p=q([Jo,zo],{parentModel:i}),c={...l,...p};return k({model:i,tools:c,systemPrompt:jp(s),input:t,maxIterations:r,onStep:n,logger:a})}var ni=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),_n=z.object({name:z.string(),type:z.string(),nullable:z.coerce.boolean().default(false),isList:z.coerce.boolean().default(false),description:z.string().default("")}),In=z.object({name:z.string(),kind:ni(["type","input","enum","interface","union"]),fields:z.array(_n).default([]),values:z.array(z.string()).default([]),description:z.string().default(""),isEntity:z.coerce.boolean().default(false),keyFields:z.array(z.string()).default([])}),si=z.object({name:z.string(),type:ni(["query","mutation","subscription"]),args:z.array(_n).default([]),returnType:z.string(),auth:z.coerce.boolean().default(true),roles:z.array(z.string()).default([]),description:z.string().default("")}),ai=z.object({name:z.string(),entity:z.string(),types:z.array(In).default([]),operations:z.array(si).default([]),datasource:z.string().default(""),loader:z.string().default("")}),mt=z.object({appName:z.string().default("app"),port:z.number().default(4e3),database:z.string().default("mongodb"),modules:z.array(ai).default([]),sharedTypes:z.array(In).default([]),authDirective:z.coerce.boolean().default(true),cacheDirective:z.coerce.boolean().default(false),envVars:z.array(z.string()).default([])});var jn=`You are an expert Apollo GraphQL subgraph architect using Apollo Federation v2.
|
|
1278
1336
|
|
|
1279
1337
|
You generate production-ready Apollo subgraph configurations from data models and API designs:
|
|
1280
1338
|
- 4-file module pattern per entity: {module}.graphql, {module}.resolver.ts, {module}.datasource.ts, {module}.loader.ts
|
|
@@ -1291,7 +1349,7 @@ You generate production-ready Apollo subgraph configurations from data models an
|
|
|
1291
1349
|
- GraphQL CodeGen for TypeScript types (generates base-types.ts)
|
|
1292
1350
|
- Module-based organization (one module per entity/domain)
|
|
1293
1351
|
|
|
1294
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1352
|
+
Output only valid JSON unless instructed otherwise.`;var ii=`## Requirements:
|
|
1295
1353
|
{requirement}
|
|
1296
1354
|
|
|
1297
1355
|
Generate an Apollo GraphQL subgraph configuration (Federation v2). Include:
|
|
@@ -1322,7 +1380,7 @@ Return ONLY valid JSON:
|
|
|
1322
1380
|
"authDirective": true,
|
|
1323
1381
|
"cacheDirective": false,
|
|
1324
1382
|
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "REDIS_URL"]
|
|
1325
|
-
}`;function
|
|
1383
|
+
}`;function qn(e){return ii.replace("{requirement}",e)}var $o=L("validate_subgraph",mt,"Validates a subgraph config JSON string against the SubgraphConfig schema. Returns valid: true or valid: false with errors.","config");function Yo(e){return f({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=qn(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,mt)}})}function qp(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}}var Ho=f({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=Ee(e,"subgraph config"),r=De.resolve(process.cwd(),".ref/templates/subgraph"),n=qp(o);return ge({templateDir:r,outputDir:t,context:n})}});function Un(e,t){let o={validate_subgraph:$o,generate_subgraph:Yo(e)};return t?.disableScaffold||(o.scaffold_subgraph=Ho),o}var Lp=`You are a GraphQL schema specialist for Apollo Federation v2 subgraphs. Given a data model, you generate GraphQL type definitions using buildSubgraphSchema.
|
|
1326
1384
|
|
|
1327
1385
|
## Type Generation
|
|
1328
1386
|
For each entity in the data model:
|
|
@@ -1353,7 +1411,7 @@ For each entity in the data model:
|
|
|
1353
1411
|
- Inputs: PascalCase + Input suffix (CreateUserInput, UpdateUserInput)
|
|
1354
1412
|
- Enums: SCREAMING_SNAKE_CASE values (ADMIN, ACTIVE)
|
|
1355
1413
|
|
|
1356
|
-
Respond with the full GraphQL SDL. Do NOT return JSON.`,
|
|
1414
|
+
Respond with the full GraphQL SDL. Do NOT return JSON.`,Qo=y({name:"schema-generator",description:"Generates GraphQL type definitions, input types, and enums from a data model. Use before generating the subgraph config.",systemPrompt:Lp,tools:{},maxIterations:2});var Up=`You are a GraphQL resolver architect for Apollo Federation v2 subgraphs. Given types and operations, you plan resolver implementations.
|
|
1357
1415
|
|
|
1358
1416
|
## 4-File Module Pattern
|
|
1359
1417
|
Each module has four files:
|
|
@@ -1400,17 +1458,17 @@ Each module has a loader file that creates DataLoader instances:
|
|
|
1400
1458
|
- Verify role permissions per operation
|
|
1401
1459
|
- Resource ownership checks for user-specific data
|
|
1402
1460
|
|
|
1403
|
-
Respond with structured analysis per module. Do NOT return JSON.`,
|
|
1461
|
+
Respond with structured analysis per module. Do NOT return JSON.`,Vo=y({name:"resolver-planner",description:"Plans resolver implementations, datasource methods, and auth integration per GraphQL module. Use after schema generation.",systemPrompt:Up,tools:{},maxIterations:2});var Fp=`
|
|
1462
|
+
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_subgraph to compile templates.`;function Gp(e){return `${jn}
|
|
1404
1463
|
|
|
1405
1464
|
You are the Apollo subgraph builder orchestrator. When the user provides requirements:
|
|
1406
1465
|
|
|
1407
1466
|
1. **Generate schema**: Use subagent_schema-generator to create GraphQL type definitions from the data model.
|
|
1408
1467
|
2. **Plan resolvers**: Use subagent_resolver-planner to design resolver implementations per module.
|
|
1409
1468
|
3. **Generate config**: Use generate_subgraph to produce the complete subgraph configuration as JSON.
|
|
1410
|
-
4. **Validate**: Use validate_subgraph to check the config JSON before returning
|
|
1411
|
-
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_subgraph to compile templates.
|
|
1469
|
+
4. **Validate**: Use validate_subgraph to check the config JSON before returning.${e?"":Fp}
|
|
1412
1470
|
|
|
1413
|
-
Respond with the final subgraph config as JSON
|
|
1471
|
+
Respond with the final subgraph config as JSON.`}async function Fn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a,disableScaffold:s}=e,i=M(o??{provider:"openai",model:"gpt-4o-mini"}),l=Un(i,{disableScaffold:s}),p=q([Qo,Vo],{parentModel:i}),c={...l,...p};return k({model:i,tools:c,systemPrompt:Gp(s),input:t,maxIterations:r,onStep:n,logger:a})}var Gn=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 Bn=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:Gn.describe("Branding information for the application"),apiEndpoint:z.url().describe("URL endpoint for the app's API calls")});var ci=z.object({minLength:z.number().optional().describe("Minimum length requirement"),zodString:z.string().describe("Raw Zod string validation (e.g. regex)")}),ui=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")}),Wo=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:ci.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:ui.optional().describe("Additional dynamic or static options for this field")}),Jn=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 $n=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"),di=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:$n.describe("Optional schema describing shape of the API response")}),mi=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:$n.describe("Optional schema describing shape of the API response")}),zn=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(Wo).describe("List of fields displayed within the drawer")}),gi=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(mi).describe("List of API calls involved in this page"),fields:z.array(Wo).optional().describe("Optional form fields needed on this auth page")}),fi=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(di).describe("List of API calls that power this listing page"),columns:z.array(Jn).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:zn.describe("Drawer configuration for creating new records"),drawerUpdate:zn.describe("Drawer configuration for editing existing records")}),Yn=z.discriminatedUnion("type",[gi,fi]);var hi=z.object({name:z.string().describe("Name of the module"),pages:z.array(Yn).describe("Pages included within this module")}),yt=z.object({app:Bn.describe("Overall application configuration"),modules:z.array(hi).describe("List of modules that make up the application. Ensure all modules use every available CRUD GraphQL query and mutation from the schema.")});var Bp=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")}),yi=z.object({_id:z.string().describe("Unique identifier of the specialization, type: string"),title:z.string().describe("Display title for the specialization, type: string")}),Jp=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(yi).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")}),zp=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")}),$p=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")}),Yp=z.object({email:z.email().describe("Email to initiate the password reset process, type: string")}),Hp=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 St=`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.
|
|
1414
1472
|
|
|
1415
1473
|
## Target Tech Stack
|
|
1416
1474
|
The generated configuration will be consumed by a Vite + React 19 + TypeScript template with:
|
|
@@ -1430,7 +1488,7 @@ Strict guidelines:
|
|
|
1430
1488
|
- Relationships \u2192 multiSelect with query-based options where appropriate.
|
|
1431
1489
|
- Add isPrivate: true for authenticated operations (route guarded by React Router).
|
|
1432
1490
|
- Form fields should map to React Hook Form + Zod validation schemas.
|
|
1433
|
-
- Maintain camelCase. Ensure valid JSON syntax.`;var
|
|
1491
|
+
- Maintain camelCase. Ensure valid JSON syntax.`;var Ko=`
|
|
1434
1492
|
Act as an expert GraphQL-to-frontend configuration converter. Transform the provided schema into a structured JSON configuration for rapid app development.
|
|
1435
1493
|
|
|
1436
1494
|
**Conversion Process**
|
|
@@ -1462,7 +1520,7 @@ Act as an expert GraphQL-to-frontend configuration converter. Transform the prov
|
|
|
1462
1520
|
6. Output:
|
|
1463
1521
|
- Generate complete CRUD pages with table column mappings, validated Create/Update forms, API hooks
|
|
1464
1522
|
- Include Zod validation strings, maintain camelCase, valid JSON only
|
|
1465
|
-
`.trim();function
|
|
1523
|
+
`.trim();function Hn(){return Ko}var Si=`
|
|
1466
1524
|
type Query {
|
|
1467
1525
|
getCurrentUser: User
|
|
1468
1526
|
getAllUser(limit: Int, offset: Int): [User]!
|
|
@@ -1481,7 +1539,7 @@ type User {
|
|
|
1481
1539
|
enum Role { ADMIN TRAINER CLIENT }
|
|
1482
1540
|
input LoginInput { email: String! password: String! }
|
|
1483
1541
|
input CreateUserInput { firstName: String! lastName: String! email: String! role: Role! }
|
|
1484
|
-
`.trim(),
|
|
1542
|
+
`.trim(),bi=`{
|
|
1485
1543
|
"app": {
|
|
1486
1544
|
"name": "my-app",
|
|
1487
1545
|
"description": "App description",
|
|
@@ -1529,40 +1587,40 @@ input CreateUserInput { firstName: String! lastName: String! email: String! role
|
|
|
1529
1587
|
]
|
|
1530
1588
|
}
|
|
1531
1589
|
]
|
|
1532
|
-
}`;function
|
|
1590
|
+
}`;function Qn(){return `
|
|
1533
1591
|
**Reference Conversion Example**
|
|
1534
1592
|
|
|
1535
1593
|
EXAMPLE GRAPHQL INPUT:
|
|
1536
1594
|
\`\`\`graphql
|
|
1537
|
-
${
|
|
1595
|
+
${Si}
|
|
1538
1596
|
\`\`\`
|
|
1539
1597
|
|
|
1540
1598
|
EXPECTED JSON OUTPUT:
|
|
1541
1599
|
\`\`\`json
|
|
1542
|
-
${
|
|
1600
|
+
${bi}
|
|
1543
1601
|
\`\`\`
|
|
1544
|
-
`.trim()}function
|
|
1602
|
+
`.trim()}function Qp(e,t){return `
|
|
1545
1603
|
Review the user feedback carefully to understand the required updates.
|
|
1546
1604
|
|
|
1547
1605
|
The user feedback for updating the generated Frontend Config JSON is provided below:
|
|
1548
1606
|
"""
|
|
1549
|
-
${
|
|
1607
|
+
${e}
|
|
1550
1608
|
"""
|
|
1551
1609
|
|
|
1552
1610
|
Now, generate the Frontend Config JSON for this project based on the provided feedback.
|
|
1553
1611
|
|
|
1554
1612
|
**Project GRAPHQL SCHEMA INPUT:**
|
|
1555
1613
|
\`\`\`graphql
|
|
1556
|
-
${
|
|
1614
|
+
${t}
|
|
1557
1615
|
\`\`\`
|
|
1558
1616
|
|
|
1559
1617
|
Update the Frontend Config JSON to incorporate the requested changes. Return ONLY valid JSON, no markdown code blocks.
|
|
1560
|
-
`.trim()}var
|
|
1618
|
+
`.trim()}var He=L("validate_frontend_config",yt,"Validates a frontend configuration JSON string against the ApplicationSchema. Returns valid: true or valid: false with errors array.","config");function Vp(e,t){let o=Hn(),r=Qn(),n=t?`
|
|
1561
1619
|
**Project context:**
|
|
1562
|
-
- name: ${
|
|
1563
|
-
- description: ${
|
|
1564
|
-
- modules: ${
|
|
1565
|
-
- apiEndpoint: ${
|
|
1620
|
+
- name: ${t.projectName??"project"}
|
|
1621
|
+
- description: ${t.projectDescription??""}
|
|
1622
|
+
- modules: ${t.modules??""}
|
|
1623
|
+
- apiEndpoint: ${t.apiEndpoint??"http://localhost:4000/graphql"}
|
|
1566
1624
|
`:"";return `${o}
|
|
1567
1625
|
|
|
1568
1626
|
${r}
|
|
@@ -1570,17 +1628,17 @@ ${n}
|
|
|
1570
1628
|
|
|
1571
1629
|
**Current Project GraphQL Schema:**
|
|
1572
1630
|
\`\`\`graphql
|
|
1573
|
-
${
|
|
1631
|
+
${e}
|
|
1574
1632
|
\`\`\`
|
|
1575
1633
|
|
|
1576
|
-
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function
|
|
1634
|
+
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function Xo(e){return f({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=Vp(t,o),n=[{role:"system",content:St},{role:"user",content:r}],a=await e.invoke(n,{temperature:.2,maxOutputTokens:16384});return C(a.text,yt)}})}function Zo(e){return f({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=`${Ko}
|
|
1577
1635
|
|
|
1578
1636
|
**Schema to analyze:**
|
|
1579
1637
|
\`\`\`graphql
|
|
1580
|
-
${
|
|
1638
|
+
${t}
|
|
1581
1639
|
\`\`\`
|
|
1582
1640
|
|
|
1583
|
-
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
|
|
1641
|
+
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 Wp(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)}}var Wn=f({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=Ee(e,"application schema config"),r=De.resolve(process.cwd(),".ref/templates/vite"),n=Wp(o);return ge({templateDir:r,outputDir:t,context:n})}});function Kn(e,t){let o={validate_frontend_config:He,generate_frontend:Xo(e),generate_feature_breakdown:Zo(e)};return t?.disableScaffold||(o.scaffold_vite=Wn),o}var Kp=`You are an expert at analyzing GraphQL schemas. Your job is to:
|
|
1584
1642
|
|
|
1585
1643
|
1. **Types**: List all object types, enums, scalars, and input types.
|
|
1586
1644
|
2. **Queries**: List every Query field with arguments and return type.
|
|
@@ -1588,13 +1646,13 @@ Respond with a structured breakdown only (no full JSON config): list modules, li
|
|
|
1588
1646
|
4. **Relationships**: Identify types that reference other types (e.g. User has role: Role, or Order has customer: User).
|
|
1589
1647
|
5. **Auth/directives**: Note any @auth, @directive usage that affects access control.
|
|
1590
1648
|
|
|
1591
|
-
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,
|
|
1649
|
+
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,er=y({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:Kp,tools:{},maxIterations:2});var Xp=`You are a frontend configuration validator. Your job is to:
|
|
1592
1650
|
|
|
1593
1651
|
1. Validate the provided frontend config JSON using the validate_frontend_config tool.
|
|
1594
1652
|
2. Compare the config against the GraphQL schema (if provided) and check that all CRUD operations are covered.
|
|
1595
1653
|
3. Report any missing modules, pages, or API hooks.
|
|
1596
1654
|
|
|
1597
|
-
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
|
|
1655
|
+
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 tr(){return y({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:Xp,tools:{validate_frontend_config:He},maxIterations:5})}var Zp=`${St}
|
|
1598
1656
|
|
|
1599
1657
|
You are the React frontend builder orchestrator. When the user provides a GraphQL schema and asks for a frontend configuration:
|
|
1600
1658
|
|
|
@@ -1604,7 +1662,7 @@ You are the React frontend builder orchestrator. When the user provides a GraphQ
|
|
|
1604
1662
|
4. **Validate directly**: You can use validate_frontend_config to check any config JSON.
|
|
1605
1663
|
5. **Feature breakdown**: Use generate_feature_breakdown to get a module/operation breakdown before generating.
|
|
1606
1664
|
|
|
1607
|
-
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
|
|
1665
|
+
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 Xn(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a,disableScaffold:s}=e,i=M(o??{provider:"openai",model:"gpt-4o-mini"}),l=Kn(i,{disableScaffold:s}),p=tr(),c=q([er,p],{parentModel:i}),u={...l,...c};return k({model:i,tools:u,systemPrompt:Zp,input:t,maxIterations:r,onStep:n,logger:a})}var Pi=e=>z.string().transform(t=>t.toLowerCase().trim()).pipe(z.enum(e)),ec=z.string().transform(e=>e.toUpperCase().trim()).pipe(z.enum(["GET","POST","PUT","PATCH","DELETE"])),Ri=z.object({path:z.string(),name:z.string(),access:Pi(["public","protected"]),routeGroup:z.string().default(""),purpose:z.string(),hasForm:z.coerce.boolean().default(false),formFields:z.array(z.string()).default([]),dataFetching:Pi(["server","client","hybrid"]).default("server"),actions:z.array(z.string()).default([])}),wi=z.object({name:z.string(),path:z.string(),routeGroup:z.string().default(""),components:z.array(z.string()).default([]),purpose:z.string()}),vi=z.object({path:z.string(),methods:z.array(ec).default([]),auth:z.coerce.boolean().default(true),description:z.string()}),Ai=z.object({name:z.string(),module:z.string(),description:z.string(),revalidates:z.array(z.string()).default([])}),bt=z.object({appName:z.string().default("app"),pages:z.array(Ri).default([]),layouts:z.array(wi).default([]),apiRoutes:z.array(vi).default([]),serverActions:z.array(Ai).default([]),middleware:z.array(z.string()).default([]),envVars:z.array(z.string()).default([]),packages:z.array(z.string()).default([])});var Zn=`You are an expert Next.js application architect using the App Router.
|
|
1608
1666
|
|
|
1609
1667
|
You generate production-ready Next.js configurations from frontend designs and API designs:
|
|
1610
1668
|
- App Router file structure with route groups, layouts, pages, loading, and error boundaries
|
|
@@ -1615,7 +1673,7 @@ You generate production-ready Next.js configurations from frontend designs and A
|
|
|
1615
1673
|
- Data fetching strategy (server vs client vs hybrid per page)
|
|
1616
1674
|
- Package recommendations (next-auth, prisma, tailwindcss, shadcn/ui)
|
|
1617
1675
|
|
|
1618
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1676
|
+
Output only valid JSON unless instructed otherwise.`;var Mi=`## Requirements:
|
|
1619
1677
|
{requirement}
|
|
1620
1678
|
|
|
1621
1679
|
Generate a Next.js App Router application configuration. Include:
|
|
@@ -1664,7 +1722,7 @@ Return ONLY valid JSON:
|
|
|
1664
1722
|
"middleware": ["Redirect unauthenticated users to /login"],
|
|
1665
1723
|
"envVars": ["DATABASE_URL", "NEXTAUTH_SECRET"],
|
|
1666
1724
|
"packages": ["next-auth", "prisma", "@prisma/client", "tailwindcss"]
|
|
1667
|
-
}`;function
|
|
1725
|
+
}`;function es(e){return Mi.replace("{requirement}",e)}var or=L("validate_nextjs",bt,"Validates a Next.js config JSON string against the NextjsConfig schema. Returns valid: true or valid: false with errors.","config");function rr(e){return f({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=es(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,bt)}})}function ts(e){return {validate_nextjs:or,generate_nextjs:rr(e)}}var tc=`You are a Next.js App Router specialist. Given page specs, you plan the file structure.
|
|
1668
1726
|
|
|
1669
1727
|
## Route Groups
|
|
1670
1728
|
- (auth) for public auth pages: login, signup, forgot-password
|
|
@@ -1690,7 +1748,7 @@ Return ONLY valid JSON:
|
|
|
1690
1748
|
- Parallel routes: @modal, @sidebar
|
|
1691
1749
|
- Intercepting routes: (.)photo, (..)details
|
|
1692
1750
|
|
|
1693
|
-
Respond with the full file tree and route structure. Do NOT return JSON.`,
|
|
1751
|
+
Respond with the full file tree and route structure. Do NOT return JSON.`,nr=y({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:tc,tools:{},maxIterations:2});var oc=`You are a Next.js API specialist. Given an API design, you plan route handlers and server actions.
|
|
1694
1752
|
|
|
1695
1753
|
## API Route Handlers (app/api/)
|
|
1696
1754
|
For external integrations, webhooks, and file uploads:
|
|
@@ -1715,7 +1773,7 @@ For form submissions and data writes:
|
|
|
1715
1773
|
- Server Actions: check session at the start of each action
|
|
1716
1774
|
- Middleware: protect route groups with matcher patterns
|
|
1717
1775
|
|
|
1718
|
-
Respond with structured analysis per module. Do NOT return JSON.`,
|
|
1776
|
+
Respond with structured analysis per module. Do NOT return JSON.`,sr=y({name:"api-route-generator",description:"Generates Next.js API route handlers and server actions from API design. Use after route planning.",systemPrompt:oc,tools:{},maxIterations:2});var rc=`${Zn}
|
|
1719
1777
|
|
|
1720
1778
|
You are the Next.js builder orchestrator. When the user provides requirements:
|
|
1721
1779
|
|
|
@@ -1724,7 +1782,7 @@ You are the Next.js builder orchestrator. When the user provides requirements:
|
|
|
1724
1782
|
3. **Generate config**: Use generate_nextjs to produce the complete Next.js configuration as JSON.
|
|
1725
1783
|
4. **Validate**: Use validate_nextjs to check the config JSON before returning.
|
|
1726
1784
|
|
|
1727
|
-
Respond with the final Next.js config as JSON.`;async function
|
|
1785
|
+
Respond with the final Next.js config as JSON.`;async function os(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=ts(s),l=q([nr,sr],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:rc,input:t,maxIterations:r,onStep:n,logger:a})}var Oi=z.object({order:z.number(),action:z.string(),details:z.string()}),Ci=z.object({name:z.string(),description:z.string(),steps:z.array(Oi)}),Ni=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"]))}),ki=z.object({flow:z.string(),item:z.string(),expectedResult:z.string()}),xt=z.object({phases:z.array(Ci).default([]),currentState:z.string().default(""),desiredEndState:z.string().default(""),edgeCases:z.array(Ni).default([]),securityNotes:z.array(z.string()).default([]),performanceNotes:z.array(z.string()).default([]),testingChecklist:z.array(ki).default([])});var rs=`You are a senior tech lead specializing in implementation strategy and project execution planning.
|
|
1728
1786
|
|
|
1729
1787
|
You create enterprise-quality execution plans with:
|
|
1730
1788
|
- Phased implementation order with concrete, numbered steps per phase
|
|
@@ -1734,7 +1792,7 @@ You create enterprise-quality execution plans with:
|
|
|
1734
1792
|
- Performance considerations (indexing, caching, lazy loading, N+1 prevention)
|
|
1735
1793
|
- Manual testing checklists grouped by feature flow
|
|
1736
1794
|
|
|
1737
|
-
Output only valid JSON unless instructed otherwise.`;var
|
|
1795
|
+
Output only valid JSON unless instructed otherwise.`;var Di=`## Full Plan Context:
|
|
1738
1796
|
{context}
|
|
1739
1797
|
|
|
1740
1798
|
Create a comprehensive execution plan. Include:
|
|
@@ -1756,7 +1814,7 @@ Return ONLY valid JSON:
|
|
|
1756
1814
|
"securityNotes": ["..."],
|
|
1757
1815
|
"performanceNotes": ["..."],
|
|
1758
1816
|
"testingChecklist": [{ "flow": "Auth Flow", "item": "Sign up with valid credentials", "expectedResult": "Account created, redirected to dashboard" }]
|
|
1759
|
-
}`;function
|
|
1817
|
+
}`;function ns(e){return Di.replace("{context}",e)}var ar=L("validate_execution_plan",xt,"Validates an execution plan JSON string against the ExecutionPlan schema. Returns valid: true or valid: false with errors.","plan");function ir(e){return f({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=ns(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,xt)}})}function ss(e){return {validate_execution_plan:ar,create_execution_plan:ir(e)}}var nc=`${rs}
|
|
1760
1818
|
|
|
1761
1819
|
You are the execution planning orchestrator. When the user provides plan sections:
|
|
1762
1820
|
|
|
@@ -1765,6 +1823,56 @@ You are the execution planning orchestrator. When the user provides plan section
|
|
|
1765
1823
|
3. **Generate plan**: Use create_execution_plan to produce the complete execution plan with phases, edge cases, and testing checklist.
|
|
1766
1824
|
4. **Validate**: Use validate_execution_plan to check the final plan JSON before returning.
|
|
1767
1825
|
|
|
1768
|
-
Respond with the final execution plan as JSON.`;async function
|
|
1769
|
-
|
|
1826
|
+
Respond with the final execution plan as JSON.`;async function Tt(e){let{input:t,model:o,maxIterations:r=15,onStep:n,logger:a}=e,s=M(o??{provider:"openai",model:"gpt-4o-mini"}),i=ss(s),l=q([Le,Ue],{parentModel:s}),p={...i,...l};return k({model:s,tools:p,systemPrompt:nc,input:t,maxIterations:r,onStep:n,logger:a})}var as=f({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 sc="You are a friendly greeter. Use the hello_world tool to greet users.";async function is(e){let{input:t,model:o,systemPrompt:r=sc,maxIterations:n=3,onStep:a,logger:s}=e,i=M(o??{provider:"openai",model:"gpt-4o-mini"});return k({model:i,tools:{hello_world:as},systemPrompt:r,input:t,maxIterations:n,onStep:a,logger:s})}function ve(e,t){return {input:e,model:t.model,maxIterations:t.maxIterations,onStep:t.onStep,logger:t.logger}}var lr=[{name:"Requirement Gatherer",key:"requirements",heading:"Requirements",run:(e,t)=>Xe(ve(e.userInput??"",t)).then(o=>o.output)},{name:"Data Modeler",key:"dataModel",heading:"Data Model",run:(e,t)=>rt(ve(`Design a data model based on these requirements:
|
|
1827
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"API Designer",key:"apiDesign",heading:"API Design",run:(e,t)=>st(ve(`Design the API based on this data model and requirements:
|
|
1828
|
+
Data Model:
|
|
1829
|
+
${e.dataModel}
|
|
1830
|
+
|
|
1831
|
+
Requirements:
|
|
1832
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"Auth Designer",key:"authDesign",heading:"Auth Design",run:(e,t)=>it(ve(`Design auth for this project:
|
|
1833
|
+
Requirements:
|
|
1834
|
+
${e.requirements}
|
|
1835
|
+
|
|
1836
|
+
API Design:
|
|
1837
|
+
${e.apiDesign}`,t)).then(o=>o.output)},{name:"Backend Architect",key:"backendDesign",heading:"Backend Architecture",run:(e,t)=>pt(ve(`Design backend architecture:
|
|
1838
|
+
Data Model:
|
|
1839
|
+
${e.dataModel}
|
|
1840
|
+
|
|
1841
|
+
API Design:
|
|
1842
|
+
${e.apiDesign}
|
|
1843
|
+
|
|
1844
|
+
Auth Design:
|
|
1845
|
+
${e.authDesign}`,t)).then(o=>o.output)},{name:"Frontend Architect",key:"frontendDesign",heading:"Frontend Architecture",run:(e,t)=>ut(ve(`Design frontend architecture:
|
|
1846
|
+
API Design:
|
|
1847
|
+
${e.apiDesign}
|
|
1848
|
+
|
|
1849
|
+
Requirements:
|
|
1850
|
+
${e.requirements}`,t)).then(o=>o.output)},{name:"Execution Planner",key:"executionPlan",heading:"Execution Plan",run:(e,t)=>Tt(ve(`Create an execution plan for this project:
|
|
1851
|
+
Requirements:
|
|
1852
|
+
${e.requirements}
|
|
1853
|
+
|
|
1854
|
+
Data Model:
|
|
1855
|
+
${e.dataModel}
|
|
1856
|
+
|
|
1857
|
+
API Design:
|
|
1858
|
+
${e.apiDesign}
|
|
1859
|
+
|
|
1860
|
+
Auth Design:
|
|
1861
|
+
${e.authDesign}
|
|
1862
|
+
|
|
1863
|
+
Backend Design:
|
|
1864
|
+
${e.backendDesign}
|
|
1865
|
+
|
|
1866
|
+
Frontend Design:
|
|
1867
|
+
${e.frontendDesign}`,t)).then(o=>o.output)}];var ls=e=>{process.stderr.write(`[full-pipeline] ${e}
|
|
1868
|
+
`);};function ac(e){return `# Full Application Specification
|
|
1869
|
+
|
|
1870
|
+
${e.map(o=>`## ${lr.find(a=>a.key===o.key)?.heading??o.name}
|
|
1871
|
+
|
|
1872
|
+
${o.output}`).join(`
|
|
1873
|
+
|
|
1874
|
+
---
|
|
1875
|
+
|
|
1876
|
+
`)}`}async function ps(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=lr.length;for(let[c,u]of lr.entries()){ls(`[${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}),ls(`[${c+1}/${p}] ${u.name} \u2014 done`);}return ls("Pipeline complete"),{output:ac(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 Qe=[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.',ps),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.',Lr),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.',Xe),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}".',rt),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}".',st),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}".',it),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}".',pt),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}".',ut),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=>Dn({...e,disableScaffold:true})),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=>Fn({...e,disableScaffold:true})),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=>Xn({...e,disableScaffold:true})),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}".',os),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}".',Tt),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".',is)];function cs(e){return Qe.find(t=>t.name===e)}var us={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 ds(e){if(!(!e.provider&&!e.model))return {provider:e.provider??"openai",model:e.model??"gpt-4o-mini",temperature:e.temperature}}var lc="sweagent",pc="0.0.3",Pt=e=>{process.stderr.write(`[sweagent] ${e}
|
|
1877
|
+
`);},ji=200;function cc(e){return t=>{let o=`${e} \u2014 step ${t.iteration+1}`;if(t.content){let r=t.content.length>ji?t.content.slice(0,ji)+"\u2026":t.content;Pt(`${o}: ${r}`);}else {let r=t.toolCalls?.map(n=>n.toolName).join(", ");Pt(`${o}${r?` (tools: ${r})`:""}`);}}}function ms(){let e=new McpServer({name:lc,version:pc},{capabilities:{tools:{}}});for(let t of Qe)e.registerTool(t.name,{description:t.description,inputSchema:us},async o=>{Pt(`${t.name} \u2014 started`);try{let r=ds(o),n=cc(t.name),a=await t.handler(o.input,r,n);return Pt(`${t.name} \u2014 completed`),{content:[{type:"text",text:a.output}]}}catch(r){let n=r instanceof Error?r.message:String(r);return Pt(`${t.name} \u2014 error: ${n}`),{content:[{type:"text",text:n}],isError:true}}});return e}export{Eo as API_DESIGNER_SYSTEM_PROMPT,jn as APOLLO_BUILDER_SYSTEM_PROMPT,xn as AUTH_DESIGNER_SYSTEM_PROMPT,ye as AgentError,$n as ApiResponseTypeSchema,Bn as AppConfigSchema,yt as ApplicationSchema,mi as AuthPageApiSchema,gi as AuthPageSchema,Rn as BACKEND_ARCHITECT_SYSTEM_PROMPT,Ft as BaseMcpClient,Gn as BrandingSchema,Di as CREATE_EXECUTION_PLAN_PROMPT,Jn as ColumnSchema,zp as CreateUserInputSchema,ho as DATA_MODELER_SYSTEM_PROMPT,oe as DB_DESIGN_SYSTEM_PROMPT,qa as DESIGN_AUTH_PROMPT,Ja as DESIGN_BACKEND_PROMPT,Yr as DESIGN_DATABASE_SYSTEM_PROMPT,ti as DESIGN_EXPRESS_PROMPT,Qa as DESIGN_FRONTEND_PROMPT,Mi as DESIGN_NEXTJS_PROMPT,ii as DESIGN_SUBGRAPH_PROMPT,Fr as DISCOVERY_SYSTEM_FRAGMENT,ia as DISCOVERY_USER_PROMPT,zn as DrawerSchema,Si as EXAMPLE_GRAPHQL_SCHEMA,bi as EXAMPLE_JSON_OUTPUT,rs as EXECUTION_PLANNER_SYSTEM_PROMPT,On as EXPRESS_BUILDER_SYSTEM_PROMPT,la as EXTRACT_ACTORS_PROMPT,ua as EXTRACT_MODULES_PROMPT,An as FRONTEND_ARCHITECT_SYSTEM_PROMPT,ui as FieldOptionsSchema,Yp as ForgotPasswordSchema,Wo as FormFieldSchema,pa as GENERATE_FLOWS_PROMPT,ca as GENERATE_STORIES_PROMPT,he as LibraryError,di as ListingPageApiSchema,fi as ListingPageSchema,Bp as LoginInputSchema,oe as MONGODB_SYSTEM_PROMPT,Q as ModelError,hi as ModuleSchema,Zn as NEXTJS_BUILDER_SYSTEM_PROMPT,ne as PLANNING_SYSTEM_PROMPT,Yn as PageSchema,Kt as PlanningContextBuilder,Ko as REACT_BUILDER_INSTRUCTION,St as REACT_BUILDER_SYSTEM_PROMPT,Re as REQUIREMENT_GATHERER_SYSTEM_PROMPT,fo as RequirementContextBuilder,Hp as ResetPasswordSchema,Qr as SYNTHESIS_SYSTEM_FRAGMENT,da as SYNTHESIS_USER_PROMPT,yi as SpecializationSchema,Me as SubagentError,Qe as TOOL_REGISTRY,W as ToolError,$p as UpdateUserInputSchema,Jp as UserSchema,vt as ValidationError,ci as ValidationSchema,Fe as actorSchema,Xt as actorsResultSchema,fe as adApiDesignSchema,hn as adGraphqlOperationSchema,fn as adRestEndpointSchema,Ke as addChatEntry,no as advanceStage,sr as apiRouteGeneratorSubagent,_r as assemblePlan,at as authDesignSchema,Da as authFlowSchema,ka as authFlowStepSchema,_a as authMiddlewareSchema,lt as backendDesignSchema,ns as buildCreateExecutionPlanPrompt,Tn as buildDesignAuthPrompt,wn as buildDesignBackendPrompt,Hr as buildDesignDatabasePrompt,Cn as buildDesignExpressPrompt,Mn as buildDesignFrontendPrompt,es as buildDesignNextjsPrompt,qn as buildDesignSubgraphPrompt,Gr as buildDiscoveryPrompt,Qn as buildExampleShotPrompt,Br as buildExtractActorsPrompt,$r as buildExtractModulesPrompt,Qp as buildFeedbackPrompt,Jr as buildGenerateFlowsPrompt,zr as buildGenerateStoriesPrompt,Hn as buildInstructionPrompt,bo as buildPromptVariables,Vr as buildSynthesisPrompt,sa as chatEntrySchema,xs as clearRun,Sr as compileTemplate,Yt as componentAnalyzerSubagent,Ha as componentDesignSchema,qe as contractDesignerSubagent,Xs as convertRequirementToContext,Lt as createAnthropicModel,bn as createApiDesignerTools,Un as createApolloBuilderTools,Pn as createAuthDesignerTools,vn as createBackendArchitectTools,tr as createConfigValidatorSubagent,dn as createDataModelerTools,Ze as createDbDesignPrompt,mn as createDbDesignerTools,No as createDesignApiProTool,Co as createDesignApiTool,Do as createDesignAuthTool,Io as createDesignBackendTool,Ao as createDesignDatabaseProTool,vo as createDesignDatabaseTool,Uo as createDesignFrontendTool,Po as createDesignSchemaProTool,To as createDesignSchemaTool,ir as createExecutionPlanTool,ss as createExecutionPlannerTools,kn as createExpressBuilderTools,En as createFrontendArchitectTools,Go as createGenerateExpressTool,Zo as createGenerateFeatureBreakdownTool,Xo as createGenerateFrontendTool,rr as createGenerateNextjsTool,Yo as createGenerateSubgraphTool,Ut as createGoogleModel,Wr as createInitialContext,gc as createLogger,M as createModel,Ze as createMongoDesignPrompt,et as createMongoProDesignPrompt,tt as createMongoRedesignPrompt,ts as createNextjsBuilderTools,qt as createOpenAIModel,ap as createPlanningContextBuilder,et as createProDbDesignPrompt,Ts as createProposalTools,Kn as createReactBuilderTools,Mo as createRedesignDatabaseTool,tt as createRedesignPrompt,Ro as createRefineSchemaTools,mp as createRequirementContextBuilder,xe as createSchemaRefinerSubagent,yr as createSubagentTool,q as createSubagentToolSet,ms as createSweagentServer,j as createToolSet,ea as crudApiSchema,Pe as databaseDesignSchema,na as databaseEntitySchema,y as defineSubagent,f as defineTool,bs as discard,xe as dmCreateSchemaRefinerSubagent,tn as dmDataEntitySchema,ae as dmDataModelDesignSchema,pe as dmEntityAnalyzerSubagent,xo as dmValidateSchemaTool,Le as edgeCaseAnalyzerSubagent,Ni as edgeCaseSchema,Wl as editPlan,je as endpointAnalyzerSubagent,pe as entityAnalyzerSubagent,ta as entityFieldSchema,oa as entityIndexSchema,ra as entityRelationSchema,We as estimateMessagesTokens,fr as estimateTokens,dr as executeTool,Ne as executeToolByName,xt as executionPlanSchema,dt as expressConfigSchema,yo as extractDataEntities,Fi as extractJson,So as extractRoles,Je as extractedModuleSchema,$e as fieldSchema,Ur as finalRequirementSchema,Nt as finalize,cs as findTool,Ie as flowDesignerSubagent,Ge as flowSchema,Zt as flowsResultSchema,$a as formFieldSchema,pn as formatTechnicalRequirements,an as formatUserFlows,ln as formatUserStories,sn as formatUserTypes,qo as frameworkSelectorSubagent,ct as frontendDesignSchema,It as generateNResponses,Ot as getProposed,Ss as getTool,ys as getTools,er as graphqlAnalyzerSubagent,_n as graphqlFieldSchema,In as graphqlTypeSchema,as as helloWorldTool,Ci as implementationPhaseSchema,zi as jsonSchema,Ct as listProposed,fc as loggerConfigFromEnv,Kr as mergeStageResult,ei as middlewareConfigSchema,zo as middlewareConfiguratorSubagent,Fa as middlewareSchema,Xa as modelFieldSchema,Za as modelSchema,Ye as moduleSchema,to as modulesResultSchema,$e as mongoFieldSchema,Ye as mongoModuleSchema,te as mongoProjectSchema,vi as nextjsApiRouteSchema,bt as nextjsConfigSchema,wi as nextjsLayoutSchema,Ri as nextjsPageSchema,Ya as pageDesignSchema,_e as pagePlannerSubagent,C as parseModelJsonResponse,Oi as phaseStepSchema,Te as processPlanningChat,go as processRequirementChat,ze as projectBriefSchema,te as projectSchema,Et as propose,ke as pruneContext,oo as questionSchema,br as registerHelpers,$t as relationshipMapperSubagent,ip as requirementContextSchema,aa as requirementSummarySchema,si as resolverOperationSchema,Vo as resolverPlannerSubagent,Ia as roleDefinitionSchema,Jo as routeGeneratorSubagent,Ba as routeGroupSchema,nr as routePlannerSubagent,Wa as routerMethodSchema,Ka as routerSchema,k as runAgent,jt as runAgentWithSteps,st as runApiDesignerAgent,Fn as runApolloBuilderAgent,it as runAuthDesignerAgent,pt as runBackendArchitectAgent,rt as runDataModelerAgent,bp as runDbDesignerAgent,Tt as runExecutionPlannerAgent,Dn as runExpressBuilderAgent,ut as runFrontendArchitectAgent,ps as runFullPipelineAgent,is as runHelloWorldAgent,os as runNextjsBuilderAgent,Lr as runPlanningAgent,np as runPlanningFromRequirements,_t as runProgrammaticStep,Xn as runReactBuilderAgent,Xe as runRequirementGathererAgent,V as runSubagent,Ee as safeJsonParse,Bo as scaffoldExpressTool,ge as scaffoldProject,Ho as scaffoldSubgraphTool,Qo as schemaGeneratorSubagent,Ht as securityAnalyzerSubagent,ja as securityPolicySchema,vs as selectByJudge,ws as selectByLength,Ai as serverActionSchema,jo as servicePlannerSubagent,Ga as serviceSchema,eo as storiesResultSchema,Be as storySchema,mt as subgraphConfigSchema,ai as subgraphModuleSchema,Se as sumTokenUsage,hr as summarizeMessage,Dt as summarizeMessages,ki as testChecklistItemSchema,Ue as testingStrategistSubagent,ur as tool,Z as truncateText,Ps as truncateToTokens,Oo as validateApiTool,ko as validateAuthTool,_o as validateBackendTool,ar as validateExecutionPlanTool,Fo as validateExpressTool,He as validateFrontendConfigTool,Lo as validateFrontendTool,or as validateNextjsTool,wo as validateSchemaTool,$o as validateSubgraphTool,zl as writePlanToFile};//# sourceMappingURL=index.js.map
|
|
1770
1878
|
//# sourceMappingURL=index.js.map
|