sweagent 0.0.1 → 0.0.3
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 +1076 -329
- package/dist/index.cjs +1598 -316
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3197 -391
- package/dist/index.d.ts +3197 -391
- package/dist/index.js +1598 -316
- package/dist/index.js.map +1 -1
- package/package.json +13 -2
package/dist/index.cjs
CHANGED
|
@@ -1,305 +1,16 @@
|
|
|
1
|
-
'use strict';var zod=require('zod'),ai=require('ai'),openai=require('@ai-sdk/openai'),anthropic=require('@ai-sdk/anthropic'),google=require('@ai-sdk/google'),client=require('@modelcontextprotocol/sdk/client'),module$1=require('module'),
|
|
2
|
-
Caused by: ${o.stack}`);}},C=class extends M{constructor(o,r,n){super(o,n);this.provider=r;this.name="ModelError";}},x=class extends M{constructor(o,r,n){super(o,n);this.toolName=r;this.name="ToolError";}},Ne=class extends M{constructor(o,r){super(o);this.errors=r;this.name="ValidationError";}},Y=class extends M{constructor(o,r,n){super(o,n);this.iteration=r;this.name="AgentError";}},D=class extends M{constructor(o,r,n){super(o,n);this.subagentName=r;this.name="SubagentError";}};var Ue={debug:0,info:1,warn:2,error:3};function Ht(t={}){let{prefix:e="",level:o="info",timestamps:r=false}=t,n=Ue[o];function i(a,p){let m=[];return r&&m.push(`[${new Date().toISOString()}]`),m.push(`[${a.toUpperCase()}]`),e&&m.push(`[${e}]`),m.push(p),m.join(" ")}function s(a){return Ue[a]>=n}return {debug(a,p){s("debug")&&console.debug(i("debug",a),p??"");},info(a,p){s("info")&&console.info(i("info",a),p??"");},warn(a,p){s("warn")&&console.warn(i("warn",a),p??"");},error(a,p){s("error")&&console.error(i("error",a),p??"");}}}var pt={noCacheTokens:void 0,cacheReadTokens:void 0,cacheWriteTokens:void 0},dt={textTokens:void 0,reasoningTokens:void 0};function ke(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:pt,outputTokenDetails:dt}}function h(t){let{name:e,description:o,input:r,handler:n}=t;return ai.tool({description:o,inputSchema:r,execute:async i=>{let s=r.safeParse(i);if(!s.success)throw new x(`Invalid input: ${s.error.message}`,e,s.error);try{return await n(s.data,void 0)}catch(a){throw a instanceof x?a:new x(`Tool "${e}" failed: ${a instanceof Error?a.message:String(a)}`,e,a instanceof Error?a:void 0)}}})}function I(t){return t}function _e(t){return Object.values(t)}function je(t,e){return t[e]}async function ce(t,e,o){if(!t.execute)return {success:false,error:"Tool has no execute function"};try{return {success:!0,output:await t.execute(e,{toolCallId:o?.toolCallId??"",messages:[],abortSignal:o?.abortSignal})}}catch(r){return {success:false,error:r instanceof Error?r.message:String(r)}}}async function H(t,e,o,r){let n=t[e];if(!n)throw new x(`Tool not found: ${e}`);return ce(n,o,r)}async function w(t){let{model:e,tools:o,systemPrompt:r,input:n,maxIterations:i=10,onStep:s}=t,a=[{role:"system",content:r},{role:"user",content:n}],p=[];for(let m=0;m<i;m++){let u=await e.invoke(a,{tools:o}),g={iteration:m,content:u.text,toolCalls:u.toolCalls,usage:u.usage};if(!u.toolCalls?.length)return p.push(g),s?.(g),{output:u.text,steps:p,totalUsage:ke(p.map(S=>S.usage)),messages:a};let y=[...u.text?[{type:"text",text:u.text}]:[],...u.toolCalls.map(S=>({type:"tool-call",toolCallId:S.toolCallId,toolName:S.toolName,input:S.input}))];a.push({role:"assistant",content:y});let G=[];for(let S of u.toolCalls){let J=await H(o,S.toolName,S.input,{toolCallId:S.toolCallId}),O={toolCallId:S.toolCallId,toolName:S.toolName,output:J.success?J.output:J.error,isError:!J.success};G.push(O);let ct=O.isError?{type:"error-text",value:String(O.output)}:{type:"text",value:typeof O.output=="string"?O.output:JSON.stringify(O.output)};a.push({role:"tool",content:[{type:"tool-result",toolCallId:S.toolCallId,toolName:S.toolName,output:ct}]});}g.toolResults=G,p.push(g),s?.(g);}throw new Y(`Agent reached maximum iterations (${i}) without completing`,i-1)}function N(t){let{provider:e,modelName:o,getModel:r}=t;return {provider:e,modelName:o,async invoke(n,i){try{let s=await r(),a=i?.tools?Object.fromEntries(Object.entries(i.tools).map(([u,g])=>{let{execute:y,...G}=g;return [u,G]})):void 0,p=await ai.generateText({model:s,messages:n,tools:a,maxOutputTokens:i?.maxOutputTokens,temperature:i?.temperature,stopSequences:i?.stop}),m=p.toolCalls.map(u=>({toolCallId:u.toolCallId,toolName:u.toolName,input:u.input}));return {text:p.text,toolCalls:m,usage:p.usage,finishReason:p.finishReason}}catch(s){let a=s instanceof Error?s:new Error(String(s));throw new C(`Failed to invoke ${e} model`,e,a)}},async generateVision(n,i,s){try{let a=await r(),p=[];for(let g of i)p.push({type:"image",image:`data:${g.mimeType};base64,${g.base64}`,mimeType:g.mimeType});p.push({type:"text",text:n});let m=[];s?.systemPrompt&&m.push({role:"system",content:s.systemPrompt}),m.push({role:"user",content:p});let u=await ai.generateText({model:a,messages:m,maxOutputTokens:s?.maxOutputTokens,temperature:s?.temperature});return {text:u.text,toolCalls:[],usage:u.usage,finishReason:u.finishReason}}catch(a){let p=a instanceof Error?a:new Error(String(a));throw new C("Failed to generate vision response",e,p)}}}}function Q(t){let{model:e,apiKey:o,baseUrl:r}=t,n=openai.createOpenAI({apiKey:o??process.env.OPENAI_API_KEY,baseURL:r});return N({provider:"openai",modelName:e,getModel:()=>n.chat(e)})}function V(t){let{model:e,apiKey:o}=t,r=anthropic.createAnthropic({apiKey:o??process.env.ANTHROPIC_API_KEY});return N({provider:"anthropic",modelName:e,getModel:()=>r(e)})}function W(t){let{model:e,apiKey:o}=t,r=google.createGoogleGenerativeAI({apiKey:o??process.env.GOOGLE_GENERATIVE_AI_API_KEY});return N({provider:"google",modelName:e,getModel:()=>r(e)})}function R(t){let{provider:e}=t;switch(e){case "openai":return Q(t);case "anthropic":return V(t);case "google":return W(t);default:throw new C(`Unsupported provider: ${e}. Supported providers: openai, anthropic, google`)}}var bt=/^[a-z0-9]+(-[a-z0-9]+)*$/;function v(t){if(!t.name.trim())throw new D("Subagent name is required",void 0);if(!bt.test(t.name))throw new D(`Subagent name must be kebab-case (lowercase letters, numbers, hyphens): ${t.name}`,t.name);return {...t}}function St(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[i,s]of Object.entries(o))i.startsWith("subagent_")||r.has(i)||(n[i]=s);return n}async function pe(t,e,o){let{parentTools:r,parentModel:n}=o??{},i=St(t,r),s=t.model==null?n:R(t.model);if(!s)throw new D("Subagent has no model: set definition.model or pass parentModel in options",t.name);return {...await w({model:s,tools:i,systemPrompt:t.systemPrompt,input:e,maxIterations:t.maxIterations??10,onStep:t.onStep}),subagentName:t.name}}function de(t,e){let o=`subagent_${t.name}`;return h({name:o,description:t.description,input:zod.z.object({prompt:zod.z.string().describe("The task or question to delegate to this subagent")}),handler:async({prompt:r})=>(await pe(t,r,{parentTools:e?.parentTools,parentModel:e?.parentModel})).output})}function U(t,e){let o={};for(let r of t){let n=de(r,e);o[`subagent_${r.name}`]=n;}return o}function xt(){let e=module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))).resolve("@modelcontextprotocol/sdk/client");return k__default.default.dirname(k__default.default.dirname(k__default.default.dirname(k__default.default.dirname(e))))}var Fe=xt();function $e(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 Be(t,e){let o=k__default.default.join(Fe,"dist","esm","client","streamableHttp.js"),r=await import(url.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 Ge(t,e){let o=k__default.default.join(Fe,"dist","esm","client","stdio.js"),r=await import(url.pathToFileURL(o).href);return new r.StdioClientTransport({command:t,args:e})}var K=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:i}=o,s=e?.url??process.env[`${r}_URL`],a=process.env[`${r}_API_KEY`],p=e?.command??process.env[`${r}_COMMAND`],m=process.env[`${r}_ARGS`],u=e?.args??(m?m.split(",").map(y=>y.trim()):void 0),g=e?.headers?{...e.headers}:void 0;if(a){let y=i??"Authorization";g=g??{},g[y]=y==="Authorization"?`Bearer ${a}`:a;}if(s)return {url:s,headers:g};if(p)return {command:p,args:u?.length?u:[]};throw new x(`${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 x("MCP connection failed.","mcp_client");return this.client}if(this.connectPromise=this.doConnect(),await this.connectPromise,this.connectPromise=null,!this.client)throw new x("MCP connection failed.","mcp_client");return this.client}async doConnect(){let e=new client.Client({name:this.info.name,version:this.info.version},{capabilities:{}});if(this.config.url)this.transport=await Be(this.config.url,this.config.headers);else if(this.config.command)this.transport=await Ge(this.config.command,this.config.args??[]);else throw new x("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?$e(n):n}async close(){this.transport&&(await this.transport.close(),this.transport=null),this.client=null,this.connectPromise=null;}};var me=h({name:"hello_world",description:"Returns a greeting message for the given name",input:zod.z.object({name:zod.z.string().describe("Name to greet")}),handler:async({name:t})=>({greeting:`Hello, ${t}! Welcome to sweagent.`})});var Rt="You are a friendly greeter. Use the hello_world tool to greet users.";async function vt(t){let{input:e,model:o,systemPrompt:r=Rt,maxIterations:n=3,onStep:i}=t,s=R(o??{provider:"openai",model:"gpt-4o-mini"});return w({model:s,tools:{hello_world:me},systemPrompt:r,input:e,maxIterations:n,onStep:i})}var ue=zod.z.object({fieldName:zod.z.string().describe("fieldName must be in camelCase"),fieldType:zod.z.enum(["string","number","boolean","Types.ObjectId","Date","object","email","password","enum"]),isArray:zod.z.boolean(),isRequired:zod.z.boolean(),isUnique:zod.z.boolean(),values:zod.z.array(zod.z.string()).describe("Enum values if fieldType is enum, else empty array"),defaultVal:zod.z.union([zod.z.string(),zod.z.boolean(),zod.z.number(),zod.z.null()]).optional(),relationTo:zod.z.string().optional().describe("Module name for relations"),relationType:zod.z.enum(["one-to-one","many-to-one",""]).optional(),isPrivate:zod.z.boolean().describe("True if password field, else false")});var ge=zod.z.object({moduleName:zod.z.string().describe("camelCase, single word, never auth/authentication"),isUserModule:zod.z.boolean(),authMethod:zod.z.enum(["EMAIL_AND_PASSWORD","PHONE_AND_OTP",""]).optional(),emailField:zod.z.string().optional(),passwordField:zod.z.string().optional(),phoneField:zod.z.string().optional(),roleField:zod.z.string().optional(),permissions:zod.z.record(zod.z.string(),zod.z.array(zod.z.enum(["CREATE","READ","UPDATE","DELETE"]))).optional().describe("Permissions per role"),fields:zod.z.array(ue)});var A=zod.z.object({projectName:zod.z.string().describe("projectName must be in kebab-case"),projectDescription:zod.z.string(),modules:zod.z.array(ge),author:zod.z.string().default("sijeeshmiziha")});var P=`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.
|
|
3
|
-
|
|
4
|
-
## ANALYSIS FRAMEWORK
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- Pattern: "Product Inventory" \u2192 product collection with inventory fields
|
|
15
|
-
|
|
16
|
-
2. **From User Types (Actors)**: Each actor type may indicate a User variant or role
|
|
17
|
-
- Pattern: "Admin", "Customer", "Vendor" \u2192 User collection with role enum
|
|
18
|
-
- Pattern: "Guest" \u2192 May not need persistence, or limited session data
|
|
19
|
-
|
|
20
|
-
3. **From User Flow Actions**: Action verbs reveal implicit entities
|
|
21
|
-
- "creates order" \u2192 Order collection
|
|
22
|
-
- "submits payment" \u2192 Payment collection
|
|
23
|
-
- "uploads document" \u2192 Document collection
|
|
24
|
-
- "sends message" \u2192 Message collection
|
|
25
|
-
|
|
26
|
-
4. **From Flow States**: Transitions reveal status enums
|
|
27
|
-
- Flow: pending \u2192 approved \u2192 completed \u2192 Order.status enum
|
|
28
|
-
- Flow: draft \u2192 published \u2192 archived \u2192 Content.status enum
|
|
29
|
-
|
|
30
|
-
### PHASE 2: Relationship Mapping
|
|
31
|
-
For each entity pair, determine relationships based on:
|
|
32
|
-
|
|
33
|
-
1. **Ownership Patterns** (from actor actions):
|
|
34
|
-
- "Customer places Order" \u2192 Order.customer (many-to-one to User)
|
|
35
|
-
- "Admin approves Request" \u2192 Request.approvedBy (many-to-one to User)
|
|
36
|
-
- "User creates Post" \u2192 Post.author (many-to-one to User)
|
|
37
|
-
|
|
38
|
-
2. **Cardinality from Flow Context**:
|
|
39
|
-
- "User has one profile" \u2192 one-to-one
|
|
40
|
-
- "User places multiple orders" \u2192 many-to-one (Order \u2192 User)
|
|
41
|
-
- "Order contains items" \u2192 many-to-one (OrderItem \u2192 Order)
|
|
42
|
-
|
|
43
|
-
3. **Shared Entities** (referenced across flows):
|
|
44
|
-
- Entity referenced by multiple actors \u2192 likely needs relationships to User
|
|
45
|
-
- Entity in multiple flows \u2192 likely a core/central entity
|
|
46
|
-
|
|
47
|
-
4. **Bidirectional References** (for one-to-one):
|
|
48
|
-
- Include reference field in BOTH collections for one-to-one relationships
|
|
49
|
-
|
|
50
|
-
### PHASE 3: Permission Derivation
|
|
51
|
-
Map actors to RBAC permissions:
|
|
52
|
-
|
|
53
|
-
1. **Role Extraction**: Each actor type becomes a role value
|
|
54
|
-
- actors: [Admin, Customer, Vendor] \u2192 role enum: ['admin', 'customer', 'vendor']
|
|
55
|
-
|
|
56
|
-
2. **Permission Mining from User Stories**:
|
|
57
|
-
- "As Admin, I can delete users" \u2192 admin: ['CREATE', 'READ', 'UPDATE', 'DELETE'] on user
|
|
58
|
-
- "As Customer, I can view my orders" \u2192 customer: ['READ'] on order (own records)
|
|
59
|
-
- "As Vendor, I can update products" \u2192 vendor: ['CREATE', 'READ', 'UPDATE'] on product
|
|
60
|
-
|
|
61
|
-
3. **Data Visibility Rules**:
|
|
62
|
-
- "view own" \u2192 READ permission with ownership filter
|
|
63
|
-
- "view all" \u2192 READ permission without filter
|
|
64
|
-
- "manage" \u2192 full CRUD permissions
|
|
65
|
-
|
|
66
|
-
### PHASE 4: Query Pattern Inference
|
|
67
|
-
Analyze flows to predict database access patterns:
|
|
68
|
-
|
|
69
|
-
1. **Read Patterns** (suggest indexes):
|
|
70
|
-
- "list orders by date" \u2192 index on order.createdAt
|
|
71
|
-
- "search products by category" \u2192 index on product.category
|
|
72
|
-
- "find user by email" \u2192 unique index on user.email
|
|
73
|
-
- "filter by status" \u2192 index on status field
|
|
74
|
-
|
|
75
|
-
2. **Write Patterns** (affect schema design):
|
|
76
|
-
- High-frequency writes \u2192 consider denormalization
|
|
77
|
-
- Audit requirements \u2192 add createdBy, updatedBy fields
|
|
78
|
-
|
|
79
|
-
3. **Aggregation Needs** (from reporting flows):
|
|
80
|
-
- "view sales dashboard" \u2192 may need summary collections
|
|
81
|
-
- "generate reports" \u2192 ensure proper indexing for date ranges
|
|
82
|
-
|
|
83
|
-
### PHASE 5: Schema Construction
|
|
84
|
-
Synthesize all analyses into the final schema:
|
|
85
|
-
|
|
86
|
-
1. **Module Definition**:
|
|
87
|
-
- One module per core entity
|
|
88
|
-
- camelCase module names (never 'auth' or 'authentication')
|
|
89
|
-
- Mark user modules with isUserModule: true
|
|
90
|
-
|
|
91
|
-
2. **Field Completeness**:
|
|
92
|
-
- All fields from dataInvolved
|
|
93
|
-
- Relationship fields (Types.ObjectId with relationTo)
|
|
94
|
-
- Status/lifecycle fields (enum type with values from flow states)
|
|
95
|
-
- Audit fields: createdAt, updatedAt (Date, required)
|
|
96
|
-
- createdBy, updatedBy when flows mention "who did what"
|
|
97
|
-
|
|
98
|
-
3. **Validation Constraints**:
|
|
99
|
-
- isRequired: true for fields mentioned in preconditions
|
|
100
|
-
- isUnique: true for identifier fields (email, slug, code)
|
|
101
|
-
- enum values from flow states and categorical data
|
|
102
|
-
|
|
103
|
-
4. **Security Fields**:
|
|
104
|
-
- password fields: fieldType: 'password', isPrivate: true
|
|
105
|
-
- email fields: fieldType: 'email', isUnique: true
|
|
106
|
-
|
|
107
|
-
## CORE CONSTRAINTS (MUST FOLLOW)
|
|
108
|
-
|
|
109
|
-
1. **Primary Key**: _id with Types.ObjectId (auto-generated, do not include in fields)
|
|
110
|
-
|
|
111
|
-
2. **Relationships**:
|
|
112
|
-
- One-to-One: Reference field in BOTH collections
|
|
113
|
-
- Many-to-One: Reference in the "many" side only
|
|
114
|
-
- Many-to-Many: ONLY when necessary, use intermediate collection
|
|
115
|
-
- One-to-Many: FORBIDDEN - invert to many-to-one from child
|
|
116
|
-
|
|
117
|
-
3. **Data Types**:
|
|
118
|
-
- NO arrays of ObjectIds for relationships
|
|
119
|
-
- Timestamps: createdAt, updatedAt (Date) in EVERY collection
|
|
120
|
-
- Enums: Use fieldType: 'enum' with values array
|
|
121
|
-
|
|
122
|
-
4. **Security**:
|
|
123
|
-
- NO separate "Auth" or "Authentication" collection
|
|
124
|
-
- NO token storage in database
|
|
125
|
-
- Password fields: isPrivate: true
|
|
126
|
-
|
|
127
|
-
5. **Authorization (RBAC)**:
|
|
128
|
-
- Define permissions per role on user modules
|
|
129
|
-
- Format: {{ "roleName": ["CREATE", "READ", "UPDATE", "DELETE"] }}`;function fe(t){return `${P}
|
|
130
|
-
|
|
131
|
-
Design a robust and efficient MongoDB database schema based on the following requirements:
|
|
132
|
-
|
|
133
|
-
## Requirements
|
|
134
|
-
${t}
|
|
135
|
-
|
|
136
|
-
## Guidelines
|
|
137
|
-
1. Use camelCase for module names and field names
|
|
138
|
-
2. Include createdAt and updatedAt Date fields in every module
|
|
139
|
-
3. Define proper relationships between modules
|
|
140
|
-
4. Set appropriate permissions for user modules
|
|
141
|
-
|
|
142
|
-
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function Ye(t){return !t||t.length===0?'No specific user types defined. Assume a general "User" role.':t.map((e,o)=>{let r=e.goals.filter(n=>n.trim()).join(`
|
|
143
|
-
- `);return `### ${o+1}. ${e.name}
|
|
144
|
-
**Description:** ${e.description}
|
|
145
|
-
**Goals:**
|
|
146
|
-
- ${r||"No specific goals defined"}`}).join(`
|
|
147
|
-
|
|
148
|
-
`)}function He(t,e){return !t||t.length===0?"No specific user flows defined.":t.map((o,r)=>{let i=e.find(s=>s.id===o.actorId)?.name||"User";return `### ${r+1}. ${o.name}
|
|
149
|
-
**Actor:** ${i}
|
|
150
|
-
**Description:** ${o.description}
|
|
151
|
-
**Trigger:** ${o.trigger||"User initiates action"}
|
|
152
|
-
**Outcome:** ${o.outcome||"Action completed"}`}).join(`
|
|
153
|
-
|
|
154
|
-
`)}function Qe(t,e){if(!t||t.length===0)return "No specific user stories defined.";let o=new Map;for(let i of t){let s=o.get(i.flowId)||[];s.push(i),o.set(i.flowId,s);}let r=[];for(let i of e){let s=o.get(i.id)||[];if(s.length!==0){r.push(`### Flow: ${i.name}
|
|
155
|
-
`);for(let a of s){let p=a.preconditions.filter(y=>y.trim()),m=a.postconditions.filter(y=>y.trim()),u=a.dataInvolved.filter(y=>y.trim()),g=`**As a** ${a.actor}, **I want to** ${a.action}, **so that** ${a.benefit}
|
|
156
|
-
`;p.length>0&&(g+=`
|
|
157
|
-
**Preconditions:**
|
|
158
|
-
${p.map(y=>`- ${y}`).join(`
|
|
159
|
-
`)}
|
|
160
|
-
`),m.length>0&&(g+=`
|
|
161
|
-
**Postconditions:**
|
|
162
|
-
${m.map(y=>`- ${y}`).join(`
|
|
163
|
-
`)}
|
|
164
|
-
`),u.length>0&&(g+=`
|
|
165
|
-
**Data Involved (IMPORTANT - these indicate entities/fields):**
|
|
166
|
-
${u.map(y=>`- ${y}`).join(`
|
|
167
|
-
`)}
|
|
168
|
-
`),r.push(g);}}}let n=t.filter(i=>!e.some(s=>s.id===i.flowId));if(n.length>0){r.push(`### Other Stories
|
|
169
|
-
`);for(let i of n){let s=i.dataInvolved.filter(p=>p.trim()),a=`**As a** ${i.actor}, **I want to** ${i.action}, **so that** ${i.benefit}
|
|
170
|
-
`;s.length>0&&(a+=`
|
|
171
|
-
**Data Involved:** ${s.join(", ")}
|
|
172
|
-
`),r.push(a);}}return r.join(`
|
|
173
|
-
`)}function Ve(t){if(!t)return "No specific technical requirements. Use defaults.";let e=[];return e.push(`**Authentication:** ${t.authentication||"none"}`),t.authorization?(e.push("**Authorization (RBAC):** Enabled"),t.roles&&t.roles.length>0&&e.push(`**Defined Roles:** ${t.roles.join(", ")}`)):e.push("**Authorization:** Disabled"),t.realtime&&e.push("**Realtime Features:** Required (consider subscription patterns)"),t.fileUpload&&e.push("**File Upload:** Required (consider file/document collection)"),t.search&&e.push("**Search Functionality:** Required (consider text indexes)"),t.integrations&&t.integrations.length>0&&e.push(`**Integrations:** ${t.integrations.join(", ")}`),e.join(`
|
|
174
|
-
`)}function he(t){let e=new Set;for(let o of t)for(let r of o.dataInvolved)r.trim()&&e.add(r.trim());return Array.from(e)}function ye(t){return t.map(e=>e.name.toLowerCase().replaceAll(/\s+/g,"_"))}function We(t){return {projectName:t.projectName,projectGoal:t.projectGoal,projectDescription:t.projectDescription||t.projectGoal,userTypes:Ye(t.actors),userFlows:He(t.flows,t.actors),userStories:Qe(t.stories,t.flows),technicalRequirements:Ve(t.technicalRequirements)}}function be(t){let e=We(t);return `${P}
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## PROJECT CONTEXT
|
|
179
|
-
|
|
180
|
-
**Project Name:** ${e.projectName}
|
|
181
|
-
**Project Goal:** ${e.projectGoal}
|
|
182
|
-
**Description:** ${e.projectDescription}
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## USER TYPES (ACTORS)
|
|
187
|
-
|
|
188
|
-
These are the different types of users who will interact with the system. Each actor represents a potential role in your RBAC system.
|
|
189
|
-
|
|
190
|
-
${e.userTypes}
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## USER FLOWS
|
|
195
|
-
|
|
196
|
-
These represent the key journeys users take through the system. Analyze these for:
|
|
197
|
-
- Entity creation/modification patterns
|
|
198
|
-
- State transitions (status enums)
|
|
199
|
-
- Relationship ownership
|
|
200
|
-
|
|
201
|
-
${e.userFlows}
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## USER STORIES WITH DATA REQUIREMENTS
|
|
206
|
-
|
|
207
|
-
Each story includes dataInvolved - these are CRITICAL signals for your entity and field design.
|
|
208
|
-
|
|
209
|
-
${e.userStories}
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## TECHNICAL REQUIREMENTS
|
|
214
|
-
|
|
215
|
-
${e.technicalRequirements}
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## YOUR TASK
|
|
220
|
-
|
|
221
|
-
Follow the 5-phase analysis framework:
|
|
222
|
-
|
|
223
|
-
### Step 1: Entity Discovery
|
|
224
|
-
- List ALL entities extracted from dataInvolved fields
|
|
225
|
-
- Identify implicit entities from user flow actions
|
|
226
|
-
- Map user types to User collection roles
|
|
227
|
-
- Extract status enums from flow transitions
|
|
228
|
-
|
|
229
|
-
### Step 2: Relationship Mapping
|
|
230
|
-
- Define ownership: which actor creates/owns each entity
|
|
231
|
-
- Determine cardinality from flow context
|
|
232
|
-
- Identify bidirectional relationships
|
|
233
|
-
|
|
234
|
-
### Step 3: Permission Derivation
|
|
235
|
-
- Map each actor to a role
|
|
236
|
-
- Extract CRUD permissions from user story actions
|
|
237
|
-
- Define the permissions object for user modules
|
|
238
|
-
|
|
239
|
-
### Step 4: Query Pattern Inference
|
|
240
|
-
- Identify likely query patterns from flows
|
|
241
|
-
- Note which fields need indexing (for your reference)
|
|
242
|
-
|
|
243
|
-
### Step 5: Schema Construction
|
|
244
|
-
Generate the final schema with:
|
|
245
|
-
- Complete module definitions
|
|
246
|
-
- All fields with proper types
|
|
247
|
-
- Relationships with relationTo and relationType
|
|
248
|
-
- Status enums from flow states
|
|
249
|
-
- RBAC permissions on user modules
|
|
250
|
-
- Timestamps on every module
|
|
251
|
-
|
|
252
|
-
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function Se(t,e){return `${P}
|
|
253
|
-
|
|
254
|
-
Update the existing MongoDB schema based on user feedback.
|
|
255
|
-
|
|
256
|
-
## Steps
|
|
257
|
-
1. Analyze the existing MongoDB schema provided
|
|
258
|
-
2. Review the user feedback to understand the required updates
|
|
259
|
-
3. Update the schema to incorporate the requested changes while adhering to best practices
|
|
260
|
-
|
|
261
|
-
## Existing Schema
|
|
262
|
-
${t}
|
|
263
|
-
|
|
264
|
-
## User Feedback
|
|
265
|
-
${e}
|
|
266
|
-
|
|
267
|
-
Return the updated schema as a valid JSON object matching the original schema format.
|
|
268
|
-
IMPORTANT: Return ONLY the JSON object, no markdown code blocks, no explanations.`}var _=h({name:"validate_schema",description:"Validates a MongoDB project schema JSON string against the expected schema. Returns valid: true or valid: false with errors array.",input:zod.z.object({schema:zod.z.string().describe("JSON string of the database project schema to validate")}),handler:async({schema:t})=>{try{let e=JSON.parse(t);return A.parse(e),{valid:!0}}catch(e){return e instanceof zod.z.ZodError?{valid:false,errors:e.issues.map(o=>`${o.path.join(".")}: ${o.message}`)}:e instanceof SyntaxError?{valid:false,errors:[`Invalid JSON: ${e.message}`]}:{valid:false,errors:[String(e)]}}}});function At(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}function Z(t){return h({name:"design_database",description:"Generate a MongoDB database schema from plain text requirements. Use for ad-hoc or legacy requirements. Returns the full project schema as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Plain text description of the database requirements")}),handler:async({requirement:e})=>{let o=fe(e),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],i=(await t.invoke(r,{temperature:.3,maxOutputTokens:8192})).text,s=At(i),a=JSON.parse(s);return A.parse(a)}})}function Pt(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}var Mt=zod.z.object({projectName:zod.z.string(),projectGoal:zod.z.string(),projectDescription:zod.z.string().optional(),actors:zod.z.array(zod.z.object({id:zod.z.string(),name:zod.z.string(),description:zod.z.string(),goals:zod.z.array(zod.z.string())})),flows:zod.z.array(zod.z.object({id:zod.z.string(),actorId:zod.z.string(),name:zod.z.string(),description:zod.z.string(),trigger:zod.z.string(),outcome:zod.z.string()})),stories:zod.z.array(zod.z.object({id:zod.z.string(),flowId:zod.z.string(),actor:zod.z.string(),action:zod.z.string(),benefit:zod.z.string(),preconditions:zod.z.array(zod.z.string()),postconditions:zod.z.array(zod.z.string()),dataInvolved:zod.z.array(zod.z.string())})),technicalRequirements:zod.z.object({authentication:zod.z.enum(["none","email","oauth","phone","email_and_phone"]),authorization:zod.z.boolean(),roles:zod.z.array(zod.z.string()).optional(),integrations:zod.z.array(zod.z.string()).optional(),realtime:zod.z.boolean().optional(),fileUpload:zod.z.boolean().optional(),search:zod.z.boolean().optional()}).optional()});function X(t){return h({name:"design_database_pro",description:"Generate a MongoDB schema from structured requirements (project name, goal, actors, flows, user stories with dataInvolved, technical requirements). Use for pro-level 5-phase analysis. Returns dbDesign and metadata (entitiesDetected, rolesExtracted).",input:Mt,handler:async e=>{let o=be(e),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.2,maxOutputTokens:16384}),i=Pt(n.text),s=JSON.parse(i),a=A.parse(s),p={entitiesDetected:he(e.stories),rolesExtracted:ye(e.actors)};return {dbDesign:a,metadata:p}}})}function Ct(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}function ee(t){return h({name:"redesign_database",description:"Update an existing MongoDB project schema based on user feedback. Provide the current schema JSON string and the feedback. Returns the updated schema as JSON.",input:zod.z.object({existingSchema:zod.z.string().describe("Current project schema as JSON string"),feedback:zod.z.string().describe("User feedback describing desired changes")}),handler:async({existingSchema:e,feedback:o})=>{let r=Se(e,o),n=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:r}],i=await t.invoke(n,{temperature:.3,maxOutputTokens:8192}),s=Ct(i.text),a=JSON.parse(s);return A.parse(a)}})}function we(t){return {validate_schema:_,design_database:Z(t),design_database_pro:X(t),redesign_database:ee(t)}}var It=`You are an expert at analyzing software requirements to extract database design signals.
|
|
269
|
-
|
|
270
|
-
Focus on PHASES 1-3 of the analysis framework:
|
|
271
|
-
|
|
272
|
-
## PHASE 1: Entity Discovery
|
|
273
|
-
- List every entity implied by the requirements (from dataInvolved, user types, flow actions, flow states).
|
|
274
|
-
- Identify user/actor types that become roles.
|
|
275
|
-
- Extract status enums from flow transitions.
|
|
276
|
-
|
|
277
|
-
## PHASE 2: Relationship Mapping
|
|
278
|
-
- For each entity pair, determine ownership (which actor creates/owns it).
|
|
279
|
-
- Determine cardinality (one-to-one, many-to-one).
|
|
280
|
-
- Note bidirectional relationships.
|
|
281
|
-
|
|
282
|
-
## PHASE 3: Permission Derivation
|
|
283
|
-
- Map each actor type to a role name.
|
|
284
|
-
- From user story actions, infer CRUD permissions per role per entity.
|
|
285
|
-
|
|
286
|
-
Respond with a clear, structured analysis (you can use headings and bullet points). The user will use this to generate or refine a MongoDB schema.`,te=v({name:"entity-analyzer",description:"Analyzes raw requirements text to extract entities, relationships, and roles. Use when you need to understand what data and actors the system has before designing the schema. Returns structured analysis (no JSON).",systemPrompt:It,tools:{},maxIterations:2});var Et=`You are an expert MongoDB schema reviewer. Your job is to:
|
|
287
|
-
|
|
288
|
-
1. Validate the provided schema using the validate_schema tool.
|
|
289
|
-
2. Compare the schema against the original requirements and identify gaps (missing fields, wrong relationships, missing permissions).
|
|
290
|
-
3. Suggest concrete improvements or return a corrected schema description.
|
|
291
|
-
|
|
292
|
-
When the user gives you a schema (as JSON string) and optionally the original requirements, first call validate_schema to check structure. Then analyze completeness and correctness. Respond with either refinement suggestions or a summary of issues.`;function oe(){return v({name:"schema-refiner",description:"Validates a MongoDB project schema and suggests refinements based on requirements. Use when you have a draft schema and want to check it or improve it. Has access to validate_schema tool.",systemPrompt:Et,tools:{validate_schema:_},maxIterations:5})}var Ot=`${P}
|
|
293
|
-
|
|
294
|
-
You are the database design orchestrator. When the user asks for a database design:
|
|
295
|
-
|
|
296
|
-
1. **Analyze first**: For complex or vague requirements, use subagent_entity-analyzer with a prompt that includes the user's requirements to get a structured analysis of entities, relationships, and roles.
|
|
297
|
-
2. **Generate schema**: Use design_database (for plain text requirements) or design_database_pro (when the user provides structured requirements: project name, goal, actors, flows, user stories with dataInvolved, technical requirements) to produce the MongoDB schema.
|
|
298
|
-
3. **Refine (optional)**: If the user wants validation or refinements, use subagent_schema-refiner with the current schema and requirements.
|
|
299
|
-
4. **Validate**: You can use validate_schema to check any schema JSON before returning.
|
|
300
|
-
5. **Redesign**: If the user asks for changes to an existing schema, use redesign_database with the existing schema string and their feedback.
|
|
301
|
-
|
|
302
|
-
Respond with the final schema (as JSON) or a clear summary and the schema.`;async function Dt(t){let{input:e,model:o,maxIterations:r=15,onStep:n}=t,i=R(o??{provider:"openai",model:"gpt-4o-mini"}),s=we(i),a=oe(),p=U([te,a],{parentModel:i}),m={...s,...p};return w({model:i,tools:m,systemPrompt:Ot,input:e,maxIterations:r,onStep:n})}var Re=zod.z.object({brandName:zod.z.string().describe("The brand's display name"),primaryColor:zod.z.string().describe("The brand's primary color code (e.g., #FFFFFF)"),secondaryColor:zod.z.string().describe("The brand's secondary color code (e.g., #000000)"),logo:zod.z.url().describe("URL pointing to the brand's logo")});var ve=zod.z.object({name:zod.z.string().describe("Application name"),description:zod.z.string().describe("Brief description of the application"),author:zod.z.string().describe("Author or owner of the application").default("sijeeshmiziha (HubSpire)"),branding:Re.describe("Branding information for the application"),apiEndpoint:zod.z.url().describe("URL endpoint for the app's API calls")});var Ze=zod.z.object({minLength:zod.z.number().optional().describe("Minimum length requirement"),zodString:zod.z.string().describe("Raw Zod string validation (e.g. regex)")}),Xe=zod.z.object({hookName:zod.z.string().optional().describe("Name of the hook for dynamic field options"),queryString:zod.z.string().optional().describe("Optional query string for fetching field options"),labelKey:zod.z.string().optional().describe("Key used as label when displaying options"),valueKey:zod.z.string().optional().describe("Key used as value for a field when selecting options"),values:zod.z.array(zod.z.string()).optional().describe("Static list of possible field values")}),re=zod.z.object({name:zod.z.string().describe("The field's key or identifier"),type:zod.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:zod.z.boolean().optional().describe("Whether this field must be filled"),validation:Ze.optional().describe("Optional field validation requirements"),defaultValue:zod.z.union([zod.z.string(),zod.z.number(),zod.z.boolean()]).optional().describe("Default value can be string, number, or boolean"),options:Xe.optional().describe("Additional dynamic or static options for this field")}),Ae=zod.z.object({field:zod.z.string().describe("Key or name of the data field in the table"),label:zod.z.string().describe("User-friendly label to show on the table header")});var Me=zod.z.object({type:zod.z.string().describe("Indicates the response type (e.g., 'object')"),properties:zod.z.record(zod.z.string(),zod.z.object({type:zod.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"),et=zod.z.object({type:zod.z.enum(["list","create","update","delete","getById"]).describe("Type of API call for CRUD operations"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useGetAllUserQuery, useCreateUserMutation)"),queryString:zod.z.string().describe("Actual GraphQL query string"),responseType:Me.describe("Optional schema describing shape of the API response")}),tt=zod.z.object({type:zod.z.enum(["login","currentUser","forgotPassword","resetPassword"]).describe("Type of API call"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useLoginMutation)"),queryString:zod.z.string().describe("Actual GraphQL query string"),responseType:Me.describe("Optional schema describing shape of the API response")}),Pe=zod.z.object({title:zod.z.string().describe("Title displayed on the drawer"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useCreateUserMutation, useDeleteOneUserMutation)"),fields:zod.z.array(re).describe("List of fields displayed within the drawer")}),ot=zod.z.object({name:zod.z.enum(["LoginPage","ForgotPasswordPage","ResetPasswordPage"]).describe("Internal name of the auth page"),type:zod.z.enum(["EmailPassword","ForgotPassword","ResetPassword"]).describe("Type of authentication page"),route:zod.z.string().describe("URL route for this page (e.g., '/login')"),isPrivate:zod.z.boolean().describe("Whether this page requires an authenticated session"),api:zod.z.array(tt).describe("List of API calls involved in this page"),fields:zod.z.array(re).optional().describe("Optional form fields needed on this auth page")}),rt=zod.z.object({type:zod.z.literal("Listing").describe("Indicates that this page is a listing-type page"),name:zod.z.string().describe("Internal name of the listing page"),route:zod.z.string().describe("URL route for this listing page"),isPrivate:zod.z.boolean().describe("Whether this page is private (requires auth)"),api:zod.z.array(et).describe("List of API calls that power this listing page"),columns:zod.z.array(Ae).describe("Table columns displayed on the listing page"),actions:zod.z.array(zod.z.string()).describe("List of possible actions on each row (e.g., create, edit, delete, view)"),drawerCreate:Pe.describe("Drawer configuration for creating new records"),drawerUpdate:Pe.describe("Drawer configuration for editing existing records")}),Ce=zod.z.discriminatedUnion("type",[ot,rt]);var nt=zod.z.object({name:zod.z.string().describe("Name of the module"),pages:zod.z.array(Ce).describe("Pages included within this module")}),$=zod.z.object({app:ve.describe("Overall application configuration"),modules:zod.z.array(nt).describe("List of modules that make up the application. Ensure all modules use every available CRUD GraphQL query and mutation from the schema.")});var Nt=zod.z.object({email:zod.z.email().describe("User's email address, must be valid format"),password:zod.z.string().min(8).describe("User's password, minimum length of 8")}),at=zod.z.object({_id:zod.z.string().describe("Unique identifier of the specialization, type: string"),title:zod.z.string().describe("Display title for the specialization, type: string")}),Ut=zod.z.object({_id:zod.z.string().describe("Unique ID of the user, type: string"),firstName:zod.z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:zod.z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:zod.z.email().describe("Email address in valid format, type: string"),phoneNumber:zod.z.string().min(10).describe("User's phone number, at least 10 digits, type: string"),profileImage:zod.z.string().optional().describe("Optional URL to user's profile image, type: string, optional"),role:zod.z.enum(["ADMIN","TRAINER","CLIENT"]).describe("User's role in the system (ADMIN, TRAINER, CLIENT)"),rate:zod.z.number().min(1).optional().describe("User's rate (e.g., hourly, etc.), type: number, optional"),specializations:zod.z.array(at).optional().describe("Array of specialization objects, optional"),languages:zod.z.array(zod.z.string()).optional().describe("Array of languages the user speaks, type: string[], optional"),about:zod.z.string().min(20).max(500).optional().describe("Brief bio or description (20-500 chars), type: string, optional"),gender:zod.z.string().optional().describe("User's gender, type: string, optional"),timezone:zod.z.string().optional().describe("User's timezone, type: string, optional"),averageRating:zod.z.number().optional().describe("Average rating for this user, type: number, optional")}),kt=zod.z.object({firstName:zod.z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:zod.z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:zod.z.email().describe("Valid email for the new user, type: string"),phoneNumber:zod.z.string().min(10).describe("Phone number (at least 10 digits), type: string"),password:zod.z.string().min(8).describe("Password with min length 8, type: string"),role:zod.z.enum(["ADMIN","TRAINER","CLIENT"]).describe("Role of the new user (ADMIN, TRAINER, CLIENT)"),rate:zod.z.number().min(1).optional().describe("Rate for the new user, type: number, optional"),specializationIds:zod.z.array(zod.z.string()).min(1).optional().describe("Array of specialization IDs, optional"),languages:zod.z.array(zod.z.string()).min(1).optional().describe("List of languages user speaks, optional"),about:zod.z.string().min(20).max(500).optional().describe("User's about/bio field, 20-500 chars, optional")}),_t=zod.z.object({_id:zod.z.string().describe("ID of the user to be updated, type: string"),firstName:zod.z.string().min(2).max(30).optional().describe("Updated first name, type: string, optional"),lastName:zod.z.string().min(2).max(30).optional().describe("Updated last name, type: string, optional"),email:zod.z.email().optional().describe("Updated email, type: string, optional"),phoneNumber:zod.z.string().min(10).optional().describe("Updated phone number, at least 10 digits, optional"),rate:zod.z.number().min(1).optional().describe("Updated rate, type: number, optional"),specializationIds:zod.z.array(zod.z.string()).min(1).optional().describe("Updated array of specialization IDs, optional"),languages:zod.z.array(zod.z.string()).min(1).optional().describe("Updated list of languages, optional"),about:zod.z.string().min(20).max(500).optional().describe("Updated about/bio (20-500 chars), optional")}),jt=zod.z.object({email:zod.z.email().describe("Email to initiate the password reset process, type: string")}),Lt=zod.z.object({type:zod.z.enum(["EMAIL","SMS"]).describe("How the reset code was sent (EMAIL or SMS)"),resetTicket:zod.z.string().describe("Token/ticket to validate the reset request, type: string"),newPassword:zod.z.string().min(8).describe("The new password, min length 8, type: string")});var B=`You are an expert GraphQL-to-frontend configuration converter. Transform the provided GraphQL schema into a structured JSON configuration for rapid app development.
|
|
1
|
+
'use strict';var Ao=require('pino'),zod=require('zod'),ai$1=require('ai'),openai=require('@ai-sdk/openai'),anthropic=require('@ai-sdk/anthropic'),google=require('@ai-sdk/google'),X=require('fs'),Te=require('path'),oe=require('handlebars'),client=require('@modelcontextprotocol/sdk/client'),module$1=require('module'),url=require('url'),promises=require('fs/promises');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var Ao__default=/*#__PURE__*/_interopDefault(Ao);var X__namespace=/*#__PURE__*/_interopNamespace(X);var Te__namespace=/*#__PURE__*/_interopNamespace(Te);var oe__default=/*#__PURE__*/_interopDefault(oe);var de=class extends Error{constructor(e,o){super(e,o===void 0?void 0:{cause:o}),this.name="LibraryError",o?.stack&&(this.stack=`${this.stack}
|
|
2
|
+
Caused by: ${o.stack}`);}},ae=class extends de{constructor(o,r,n){super(o,n);this.provider=r;this.name="ModelError";}},$=class extends de{constructor(o,r,n){super(o,n);this.toolName=r;this.name="ToolError";}},yn=class extends de{constructor(o,r){super(o);this.errors=r;this.name="ValidationError";}},et=class extends de{constructor(o,r,n){super(o,n);this.iteration=r;this.name="AgentError";}},Se=class extends de{constructor(o,r,n){super(o,n);this.subagentName=r;this.name="SubagentError";}};function Ma(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}function M(t,e){let o=Ma(t),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=e.safeParse(r);if(!n.success){let a=n.error.issues.slice(0,5).map(s=>` ${s.path.join(".")}: ${s.message}`).join(`
|
|
3
|
+
`);throw new Error(`Model JSON does not match expected schema:
|
|
4
|
+
${a}`)}return n.data}function be(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 Sn={debug:()=>{},info:()=>{},warn:()=>{},error:()=>{},child:()=>Sn};function Jl(t={}){if(t.enabled===false)return Sn;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=Ao__default.default({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=Ao__default.default.transport({targets:c});l=Ao__default.default({name:e,level:o},p);}return bn(l)}function Bl(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 bn(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=>bn(t.child(e))}}var Oa={noCacheTokens:void 0,cacheReadTokens:void 0,cacheWriteTokens:void 0},Ca={textTokens:void 0,reasoningTokens:void 0};function Mo(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:Oa,outputTokenDetails:Ca}}function h(t){let{name:e,description:o,input:r,handler:n}=t;return ai$1.tool({description:o,inputSchema:r,execute:async a=>{let s=r.safeParse(a);if(!s.success)throw new $(`Invalid input: ${s.error.message}`,e,s.error);try{return await n(s.data,void 0)}catch(i){throw i instanceof $?i:new $(`Tool "${e}" failed: ${i instanceof Error?i.message:String(i)}`,e,i instanceof Error?i:void 0)}}})}function _(t){return t}function xn(t){return Object.values(t)}function Tn(t,e){return t[e]}async function Oo(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 tt(t,e,o,r){let n=t[e];if(!n)throw r?.logger?.error("Tool not found",{name:e,availableTools:Object.keys(t)}),new $(`Tool not found: ${e}`);return Oo(n,o,{...r,toolName:e})}function q(t,e,o,r="json"){return h({name:t,description:o,input:zod.z.object({[r]:zod.z.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 zod.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)]}}}})}function No(t,e){t?.forEach(o=>o.onStep?.(e));}function Pn(t,e,o){t?.forEach(r=>r.onToolExecution?.(e,o));}function Rn(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),No(i,m),l?.info("Agent completed",{steps:p.length,totalUsage:Mo(p.map(j=>j.usage))}),{output:y.text,steps:p,totalUsage:Mo(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 B=[...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:B});let L=[];for(let j of y.toolCalls){let ye=await tt(o,j.toolName,j.input,{toolCallId:j.toolCallId,logger:l}),pe={toolCallId:j.toolCallId,toolName:j.toolName,output:ye.success?ye.output:ye.error,isError:!ye.success};L.push(pe),Pn(i,j.toolName,pe.output);let Aa=pe.isError?{type:"error-text",value:String(pe.output)}:{type:"text",value:typeof pe.output=="string"?pe.output:JSON.stringify(pe.output)};c.push({role:"tool",content:[{type:"tool-result",toolCallId:j.toolCallId,toolName:j.toolName,output:Aa}]});}m.toolResults=L,p.push(m),s?.(m),No(i,m);}let d=new et(`Agent reached maximum iterations (${a}) without completing`,a-1);throw Rn(i,d),l?.error("Agent failed: max iterations reached",{maxIterations:a,error:d}),d}function xe(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 ai$1.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 ae(`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 ai$1.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 ae("Failed to generate vision response",e,l)}},async invokeObject(n,a,s){try{let i=await r(),l=ai$1.zodSchema(a),c=await ai$1.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 ae(`Failed to invokeObject ${e} model`,e,l)}}}}function ot(t){let{model:e,apiKey:o,baseUrl:r}=t,n=openai.createOpenAI({apiKey:o??process.env.OPENAI_API_KEY,baseURL:r});return xe({provider:"openai",modelName:e,getModel:()=>n.chat(e)})}function rt(t){let{model:e,apiKey:o}=t,r=anthropic.createAnthropic({apiKey:o??process.env.ANTHROPIC_API_KEY});return xe({provider:"anthropic",modelName:e,getModel:()=>r(e)})}function nt(t){let{model:e,apiKey:o}=t,r=google.createGoogleGenerativeAI({apiKey:o??process.env.GOOGLE_GENERATIVE_AI_API_KEY});return xe({provider:"google",modelName:e,getModel:()=>r(e)})}function v(t){let{provider:e}=t;switch(e){case "openai":return ot(t);case "anthropic":return rt(t);case "google":return nt(t);default:throw new ae(`Unsupported provider: ${e}. Supported providers: openai, anthropic, google`)}}var Ua=/^[a-z0-9]+(-[a-z0-9]+)*$/;function f(t){if(!t.name.trim())throw new Se("Subagent name is required",void 0);if(!Ua.test(t.name))throw new Se(`Subagent name must be kebab-case (lowercase letters, numbers, hyphens): ${t.name}`,t.name);return {...t}}function La(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=La(t,r),s=t.model==null?n:v(t.model);if(!s)throw new Se("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 Do(t,e){let o=`subagent_${t.name}`;return h({name:o,description:t.description,input:zod.z.object({prompt:zod.z.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=Do(r,e);o[`subagent_${r.name}`]=n;}return o}function ko(t,e){return oe__default.default.compile(t,{noEscape:true})(e)}function En(t,e=t){let o=[];if(!X__namespace.existsSync(t))return o;let r=X__namespace.readdirSync(t,{withFileTypes:true});for(let n of r){let a=Te__namespace.join(t,n.name);n.isDirectory()?o.push(...En(a,e)):n.name.endsWith(".hbs")&&o.push(Te__namespace.relative(e,a));}return o}function Ga(t){return t.replace(/\.hbs$/,"")}function Ja(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 le(t){let{templateDir:e,outputDir:o,context:r,skipPatterns:n=[]}=t,a=En(e),s=[],i=[];for(let l of a){if(Ja(l,n))continue;let c=Ga(l),p=Te__namespace.join(e,l),d=Te__namespace.join(o,c);try{let u=X__namespace.readFileSync(p,"utf-8"),y=ko(u,r);X__namespace.mkdirSync(Te__namespace.dirname(d),{recursive:!0}),X__namespace.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 _o(){oe__default.default.registerHelper("eq",(t,e)=>t===e),oe__default.default.registerHelper("neq",(t,e)=>t!==e),oe__default.default.registerHelper("json",t=>JSON.stringify(t,null,2)),oe__default.default.registerHelper("uppercase",t=>typeof t=="string"?t.toUpperCase():""),oe__default.default.registerHelper("lowercase",t=>typeof t=="string"?t.toLowerCase():""),oe__default.default.registerHelper("capitalize",t=>typeof t=="string"?t.charAt(0).toUpperCase()+t.slice(1):""),oe__default.default.registerHelper("camelCase",t=>typeof t!="string"?"":t.replace(/[-_\s]+(.)?/g,(e,o)=>o?o.toUpperCase():"").replace(/^(.)/,e=>e.toLowerCase())),oe__default.default.registerHelper("pascalCase",t=>typeof t!="string"?"":t.replace(/[-_\s]+(.)?/g,(e,o)=>o?o.toUpperCase():"").replace(/^(.)/,e=>e.toUpperCase()));}_o();function Ya(){let e=module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))).resolve("@modelcontextprotocol/sdk/client");return Te__namespace.default.dirname(Te__namespace.default.dirname(Te__namespace.default.dirname(Te__namespace.default.dirname(e))))}var Mn=Ya();function On(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 Cn(t,e){let o=Te__namespace.default.join(Mn,"dist","esm","client","streamableHttp.js"),r=await import(url.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 Nn(t,e){let o=Te__namespace.default.join(Mn,"dist","esm","client","stdio.js"),r=await import(url.pathToFileURL(o).href);return new r.StdioClientTransport({command:t,args:e})}var st=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 $(`${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 $("MCP connection failed.","mcp_client");return this.client}if(this.connectPromise=this.doConnect(),await this.connectPromise,this.connectPromise=null,!this.client)throw new $("MCP connection failed.","mcp_client");return this.client}async doConnect(){let e=new client.Client({name:this.info.name,version:this.info.version},{capabilities:{}});if(this.config.url)this.transport=await Cn(this.config.url,this.config.headers);else if(this.config.command)this.transport=await Nn(this.config.command,this.config.args??[]);else throw new $("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?On(n):n}async close(){this.transport&&(await this.transport.close(),this.transport=null),this.client=null,this.connectPromise=null;}};var Io=h({name:"hello_world",description:"Returns a greeting message for the given name",input:zod.z.object({name:zod.z.string().describe("Name to greet")}),handler:async({name:t})=>({greeting:`Hello, ${t}! Welcome to sweagent.`})});var $a="You are a friendly greeter. Use the hello_world tool to greet users.";async function Ha(t){let{input:e,model:o,systemPrompt:r=$a,maxIterations:n=3,onStep:a,logger:s}=t,i=v(o??{provider:"openai",model:"gpt-4o-mini"});return C({model:i,tools:{hello_world:Io},systemPrompt:r,input:e,maxIterations:n,onStep:a,logger:s})}var jo=zod.z.object({brandName:zod.z.string().describe("The brand's display name"),primaryColor:zod.z.string().describe("The brand's primary color code (e.g., #FFFFFF)"),secondaryColor:zod.z.string().describe("The brand's secondary color code (e.g., #000000)"),logo:zod.z.url().describe("URL pointing to the brand's logo")});var qo=zod.z.object({name:zod.z.string().describe("Application name"),description:zod.z.string().describe("Brief description of the application"),author:zod.z.string().describe("Author or owner of the application").default("sijeeshmiziha (HubSpire)"),branding:jo.describe("Branding information for the application"),apiEndpoint:zod.z.url().describe("URL endpoint for the app's API calls")});var kn=zod.z.object({minLength:zod.z.number().optional().describe("Minimum length requirement"),zodString:zod.z.string().describe("Raw Zod string validation (e.g. regex)")}),_n=zod.z.object({hookName:zod.z.string().optional().describe("Name of the hook for dynamic field options"),queryString:zod.z.string().optional().describe("Optional query string for fetching field options"),labelKey:zod.z.string().optional().describe("Key used as label when displaying options"),valueKey:zod.z.string().optional().describe("Key used as value for a field when selecting options"),values:zod.z.array(zod.z.string()).optional().describe("Static list of possible field values")}),at=zod.z.object({name:zod.z.string().describe("The field's key or identifier"),type:zod.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:zod.z.boolean().optional().describe("Whether this field must be filled"),validation:kn.optional().describe("Optional field validation requirements"),defaultValue:zod.z.union([zod.z.string(),zod.z.number(),zod.z.boolean()]).optional().describe("Default value can be string, number, or boolean"),options:_n.optional().describe("Additional dynamic or static options for this field")}),Fo=zod.z.object({field:zod.z.string().describe("Key or name of the data field in the table"),label:zod.z.string().describe("User-friendly label to show on the table header")});var Lo=zod.z.object({type:zod.z.string().describe("Indicates the response type (e.g., 'object')"),properties:zod.z.record(zod.z.string(),zod.z.object({type:zod.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"),In=zod.z.object({type:zod.z.enum(["list","create","update","delete","getById"]).describe("Type of API call for CRUD operations"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useGetAllUserQuery, useCreateUserMutation)"),queryString:zod.z.string().describe("Actual GraphQL query string"),responseType:Lo.describe("Optional schema describing shape of the API response")}),jn=zod.z.object({type:zod.z.enum(["login","currentUser","forgotPassword","resetPassword"]).describe("Type of API call"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useLoginMutation)"),queryString:zod.z.string().describe("Actual GraphQL query string"),responseType:Lo.describe("Optional schema describing shape of the API response")}),Uo=zod.z.object({title:zod.z.string().describe("Title displayed on the drawer"),graphqlHook:zod.z.string().describe("Name of the GraphQL hook (e.g. useCreateUserMutation, useDeleteOneUserMutation)"),fields:zod.z.array(at).describe("List of fields displayed within the drawer")}),qn=zod.z.object({name:zod.z.enum(["LoginPage","ForgotPasswordPage","ResetPasswordPage"]).describe("Internal name of the auth page"),type:zod.z.enum(["EmailPassword","ForgotPassword","ResetPassword"]).describe("Type of authentication page"),route:zod.z.string().describe("URL route for this page (e.g., '/login')"),isPrivate:zod.z.boolean().describe("Whether this page requires an authenticated session"),api:zod.z.array(jn).describe("List of API calls involved in this page"),fields:zod.z.array(at).optional().describe("Optional form fields needed on this auth page")}),Fn=zod.z.object({type:zod.z.literal("Listing").describe("Indicates that this page is a listing-type page"),name:zod.z.string().describe("Internal name of the listing page"),route:zod.z.string().describe("URL route for this listing page"),isPrivate:zod.z.boolean().describe("Whether this page is private (requires auth)"),api:zod.z.array(In).describe("List of API calls that power this listing page"),columns:zod.z.array(Fo).describe("Table columns displayed on the listing page"),actions:zod.z.array(zod.z.string()).describe("List of possible actions on each row (e.g., create, edit, delete, view)"),drawerCreate:Uo.describe("Drawer configuration for creating new records"),drawerUpdate:Uo.describe("Drawer configuration for editing existing records")}),Go=zod.z.discriminatedUnion("type",[qn,Fn]);var Un=zod.z.object({name:zod.z.string().describe("Name of the module"),pages:zod.z.array(Go).describe("Pages included within this module")}),Ue=zod.z.object({app:qo.describe("Overall application configuration"),modules:zod.z.array(Un).describe("List of modules that make up the application. Ensure all modules use every available CRUD GraphQL query and mutation from the schema.")});var Qa=zod.z.object({email:zod.z.email().describe("User's email address, must be valid format"),password:zod.z.string().min(8).describe("User's password, minimum length of 8")}),Ln=zod.z.object({_id:zod.z.string().describe("Unique identifier of the specialization, type: string"),title:zod.z.string().describe("Display title for the specialization, type: string")}),Va=zod.z.object({_id:zod.z.string().describe("Unique ID of the user, type: string"),firstName:zod.z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:zod.z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:zod.z.email().describe("Email address in valid format, type: string"),phoneNumber:zod.z.string().min(10).describe("User's phone number, at least 10 digits, type: string"),profileImage:zod.z.string().optional().describe("Optional URL to user's profile image, type: string, optional"),role:zod.z.enum(["ADMIN","TRAINER","CLIENT"]).describe("User's role in the system (ADMIN, TRAINER, CLIENT)"),rate:zod.z.number().min(1).optional().describe("User's rate (e.g., hourly, etc.), type: number, optional"),specializations:zod.z.array(Ln).optional().describe("Array of specialization objects, optional"),languages:zod.z.array(zod.z.string()).optional().describe("Array of languages the user speaks, type: string[], optional"),about:zod.z.string().min(20).max(500).optional().describe("Brief bio or description (20-500 chars), type: string, optional"),gender:zod.z.string().optional().describe("User's gender, type: string, optional"),timezone:zod.z.string().optional().describe("User's timezone, type: string, optional"),averageRating:zod.z.number().optional().describe("Average rating for this user, type: number, optional")}),Wa=zod.z.object({firstName:zod.z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:zod.z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:zod.z.email().describe("Valid email for the new user, type: string"),phoneNumber:zod.z.string().min(10).describe("Phone number (at least 10 digits), type: string"),password:zod.z.string().min(8).describe("Password with min length 8, type: string"),role:zod.z.enum(["ADMIN","TRAINER","CLIENT"]).describe("Role of the new user (ADMIN, TRAINER, CLIENT)"),rate:zod.z.number().min(1).optional().describe("Rate for the new user, type: number, optional"),specializationIds:zod.z.array(zod.z.string()).min(1).optional().describe("Array of specialization IDs, optional"),languages:zod.z.array(zod.z.string()).min(1).optional().describe("List of languages user speaks, optional"),about:zod.z.string().min(20).max(500).optional().describe("User's about/bio field, 20-500 chars, optional")}),Ka=zod.z.object({_id:zod.z.string().describe("ID of the user to be updated, type: string"),firstName:zod.z.string().min(2).max(30).optional().describe("Updated first name, type: string, optional"),lastName:zod.z.string().min(2).max(30).optional().describe("Updated last name, type: string, optional"),email:zod.z.email().optional().describe("Updated email, type: string, optional"),phoneNumber:zod.z.string().min(10).optional().describe("Updated phone number, at least 10 digits, optional"),rate:zod.z.number().min(1).optional().describe("Updated rate, type: number, optional"),specializationIds:zod.z.array(zod.z.string()).min(1).optional().describe("Updated array of specialization IDs, optional"),languages:zod.z.array(zod.z.string()).min(1).optional().describe("Updated list of languages, optional"),about:zod.z.string().min(20).max(500).optional().describe("Updated about/bio (20-500 chars), optional")}),Xa=zod.z.object({email:zod.z.email().describe("Email to initiate the password reset process, type: string")}),Za=zod.z.object({type:zod.z.enum(["EMAIL","SMS"]).describe("How the reset code was sent (EMAIL or SMS)"),resetTicket:zod.z.string().describe("Token/ticket to validate the reset request, type: string"),newPassword:zod.z.string().min(8).describe("The new password, min length 8, type: string")});var Le=`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.
|
|
5
|
+
|
|
6
|
+
## Target Tech Stack
|
|
7
|
+
The generated configuration will be consumed by a Vite + React 19 + TypeScript template with:
|
|
8
|
+
- **UI Components**: ShadCN UI (Radix-based) from src/components/ui/
|
|
9
|
+
- **Styling**: Tailwind CSS v4 with OKLCH color space
|
|
10
|
+
- **Routing**: React Router v7 with private route support
|
|
11
|
+
- **Forms**: React Hook Form + Zod validation (zodResolver)
|
|
12
|
+
- **GraphQL Client**: Apollo Client with typed hooks from CodeGen
|
|
13
|
+
- **Path Aliases**: @/{appName}/* maps to ./src/*
|
|
303
14
|
|
|
304
15
|
**Your output must be valid JSON only.** No markdown code fences, no explanations. Return the raw JSON object matching the application schema (app with name, description, author, branding, apiEndpoint; modules array with name and pages; each page has type, name, route, isPrivate, api, and for listing pages: columns, actions, drawerCreate, drawerUpdate; for auth pages: fields when needed).
|
|
305
16
|
|
|
@@ -308,8 +19,9 @@ Strict guidelines:
|
|
|
308
19
|
- Map GraphQL types to frontend modules and pages.
|
|
309
20
|
- EmailAddress \u2192 "type": "email" with validation; DateTime \u2192 "type": "date"; enums \u2192 select with options.values.
|
|
310
21
|
- Relationships \u2192 multiSelect with query-based options where appropriate.
|
|
311
|
-
- Add isPrivate: true for authenticated operations.
|
|
312
|
-
-
|
|
22
|
+
- Add isPrivate: true for authenticated operations (route guarded by React Router).
|
|
23
|
+
- Form fields should map to React Hook Form + Zod validation schemas.
|
|
24
|
+
- Maintain camelCase. Ensure valid JSON syntax.`;var it=`
|
|
313
25
|
Act as an expert GraphQL-to-frontend configuration converter. Transform the provided schema into a structured JSON configuration for rapid app development.
|
|
314
26
|
|
|
315
27
|
**Conversion Process**
|
|
@@ -341,7 +53,7 @@ Act as an expert GraphQL-to-frontend configuration converter. Transform the prov
|
|
|
341
53
|
6. Output:
|
|
342
54
|
- Generate complete CRUD pages with table column mappings, validated Create/Update forms, API hooks
|
|
343
55
|
- Include Zod validation strings, maintain camelCase, valid JSON only
|
|
344
|
-
`.trim();function
|
|
56
|
+
`.trim();function Jo(){return it}var Gn=`
|
|
345
57
|
type Query {
|
|
346
58
|
getCurrentUser: User
|
|
347
59
|
getAllUser(limit: Int, offset: Int): [User]!
|
|
@@ -360,7 +72,7 @@ type User {
|
|
|
360
72
|
enum Role { ADMIN TRAINER CLIENT }
|
|
361
73
|
input LoginInput { email: String! password: String! }
|
|
362
74
|
input CreateUserInput { firstName: String! lastName: String! email: String! role: Role! }
|
|
363
|
-
`.trim(),
|
|
75
|
+
`.trim(),Jn=`{
|
|
364
76
|
"app": {
|
|
365
77
|
"name": "my-app",
|
|
366
78
|
"description": "App description",
|
|
@@ -408,19 +120,19 @@ input CreateUserInput { firstName: String! lastName: String! email: String! role
|
|
|
408
120
|
]
|
|
409
121
|
}
|
|
410
122
|
]
|
|
411
|
-
}`;function
|
|
123
|
+
}`;function Bo(){return `
|
|
412
124
|
**Reference Conversion Example**
|
|
413
125
|
|
|
414
126
|
EXAMPLE GRAPHQL INPUT:
|
|
415
127
|
\`\`\`graphql
|
|
416
|
-
${
|
|
128
|
+
${Gn}
|
|
417
129
|
\`\`\`
|
|
418
130
|
|
|
419
131
|
EXPECTED JSON OUTPUT:
|
|
420
132
|
\`\`\`json
|
|
421
|
-
${
|
|
133
|
+
${Jn}
|
|
422
134
|
\`\`\`
|
|
423
|
-
`.trim()}function
|
|
135
|
+
`.trim()}function ei(t,e){return `
|
|
424
136
|
Review the user feedback carefully to understand the required updates.
|
|
425
137
|
|
|
426
138
|
The user feedback for updating the generated Frontend Config JSON is provided below:
|
|
@@ -436,7 +148,7 @@ ${e}
|
|
|
436
148
|
\`\`\`
|
|
437
149
|
|
|
438
150
|
Update the Frontend Config JSON to incorporate the requested changes. Return ONLY valid JSON, no markdown code blocks.
|
|
439
|
-
`.trim()}var
|
|
151
|
+
`.trim()}var Pe=q("validate_frontend_config",Ue,"Validates a frontend configuration JSON string against the ApplicationSchema. Returns valid: true or valid: false with errors array.","config");function ti(t,e){let o=Jo(),r=Bo(),n=e?`
|
|
440
152
|
**Project context:**
|
|
441
153
|
- name: ${e.projectName??"project"}
|
|
442
154
|
- description: ${e.projectDescription??""}
|
|
@@ -452,14 +164,14 @@ ${n}
|
|
|
452
164
|
${t}
|
|
453
165
|
\`\`\`
|
|
454
166
|
|
|
455
|
-
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function
|
|
167
|
+
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function lt(t){return h({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:zod.z.object({graphqlSchema:zod.z.string().describe("The GraphQL schema string to convert"),appInfo:zod.z.object({projectName:zod.z.string().optional(),projectDescription:zod.z.string().optional(),modules:zod.z.string().optional(),apiEndpoint:zod.z.string().optional()}).optional().describe("Optional project/app context")}),handler:async({graphqlSchema:e,appInfo:o})=>{let r=ti(e,o),n=[{role:"system",content:Le},{role:"user",content:r}],a=await t.invoke(n,{temperature:.2,maxOutputTokens:16384});return M(a.text,Ue)}})}function ct(t){return h({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:zod.z.object({graphqlSchema:zod.z.string().describe("The GraphQL schema string to analyze")}),handler:async({graphqlSchema:e})=>{let o=`${it}
|
|
456
168
|
|
|
457
169
|
**Schema to analyze:**
|
|
458
170
|
\`\`\`graphql
|
|
459
171
|
${e}
|
|
460
172
|
\`\`\`
|
|
461
173
|
|
|
462
|
-
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 t.invoke(r,{temperature:.3,maxOutputTokens:4096})).text,modules:[],operations:[],suggestedPages:[]}}})}function
|
|
174
|
+
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 t.invoke(r,{temperature:.3,maxOutputTokens:4096})).text,modules:[],operations:[],suggestedPages:[]}}})}function oi(t){return {appName:t.app.name,description:t.app.description,apiEndpoint:t.app.apiEndpoint,branding:{brandName:t.app.branding.brandName,primaryColor:t.app.branding.primaryColor,secondaryColor:t.app.branding.secondaryColor,logo:t.app.branding.logo},modules:t.modules.map(e=>({name:e.name,pascalName:e.name.charAt(0).toUpperCase()+e.name.slice(1),camelName:e.name.charAt(0).toLowerCase()+e.name.slice(1)})),author:t.app.author,pages:t.modules.flatMap(e=>e.pages)}}var zo=h({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:zod.z.object({config:zod.z.string().describe("JSON string of the validated ApplicationSchema config"),outputDir:zod.z.string().describe("Absolute path to the output directory")}),handler:async({config:t,outputDir:e})=>{let o=be(t,"application schema config"),r=Te__namespace.resolve(process.cwd(),".ref/templates/vite"),n=oi(o);return le({templateDir:r,outputDir:e,context:n})}});function $o(t){return {validate_frontend_config:Pe,generate_frontend:lt(t),generate_feature_breakdown:ct(t),scaffold_vite:zo}}var ri=`You are an expert at analyzing GraphQL schemas. Your job is to:
|
|
463
175
|
|
|
464
176
|
1. **Types**: List all object types, enums, scalars, and input types.
|
|
465
177
|
2. **Queries**: List every Query field with arguments and return type.
|
|
@@ -467,13 +179,13 @@ Respond with a structured breakdown only (no full JSON config): list modules, li
|
|
|
467
179
|
4. **Relationships**: Identify types that reference other types (e.g. User has role: Role, or Order has customer: User).
|
|
468
180
|
5. **Auth/directives**: Note any @auth, @directive usage that affects access control.
|
|
469
181
|
|
|
470
|
-
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,
|
|
182
|
+
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,pt=f({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:ri,tools:{},maxIterations:2});var ni=`You are a frontend configuration validator. Your job is to:
|
|
471
183
|
|
|
472
184
|
1. Validate the provided frontend config JSON using the validate_frontend_config tool.
|
|
473
185
|
2. Compare the config against the GraphQL schema (if provided) and check that all CRUD operations are covered.
|
|
474
186
|
3. Report any missing modules, pages, or API hooks.
|
|
475
187
|
|
|
476
|
-
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
|
|
188
|
+
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 dt(){return f({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:ni,tools:{validate_frontend_config:Pe},maxIterations:5})}var si=`${Le}
|
|
477
189
|
|
|
478
190
|
You are the React frontend builder orchestrator. When the user provides a GraphQL schema and asks for a frontend configuration:
|
|
479
191
|
|
|
@@ -483,5 +195,1575 @@ You are the React frontend builder orchestrator. When the user provides a GraphQ
|
|
|
483
195
|
4. **Validate directly**: You can use validate_frontend_config to check any config JSON.
|
|
484
196
|
5. **Feature breakdown**: Use generate_feature_breakdown to get a module/operation breakdown before generating.
|
|
485
197
|
|
|
486
|
-
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
|
|
198
|
+
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 ai(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=$o(s),l=dt(),c=I([pt,l],{parentModel:s}),p={...i,...c};return C({model:s,tools:p,systemPrompt:si,input:e,maxIterations:r,onStep:n,logger:a})}var Re=zod.z.object({id:zod.z.string(),name:zod.z.string(),description:zod.z.string(),goals:zod.z.array(zod.z.string())}),ut=zod.z.object({actors:zod.z.array(Re),message:zod.z.string()});var we=zod.z.object({id:zod.z.string(),actorId:zod.z.string(),name:zod.z.string(),description:zod.z.string(),trigger:zod.z.string(),outcome:zod.z.string()}),mt=zod.z.object({flows:zod.z.array(we),message:zod.z.string()});var ve=zod.z.object({id:zod.z.string(),flowId:zod.z.string(),actor:zod.z.string(),action:zod.z.string(),benefit:zod.z.string(),preconditions:zod.z.array(zod.z.string()),postconditions:zod.z.array(zod.z.string()),dataInvolved:zod.z.array(zod.z.string())}),gt=zod.z.object({stories:zod.z.array(ve),message:zod.z.string()});var zn=zod.z.object({id:zod.z.string(),name:zod.z.string(),operation:zod.z.enum(["create","read","readAll","update","delete"]),description:zod.z.string(),inputs:zod.z.array(zod.z.string()),outputs:zod.z.array(zod.z.string())}),Ee=zod.z.object({id:zod.z.string(),name:zod.z.string(),description:zod.z.string(),entity:zod.z.string(),apis:zod.z.array(zn)}),ft=zod.z.object({modules:zod.z.array(Ee),summary:zod.z.object({totalModules:zod.z.number(),totalApis:zod.z.number()}),message:zod.z.string()});var $n=zod.z.object({name:zod.z.string(),type:zod.z.string(),required:zod.z.boolean(),unique:zod.z.boolean(),description:zod.z.string(),default:zod.z.string().optional()}),Hn=zod.z.object({name:zod.z.string(),fields:zod.z.array(zod.z.string()),unique:zod.z.boolean()}),Qn=zod.z.object({field:zod.z.string(),references:zod.z.string(),description:zod.z.string()}),Vn=zod.z.object({name:zod.z.string(),description:zod.z.string(),fields:zod.z.array($n),indexes:zod.z.array(Hn),relations:zod.z.array(Qn)}),me=zod.z.object({type:zod.z.enum(["mongodb","postgresql"]),reasoning:zod.z.string(),entities:zod.z.array(Vn)});var Ae=zod.z.object({name:zod.z.string(),goal:zod.z.string(),features:zod.z.array(zod.z.string()),domain:zod.z.string(),database:zod.z.enum(["mongodb","postgresql"]),backendRuntime:zod.z.literal("nodejs"),apiStyle:zod.z.enum(["rest","graphql"])}),ht=zod.z.object({id:zod.z.string(),question:zod.z.string(),context:zod.z.string(),suggestions:zod.z.array(zod.z.string()),multiSelect:zod.z.boolean(),required:zod.z.boolean()}),Wn=zod.z.object({role:zod.z.enum(["user","assistant"]),content:zod.z.string()}),ii=zod.z.object({stage:zod.z.enum(["discovery","requirements","design","complete"]),projectBrief:Ae.nullable(),actors:zod.z.array(Re),flows:zod.z.array(we),stories:zod.z.array(ve),modules:zod.z.array(Ee),database:me.nullable(),history:zod.z.array(Wn),pendingQuestions:zod.z.array(ht)});var Kn=zod.z.object({totalActors:zod.z.number(),totalFlows:zod.z.number(),totalStories:zod.z.number(),totalModules:zod.z.number(),totalEntities:zod.z.number(),overview:zod.z.string()}),Ho=zod.z.object({project:Ae,actors:zod.z.array(Re),flows:zod.z.array(we),stories:zod.z.array(ve),modules:zod.z.array(Ee),database:me,summary:Kn});var ge=`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.
|
|
199
|
+
|
|
200
|
+
You work in stages: discovery (understand the project and tech preferences), requirements (actors, flows, stories, modules), design (database + APIs), and complete (final document).
|
|
201
|
+
|
|
202
|
+
Think about the project the way a developer would: core problem, user interactions, data model, auth, integrations, real-time needs. Do NOT ask generic template questions (e.g. scale, complexity level, "how many users?"). Ask only questions that directly unblock design decisions.
|
|
203
|
+
|
|
204
|
+
Guidelines:
|
|
205
|
+
- For tech choices (API style: REST vs GraphQL; database: MongoDB vs PostgreSQL), offer predefined options and ask what the user is comfortable with.
|
|
206
|
+
- For everything else, ask open-ended, context-specific questions based on what the user described. Leave suggestions empty for those.
|
|
207
|
+
- Never repeat a question already answered in the conversation history.
|
|
208
|
+
- When the user says "continue", "yes", "looks good", or similar, treat it as confirmation and advance.
|
|
209
|
+
- Return valid JSON only when the prompt asks for JSON (no markdown code fences unless specified).
|
|
210
|
+
- Backend is Node.js only; database is MongoDB or PostgreSQL per user preference.`;var Qo=`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.
|
|
211
|
+
|
|
212
|
+
Determine from the user's words:
|
|
213
|
+
- Project name and goal
|
|
214
|
+
- Key features (array of strings)
|
|
215
|
+
- Domain (e.g. e-commerce, healthcare, saas)
|
|
216
|
+
- API style: "rest" | "graphql" \u2014 infer from context or ask with predefined options
|
|
217
|
+
- Database: "mongodb" | "postgresql" \u2014 ask which they are comfortable with, with predefined options
|
|
218
|
+
- Backend is always "nodejs"
|
|
219
|
+
|
|
220
|
+
Question rules:
|
|
221
|
+
- Tech stack (API style, database): Always provide "suggestions" with predefined options (e.g. ["REST", "GraphQL"], ["MongoDB", "PostgreSQL"]). Frame as "which are you comfortable with?"
|
|
222
|
+
- 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).
|
|
223
|
+
- Never ask: scale, "how many users?", "what's the complexity?", or generic intake-form questions.
|
|
224
|
+
- Before asking, check conversation history \u2014 never repeat something already answered.
|
|
225
|
+
- 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.`,Xn=`## Current user message:
|
|
226
|
+
{userMessage}
|
|
227
|
+
|
|
228
|
+
## Prior conversation (if any):
|
|
229
|
+
{history}
|
|
230
|
+
|
|
231
|
+
Analyze the message and prior context. If you have enough to fill the project brief, return it and set needsClarification to false. Otherwise ask 1-3 short, problem-focused questions.
|
|
232
|
+
|
|
233
|
+
Return ONLY valid JSON (no markdown, no explanation) in this shape:
|
|
234
|
+
{
|
|
235
|
+
"needsClarification": boolean,
|
|
236
|
+
"questions": [
|
|
237
|
+
{
|
|
238
|
+
"id": "q1",
|
|
239
|
+
"question": "Question text",
|
|
240
|
+
"context": "Why this helps",
|
|
241
|
+
"suggestions": [],
|
|
242
|
+
"multiSelect": false,
|
|
243
|
+
"required": true
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
"conversationalMessage": "Brief friendly message to the user",
|
|
247
|
+
"projectBrief": {
|
|
248
|
+
"name": "string",
|
|
249
|
+
"goal": "string",
|
|
250
|
+
"features": ["string"],
|
|
251
|
+
"domain": "string",
|
|
252
|
+
"database": "mongodb" | "postgresql",
|
|
253
|
+
"backendRuntime": "nodejs",
|
|
254
|
+
"apiStyle": "rest" | "graphql"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
For tech choices (API style, database), populate "suggestions" with the predefined options. For all other questions, use "suggestions": [].
|
|
259
|
+
If needsClarification is true, projectBrief can have empty/default values. If false, projectBrief must be complete.`;function Vo(t,e){return Xn.replace("{userMessage}",t).replace("{history}",e||"(No prior messages)")}var yt=`## Project:
|
|
260
|
+
- **Name**: {projectName}
|
|
261
|
+
- **Goal**: {projectGoal}
|
|
262
|
+
- **Features**: {projectFeatures}`,Zn=`${yt}
|
|
263
|
+
|
|
264
|
+
Identify ALL distinct user types (actors) who will use this system. 2-5 actors. Include unauthenticated and admin roles if applicable.
|
|
265
|
+
|
|
266
|
+
Return ONLY valid JSON:
|
|
267
|
+
{
|
|
268
|
+
"actors": [
|
|
269
|
+
{ "id": "actor-1", "name": "Name", "description": "Who they are", "goals": ["goal1", "goal2"] }
|
|
270
|
+
],
|
|
271
|
+
"message": "Brief explanation"
|
|
272
|
+
}`,es=`${yt}
|
|
273
|
+
|
|
274
|
+
## Actors (JSON):
|
|
275
|
+
{actors}
|
|
276
|
+
|
|
277
|
+
For EACH actor, identify 2-5 key user journeys (flows). Each flow: id, actorId, name, description, trigger, outcome.
|
|
278
|
+
|
|
279
|
+
Return ONLY valid JSON:
|
|
280
|
+
{
|
|
281
|
+
"flows": [
|
|
282
|
+
{ "id": "flow-1", "actorId": "actor-1", "name": "Flow Name", "description": "...", "trigger": "...", "outcome": "..." }
|
|
283
|
+
],
|
|
284
|
+
"message": "Brief explanation"
|
|
285
|
+
}`,ts=`${yt}
|
|
286
|
+
|
|
287
|
+
## Actors: {actors}
|
|
288
|
+
|
|
289
|
+
## Flows (JSON):
|
|
290
|
+
{flows}
|
|
291
|
+
|
|
292
|
+
For EACH flow, generate 2-5 user stories. Each story MUST include dataInvolved (entity.field names) for DB design. Include preconditions, postconditions.
|
|
293
|
+
|
|
294
|
+
Return ONLY valid JSON:
|
|
295
|
+
{
|
|
296
|
+
"stories": [
|
|
297
|
+
{ "id": "story-1", "flowId": "flow-1", "actor": "ActorName", "action": "...", "benefit": "...", "preconditions": [], "postconditions": [], "dataInvolved": ["User.email", "Order.total"] }
|
|
298
|
+
],
|
|
299
|
+
"message": "Brief explanation"
|
|
300
|
+
}`,os=`${yt}
|
|
301
|
+
|
|
302
|
+
## Actors: {actors}
|
|
303
|
+
## Flows: {flows}
|
|
304
|
+
## Stories (JSON):
|
|
305
|
+
{stories}
|
|
306
|
+
|
|
307
|
+
Extract modules (one per major entity). Each module has apis: create, read, readAll, update, delete plus any extra (e.g. searchUsers). CamelCase names. Clear inputs/outputs.
|
|
308
|
+
|
|
309
|
+
Return ONLY valid JSON:
|
|
310
|
+
{
|
|
311
|
+
"modules": [
|
|
312
|
+
{ "id": "module-1", "name": "User", "description": "...", "entity": "User", "apis": [ { "id": "api-1-1", "name": "createUser", "operation": "create", "description": "...", "inputs": [], "outputs": [] } ] }
|
|
313
|
+
],
|
|
314
|
+
"summary": { "totalModules": 0, "totalApis": 0 },
|
|
315
|
+
"message": "Brief explanation"
|
|
316
|
+
}`;function Wo(t,e,o){return Zn.replace("{projectName}",t).replace("{projectGoal}",e).replace("{projectFeatures}",o)}function Ko(t,e,o,r){return es.replace("{projectName}",t).replace("{projectGoal}",e).replace("{projectFeatures}",o).replace("{actors}",r)}function Xo(t,e,o,r,n){return ts.replace("{projectName}",t).replace("{projectGoal}",e).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n)}function Zo(t,e,o,r,n,a){return os.replace("{projectName}",t).replace("{projectGoal}",e).replace("{projectFeatures}",o).replace("{actors}",r).replace("{flows}",n).replace("{stories}",a)}var li=`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.
|
|
317
|
+
|
|
318
|
+
## Project brief (includes database: "mongodb" | "postgresql"):
|
|
319
|
+
{projectBrief}
|
|
320
|
+
|
|
321
|
+
## Modules (entities and CRUD):
|
|
322
|
+
{modules}
|
|
323
|
+
|
|
324
|
+
## User stories (data involved):
|
|
325
|
+
{stories}
|
|
326
|
+
|
|
327
|
+
Design the schema for the chosen database. For MongoDB use types like ObjectId, string, number, date, array; for PostgreSQL use varchar(n), text, integer, uuid, timestamp, jsonb, and proper foreign key relations.
|
|
328
|
+
|
|
329
|
+
Return ONLY valid JSON (no markdown) in this exact shape. Set "type" to the database from the project brief.
|
|
330
|
+
{
|
|
331
|
+
"type": "mongodb" | "postgresql",
|
|
332
|
+
"reasoning": "2-4 sentences on how the schema fits the project",
|
|
333
|
+
"entities": [
|
|
334
|
+
{
|
|
335
|
+
"name": "EntityName",
|
|
336
|
+
"description": "Brief description",
|
|
337
|
+
"fields": [
|
|
338
|
+
{ "name": "fieldName", "type": "DB-native type", "required": true, "unique": false, "description": "..." }
|
|
339
|
+
],
|
|
340
|
+
"indexes": [ { "name": "index_name", "fields": ["field1"], "unique": false } ],
|
|
341
|
+
"relations": [ { "field": "refField", "references": "OtherEntity", "description": "..." } ]
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
}`;var er="You output only valid JSON. No markdown, no explanation.";function tr(t,e,o){return li.replace("{projectBrief}",t).replace("{modules}",e).replace("{stories}",o)}var or="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.",rs=`## Project brief (JSON):
|
|
345
|
+
{projectBrief}
|
|
346
|
+
|
|
347
|
+
## Actors (JSON):
|
|
348
|
+
{actors}
|
|
349
|
+
|
|
350
|
+
## Flows (JSON):
|
|
351
|
+
{flows}
|
|
352
|
+
|
|
353
|
+
## Stories (JSON):
|
|
354
|
+
{stories}
|
|
355
|
+
|
|
356
|
+
## Modules (JSON):
|
|
357
|
+
{modules}
|
|
358
|
+
|
|
359
|
+
## Database design (JSON):
|
|
360
|
+
{database}
|
|
361
|
+
|
|
362
|
+
Compile the above into one FinalRequirement JSON. Include a "summary" object with: totalActors, totalFlows, totalStories, totalModules, totalEntities (from database.entities.length), and "overview" (2-4 sentence paragraph summarizing the project and tech choices).
|
|
363
|
+
|
|
364
|
+
Return ONLY valid JSON in this shape (no markdown, no extra text):
|
|
365
|
+
{
|
|
366
|
+
"project": { ... },
|
|
367
|
+
"actors": [ ... ],
|
|
368
|
+
"flows": [ ... ],
|
|
369
|
+
"stories": [ ... ],
|
|
370
|
+
"modules": [ ... ],
|
|
371
|
+
"database": { ... },
|
|
372
|
+
"summary": {
|
|
373
|
+
"totalActors": 0,
|
|
374
|
+
"totalFlows": 0,
|
|
375
|
+
"totalStories": 0,
|
|
376
|
+
"totalModules": 0,
|
|
377
|
+
"totalEntities": 0,
|
|
378
|
+
"overview": "string"
|
|
379
|
+
}
|
|
380
|
+
}`;function rr(t,e,o,r,n,a){return rs.replace("{projectBrief}",t).replace("{actors}",e).replace("{flows}",o).replace("{stories}",r).replace("{modules}",n).replace("{database}",a)}function nr(){return {stage:"discovery",projectBrief:null,actors:[],flows:[],stories:[],modules:[],database:null,history:[],pendingQuestions:[]}}function sr(t,e){let o=e.data;return {...t,...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 Ge(t,e,o){let r={role:e,content:o};return {...t,history:[...t.history,r]}}function St(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 ns(t){return t.map(e=>`${e.name}: ${e.entity} (${e.apis.length} APIs)`).join(`
|
|
381
|
+
`)}function ss(t){return t.map(e=>`- ${e.actor}: ${e.action}`).join(`
|
|
382
|
+
`)}function Q(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}function V(t){try{return {success:!0,data:JSON.parse(t)}}catch(e){return {success:false,error:e instanceof Error?e.message:String(e)}}}async function bt(t,e,o,r){r?.debug("Discovery stage started",{historyLength:e.history.length});let n=e.history.map(L=>`${L.role}: ${L.content}`).slice(-10).join(`
|
|
383
|
+
`),a=Vo(t,n),i=[{role:"system",content:`${ge}
|
|
384
|
+
|
|
385
|
+
${Qo}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.4,maxOutputTokens:4096}),c=Q(l.text),p=V(c);if(!p.success)return r?.warn("Discovery response was not valid JSON",{error:p.error}),{message:"I couldn't parse that. Could you describe your project in a few sentences?",advance:false,data:{}};let d=p.data,u=d.conversationalMessage??l.text?.slice(0,500)??"Thanks for the details.",y=d.needsClarification===true,m=[];if(Array.isArray(d.questions))for(let L of d.questions){let j=ht.safeParse(L);j.success&&m.push(j.data);}let B=null;if(d.projectBrief&&!y){let L=Ae.safeParse(d.projectBrief);L.success&&(B=L.data);}return r?.debug("Discovery stage complete",{advance:!y&&B!==null,hasProjectBrief:!!B,questionsCount:m.length}),{message:u,questions:m.length?m:void 0,advance:!y&&B!==null,data:{...B&&{projectBrief:B},pendingQuestions:m}}}async function as(t,e,o){if(t.invokeObject)return (await t.invokeObject(e,ut,{temperature:.4,maxOutputTokens:4096})).data;let r=await t.invoke(e,{temperature:.4,maxOutputTokens:4096}),n=V(Q(r.text));if(!n.success)throw new Error(`Actors: ${n.error}`);let a=ut.safeParse(n.data);if(!a.success)throw new Error(`Actors schema: ${a.error.message}`);return a.data}async function is(t,e,o,r){if(t.invokeObject)return (await t.invokeObject(e,mt,{temperature:.4,maxOutputTokens:8192})).data;let n=await t.invoke(e,{temperature:.4,maxOutputTokens:8192}),a=V(Q(n.text));if(!a.success)throw new Error(`Flows: ${a.error}`);let s=mt.safeParse(a.data);if(!s.success)throw new Error(`Flows schema: ${s.error.message}`);return s.data}async function ls(t,e,o,r,n){if(t.invokeObject)return (await t.invokeObject(e,gt,{temperature:.4,maxOutputTokens:16384})).data;let a=await t.invoke(e,{temperature:.4,maxOutputTokens:16384}),s=V(Q(a.text));if(!s.success)throw new Error(`Stories: ${s.error}`);let i=gt.safeParse(s.data);if(!i.success)throw new Error(`Stories schema: ${i.error.message}`);return i.data}async function cs(t,e,o,r,n,a){if(t.invokeObject)return (await t.invokeObject(e,ft,{temperature:.4,maxOutputTokens:16384})).data;let s=await t.invoke(e,{temperature:.4,maxOutputTokens:16384}),i=V(Q(s.text));if(!i.success)throw new Error(`Modules: ${i.error}`);let l=ft.safeParse(i.data);if(!l.success)throw new Error(`Modules schema: ${l.error.message}`);return l.data}async function xt(t,e,o,r){r?.debug("Requirements stage started");let n=e.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:ge}];try{l.push({role:"user",content:Wo(a,s,i)});let p=(await as(o,l,r)).actors;r?.debug("Requirements: actors",{count:p.length}),l.push({role:"assistant",content:`[Extracted ${p.length} actors]`}),l.push({role:"user",content:Ko(a,s,i,JSON.stringify(p))});let u=(await is(o,l,p,r)).flows;r?.debug("Requirements: flows",{count:u.length}),l.push({role:"assistant",content:`[Generated ${u.length} flows]`}),l.push({role:"user",content:Xo(a,s,i,JSON.stringify(p),JSON.stringify(u))});let m=(await ls(o,l,p,u,r)).stories;r?.debug("Requirements: stories",{count:m.length}),l.push({role:"assistant",content:`[Generated ${m.length} stories]`}),l.push({role:"user",content:Zo(a,s,i,JSON.stringify(p),JSON.stringify(u),JSON.stringify(m))});let L=(await cs(o,l,p,u,m,r)).modules;return r?.debug("Requirements stage complete",{actors:p.length,flows:u.length,stories:m.length,modules:L.length}),{message:`I've identified ${p.length} actors, ${u.length} flows, ${m.length} stories, and ${L.length} modules. Proceeding to technical design.`,advance:!0,data:{actors:p,flows:u,stories:m,modules:L,pendingQuestions:[]}}}catch(c){let p=c instanceof Error?c.message:String(c);return r?.warn("Requirements stage failed",{error:p}),{message:`Requirements step failed: ${p}. Please try again.`,advance:false,data:{}}}}async function Tt(t,e,o,r){let n=e.projectBrief;if(!n)return {message:"Project brief is missing.",advance:false,data:{}};if(!e.modules.length||!e.stories.length)return {message:"Requirements (modules and stories) are missing. Run requirements stage first.",advance:false,data:{}};r?.info("Design stage: database design",{modules:e.modules.length,stories:e.stories.length});let a=JSON.stringify(n),s=ns(e.modules),i=ss(e.stories),l=tr(a,s,i),c=[{role:"system",content:er},{role:"user",content:l}],p=await o.invoke(c,{temperature:.3,maxOutputTokens:8192}),d=Q(p.text),u=V(d);if(!u.success)return r?.warn("Database design response was not valid JSON",{error:u.error}),{message:"Failed to parse database design response. Please try again.",advance:false,data:{}};let y=me.safeParse(u.data);if(!y.success){let B=y.error;return r?.warn("Database design schema validation failed",{error:zod.z.treeifyError(B)}),{message:"Failed to produce database design. Please try again.",advance:false,data:{}}}let m=y.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 Pt(t,e,o,r){r?.debug("Synthesis stage started");let n=e.projectBrief;if(!n||!e.database)return {message:"Missing project brief or database design. Complete earlier stages first.",advance:false,data:{}};let a=rr(JSON.stringify(n),JSON.stringify(e.actors),JSON.stringify(e.flows),JSON.stringify(e.stories),JSON.stringify(e.modules),JSON.stringify(e.database)),i=[{role:"system",content:`${ge}
|
|
386
|
+
|
|
387
|
+
${or}`},{role:"user",content:a}],l=await o.invoke(i,{temperature:.3,maxOutputTokens:16384}),c=Q(l.text),p=V(c);if(!p.success)return r?.warn("Synthesis response was not valid JSON",{error:p.error}),{message:"Failed to compile final requirement document. Please try again.",advance:false,data:{}};let d=Ho.safeParse(p.data);if(!d.success)return r?.warn("Synthesis: final requirement schema validation failed",{error:d.error.message}),{message:"Final document did not match schema. "+(l.text?.slice(0,300)??""),advance:false,data:{}};let u=d.data;return r?.info("Synthesis stage complete",{overview:u.summary?.overview}),{message:`Requirement document ready. ${u.summary.overview}`,advance:true,data:{finalRequirement:u}}}var Rt=class{stageName="discovery";async process(e,o){return bt(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "requirements"}};var wt=class{stageName="requirements";async process(e,o){return xt(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "design"}};var vt=class{stageName="design";async process(e,o){return Tt(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "complete"}};var Et=class{stageName="complete";async process(e,o){return Pt(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return null}};var pi={discovery:new Rt,requirements:new wt,design:new vt,complete:new Et};function ar(t){return pi[t]}async function ps(t,e,o,r,n){n?.debug("Stage processor invoked",{stage:t});let s=await ar(t).process(o,{userMessage:e,model:r,logger:n}),i=sr(o,s),l="finalRequirement"in s.data?s.data.finalRequirement:void 0;n?.debug("Stage result",{stage:t,advance:s.advance,hasFinalRequirement:!!l});let c={...i,pendingQuestions:s.questions??i.pendingQuestions};return {message:s.message,questions:s.questions??i.pendingQuestions,advance:s.advance,data:c,finalRequirement:l}}var ir=["discovery","requirements","design","complete"];async function At(t,e,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=v(n),s=e??nr();s=Ge(s,"user",t),r?.info("Chat turn",{stage:s.stage,messageLength:t.length});let i="",l=[],c=null,p=async y=>{let m=await ps(y,t,s,a,r);return i=m.message,l=m.questions,s=m.data,m.finalRequirement&&(c=m.finalRequirement),{advance:m.advance,finalReq:m.finalRequirement}},d=s.stage;r?.info("Stage",{stage:d});let u=await p(d);for(s={...s,pendingQuestions:l};u.advance&&!c;){let y=ir.indexOf(d),m=y>=0&&y<ir.length-1?ir[y+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:d,to:m}),d=m,s=St(s),s={...s,stage:d},r?.info("Stage",{stage:d}),u=await p(d),s={...s,pendingQuestions:l};}return s=Ge(s,"assistant",i),r?.info("Chat turn done",{stage:d,hasFinalRequirement:!!c}),{message:i,context:s,questions:l,finalRequirement:c}}var ds=10;async function ui(t){let{input:e,model:o,onStep:r,logger:n}=t;n?.info("Starting requirement gatherer agent",{maxTurns:ds});let a=null,s=await At(e,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.finalRequirement&&i<ds;)n?.debug("Requirement gatherer turn",{turn:i}),s=await At("continue",a,{model:o,logger:n}),a=s.context,i++;let l=s.finalRequirement?JSON.stringify(s.finalRequirement,null,2):s.message,c=a.history.map(p=>({role:p.role,content:p.content}));return n?.info("Requirement gatherer agent completed",{turns:i,hasFinalRequirement:!!s.finalRequirement}),{output:l,steps:[],totalUsage:void 0,messages:c}}var mi="discovery",Mt=class{data={};withStage(e){return this.data.stage=e,this}withProjectBrief(e){return this.data.projectBrief=e,this}withActors(e){return this.data.actors=e,this}withFlows(e){return this.data.flows=e,this}withStories(e){return this.data.stories=e,this}withModules(e){return this.data.modules=e,this}withDatabase(e){return this.data.database=e,this}withHistory(e){return this.data.history=e,this}withPendingQuestions(e){return this.data.pendingQuestions=e,this}reset(){return this.data={},this}build(){return {stage:this.data.stage??mi,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 gi(){return new Mt}var fi={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};function us(){return {stage:"discovery",projectDescription:null,sections:{...fi},history:[],pendingQuestions:[]}}function ms(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 Ot(t,e,o){let r={role:e,content:o};return {...t,history:[...t.history,r]}}function lr(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 Ct(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.
|
|
388
|
+
|
|
389
|
+
CRITICAL RULES:
|
|
390
|
+
- 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.
|
|
391
|
+
- 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**).
|
|
392
|
+
- 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 cr=`You are in the discovery stage. Your goal is to understand what the user wants to build.
|
|
393
|
+
|
|
394
|
+
Respond in natural language only. Do NOT output JSON.
|
|
395
|
+
|
|
396
|
+
- If you need more information: ask 1-3 short, specific questions. Focus on tech choices (REST vs GraphQL, MongoDB vs PostgreSQL) and any gaps that block design.
|
|
397
|
+
- When you have enough to proceed: output the project overview in this exact pro format so it matches the rest of the plan:
|
|
398
|
+
- **## Overview** \u2014 One paragraph (2\u20134 sentences) summarizing the project and its purpose.
|
|
399
|
+
- **## Core Features** \u2014 Numbered list: 1. **Feature Name** - Short description. (one line per feature)
|
|
400
|
+
- **## Tech Stack** \u2014 Bullet list with category labels: - **Frontend**: ... (versions if known), - **Database**: ..., - **Authentication**: ..., - **API**: ..., - **Backend**: ... Include versions and key libraries where relevant.
|
|
401
|
+
|
|
402
|
+
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.`,gs=`## Current user message:
|
|
403
|
+
{userMessage}
|
|
404
|
+
|
|
405
|
+
## Prior conversation (if any):
|
|
406
|
+
{history}
|
|
407
|
+
|
|
408
|
+
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(t,e){return gs.replace("{userMessage}",t).replace("{history}",e||"(No prior messages)")}var Nt=`## Project description / context:
|
|
409
|
+
{context}`,fs=`${Nt}
|
|
410
|
+
|
|
411
|
+
Using the project description above, write two markdown sections in this exact format:
|
|
412
|
+
|
|
413
|
+
1. **## Overview** \u2014 One paragraph only (2\u20134 sentences) summarizing the project and its purpose.
|
|
414
|
+
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.
|
|
415
|
+
|
|
416
|
+
Output only these two sections in markdown. Do NOT output JSON.`,hs=`${Nt}
|
|
417
|
+
|
|
418
|
+
## Already written (Overview + Tech Stack):
|
|
419
|
+
{overviewAndTechStack}
|
|
420
|
+
|
|
421
|
+
Write the next two markdown sections in this exact format:
|
|
422
|
+
|
|
423
|
+
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).
|
|
424
|
+
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.
|
|
425
|
+
|
|
426
|
+
Output only markdown. Do NOT output JSON.`;function dr(t){return fs.replace("{context}",t)}function ur(t,e){return hs.replace("{context}",t).replace("{overviewAndTechStack}",e)}var ys=`## Project context (all sections so far):
|
|
427
|
+
{priorSections}`,Ss=`${ys}
|
|
428
|
+
|
|
429
|
+
## API Routes (already written):
|
|
430
|
+
{apiRoutes}
|
|
431
|
+
|
|
432
|
+
Write the next markdown section in this exact format:
|
|
433
|
+
|
|
434
|
+
**## Implementation Details**
|
|
435
|
+
- **### File Structure** \u2014 Full directory tree in a **code block** (e.g. src/app/(auth)/login/page.tsx, src/app/api/auth/signup/route.ts, src/components/..., src/lib/, src/models/). Show the real layout a developer would create.
|
|
436
|
+
- **### Environment Variables** \u2014 List with comments (e.g. MONGODB_URI=... # connection string, JWT_SECRET=... # change in production).
|
|
437
|
+
- **### Dependencies to Install** \u2014 npm install line and short explanation per dependency (e.g. mongoose: MongoDB ODM; bcryptjs: password hashing; jsonwebtoken: JWT; cookie: cookie parsing).
|
|
438
|
+
- **### 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).
|
|
439
|
+
- 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).
|
|
440
|
+
|
|
441
|
+
Output only markdown. Do NOT output JSON.`;function mr(t,e){return Ss.replace("{priorSections}",t).replace("{apiRoutes}",e)}var bi=`## Full plan so far (all sections):
|
|
442
|
+
{priorSections}`,gr="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.",bs=`${bi}
|
|
443
|
+
|
|
444
|
+
Write the following sections in this exact order. Output only markdown. Do NOT output JSON.
|
|
445
|
+
|
|
446
|
+
**Block 1 \u2014 Implementation Order, Current State, Desired End State**
|
|
447
|
+
|
|
448
|
+
1. **## Implementation Order** \u2014 Phased: ### Phase 1: Foundation, ### Phase 2: Authentication, etc. Under each phase, numbered steps (e.g. "1. Install dependencies", "2. Create User model", "3. Implement POST /api/auth/signup", "4. Create login page"). Be concrete so a developer can follow step-by-step.
|
|
449
|
+
|
|
450
|
+
2. **## Current State Analysis** \u2014 What the project starts with (e.g. vanilla Next.js, no DB, no auth). Then a short bullet list: "What needs to be built from scratch" (all auth, models, API routes, pages, etc.).
|
|
451
|
+
|
|
452
|
+
3. **## Desired End State** \u2014 Short subsections or bullets: (1) For users: what they can do when the app is done; (2) Technical verification: what must work (DB connected, auth working, endpoints returning correct data, etc.); (3) Testing approach: manual flows, API checks, DB checks.
|
|
453
|
+
|
|
454
|
+
**Block 2 \u2014 Edge Cases, Security, Performance, Future Enhancements**
|
|
455
|
+
|
|
456
|
+
4. **## Edge Cases and Considerations** \u2014 ### per area (e.g. ### Authentication, ### Workouts, ### Nutrition, ### Goals, ### Profile, ### General). Under each, bullets for edge cases and how to handle them (e.g. "Email already exists: return 400 with clear message"; "External API down: show error, allow manual entry").
|
|
457
|
+
|
|
458
|
+
5. **## Security Considerations** \u2014 Numbered list: passwords (bcrypt, min length); JWT (HTTP-only cookie, secure flag, strong secret, expiry); API (verify JWT on protected routes, check resource ownership); env (never commit secrets, different values in production).
|
|
459
|
+
|
|
460
|
+
6. **## Performance Considerations** \u2014 Numbered list: DB (index user id and date fields, lean queries, avoid N+1); API (debounce search, cache external API if applicable); frontend (RSC where possible, lazy load heavy components); optional future caching.
|
|
461
|
+
|
|
462
|
+
7. **## Future Enhancements (Not in Current Scope)** \u2014 Short grouped list (e.g. Social, Analytics, Integrations, Mobile, Premium) so scope is clear. One line per group is enough.
|
|
463
|
+
|
|
464
|
+
**Block 3 \u2014 Manual Testing Checklist**
|
|
465
|
+
|
|
466
|
+
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").
|
|
467
|
+
|
|
468
|
+
Output all eight sections in the order above. Do NOT output JSON.`;function fr(t){return bs.replace("{priorSections}",t)}var hr=`You are a senior software architect revising an existing implementation plan.
|
|
469
|
+
|
|
470
|
+
CRITICAL RULES:
|
|
471
|
+
- You will receive the FULL existing plan and the user's feedback or edit instructions.
|
|
472
|
+
- Output ONLY the complete revised plan in markdown. Do NOT output partial plans, explanations, or commentary.
|
|
473
|
+
- Preserve the same section structure (## headings) as the original plan.
|
|
474
|
+
- Only modify sections that are affected by the feedback. Leave unrelated sections intact.
|
|
475
|
+
- Use code blocks ONLY for: request/response JSON examples, file/directory trees, and env or config snippets.
|
|
476
|
+
- Be concrete and actionable: include validation rules, HTTP status codes, redirects, field-level data model descriptions, and step-by-step auth flows.
|
|
477
|
+
- 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 yr(t,e){return `## Existing Plan
|
|
478
|
+
|
|
479
|
+
${t}
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Edit Instructions
|
|
484
|
+
|
|
485
|
+
${e}`}function xi(t){let e=t.trim();if(e.length<100)return false;if(e.includes("## Overview")||e.includes("## Core Features"))return true;let o=e.toLowerCase();return !!((o.includes("overview")||o.includes("core features"))&&(o.includes("tech stack")||o.includes("technology")))}async function Sr(t,e,o,r){r?.debug("Discovery stage started",{historyLength:e.history.length});let a=e.history.slice(0,-1).map(L=>`${L.role}: ${L.content}`).slice(-10).join(`
|
|
486
|
+
`),s=pr(t,a),l=[{role:"system",content:`${ee}
|
|
487
|
+
|
|
488
|
+
${cr}`},{role:"user",content:s}],p=(await o.invoke(l,{temperature:.4,maxOutputTokens:4096})).text?.trim()??"",d=xi(p),u=Ct(t),y=u&&e.history.length>=7&&p.length>50,m=d&&(e.projectDescription==null||u)||u&&e.projectDescription!=null||y,B=d||y&&p.length>50;return r?.debug("Discovery stage complete",{advance:m,hasOverview:d,userConfirmed:u,forceAdvance:y}),{message:p,advance:m,sections:{},...B&&{projectDescription:p}}}var Dt=class{stageName="discovery";async process(e,o){return Sr(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "requirements"}};var Ti=`You are an expert database entity analyst. Your job is to extract data model signals from requirements.
|
|
489
|
+
|
|
490
|
+
Perform these analyses:
|
|
491
|
+
|
|
492
|
+
## Entity Discovery
|
|
493
|
+
- List every entity implied by the requirements (users, domain objects, settings, logs).
|
|
494
|
+
- For each entity: name, purpose, key fields (with types), and which user type owns it.
|
|
495
|
+
- Identify status enums from flow transitions (e.g. pending -> active -> completed).
|
|
496
|
+
|
|
497
|
+
## Field Analysis
|
|
498
|
+
- For each entity, list fields with: name, likely type, required/optional, unique constraints.
|
|
499
|
+
- Identify computed vs stored fields.
|
|
500
|
+
- Note fields that need indexing (lookups, sorting, filtering).
|
|
501
|
+
|
|
502
|
+
## Relationship Signals
|
|
503
|
+
- List entity pairs that reference each other.
|
|
504
|
+
- Note ownership direction (which entity "belongs to" which).
|
|
505
|
+
- Identify potential M:N relationships that may need join tables.
|
|
506
|
+
|
|
507
|
+
Respond with a clear, structured analysis using headings and bullet points. Do NOT return JSON.`,ne=f({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:Ti,tools:{},maxIterations:2});var Pi=`You are a database relationship specialist. Given a list of entities and their fields, you determine:
|
|
508
|
+
|
|
509
|
+
## Cardinality Analysis
|
|
510
|
+
- For every entity pair that references each other, classify: 1:1, 1:N, or M:N.
|
|
511
|
+
- Explain the reasoning (e.g. "A User has many Orders, but an Order belongs to one User -> 1:N").
|
|
512
|
+
|
|
513
|
+
## Foreign Key / Reference Strategy
|
|
514
|
+
- For MongoDB: recommend ObjectId references vs embedding. Embed when: data is small, always read together, rarely updated independently.
|
|
515
|
+
- For PostgreSQL: define foreign key columns, ON DELETE behavior (CASCADE, SET NULL, RESTRICT).
|
|
516
|
+
|
|
517
|
+
## Join Table Design (M:N)
|
|
518
|
+
- When M:N is detected, design the join table with: both foreign keys, any extra fields (e.g. role in a membership), indexes.
|
|
519
|
+
|
|
520
|
+
## Index Recommendations
|
|
521
|
+
- Suggest compound indexes for common query patterns.
|
|
522
|
+
- Suggest unique indexes for natural keys (email, slug, etc.).
|
|
523
|
+
- Note partial indexes where applicable (e.g. only active records).
|
|
524
|
+
|
|
525
|
+
Respond with structured analysis. Do NOT return JSON.`,kt=f({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:Pi,tools:{},maxIterations:2});var Ri=`You are an expert database schema reviewer. Your job is to:
|
|
526
|
+
|
|
527
|
+
1. Validate the schema structure: every entity has fields, indexes, and relations properly defined.
|
|
528
|
+
2. Check completeness: all entities from requirements are present, all relationships are bidirectional where needed.
|
|
529
|
+
3. Check normalization: no redundant data, proper use of references vs embedding.
|
|
530
|
+
4. Check performance: indexes cover common query patterns, no missing indexes on foreign keys.
|
|
531
|
+
5. Check security: passwords are marked as hashed, sensitive fields noted, no plaintext secrets.
|
|
532
|
+
6. Check conventions: consistent naming (camelCase or snake_case), timestamps on all entities.
|
|
533
|
+
|
|
534
|
+
If you have access to the validate_schema tool, use it first. Then provide a detailed review with:
|
|
535
|
+
- Issues found (with severity: critical, warning, suggestion)
|
|
536
|
+
- Specific fixes for each issue
|
|
537
|
+
- Overall assessment (ready / needs work)
|
|
538
|
+
|
|
539
|
+
Respond with structured analysis. Do NOT return JSON.`;function fe(){return f({name:"schema-refiner",description:"Reviews a data model schema for completeness, normalization, performance, and security. Has access to validate_schema tool.",systemPrompt:Ri,tools:{},maxIterations:3})}var wi=`You are a UX-focused frontend architect. You design detailed page specifications.
|
|
540
|
+
|
|
541
|
+
## Page Planning
|
|
542
|
+
For each page in the application:
|
|
543
|
+
|
|
544
|
+
### Route Definition
|
|
545
|
+
- Path (e.g. /login, /dashboard, /workouts/:id)
|
|
546
|
+
- Access level: public (no auth) or protected (requires auth)
|
|
547
|
+
- Page name and purpose (one sentence)
|
|
548
|
+
|
|
549
|
+
### Page Detail
|
|
550
|
+
- **Form fields**: name, type (text, email, password, number, select, textarea, date, checkbox), required flag, validation rule.
|
|
551
|
+
- **Actions**: buttons and what they do (e.g. "Submit form", "Delete item", "Export CSV").
|
|
552
|
+
- **Empty state**: what to show when there's no data (e.g. "No workouts yet. Click + to add one.").
|
|
553
|
+
- **Error state**: how to handle errors (e.g. "Show inline validation errors", "Toast notification").
|
|
554
|
+
- **Redirect on success**: where to go after successful action (e.g. "/dashboard").
|
|
555
|
+
- **Key UI elements**: cards, tables, charts, sidebar, modals, tabs.
|
|
556
|
+
|
|
557
|
+
### Page Grouping
|
|
558
|
+
- Group by access: public pages first, then protected.
|
|
559
|
+
- Order by user flow: signup -> login -> dashboard -> feature pages -> settings -> admin.
|
|
560
|
+
|
|
561
|
+
Respond with structured page specs. Do NOT return JSON.`,Me=f({name:"page-planner",description:"Designs detailed page specifications with routes, form fields, actions, states, and UI elements. Use for frontend page design.",systemPrompt:wi,tools:{},maxIterations:2});var vi=`You are a component design specialist. Given page specifications, you identify reusable components and shared patterns.
|
|
562
|
+
|
|
563
|
+
## Component Identification
|
|
564
|
+
- **Layout components**: main layout (with nav, sidebar, content area), auth layout (centered form), admin layout.
|
|
565
|
+
- **Navigation components**: navbar, sidebar, breadcrumbs, mobile menu.
|
|
566
|
+
- **Form components**: reusable form inputs, form wrappers, validation display.
|
|
567
|
+
- **Display components**: cards, tables, lists, stat widgets, charts, badges.
|
|
568
|
+
- **Shared components**: modals, toasts, loading spinners, empty state illustrations, error boundaries.
|
|
569
|
+
|
|
570
|
+
## Component Analysis
|
|
571
|
+
For each component:
|
|
572
|
+
- Name (PascalCase)
|
|
573
|
+
- Type: layout, shared, form, display, navigation
|
|
574
|
+
- Purpose (one sentence)
|
|
575
|
+
- Props it accepts (e.g. "user", "items", "onSubmit", "isLoading")
|
|
576
|
+
- Which pages use it
|
|
577
|
+
|
|
578
|
+
## State Management
|
|
579
|
+
- Identify which state is per-page (form state, UI state) vs global (auth state, user preferences).
|
|
580
|
+
- Recommend server vs client state strategy.
|
|
581
|
+
- Identify data fetching patterns (on mount, on action, real-time).
|
|
582
|
+
|
|
583
|
+
Respond with structured analysis. Do NOT return JSON.`,_t=f({name:"component-analyzer",description:"Identifies reusable components, shared layouts, and state management patterns from page specifications. Use after page planning.",systemPrompt:vi,tools:{},maxIterations:2});var Ei=`You are a frontend technology advisor. Given project requirements, you recommend the best frontend framework.
|
|
584
|
+
|
|
585
|
+
## Decision Criteria
|
|
586
|
+
|
|
587
|
+
### Choose "react-vite" (Vite + React SPA) when:
|
|
588
|
+
- The app is a single-page application (SPA) behind authentication
|
|
589
|
+
- No SEO requirements (admin dashboards, internal tools, B2B apps)
|
|
590
|
+
- Backend is a separate API (GraphQL or REST) already built
|
|
591
|
+
- Simple routing with client-side navigation
|
|
592
|
+
- Team prefers traditional React patterns (hooks, context)
|
|
593
|
+
|
|
594
|
+
### Choose "nextjs" (Next.js App Router) when:
|
|
595
|
+
- SEO is important (marketing pages, blogs, e-commerce storefronts)
|
|
596
|
+
- Need server-side rendering (SSR) or static site generation (SSG)
|
|
597
|
+
- Want unified frontend + API in one project (server actions, API routes)
|
|
598
|
+
- Need streaming and progressive rendering
|
|
599
|
+
- Complex data fetching with caching requirements
|
|
600
|
+
- Mix of public and authenticated pages
|
|
601
|
+
|
|
602
|
+
## Output Format
|
|
603
|
+
State your recommendation clearly:
|
|
604
|
+
- Framework: react-vite | nextjs
|
|
605
|
+
- Reasoning: 2-3 sentences explaining why
|
|
606
|
+
- Trade-offs: what you would lose with the alternative
|
|
607
|
+
|
|
608
|
+
Respond with structured analysis. Do NOT return JSON.`,br=f({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:Ei,tools:{},maxIterations:2});var Ai=`You are a web security specialist. You analyze project requirements for security concerns and design security policies.
|
|
609
|
+
|
|
610
|
+
## Authentication Analysis
|
|
611
|
+
- Determine the best auth strategy (JWT, session, OAuth) based on requirements.
|
|
612
|
+
- JWT: token expiry, refresh strategy, cookie vs header, httpOnly/secure/sameSite flags.
|
|
613
|
+
- Session: session store (memory, Redis, DB), cookie config, session expiry.
|
|
614
|
+
- OAuth: which providers, callback flow, token exchange, account linking.
|
|
615
|
+
|
|
616
|
+
## Password Security
|
|
617
|
+
- Hashing algorithm (bcrypt recommended), cost factor (10+ rounds).
|
|
618
|
+
- Password requirements: minimum length, complexity rules.
|
|
619
|
+
- Password reset flow: token generation, expiry, one-time use.
|
|
620
|
+
|
|
621
|
+
## Authorization Analysis
|
|
622
|
+
- Identify role hierarchy (e.g. admin > moderator > user).
|
|
623
|
+
- Map roles to permissions per resource (CRUD matrix).
|
|
624
|
+
- Resource ownership checks (users can only modify their own data).
|
|
625
|
+
|
|
626
|
+
## Threat Analysis
|
|
627
|
+
- Rate limiting: login attempts, API calls, password reset requests.
|
|
628
|
+
- CORS: allowed origins, methods, headers.
|
|
629
|
+
- Input sanitization: XSS prevention, SQL injection prevention.
|
|
630
|
+
- Brute force protection: account lockout, exponential backoff.
|
|
631
|
+
|
|
632
|
+
Respond with structured analysis. Do NOT return JSON.`,It=f({name:"security-analyzer",description:"Analyzes security requirements, threat vectors, and designs security policies. Use to understand auth needs before designing flows.",systemPrompt:Ai,tools:{},maxIterations:2});var Mi=`You are an authentication flow architect. You design detailed, numbered step-by-step auth flows.
|
|
633
|
+
|
|
634
|
+
For each flow (signup, login, logout, password reset, protected route middleware, API auth middleware):
|
|
635
|
+
|
|
636
|
+
## Flow Design Pattern
|
|
637
|
+
1. Number each step sequentially.
|
|
638
|
+
2. Mark each step as "frontend" or "backend".
|
|
639
|
+
3. Describe the action clearly (e.g. "Frontend sends POST to /api/auth/signup with { name, email, password }").
|
|
640
|
+
4. Include implementation details (e.g. "Backend hashes password with bcrypt (10 rounds)").
|
|
641
|
+
|
|
642
|
+
## Signup Flow
|
|
643
|
+
- Frontend: form validation, submit request.
|
|
644
|
+
- Backend: validate input, check existing user, hash password, create user + profile, generate token, set cookie.
|
|
645
|
+
- Frontend: redirect to dashboard.
|
|
646
|
+
|
|
647
|
+
## Login Flow
|
|
648
|
+
- Frontend: form validation, submit credentials.
|
|
649
|
+
- Backend: find user, compare password hash, generate token, set cookie.
|
|
650
|
+
- Frontend: redirect to dashboard.
|
|
651
|
+
|
|
652
|
+
## Password Reset Flow
|
|
653
|
+
- Frontend: request reset (email).
|
|
654
|
+
- Backend: generate reset token, send email.
|
|
655
|
+
- Frontend: enter new password with token.
|
|
656
|
+
- Backend: validate token, hash new password, update user, invalidate token.
|
|
657
|
+
|
|
658
|
+
## Middleware Flows
|
|
659
|
+
- Protected route: check cookie/header, verify token, attach user to request, reject if invalid.
|
|
660
|
+
- API auth: same as above but for API routes, return 401 JSON.
|
|
661
|
+
|
|
662
|
+
Respond with structured numbered flows. Do NOT return JSON.`,Oe=f({name:"flow-designer",description:"Designs detailed step-by-step authentication flows (signup, login, logout, password reset, middleware). Use after security analysis.",systemPrompt:Mi,tools:{},maxIterations:2});function xs(t,e,o){let r=[{role:"system",content:e},{role:"user",content:o}];return t.invoke(r,{temperature:.3,maxOutputTokens:8192}).then(n=>n.text?.trim()??"")}function Oi(t){let e=t.indexOf("## Tech Stack");return e<0?{overview:t,techStack:""}:{overview:t.slice(0,e).trim(),techStack:t.slice(e).trim()}}function Ci(t){let e=t.indexOf("## Data Models");return e<0?{featureDecisions:t,dataModels:""}:{featureDecisions:t.slice(0,e).trim(),dataModels:t.slice(e).trim()}}async function xr(t,e,o,r){r?.debug("Requirements stage started (specialist agents)");let n=e.projectDescription??"";if(!n)return {message:"No project description yet. Complete discovery first.",advance:false,sections:{}};let a=`${ee}
|
|
663
|
+
|
|
664
|
+
Output only markdown. Do NOT output JSON.`,s=await xs(o,a,dr(n)),{overview:i,techStack:l}=Oi(s),c=await xs(o,a,ur(n,s)),{featureDecisions:p}=Ci(c);r?.info("Delegating to data-modeler specialist");let u=(await z(ne,`Analyze the data model for this project:
|
|
665
|
+
|
|
666
|
+
${n}
|
|
667
|
+
|
|
668
|
+
Features:
|
|
669
|
+
${p}`,{parentModel:o})).output;r?.info("Delegating to frontend-architect specialist");let y=[s,p,u].join(`
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
`),B=(await z(Me,`Design the pages and routes for this project:
|
|
674
|
+
|
|
675
|
+
${n}
|
|
676
|
+
|
|
677
|
+
Context:
|
|
678
|
+
${y}`,{parentModel:o})).output;r?.info("Delegating to auth-designer specialist");let L=[y,B].join(`
|
|
679
|
+
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
`),ye=(await z(Oe,`Design the authentication flows for this project:
|
|
683
|
+
|
|
684
|
+
${n}
|
|
685
|
+
|
|
686
|
+
Context:
|
|
687
|
+
${L}`,{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:p,dataModels:u,pagesAndRoutes:B,authFlow:ye}}}var jt=class{stageName="requirements";async process(e,o){return xr(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "design"}};var Ni=`You are an API endpoint analyst. Given a data model and requirements, you derive the complete API surface.
|
|
688
|
+
|
|
689
|
+
## Endpoint Discovery
|
|
690
|
+
- For each entity in the data model, determine CRUD operations: create, read (by ID), list (with filters/pagination), update, delete.
|
|
691
|
+
- From user stories/flows, identify custom operations beyond CRUD (e.g. searchUsers, bulkImport, exportCsv, toggleStatus).
|
|
692
|
+
- Group endpoints by resource name (pluralized entity name).
|
|
693
|
+
|
|
694
|
+
## Route Design
|
|
695
|
+
- Design RESTful routes: POST /resource, GET /resource/:id, GET /resource, PUT /resource/:id, DELETE /resource/:id.
|
|
696
|
+
- For nested resources: GET /users/:userId/orders, POST /users/:userId/orders.
|
|
697
|
+
- For custom operations: POST /resource/:id/actions/activate, GET /resource/search.
|
|
698
|
+
|
|
699
|
+
## Auth Annotations
|
|
700
|
+
- Mark which endpoints require authentication.
|
|
701
|
+
- Mark which endpoints require specific roles (admin, owner).
|
|
702
|
+
- Identify resource-ownership checks (user can only access their own data).
|
|
703
|
+
|
|
704
|
+
Respond with structured analysis using headings and bullet points. Do NOT return JSON.`,Ce=f({name:"endpoint-analyzer",description:"Analyzes data model and requirements to derive API endpoints, routes, and auth annotations. Use before generating the API design.",systemPrompt:Ni,tools:{},maxIterations:2});var Di=`You are an API contract specialist. Given endpoints and a data model, you design detailed request/response contracts.
|
|
705
|
+
|
|
706
|
+
## Request Design
|
|
707
|
+
- For each endpoint, define: required fields, optional fields, field types, validation rules.
|
|
708
|
+
- Validation rules: required, min/max length, email format, enum values, numeric ranges.
|
|
709
|
+
- For list endpoints: pagination (page, limit, offset), sorting (sortBy, order), filtering (query params).
|
|
710
|
+
|
|
711
|
+
## Response Design
|
|
712
|
+
- Success responses: HTTP status (200, 201, 204), response body shape.
|
|
713
|
+
- For list endpoints: { items: T[], total: number, page: number, limit: number }.
|
|
714
|
+
- For single item: the entity shape with all fields.
|
|
715
|
+
|
|
716
|
+
## Error Responses
|
|
717
|
+
- 400: validation errors with field-level messages.
|
|
718
|
+
- 401: unauthenticated (missing or invalid token).
|
|
719
|
+
- 403: forbidden (insufficient role or not resource owner).
|
|
720
|
+
- 404: resource not found.
|
|
721
|
+
- 409: conflict (duplicate unique field).
|
|
722
|
+
- 500: internal server error.
|
|
723
|
+
|
|
724
|
+
## Naming Conventions
|
|
725
|
+
- Use consistent field naming (camelCase for JSON, snake_case for query params if preferred).
|
|
726
|
+
- Use ISO 8601 for dates in responses.
|
|
727
|
+
|
|
728
|
+
Respond with structured analysis. Do NOT return JSON.`,Ne=f({name:"contract-designer",description:"Designs detailed request/response contracts, validation rules, and error responses per API endpoint. Use after endpoint analysis.",systemPrompt:Di,tools:{},maxIterations:2});function ki(t){let e=[];t.projectDescription&&e.push(t.projectDescription);let o=t.sections;return o.overview&&e.push(o.overview),o.techStack&&e.push(o.techStack),o.featureDecisions&&e.push(o.featureDecisions),o.dataModels&&e.push(o.dataModels),o.pagesAndRoutes&&e.push(o.pagesAndRoutes),o.authFlow&&e.push(o.authFlow),e.join(`
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
`)}async function Tr(t,e,o,r){r?.debug("Design stage started (specialist agents)");let n=ki(e);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 z(Ce,`Design the API routes for this project:
|
|
733
|
+
|
|
734
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to api-designer contract-designer specialist");let i=await z(Ne,`Design detailed request/response contracts for these API endpoints:
|
|
735
|
+
|
|
736
|
+
${s}
|
|
737
|
+
|
|
738
|
+
Project context:
|
|
739
|
+
${n}`,{parentModel:o}),l=`${ee}
|
|
740
|
+
|
|
741
|
+
Output only markdown. Do NOT output JSON.`,c=await o.invoke([{role:"system",content:l},{role:"user",content:mr(n,s+`
|
|
742
|
+
|
|
743
|
+
`+i.output)}],{temperature:.3,maxOutputTokens:8192}).then(p=>p.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:c}}}var qt=class{stageName="design";async process(e,o){return Tr(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return "complete"}};function Pr(t,e){return [`# ${t} Implementation Plan
|
|
744
|
+
`,e.overview,e.techStack,e.featureDecisions,"---",e.dataModels,"---",e.pagesAndRoutes,"---",e.authFlow,"---",e.apiRoutes,"---",e.implementation,"---",e.executionPlan,"---",e.edgeCases,"---",e.testingChecklist].filter(Boolean).join(`
|
|
745
|
+
|
|
746
|
+
`)}async function Ii(t,e){await promises.writeFile(e,t,"utf-8");}var ji=`You are a QA-minded tech lead. You identify edge cases that developers often miss.
|
|
747
|
+
|
|
748
|
+
For each domain area (Authentication, Data, API, Frontend, Integrations):
|
|
749
|
+
|
|
750
|
+
## Edge Case Analysis
|
|
751
|
+
- **Scenario**: Describe the edge case concretely (e.g. "User submits signup form with email that already exists").
|
|
752
|
+
- **Handling**: How to handle it (e.g. "Return 400 with message 'Email already in use'").
|
|
753
|
+
- **Severity**: critical (must handle or app breaks), warning (should handle for good UX), info (nice to have).
|
|
754
|
+
|
|
755
|
+
## Common Areas to Check
|
|
756
|
+
- **Authentication**: duplicate email, invalid credentials, expired token, concurrent sessions, password reset with invalid token.
|
|
757
|
+
- **Data**: empty collections, max field lengths, special characters in input, date timezone issues, null references.
|
|
758
|
+
- **API**: missing required fields, invalid field types, unauthorized access, rate limiting, pagination edge (page 0, negative page).
|
|
759
|
+
- **Frontend**: empty states, loading states, network errors, form resubmission, back button behavior.
|
|
760
|
+
- **Integrations**: external API down, timeout, rate limited, invalid response format.
|
|
761
|
+
|
|
762
|
+
Respond with structured edge cases grouped by area. Do NOT return JSON.`,De=f({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:ji,tools:{},maxIterations:2});var qi=`You are a testing strategy specialist. You design comprehensive manual testing checklists.
|
|
763
|
+
|
|
764
|
+
## Testing Checklist Design
|
|
765
|
+
Group test items by flow (Authentication, CRUD operations, Edge cases, etc.).
|
|
766
|
+
|
|
767
|
+
For each test item:
|
|
768
|
+
- **Flow name**: which feature flow this tests (e.g. "Authentication Flow", "Workout CRUD Flow").
|
|
769
|
+
- **Test item**: what to verify (e.g. "Sign up with valid credentials creates account").
|
|
770
|
+
- **Expected result**: what should happen (e.g. "User created in DB, JWT cookie set, redirected to /dashboard").
|
|
771
|
+
|
|
772
|
+
## Coverage Areas
|
|
773
|
+
- **Happy paths**: normal user flows work end-to-end.
|
|
774
|
+
- **Validation**: invalid inputs are rejected with clear messages.
|
|
775
|
+
- **Authorization**: users can only access what they should.
|
|
776
|
+
- **Error handling**: errors are caught and displayed properly.
|
|
777
|
+
- **Data integrity**: data is saved correctly, relationships maintained.
|
|
778
|
+
- **UI states**: loading, empty, error, success states display correctly.
|
|
779
|
+
|
|
780
|
+
## Checklist Format
|
|
781
|
+
Present as grouped checklist items using markdown checkboxes:
|
|
782
|
+
### Flow Name
|
|
783
|
+
- [ ] Test item description -> Expected result
|
|
784
|
+
|
|
785
|
+
Respond with structured checklist. Do NOT return JSON.`,ke=f({name:"testing-strategist",description:"Designs comprehensive manual testing checklists grouped by feature flow. Use for testing strategy and QA planning.",systemPrompt:qi,tools:{},maxIterations:2});function Fi(t){let e=[];t.projectDescription&&e.push(t.projectDescription);let o=t.sections;return [o.overview,o.techStack,o.featureDecisions,o.dataModels,o.pagesAndRoutes,o.authFlow,o.apiRoutes,o.implementation].forEach(r=>{r&&e.push(r);}),e.join(`
|
|
786
|
+
|
|
787
|
+
---
|
|
788
|
+
|
|
789
|
+
`)}function Ui(t){let o=(t.sections.overview??t.projectDescription??"").split(`
|
|
790
|
+
`)[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 Rr(t,e,o,r){r?.debug("Synthesis stage started (specialist agents)");let n=Fi(e);if(!n)return {message:"No prior sections. Complete earlier stages first.",advance:false,sections:{}};let a=`${ee}
|
|
791
|
+
|
|
792
|
+
${gr}
|
|
793
|
+
|
|
794
|
+
Output only markdown. Do NOT output JSON.`,s=await o.invoke([{role:"system",content:a},{role:"user",content:fr(n)}],{temperature:.3,maxOutputTokens:8192}).then(m=>m.text?.trim()??"");r?.info("Delegating to execution-planner edge-case-analyzer specialist");let l=(await z(De,`Identify edge cases for this project:
|
|
795
|
+
|
|
796
|
+
${n}`,{parentModel:o})).output;r?.info("Delegating to execution-planner testing-strategist specialist");let p=(await z(ke,`Design the manual testing checklist for this project:
|
|
797
|
+
|
|
798
|
+
${n}`,{parentModel:o})).output,d=Ui(e),u={...e.sections,executionPlan:s||null,edgeCases:l||null,testingChecklist:p||null},y=Pr(d,u);return r?.info("Synthesis stage complete (specialist agents)",{projectName:d}),{message:`Plan complete: ${d}. Generated via specialist agents.`,advance:true,sections:{executionPlan:s,edgeCases:l,testingChecklist:p},planMarkdown:y}}var Ft=class{stageName="complete";async process(e,o){return Rr(o.userMessage,e,o.model,o.logger)}canAdvance(e){return e.advance}getNextStageName(){return null}};var Li={discovery:new Dt,requirements:new jt,design:new qt,complete:new Ft};function wr(t){return Li[t]}async function Ts(t,e,o,r,n){n?.debug("Stage processor invoked",{stage:t});let s=await wr(t).process(o,{userMessage:e,model:r,logger:n}),i=ms(o,s),l={...i,pendingQuestions:s.pendingQuestions??i.pendingQuestions};return n?.debug("Stage result",{stage:t,advance:s.advance,hasPlanMarkdown:!!s.planMarkdown}),{message:s.message,pendingQuestions:s.pendingQuestions??i.pendingQuestions,advance:s.advance,data:l,planMarkdown:s.planMarkdown}}var vr=["discovery","requirements","design","complete"];async function he(t,e,o){let{logger:r}=o,n=o.model??{provider:"openai",model:"gpt-4o-mini"},a=v(n),s=e??us();s=Ot(s,"user",t),r?.info("Planning chat turn",{stage:s.stage,messageLength:t.length});let i="",l=[],c=null,p=async y=>{let m=await Ts(y,t,s,a,r);return i=m.message,l=m.pendingQuestions,s=m.data,m.planMarkdown&&(c=m.planMarkdown),{advance:m.advance,planMarkdown:m.planMarkdown}},d=s.stage;r?.info("Stage",{stage:d});let u=await p(d);for(;u.advance&&!c;){let y=vr.indexOf(d),m=y>=0&&y<vr.length-1?vr[y+1]:void 0;if(m===void 0)break;r?.info("Stage transition",{from:d,to:m}),d=m,s=lr(s),s={...s,stage:d},r?.info("Stage",{stage:d}),u=await p(d);}return s=Ot(s,"assistant",i),r?.info("Planning chat turn done",{stage:d,hasPlanMarkdown:!!c}),{message:i,context:s,pendingQuestions:l,planMarkdown:c}}var Ps=10;async function Gi(t){let{input:e,model:o,onStep:r,logger:n}=t;n?.info("Starting planning agent",{maxTurns:Ps});let a=null,s=await he(e,a,{model:o,logger:n});a=s.context;let i=1;for(;!s.planMarkdown&&i<Ps;){n?.debug("Planning agent turn",{turn:i});let p=`continue - proceed with the project: "${e}". Make reasonable assumptions for any unresolved details and produce the required output format.`;s=await he(p,a,{model:o,logger:n}),a=s.context,i++;}let l=s.planMarkdown??s.message,c=a.history.map(p=>({role:p.role,content:p.content}));return n?.info("Planning agent completed",{turns:i,hasPlanMarkdown:!!s.planMarkdown}),{output:l,steps:[],totalUsage:void 0,messages:c}}async function Ji(t){let{existingPlan:e,feedback:o,logger:r}=t;if(r?.info("Editing plan",{feedbackLength:o.length}),!e||e.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=t.model??{provider:"openai",model:"gpt-4o-mini"},i=(await v(n).invoke([{role:"system",content:hr},{role:"user",content:yr(e,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 Bi(t){return t.fields.length?`| Field | Type | Constraints | Description |
|
|
799
|
+
| --- | --- | --- | --- |
|
|
800
|
+
${t.fields.map(o=>{let r=[o.required?"required":"",o.unique?"unique":""].filter(Boolean).join(", ");return `| ${o.name} | ${o.type} | ${r||"-"} | ${o.description} |`}).join(`
|
|
801
|
+
`)}`:""}function Yi(t){let e=`## Data Models
|
|
802
|
+
|
|
803
|
+
**Database:** ${t.type}
|
|
804
|
+
**Reasoning:** ${t.reasoning}
|
|
805
|
+
`,o=t.entities.map(r=>{let n=Bi(r),a=r.relations.map(c=>c.field+" \u2192 "+c.references+" ("+c.description+")"),s=a.length?`
|
|
806
|
+
**Relations:** `+a.join("; "):"",i=r.indexes.map(c=>c.name+" ["+c.fields.join(", ")+"]"+(c.unique?" (unique)":"")),l=i.length?`
|
|
807
|
+
**Indexes:** `+i.join("; "):"";return `### ${r.name}
|
|
808
|
+
|
|
809
|
+
${r.description}
|
|
810
|
+
|
|
811
|
+
${n}${s}${l}`}).join(`
|
|
812
|
+
|
|
813
|
+
`);return `${e}
|
|
814
|
+
${o}`}function zi(t){return `## Feature Decisions
|
|
815
|
+
|
|
816
|
+
${t.map(o=>{let r=o.apis.map(n=>` - \`${n.operation}\` ${n.name}: ${n.description}`).join(`
|
|
817
|
+
`);return `### ${o.name}
|
|
818
|
+
|
|
819
|
+
${o.description} (entity: ${o.entity})
|
|
820
|
+
|
|
821
|
+
**APIs:**
|
|
822
|
+
${r}`}).join(`
|
|
823
|
+
|
|
824
|
+
`)}`}function $i(t){let e=t.project,o=e.features.map(r=>`- ${r}`).join(`
|
|
825
|
+
`);return `# ${e.name}
|
|
826
|
+
|
|
827
|
+
**Goal:** ${e.goal}
|
|
828
|
+
**Domain:** ${e.domain}
|
|
829
|
+
|
|
830
|
+
${t.summary.overview}
|
|
831
|
+
|
|
832
|
+
**Key Features:**
|
|
833
|
+
${o}`}function Hi(t){let e=t.project;return ["## Tech Stack","",`- **Database:** ${e.database}`,`- **Backend Runtime:** ${e.backendRuntime}`,`- **API Style:** ${e.apiStyle}`].join(`
|
|
834
|
+
`)}function Qi(t,e,o){let r=["## Actors and Flows"];for(let n of t){r.push(`
|
|
835
|
+
### ${n.name}
|
|
836
|
+
${n.description}`);let a=e.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(`
|
|
837
|
+
### 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(`
|
|
838
|
+
`)}function Rs(t){let e={overview:`## Overview
|
|
839
|
+
|
|
840
|
+
${t.summary.overview}`,techStack:Hi(t),featureDecisions:zi(t.modules),dataModels:Yi(t.database),pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null};return {stage:"design",projectDescription:$i(t)+`
|
|
841
|
+
|
|
842
|
+
`+Qi(t.actors,t.flows,t.stories),sections:e,history:[],pendingQuestions:[]}}var Vi=8;async function Wi(t){let{requirement:e,model:o,onStep:r,logger:n}=t;n?.info("Starting planning from requirements (fast path)",{project:e.project.name});let a=Rs(e),s=`Generate the implementation plan for "${e.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 he(s,a,{model:o,logger:n}),l=1;for(;!i.planMarkdown&&l<Vi;)n?.debug("Planning from requirements turn",{turn:l}),i=await he("continue - produce the complete implementation plan.",i.context,{model:o,logger:n}),l++;let c=i.planMarkdown??i.message,p=i.context.history.map(d=>({role:d.role,content:d.content}));return n?.info("Planning from requirements completed",{turns:l,hasPlanMarkdown:!!i.planMarkdown}),{output:c,steps:[],totalUsage:void 0,messages:p}}var Ki="discovery",ws={overview:null,techStack:null,featureDecisions:null,dataModels:null,pagesAndRoutes:null,authFlow:null,apiRoutes:null,implementation:null,executionPlan:null,edgeCases:null,testingChecklist:null},Ut=class{data={};withStage(e){return this.data.stage=e,this}withProjectDescription(e){return this.data.projectDescription=e,this}withSections(e){return this.data.sections={...this.data.sections??ws,...e},this}withHistory(e){return this.data.history=e,this}withPendingQuestions(e){return this.data.pendingQuestions=e,this}reset(){return this.data={},this}build(){return {stage:this.data.stage??Ki,projectDescription:this.data.projectDescription??null,sections:this.data.sections??{...ws},history:this.data.history??[],pendingQuestions:this.data.pendingQuestions??[]}}};function Xi(){return new Ut}var Er=zod.z.object({name:zod.z.string(),type:zod.z.string(),required:zod.z.coerce.boolean().default(false),unique:zod.z.coerce.boolean().default(false),description:zod.z.string().default(""),default:zod.z.string().optional()}),vs=zod.z.object({name:zod.z.string().default(""),fields:zod.z.array(zod.z.string()).default([]),unique:zod.z.coerce.boolean().default(false)}),Zi=zod.z.string().transform(t=>{let e=t.toLowerCase().replace(/[\s_-]+/g,"");return ["1:1","onetoone"].includes(e)?"1:1":["1:n","1:m","n:1","onetomany","manytoone"].includes(e)?"1:N":["m:n","n:m","manytomany"].includes(e)?"M:N":t}).pipe(zod.z.enum(["1:1","1:N","M:N"])),Es=zod.z.object({field:zod.z.string(),references:zod.z.string(),type:Zi,description:zod.z.string().default("")}),Ar=zod.z.object({name:zod.z.string(),description:zod.z.string().default(""),fields:zod.z.union([zod.z.array(Er),zod.z.record(zod.z.string(),zod.z.unknown())]).transform((t,e)=>{if(Array.isArray(t))return t;let o=[];for(let[r,n]of Object.entries(t)){let a=typeof n=="object"&&n!==null?{...n}:{};a.name||(a.name=r);let s=Er.safeParse(a);if(s.success)o.push(s.data);else for(let i of s.error.issues)e.addIssue({...i,path:[r,...i.path]});}return o}),indexes:zod.z.array(vs).default([]),relations:zod.z.array(Es).default([])}),el=zod.z.string().transform(t=>t.toLowerCase().trim()).pipe(zod.z.enum(["mongodb","postgresql"])),te=zod.z.object({type:el,reasoning:zod.z.string().default(""),entities:zod.z.array(Ar).default([])});var _e=zod.z.object({fieldName:zod.z.string().describe("fieldName must be in camelCase"),fieldType:zod.z.string().default("string").transform(t=>{let e=t.toLowerCase().trim();return ["string","text","varchar"].includes(e)?"string":["number","int","integer","float","double","decimal"].includes(e)?"number":["boolean","bool"].includes(e)?"boolean":["types.objectid","objectid","ref","reference"].includes(e)?"Types.ObjectId":["date","datetime","timestamp"].includes(e)?"Date":["object","json","mixed"].includes(e)?"object":["email"].includes(e)?"email":["password","hash"].includes(e)?"password":["enum","select"].includes(e)?"enum":("string")}).pipe(zod.z.enum(["string","number","boolean","Types.ObjectId","Date","object","email","password","enum"])),isArray:zod.z.coerce.boolean().default(false),isRequired:zod.z.coerce.boolean().default(true),isUnique:zod.z.coerce.boolean().default(false),values:zod.z.array(zod.z.string()).default([]).describe("Enum values if fieldType is enum, else empty array"),defaultVal:zod.z.union([zod.z.string(),zod.z.boolean(),zod.z.number(),zod.z.null()]).optional(),relationTo:zod.z.string().optional().describe("Module name for relations"),relationType:zod.z.string().transform(t=>{let e=t.toLowerCase().replace(/[\s_]+/g,"-");return ["one-to-one","1:1","1-to-1"].includes(e)?"one-to-one":["many-to-one","n:1","n-to-1","many-to-1","*:1"].includes(e)?"many-to-one":""}).pipe(zod.z.enum(["one-to-one","many-to-one",""])).optional(),isPrivate:zod.z.coerce.boolean().default(false).describe("True if password field, else false")});var Ie=zod.z.object({moduleName:zod.z.string().describe("camelCase, single word, never auth/authentication"),isUserModule:zod.z.coerce.boolean().default(false),authMethod:zod.z.string().transform(t=>{let e=t.toUpperCase().replace(/[\s-]+/g,"_");return ["EMAIL_AND_PASSWORD","EMAIL_PASSWORD","EMAIL"].includes(e)?"EMAIL_AND_PASSWORD":["PHONE_AND_OTP","PHONE_OTP","PHONE","SMS"].includes(e)?"PHONE_AND_OTP":""}).pipe(zod.z.enum(["EMAIL_AND_PASSWORD","PHONE_AND_OTP",""])).optional(),emailField:zod.z.string().optional(),passwordField:zod.z.string().optional(),phoneField:zod.z.string().optional(),roleField:zod.z.string().optional(),permissions:zod.z.record(zod.z.string(),zod.z.array(zod.z.enum(["CREATE","READ","UPDATE","DELETE"]))).optional().describe("Permissions per role"),fields:zod.z.union([zod.z.array(_e),zod.z.record(zod.z.string(),zod.z.unknown())]).transform((t,e)=>{if(Array.isArray(t))return t;let o=[];for(let[r,n]of Object.entries(t)){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)e.addIssue({...i,path:[r,...i.path]});}return o})});var W=zod.z.object({projectName:zod.z.string().default("project").describe("projectName must be in kebab-case"),projectDescription:zod.z.string().default(""),modules:zod.z.union([zod.z.array(Ie),zod.z.record(zod.z.string(),zod.z.unknown())]).transform((t,e)=>{if(Array.isArray(t))return t;let o=[];for(let[r,n]of Object.entries(t)){let a=typeof n=="object"&&n!==null?{...n}:{};a.moduleName||(a.moduleName=r);let s=Ie.safeParse(a);if(s.success)o.push(s.data);else for(let i of s.error.issues)e.addIssue({...i,path:[r,...i.path]});}return o}),author:zod.z.string().default("sijeeshmiziha")});var Lt=`You are a senior database architect specializing in both MongoDB and PostgreSQL schema design.
|
|
843
|
+
|
|
844
|
+
You analyze requirements and produce enterprise-quality data models with:
|
|
845
|
+
- Properly typed fields (MongoDB: ObjectId, string, number, date, array; PostgreSQL: uuid, varchar, text, integer, timestamp, jsonb)
|
|
846
|
+
- Indexes optimized for query patterns
|
|
847
|
+
- Relationships with correct cardinality (1:1, 1:N, M:N)
|
|
848
|
+
- Validation constraints and default values
|
|
849
|
+
- Security considerations (hashed passwords, encrypted fields)
|
|
850
|
+
|
|
851
|
+
Output only valid JSON unless instructed otherwise.`;var As=`## Requirements:
|
|
852
|
+
{requirement}
|
|
853
|
+
|
|
854
|
+
Design the database schema. Determine the best database type (mongodb or postgresql) based on the requirements, or use the one specified.
|
|
855
|
+
|
|
856
|
+
For MongoDB use types: ObjectId, string, number, boolean, date, array, mixed.
|
|
857
|
+
For PostgreSQL use types: uuid, varchar(n), text, integer, bigint, boolean, timestamp, jsonb, and proper foreign key relations.
|
|
858
|
+
|
|
859
|
+
Return ONLY valid JSON:
|
|
860
|
+
{
|
|
861
|
+
"type": "mongodb" | "postgresql",
|
|
862
|
+
"reasoning": "2-4 sentences explaining the choice and design approach",
|
|
863
|
+
"entities": [
|
|
864
|
+
{
|
|
865
|
+
"name": "EntityName",
|
|
866
|
+
"description": "Brief description",
|
|
867
|
+
"fields": [
|
|
868
|
+
{ "name": "fieldName", "type": "DB-native type", "required": true, "unique": false, "description": "..." }
|
|
869
|
+
],
|
|
870
|
+
"indexes": [ { "name": "idx_name", "fields": ["field1"], "unique": false } ],
|
|
871
|
+
"relations": [ { "field": "refField", "references": "OtherEntity", "type": "1:N", "description": "..." } ]
|
|
872
|
+
}
|
|
873
|
+
]
|
|
874
|
+
}`,Ms=`## Current Schema (JSON):
|
|
875
|
+
{existingSchema}
|
|
876
|
+
|
|
877
|
+
## Feedback:
|
|
878
|
+
{feedback}
|
|
879
|
+
|
|
880
|
+
Update the schema based on the feedback. Return the complete updated schema as valid JSON in the same format.`;function Mr(t){return As.replace("{requirement}",t)}function Or(t,e){return Ms.replace("{existingSchema}",t).replace("{feedback}",e)}var Os=`## Project: {projectName}
|
|
881
|
+
## Goal: {projectGoal}
|
|
882
|
+
## Database: {databaseType}
|
|
883
|
+
|
|
884
|
+
## Context:
|
|
885
|
+
{context}
|
|
886
|
+
|
|
887
|
+
Apply the 5-phase enterprise data modeling process:
|
|
888
|
+
|
|
889
|
+
### Phase 1: Entity Discovery
|
|
890
|
+
- Extract every entity from the context (user types, domain objects, settings, logs).
|
|
891
|
+
- Identify status enums from flow transitions.
|
|
892
|
+
|
|
893
|
+
### Phase 2: Relationship Mapping
|
|
894
|
+
- For each entity pair, determine ownership and cardinality (1:1, 1:N, M:N).
|
|
895
|
+
- Note bidirectional references and join tables (PostgreSQL) or embedded arrays (MongoDB).
|
|
896
|
+
|
|
897
|
+
### Phase 3: Permission Derivation
|
|
898
|
+
- Map actor types to role names.
|
|
899
|
+
- From actions, derive which role can CRUD which entity.
|
|
900
|
+
|
|
901
|
+
### Phase 4: Schema Generation
|
|
902
|
+
- Generate fields with DB-native types, required/unique flags, defaults.
|
|
903
|
+
- Add indexes for common queries (user lookups, date ranges, foreign keys).
|
|
904
|
+
- Include timestamps (createdAt, updatedAt) on all entities.
|
|
905
|
+
|
|
906
|
+
### Phase 5: Validation
|
|
907
|
+
- Verify every entity referenced in relations exists.
|
|
908
|
+
- Verify no orphan fields or missing indexes.
|
|
909
|
+
|
|
910
|
+
Return ONLY valid JSON in the DataModelDesign format.`;function Cr(t,e,o,r){return Os.replace("{projectName}",t).replace("{projectGoal}",e).replace("{databaseType}",o).replace("{context}",r)}var K=`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.
|
|
911
|
+
|
|
912
|
+
## ANALYSIS FRAMEWORK
|
|
913
|
+
|
|
914
|
+
You MUST follow this 5-phase analysis process before generating the schema:
|
|
915
|
+
|
|
916
|
+
### PHASE 1: Entity Discovery
|
|
917
|
+
Systematically extract all entities from the provided requirements:
|
|
918
|
+
|
|
919
|
+
1. **From dataInvolved fields**: Every item in user stories' dataInvolved[] array indicates a potential entity or field
|
|
920
|
+
2. **From User Types (Actors)**: Each actor type may indicate a User variant or role
|
|
921
|
+
3. **From User Flow Actions**: Action verbs reveal implicit entities
|
|
922
|
+
4. **From Flow States**: Transitions reveal status enums
|
|
923
|
+
|
|
924
|
+
### PHASE 2: Relationship Mapping
|
|
925
|
+
For each entity pair, determine relationships based on:
|
|
926
|
+
|
|
927
|
+
1. **Ownership Patterns** (from actor actions)
|
|
928
|
+
2. **Cardinality from Flow Context** (one-to-one, many-to-one)
|
|
929
|
+
3. **Shared Entities** (referenced across flows)
|
|
930
|
+
4. **Bidirectional References** (for one-to-one)
|
|
931
|
+
|
|
932
|
+
### PHASE 3: Permission Derivation
|
|
933
|
+
Map actors to RBAC permissions:
|
|
934
|
+
|
|
935
|
+
1. **Role Extraction**: Each actor type becomes a role value
|
|
936
|
+
2. **Permission Mining from User Stories**: Map actions to CRUD per role
|
|
937
|
+
3. **Data Visibility Rules**: "view own" vs "view all" vs "manage"
|
|
938
|
+
|
|
939
|
+
### PHASE 4: Query Pattern Inference
|
|
940
|
+
Analyze flows to predict database access patterns:
|
|
941
|
+
|
|
942
|
+
1. **Read Patterns** (suggest indexes)
|
|
943
|
+
2. **Write Patterns** (affect schema design)
|
|
944
|
+
3. **Aggregation Needs** (from reporting flows)
|
|
945
|
+
|
|
946
|
+
### PHASE 5: Schema Construction
|
|
947
|
+
Synthesize all analyses into the final schema:
|
|
948
|
+
|
|
949
|
+
1. **Module Definition**: One module per core entity, camelCase names
|
|
950
|
+
2. **Field Completeness**: All fields from dataInvolved, relationships, status enums, timestamps
|
|
951
|
+
3. **Validation Constraints**: isRequired, isUnique, enum values
|
|
952
|
+
4. **Security Fields**: password fields with isPrivate: true
|
|
953
|
+
|
|
954
|
+
## CORE CONSTRAINTS (MUST FOLLOW)
|
|
955
|
+
|
|
956
|
+
1. **Primary Key**: _id with Types.ObjectId (auto-generated, do not include in fields)
|
|
957
|
+
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
|
|
958
|
+
3. **Data Types**: NO arrays of ObjectIds; Timestamps: createdAt, updatedAt in EVERY collection; Enums: fieldType: 'enum' with values array
|
|
959
|
+
4. **Security**: NO separate "Auth" collection; NO token storage; Password fields: isPrivate: true
|
|
960
|
+
5. **Authorization (RBAC)**: Define permissions per role on user modules`;function Nr(t){return !t||t.length===0?'No specific user types defined. Assume a general "User" role.':t.map((e,o)=>{let r=e.goals.filter(n=>n.trim()).join(`
|
|
961
|
+
- `);return `### ${o+1}. ${e.name}
|
|
962
|
+
**Description:** ${e.description}
|
|
963
|
+
**Goals:**
|
|
964
|
+
- ${r||"No specific goals defined"}`}).join(`
|
|
965
|
+
|
|
966
|
+
`)}function Dr(t,e){return !t||t.length===0?"No specific user flows defined.":t.map((o,r)=>{let n=e.find(a=>a.id===o.actorId);return `### ${r+1}. ${o.name}
|
|
967
|
+
**Actor:** ${n?.name||"User"}
|
|
968
|
+
**Description:** ${o.description}
|
|
969
|
+
**Trigger:** ${o.trigger||"User initiates action"}
|
|
970
|
+
**Outcome:** ${o.outcome||"Action completed"}`}).join(`
|
|
971
|
+
|
|
972
|
+
`)}function kr(t,e){if(!t||t.length===0)return "No specific user stories defined.";let o=new Map;for(let a of t){let s=o.get(a.flowId)||[];s.push(a),o.set(a.flowId,s);}let r=[];for(let a of e){let s=o.get(a.id)||[];if(s.length!==0){r.push(`### Flow: ${a.name}
|
|
973
|
+
`);for(let i of s){let l=i.preconditions.filter(u=>u.trim()),c=i.postconditions.filter(u=>u.trim()),p=i.dataInvolved.filter(u=>u.trim()),d=`**As a** ${i.actor}, **I want to** ${i.action}, **so that** ${i.benefit}
|
|
974
|
+
`;l.length&&(d+=`
|
|
975
|
+
**Preconditions:**
|
|
976
|
+
${l.map(u=>`- ${u}`).join(`
|
|
977
|
+
`)}
|
|
978
|
+
`),c.length&&(d+=`
|
|
979
|
+
**Postconditions:**
|
|
980
|
+
${c.map(u=>`- ${u}`).join(`
|
|
981
|
+
`)}
|
|
982
|
+
`),p.length&&(d+=`
|
|
983
|
+
**Data Involved (IMPORTANT):**
|
|
984
|
+
${p.map(u=>`- ${u}`).join(`
|
|
985
|
+
`)}
|
|
986
|
+
`),r.push(d);}}}let n=t.filter(a=>!e.some(s=>s.id===a.flowId));if(n.length){r.push(`### Other Stories
|
|
987
|
+
`);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}
|
|
988
|
+
`;s.length&&(i+=`
|
|
989
|
+
**Data Involved:** ${s.join(", ")}
|
|
990
|
+
`),r.push(i);}}return r.join(`
|
|
991
|
+
`)}function _r(t){if(!t)return "No specific technical requirements. Use defaults.";let e=[`**Authentication:** ${t.authentication||"none"}`];return t.authorization?(e.push("**Authorization (RBAC):** Enabled"),t.roles?.length&&e.push(`**Defined Roles:** ${t.roles.join(", ")}`)):e.push("**Authorization:** Disabled"),t.realtime&&e.push("**Realtime Features:** Required"),t.fileUpload&&e.push("**File Upload:** Required"),t.search&&e.push("**Search Functionality:** Required"),t.integrations?.length&&e.push(`**Integrations:** ${t.integrations.join(", ")}`),e.join(`
|
|
992
|
+
`)}function Gt(t){let e=new Set;for(let o of t)for(let r of o.dataInvolved)r.trim()&&e.add(r.trim());return Array.from(e)}function Jt(t){return t.map(e=>e.name.toLowerCase().replaceAll(/\s+/g,"_"))}function Bt(t){return {projectName:t.projectName,projectGoal:t.projectGoal,projectDescription:t.projectDescription||t.projectGoal,userTypes:Nr(t.actors),userFlows:Dr(t.flows,t.actors),userStories:kr(t.stories,t.flows),technicalRequirements:_r(t.technicalRequirements)}}function Je(t){return `${K}
|
|
993
|
+
|
|
994
|
+
Design a robust and efficient MongoDB database schema based on the following requirements:
|
|
995
|
+
|
|
996
|
+
## Requirements
|
|
997
|
+
${t}
|
|
998
|
+
|
|
999
|
+
## Guidelines
|
|
1000
|
+
1. Use camelCase for module names and field names
|
|
1001
|
+
2. Include createdAt and updatedAt Date fields in every module
|
|
1002
|
+
3. Define proper relationships between modules
|
|
1003
|
+
4. Set appropriate permissions for user modules
|
|
1004
|
+
|
|
1005
|
+
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function Be(t){let e=Bt(t);return `${K}
|
|
1006
|
+
|
|
1007
|
+
---
|
|
1008
|
+
|
|
1009
|
+
## PROJECT CONTEXT
|
|
1010
|
+
|
|
1011
|
+
**Project Name:** ${e.projectName}
|
|
1012
|
+
**Project Goal:** ${e.projectGoal}
|
|
1013
|
+
**Description:** ${e.projectDescription}
|
|
1014
|
+
|
|
1015
|
+
---
|
|
1016
|
+
|
|
1017
|
+
## USER TYPES (ACTORS)
|
|
1018
|
+
|
|
1019
|
+
${e.userTypes}
|
|
1020
|
+
|
|
1021
|
+
---
|
|
1022
|
+
|
|
1023
|
+
## USER FLOWS
|
|
1024
|
+
|
|
1025
|
+
${e.userFlows}
|
|
1026
|
+
|
|
1027
|
+
---
|
|
1028
|
+
|
|
1029
|
+
## USER STORIES WITH DATA REQUIREMENTS
|
|
1030
|
+
|
|
1031
|
+
${e.userStories}
|
|
1032
|
+
|
|
1033
|
+
---
|
|
1034
|
+
|
|
1035
|
+
## TECHNICAL REQUIREMENTS
|
|
1036
|
+
|
|
1037
|
+
${e.technicalRequirements}
|
|
1038
|
+
|
|
1039
|
+
---
|
|
1040
|
+
|
|
1041
|
+
## YOUR TASK
|
|
1042
|
+
|
|
1043
|
+
Follow the 5-phase analysis framework:
|
|
1044
|
+
|
|
1045
|
+
### Step 1: Entity Discovery
|
|
1046
|
+
- List ALL entities extracted from dataInvolved fields
|
|
1047
|
+
- Identify implicit entities from user flow actions
|
|
1048
|
+
- Map user types to User collection roles
|
|
1049
|
+
- Extract status enums from flow transitions
|
|
1050
|
+
|
|
1051
|
+
### Step 2: Relationship Mapping
|
|
1052
|
+
- Define ownership: which actor creates/owns each entity
|
|
1053
|
+
- Determine cardinality from flow context
|
|
1054
|
+
|
|
1055
|
+
### Step 3: Permission Derivation
|
|
1056
|
+
- Map each actor to a role
|
|
1057
|
+
- Extract CRUD permissions from user story actions
|
|
1058
|
+
|
|
1059
|
+
### Step 4: Query Pattern Inference
|
|
1060
|
+
- Identify likely query patterns from flows
|
|
1061
|
+
|
|
1062
|
+
### Step 5: Schema Construction
|
|
1063
|
+
Generate the final schema with complete module definitions, fields, relationships, RBAC permissions, and timestamps.
|
|
1064
|
+
|
|
1065
|
+
Return ONLY valid JSON matching the schema specified. No markdown code blocks, no explanations.`}function Ye(t,e){return `${K}
|
|
1066
|
+
|
|
1067
|
+
Update the existing MongoDB schema based on user feedback.
|
|
1068
|
+
|
|
1069
|
+
## Steps
|
|
1070
|
+
1. Analyze the existing MongoDB schema provided
|
|
1071
|
+
2. Review the user feedback to understand the required updates
|
|
1072
|
+
3. Update the schema to incorporate the requested changes while adhering to best practices
|
|
1073
|
+
|
|
1074
|
+
## Existing Schema
|
|
1075
|
+
${t}
|
|
1076
|
+
|
|
1077
|
+
## User Feedback
|
|
1078
|
+
${e}
|
|
1079
|
+
|
|
1080
|
+
Return the updated schema as a valid JSON object matching the original schema format.
|
|
1081
|
+
IMPORTANT: Return ONLY the JSON object, no markdown code blocks, no explanations.`}var Yt=q("validate_data_model",te,"Validates a data model JSON string against the DataModelDesign schema. Returns valid: true or valid: false with errors.","schema");function zt(t){return h({name:"design_schema",description:"Generate a database schema (MongoDB or PostgreSQL) from plain text requirements. Returns the full data model as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Plain text description of the data modeling requirements")}),handler:async({requirement:e})=>{let o=Mr(e),r=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:8192});return M(n.text,te)}})}function $t(t){return h({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:zod.z.object({projectName:zod.z.string().describe("Project name"),projectGoal:zod.z.string().describe("Project goal / purpose"),databaseType:zod.z.enum(["mongodb","postgresql"]).describe("Target database type"),context:zod.z.string().describe("Full project context: features, actors, flows, stories")}),handler:async({projectName:e,projectGoal:o,databaseType:r,context:n})=>{let a=Cr(e,o,r,n),s=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:a}],i=await t.invoke(s,{temperature:.2,maxOutputTokens:16384});return M(i.text,te)}})}function Ht(t){return h({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:zod.z.object({existingSchema:zod.z.string().describe("Current data model schema as JSON string"),feedback:zod.z.string().describe("Feedback describing desired changes")}),handler:async({existingSchema:e,feedback:o})=>{let r=Or(e,o),n=[{role:"system",content:"You are a database schema expert. Return only valid JSON."},{role:"user",content:r}],a=await t.invoke(n,{temperature:.3,maxOutputTokens:8192});return M(a.text,te)}})}var Qt=q("validate_schema",W,"Validates a MongoDB project schema JSON string against the expected schema. Returns valid: true or valid: false with errors.","schema");function Vt(t){return h({name:"design_database",description:"Generate a MongoDB database schema from plain text requirements. Returns the full project schema as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Plain text description of the database requirements")}),handler:async({requirement:e})=>{let o=Je(e),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:8192});return M(n.text,W)}})}var tl=zod.z.object({projectName:zod.z.string(),projectGoal:zod.z.string(),projectDescription:zod.z.string().optional(),actors:zod.z.array(zod.z.object({id:zod.z.string(),name:zod.z.string(),description:zod.z.string(),goals:zod.z.array(zod.z.string())})),flows:zod.z.array(zod.z.object({id:zod.z.string(),actorId:zod.z.string(),name:zod.z.string(),description:zod.z.string(),trigger:zod.z.string(),outcome:zod.z.string()})),stories:zod.z.array(zod.z.object({id:zod.z.string(),flowId:zod.z.string(),actor:zod.z.string(),action:zod.z.string(),benefit:zod.z.string(),preconditions:zod.z.array(zod.z.string()),postconditions:zod.z.array(zod.z.string()),dataInvolved:zod.z.array(zod.z.string())})),technicalRequirements:zod.z.object({authentication:zod.z.string().transform(t=>{let e=t.toLowerCase().replace(/[\s_-]+/g,"");return ["none","no",""].includes(e)?"none":["email","emailpassword","emailandpassword"].includes(e)?"email":["oauth","oauth2","social"].includes(e)?"oauth":["phone","phoneotp","sms"].includes(e)?"phone":["emailandphone","emailphone","both"].includes(e)?"email_and_phone":"email"}).pipe(zod.z.enum(["none","email","oauth","phone","email_and_phone"])),authorization:zod.z.coerce.boolean().default(false),roles:zod.z.array(zod.z.string()).optional(),integrations:zod.z.array(zod.z.string()).optional(),realtime:zod.z.boolean().optional(),fileUpload:zod.z.boolean().optional(),search:zod.z.boolean().optional()}).optional()});function Wt(t){return h({name:"design_database_pro",description:"Generate a MongoDB schema from structured requirements (actors, flows, stories, technical requirements). Returns dbDesign and metadata.",input:tl,handler:async e=>{let o=Be(e),r=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.2,maxOutputTokens:16384}),a=M(n.text,W),s={entitiesDetected:Gt(e.stories),rolesExtracted:Jt(e.actors)};return {dbDesign:a,metadata:s}}})}function Kt(t){return h({name:"redesign_database",description:"Update an existing MongoDB project schema based on user feedback. Provide the current schema JSON string and the feedback.",input:zod.z.object({existingSchema:zod.z.string().describe("Current project schema as JSON string"),feedback:zod.z.string().describe("User feedback describing desired changes")}),handler:async({existingSchema:e,feedback:o})=>{let r=Ye(e,o),n=[{role:"system",content:"You are a MongoDB schema expert. Return only valid JSON."},{role:"user",content:r}],a=await t.invoke(n,{temperature:.3,maxOutputTokens:8192});return M(a.text,W)}})}function qr(t){return {validate_data_model:Yt,design_schema:zt(t),design_schema_pro:$t(t),refine_schema:Ht(t)}}function Fr(t){return {validate_schema:Qt,design_database:Vt(t),design_database_pro:Wt(t),redesign_database:Kt(t)}}var ol=`${Lt}
|
|
1082
|
+
|
|
1083
|
+
You are the data modeling orchestrator. When the user asks for a data model:
|
|
1084
|
+
|
|
1085
|
+
1. **Analyze first**: Use subagent_entity-analyzer to extract entities, fields, and relationships from the requirements.
|
|
1086
|
+
2. **Map relationships**: Use subagent_relationship-mapper with the entity analysis to determine cardinality, foreign keys, and indexes.
|
|
1087
|
+
3. **Generate schema**: Use design_schema (plain text) or design_schema_pro (when structured context is available) to produce the data model.
|
|
1088
|
+
4. **Refine (optional)**: Use subagent_schema-refiner to validate and suggest improvements to the generated schema.
|
|
1089
|
+
5. **Validate**: Use validate_data_model to check the final schema JSON before returning.
|
|
1090
|
+
|
|
1091
|
+
Respond with the final data model schema as JSON.`;async function rl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=qr(s),l=fe(),c=I([ne,kt,l],{parentModel:s}),p={...i,...c};return C({model:s,tools:p,systemPrompt:ol,input:e,maxIterations:r,onStep:n,logger:a})}var nl=`${K}
|
|
1092
|
+
|
|
1093
|
+
You are the MongoDB database design orchestrator. When the user asks for a database design:
|
|
1094
|
+
|
|
1095
|
+
1. **Analyze first**: Use subagent_entity-analyzer to extract entities, relationships, and roles.
|
|
1096
|
+
2. **Generate schema**: Use design_database (plain text) or design_database_pro (structured requirements) to produce the MongoDB schema.
|
|
1097
|
+
3. **Refine (optional)**: Use subagent_schema-refiner to validate and suggest improvements.
|
|
1098
|
+
4. **Validate**: Use validate_schema to check the final schema JSON.
|
|
1099
|
+
5. **Redesign**: If changes are requested, use redesign_database with existing schema and feedback.
|
|
1100
|
+
|
|
1101
|
+
Respond with the final schema as JSON.`;async function sl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=Fr(s),l=fe(),c=I([ne,l],{parentModel:s}),p={...i,...c};return C({model:s,tools:p,systemPrompt:nl,input:e,maxIterations:r,onStep:n,logger:a})}var al=zod.z.union([zod.z.enum(["GET","POST","PUT","PATCH","DELETE"]),zod.z.string()]).transform(t=>typeof t=="string"?t.toUpperCase():t).pipe(zod.z.enum(["GET","POST","PUT","PATCH","DELETE"])),Ur=zod.z.record(zod.z.string(),zod.z.unknown()).optional().default({}).transform(t=>Object.fromEntries(Object.entries(t??{}).map(([e,o])=>[e,typeof o=="string"?o:String(o)]))),Ds=zod.z.array(zod.z.unknown()).default([]).transform(t=>t.map(e=>typeof e=="string"?e:JSON.stringify(e))),Lr=zod.z.object({id:zod.z.string(),resource:zod.z.string(),method:al,path:zod.z.string(),description:zod.z.string(),auth:zod.z.coerce.boolean(),roles:zod.z.array(zod.z.string()).default([]),requestBody:Ur,responseBody:Ur,queryParams:Ur,validation:Ds,errorResponses:Ds}),Gr=zod.z.object({name:zod.z.string(),type:zod.z.enum(["query","mutation","subscription"]),description:zod.z.string(),auth:zod.z.coerce.boolean(),roles:zod.z.array(zod.z.string()).default([]),args:zod.z.array(zod.z.object({name:zod.z.string(),type:zod.z.string(),required:zod.z.coerce.boolean()})),returnType:zod.z.string()}),il=zod.z.unknown().transform(t=>(typeof t=="string"?t.toLowerCase().trim():"rest").includes("graphql")?"graphql":"rest"),ce=zod.z.object({style:il,baseUrl:zod.z.string().default("/api/v1"),endpoints:zod.z.array(Lr).default([]),graphqlOperations:zod.z.array(Gr).default([])});var Xt=`You are a senior API architect specializing in REST and GraphQL API design.
|
|
1102
|
+
|
|
1103
|
+
You analyze data models and requirements to produce enterprise-quality API designs with:
|
|
1104
|
+
- RESTful endpoints grouped by resource with proper HTTP methods
|
|
1105
|
+
- Request/response contracts with field types and validation rules
|
|
1106
|
+
- Error responses with appropriate HTTP status codes (400, 401, 403, 404, 500)
|
|
1107
|
+
- Pagination, filtering, and sorting patterns
|
|
1108
|
+
- Authentication and authorization annotations per endpoint
|
|
1109
|
+
- GraphQL types, queries, mutations, and subscriptions when applicable
|
|
1110
|
+
|
|
1111
|
+
Output only valid JSON unless instructed otherwise.`;var ks=`## Requirements:
|
|
1112
|
+
{requirement}
|
|
1113
|
+
|
|
1114
|
+
Design the API. Determine the best API style (rest or graphql) based on the requirements, or use the one specified.
|
|
1115
|
+
|
|
1116
|
+
For REST: group endpoints by resource. Each endpoint needs method, path, description, auth flag, roles, requestBody, responseBody, queryParams, validation rules, and error responses.
|
|
1117
|
+
For GraphQL: define operations (queries, mutations, subscriptions) with args and return types.
|
|
1118
|
+
|
|
1119
|
+
Return ONLY valid JSON:
|
|
1120
|
+
{
|
|
1121
|
+
"style": "rest" | "graphql",
|
|
1122
|
+
"baseUrl": "/api/v1",
|
|
1123
|
+
"endpoints": [
|
|
1124
|
+
{ "id": "ep-1", "resource": "users", "method": "POST", "path": "/api/v1/users", "description": "Create user", "auth": false, "roles": [], "requestBody": {}, "responseBody": {}, "queryParams": {}, "validation": [], "errorResponses": [] }
|
|
1125
|
+
],
|
|
1126
|
+
"graphqlOperations": []
|
|
1127
|
+
}`,_s=`## Project: {projectName}
|
|
1128
|
+
## API Style: {apiStyle}
|
|
1129
|
+
## Data Model:
|
|
1130
|
+
{dataModel}
|
|
1131
|
+
## Requirements:
|
|
1132
|
+
{context}
|
|
1133
|
+
|
|
1134
|
+
Design a comprehensive API surface from the data model and requirements. For each entity in the data model, generate CRUD endpoints plus any custom operations implied by the requirements.
|
|
1135
|
+
|
|
1136
|
+
Include per-endpoint: validation rules (required fields, formats, lengths), error responses (400 validation, 401 unauthenticated, 403 forbidden, 404 not found, 500 server error), and auth/role annotations.
|
|
1137
|
+
|
|
1138
|
+
Return ONLY valid JSON in the ApiDesign format.`;function Jr(t){return ks.replace("{requirement}",t)}function Br(t,e,o,r){return _s.replace("{projectName}",t).replace("{apiStyle}",e).replace("{dataModel}",o).replace("{context}",r)}var Zt=q("validate_api",ce,"Validates an API design JSON string against the ApiDesign schema. Returns valid: true or valid: false with errors.","design");function eo(t){return h({name:"design_api",description:"Generate an API design (REST or GraphQL) from plain text requirements. Returns the full API design as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Plain text description of the API requirements")}),handler:async({requirement:e})=>{let o=Jr(e),r=[{role:"system",content:"You are an API architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:8192});return M(n.text,ce)}})}function to(t){return h({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:zod.z.object({projectName:zod.z.string().describe("Project name"),apiStyle:zod.z.enum(["rest","graphql"]).describe("Target API style"),dataModel:zod.z.string().describe("Data model JSON or description"),context:zod.z.string().describe("Project context: features, actors, stories")}),handler:async({projectName:e,apiStyle:o,dataModel:r,context:n})=>{let a=Br(e,o,r,n),s=[{role:"system",content:"You are an API architect. Return only valid JSON."},{role:"user",content:a}],i=await t.invoke(s,{temperature:.2,maxOutputTokens:16384});return M(i.text,ce)}})}function Yr(t){return {validate_api:Zt,design_api:eo(t),design_api_pro:to(t)}}var ll=`${Xt}
|
|
1139
|
+
|
|
1140
|
+
You are the API design orchestrator. When the user asks for an API design:
|
|
1141
|
+
|
|
1142
|
+
1. **Analyze endpoints**: Use subagent_endpoint-analyzer to derive endpoints from the data model and requirements.
|
|
1143
|
+
2. **Design contracts**: Use subagent_contract-designer to design request/response contracts, validation rules, and error responses.
|
|
1144
|
+
3. **Generate design**: Use design_api (plain text) or design_api_pro (when data model and structured context are available) to produce the API design.
|
|
1145
|
+
4. **Validate**: Use validate_api to check the final API design JSON before returning.
|
|
1146
|
+
|
|
1147
|
+
Respond with the final API design as JSON.`;async function cl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=Yr(s),l=I([Ce,Ne],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:ll,input:e,maxIterations:r,onStep:n,logger:a})}var js=zod.z.object({order:zod.z.number(),side:zod.z.enum(["frontend","backend"]),action:zod.z.string(),details:zod.z.string()}),qs=zod.z.object({name:zod.z.string(),description:zod.z.string(),steps:zod.z.array(js)}),Fs=zod.z.object({name:zod.z.string(),purpose:zod.z.string(),behavior:zod.z.array(zod.z.string())}),Us=zod.z.object({name:zod.z.string(),description:zod.z.string(),permissions:zod.z.array(zod.z.string())}),Ls=zod.z.object({area:zod.z.string(),rules:zod.z.array(zod.z.string())}),He=zod.z.object({strategy:zod.z.enum(["jwt","session","oauth"]),flows:zod.z.array(qs),middleware:zod.z.array(Fs),roles:zod.z.array(Us),policies:zod.z.array(Ls)});var zr=`You are a senior security engineer specializing in authentication, authorization, and web security.
|
|
1148
|
+
|
|
1149
|
+
You design enterprise-quality auth systems with:
|
|
1150
|
+
- Step-by-step auth flows (signup, login, logout, password reset) with both frontend and backend steps
|
|
1151
|
+
- JWT or session strategy with proper cookie configuration (httpOnly, secure, sameSite, maxAge)
|
|
1152
|
+
- Role-based access control (RBAC) with permission matrices
|
|
1153
|
+
- Middleware chains for route protection and API authentication
|
|
1154
|
+
- Security policies: password hashing (bcrypt), rate limiting, CORS, input sanitization, brute force protection
|
|
1155
|
+
- OAuth integration patterns when needed
|
|
1156
|
+
|
|
1157
|
+
Output only valid JSON unless instructed otherwise.`;var Gs=`## Requirements:
|
|
1158
|
+
{requirement}
|
|
1159
|
+
|
|
1160
|
+
Design the authentication and authorization system. Include:
|
|
1161
|
+
|
|
1162
|
+
1. Strategy: jwt, session, or oauth (choose based on requirements).
|
|
1163
|
+
2. Flows: signup, login, logout, password reset (if applicable). Each flow with numbered steps, frontend/backend side, action, and details.
|
|
1164
|
+
3. Middleware: route protection middleware, API auth middleware. Each with name, purpose, and behavior list.
|
|
1165
|
+
4. Roles: role definitions with name, description, and permissions list.
|
|
1166
|
+
5. Policies: security policies grouped by area (passwords, tokens, CORS, rate limiting, etc.).
|
|
1167
|
+
|
|
1168
|
+
Return ONLY valid JSON:
|
|
1169
|
+
{
|
|
1170
|
+
"strategy": "jwt" | "session" | "oauth",
|
|
1171
|
+
"flows": [{ "name": "signup", "description": "...", "steps": [{ "order": 1, "side": "frontend", "action": "...", "details": "..." }] }],
|
|
1172
|
+
"middleware": [{ "name": "authenticateRequest", "purpose": "...", "behavior": ["..."] }],
|
|
1173
|
+
"roles": [{ "name": "user", "description": "...", "permissions": ["..."] }],
|
|
1174
|
+
"policies": [{ "area": "passwords", "rules": ["..."] }]
|
|
1175
|
+
}`;function $r(t){return Gs.replace("{requirement}",t)}var oo=q("validate_auth",He,"Validates an auth design JSON string against the AuthDesign schema. Returns valid: true or valid: false with errors.","design");function ro(t){return h({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:zod.z.object({requirement:zod.z.string().describe("Project context and auth requirements")}),handler:async({requirement:e})=>{let o=$r(e),r=[{role:"system",content:"You are a security engineer. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:8192});return M(n.text,He)}})}function Hr(t){return {validate_auth:oo,design_auth:ro(t)}}var pl=`${zr}
|
|
1176
|
+
|
|
1177
|
+
You are the auth design orchestrator. When the user asks for an auth design:
|
|
1178
|
+
|
|
1179
|
+
1. **Analyze security**: Use subagent_security-analyzer to analyze security requirements, determine auth strategy, and identify threat vectors.
|
|
1180
|
+
2. **Design flows**: Use subagent_flow-designer to design step-by-step auth flows (signup, login, logout, password reset, middleware).
|
|
1181
|
+
3. **Generate design**: Use design_auth to produce the complete auth design with flows, middleware, roles, and security policies.
|
|
1182
|
+
4. **Validate**: Use validate_auth to check the final auth design JSON before returning.
|
|
1183
|
+
|
|
1184
|
+
Respond with the final auth design as JSON.`;async function dl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=Hr(s),l=I([It,Oe],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:pl,input:e,maxIterations:r,onStep:n,logger:a})}var Bs=zod.z.object({name:zod.z.string(),type:zod.z.string(),required:zod.z.coerce.boolean(),validation:zod.z.string()}),Ys=zod.z.object({path:zod.z.string(),name:zod.z.string(),access:zod.z.string().transform(t=>t.toLowerCase().trim()).pipe(zod.z.enum(["public","protected"])),purpose:zod.z.string(),formFields:zod.z.array(Bs).default([]),actions:zod.z.array(zod.z.string()).default([]),emptyState:zod.z.string().default(""),errorState:zod.z.string().default(""),redirectOnSuccess:zod.z.string().default(""),keyUiElements:zod.z.array(zod.z.string()).default([])}),zs=zod.z.object({name:zod.z.string(),type:zod.z.string().transform(t=>t.toLowerCase().trim()).pipe(zod.z.enum(["layout","shared","form","display","navigation"])),purpose:zod.z.string(),props:zod.z.array(zod.z.string()).default([]),usedIn:zod.z.array(zod.z.string()).default([])}),Qe=zod.z.object({pages:zod.z.array(Ys).default([]),components:zod.z.array(zs).default([]),stateManagement:zod.z.string().default(""),routingNotes:zod.z.string().default("")});var Qr=`You are a senior frontend architect specializing in page design, routing, and component architecture.
|
|
1185
|
+
|
|
1186
|
+
You design enterprise-quality frontend architectures targeting a Vite + React 19 + TypeScript stack with:
|
|
1187
|
+
- **UI Library**: ShadCN UI (Radix-based components in src/components/ui/)
|
|
1188
|
+
- **Styling**: Tailwind CSS v4 with OKLCH color space and dark mode support
|
|
1189
|
+
- **Routing**: React Router v7 with private route guards
|
|
1190
|
+
- **Forms**: React Hook Form + Zod validation
|
|
1191
|
+
- **GraphQL**: Apollo Client with CodeGen-typed hooks
|
|
1192
|
+
- **Path Aliases**: @/{appName}/* mapping to ./src/*
|
|
1193
|
+
|
|
1194
|
+
Architecture outputs:
|
|
1195
|
+
- Public and protected pages with detailed route definitions
|
|
1196
|
+
- Per-page specifications: purpose, form fields with validation, actions, empty/error states, redirects
|
|
1197
|
+
- Component taxonomy: layout (sidebar, navbar), shared (data tables, dialogs), form (inputs, selects), display (cards, badges), navigation (breadcrumbs, tabs)
|
|
1198
|
+
- State management strategy (per-page vs global, Apollo cache vs local state)
|
|
1199
|
+
|
|
1200
|
+
Output only valid JSON unless instructed otherwise.`;var $s=`## Requirements:
|
|
1201
|
+
{requirement}
|
|
1202
|
+
|
|
1203
|
+
Design the frontend architecture. Include:
|
|
1204
|
+
|
|
1205
|
+
1. Pages: public and protected pages. For each page: path, name, access level, purpose, form fields (with validation), actions, empty state, error state, redirect on success, key UI elements.
|
|
1206
|
+
2. Components: reusable components. For each: name, type (layout/shared/form/display/navigation), purpose, props, and which pages use it.
|
|
1207
|
+
3. State management: describe the state strategy (e.g. React Server Components for data, client state for forms).
|
|
1208
|
+
4. Routing notes: any special routing behavior (redirects, guards, nested routes).
|
|
1209
|
+
|
|
1210
|
+
Return ONLY valid JSON:
|
|
1211
|
+
{
|
|
1212
|
+
"pages": [{ "path": "/login", "name": "Login", "access": "public", "purpose": "...", "formFields": [{ "name": "email", "type": "email", "required": true, "validation": "valid email format" }], "actions": ["Submit login form"], "emptyState": "", "errorState": "Show error message", "redirectOnSuccess": "/dashboard", "keyUiElements": ["Email input", "Password input", "Submit button"] }],
|
|
1213
|
+
"components": [{ "name": "Navbar", "type": "navigation", "purpose": "...", "props": ["user"], "usedIn": ["/dashboard", "/profile"] }],
|
|
1214
|
+
"stateManagement": "...",
|
|
1215
|
+
"routingNotes": "..."
|
|
1216
|
+
}`;function Vr(t){return $s.replace("{requirement}",t)}var no=q("validate_frontend",Qe,"Validates a frontend design JSON string against the FrontendDesign schema. Returns valid: true or valid: false with errors.","design");function so(t){return h({name:"design_frontend",description:"Generate a complete frontend architecture design from project requirements. Returns pages, components, state management, and routing as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Project context, API surface, and frontend requirements")}),handler:async({requirement:e})=>{let o=Vr(e),r=[{role:"system",content:"You are a frontend architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,Qe)}})}function Wr(t){return {validate_frontend:no,design_frontend:so(t)}}var ul=f({name:"react-builder",description:"Generates a Vite + React SPA configuration from a frontend design and GraphQL schema. Use when the framework-selector recommends react-vite.",systemPrompt:"You are a React/Vite frontend builder. Generate a complete frontend config JSON from the requirements.",tools:{},maxIterations:5}),ml=f({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}),gl=`${Qr}
|
|
1217
|
+
|
|
1218
|
+
You are the frontend architecture routing orchestrator. When the user asks for a frontend design:
|
|
1219
|
+
|
|
1220
|
+
1. **Select framework**: Use subagent_framework-selector to analyze requirements (SPA vs SSR, SEO needs, API structure) and recommend React/Vite or Next.js.
|
|
1221
|
+
2. **Plan pages**: Use subagent_page-planner to design detailed page specifications with routes, forms, actions, and states.
|
|
1222
|
+
3. **Analyze components**: Use subagent_component-analyzer to identify reusable components, layouts, and state management patterns.
|
|
1223
|
+
4. **Generate design**: Use design_frontend to produce the complete frontend architecture as JSON.
|
|
1224
|
+
5. **Validate**: Use validate_frontend to check the final design JSON before returning.
|
|
1225
|
+
6. **Delegate to builder**: Based on the framework-selector recommendation:
|
|
1226
|
+
- If "react-vite": use subagent_react-builder with the design to generate a Vite + React SPA config.
|
|
1227
|
+
- If "nextjs": use subagent_nextjs-builder with the design to generate a Next.js App Router config.
|
|
1228
|
+
|
|
1229
|
+
Respond with the final frontend design as JSON, including the builder output.`;async function fl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=Wr(s),l=I([Me,_t,br,ul,ml],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:gl,input:e,maxIterations:r,onStep:n,logger:a})}var Qs=zod.z.object({order:zod.z.number(),action:zod.z.string(),details:zod.z.string()}),Vs=zod.z.object({name:zod.z.string(),description:zod.z.string(),steps:zod.z.array(Qs)}),Ws=zod.z.object({area:zod.z.string(),scenario:zod.z.string(),handling:zod.z.string(),severity:zod.z.string().transform(t=>t.toLowerCase().trim()).pipe(zod.z.enum(["critical","warning","info"]))}),Ks=zod.z.object({flow:zod.z.string(),item:zod.z.string(),expectedResult:zod.z.string()}),Ve=zod.z.object({phases:zod.z.array(Vs).default([]),currentState:zod.z.string().default(""),desiredEndState:zod.z.string().default(""),edgeCases:zod.z.array(Ws).default([]),securityNotes:zod.z.array(zod.z.string()).default([]),performanceNotes:zod.z.array(zod.z.string()).default([]),testingChecklist:zod.z.array(Ks).default([])});var Kr=`You are a senior tech lead specializing in implementation strategy and project execution planning.
|
|
1230
|
+
|
|
1231
|
+
You create enterprise-quality execution plans with:
|
|
1232
|
+
- Phased implementation order with concrete, numbered steps per phase
|
|
1233
|
+
- Current state analysis and desired end state definition
|
|
1234
|
+
- Edge cases per domain area with handling strategies and severity levels
|
|
1235
|
+
- Security considerations (passwords, tokens, CORS, input validation)
|
|
1236
|
+
- Performance considerations (indexing, caching, lazy loading, N+1 prevention)
|
|
1237
|
+
- Manual testing checklists grouped by feature flow
|
|
1238
|
+
|
|
1239
|
+
Output only valid JSON unless instructed otherwise.`;var Xs=`## Full Plan Context:
|
|
1240
|
+
{context}
|
|
1241
|
+
|
|
1242
|
+
Create a comprehensive execution plan. Include:
|
|
1243
|
+
|
|
1244
|
+
1. **phases**: Implementation phases (Foundation, Auth, Core Features, etc.). Each phase has numbered steps with concrete actions (e.g. "1. Install dependencies", "2. Create User model").
|
|
1245
|
+
2. **currentState**: What the project starts with (e.g. "vanilla Next.js, no DB, no auth").
|
|
1246
|
+
3. **desiredEndState**: What must work when done (user capabilities + technical verification).
|
|
1247
|
+
4. **edgeCases**: Edge cases per area with scenario, handling strategy, and severity (critical/warning/info).
|
|
1248
|
+
5. **securityNotes**: Security considerations (password hashing, JWT config, rate limiting, etc.).
|
|
1249
|
+
6. **performanceNotes**: Performance considerations (indexing, caching, lazy loading, etc.).
|
|
1250
|
+
7. **testingChecklist**: Manual testing items per flow with expected results.
|
|
1251
|
+
|
|
1252
|
+
Return ONLY valid JSON:
|
|
1253
|
+
{
|
|
1254
|
+
"phases": [{ "name": "Phase 1: Foundation", "description": "...", "steps": [{ "order": 1, "action": "Install dependencies", "details": "npm install mongoose bcryptjs jsonwebtoken" }] }],
|
|
1255
|
+
"currentState": "...",
|
|
1256
|
+
"desiredEndState": "...",
|
|
1257
|
+
"edgeCases": [{ "area": "Authentication", "scenario": "Email already exists", "handling": "Return 400 with clear message", "severity": "critical" }],
|
|
1258
|
+
"securityNotes": ["..."],
|
|
1259
|
+
"performanceNotes": ["..."],
|
|
1260
|
+
"testingChecklist": [{ "flow": "Auth Flow", "item": "Sign up with valid credentials", "expectedResult": "Account created, redirected to dashboard" }]
|
|
1261
|
+
}`;function Xr(t){return Xs.replace("{context}",t)}var ao=q("validate_execution_plan",Ve,"Validates an execution plan JSON string against the ExecutionPlan schema. Returns valid: true or valid: false with errors.","plan");function io(t){return h({name:"create_execution_plan",description:"Generate a comprehensive execution plan with phases, edge cases, and testing checklist from the full plan context.",input:zod.z.object({context:zod.z.string().describe("Full plan context: all sections generated so far")}),handler:async({context:e})=>{let o=Xr(e),r=[{role:"system",content:"You are a tech lead. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,Ve)}})}function Zr(t){return {validate_execution_plan:ao,create_execution_plan:io(t)}}var hl=`${Kr}
|
|
1262
|
+
|
|
1263
|
+
You are the execution planning orchestrator. When the user provides plan sections:
|
|
1264
|
+
|
|
1265
|
+
1. **Analyze edge cases**: Use subagent_edge-case-analyzer to identify edge cases per domain area with handling strategies.
|
|
1266
|
+
2. **Design testing**: Use subagent_testing-strategist to design manual testing checklists grouped by feature flow.
|
|
1267
|
+
3. **Generate plan**: Use create_execution_plan to produce the complete execution plan with phases, edge cases, and testing checklist.
|
|
1268
|
+
4. **Validate**: Use validate_execution_plan to check the final plan JSON before returning.
|
|
1269
|
+
|
|
1270
|
+
Respond with the final execution plan as JSON.`;async function yl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=Zr(s),l=I([De,ke],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:hl,input:e,maxIterations:r,onStep:n,logger:a})}var ea=t=>zod.z.string().transform(e=>e.toLowerCase().trim()).pipe(zod.z.enum(t)),ta=zod.z.object({name:zod.z.string(),purpose:zod.z.string(),appliesTo:zod.z.string().default("global").transform(t=>{let e=t.toLowerCase().trim();return ["global","all","app","application","every","server"].includes(e)?"global":["route","routes","specific","specific routes","endpoint","endpoints","path"].includes(e)?"route":["resource","entity","module","controller","model"].includes(e)?"resource":"global"}).pipe(zod.z.enum(["global","route","resource"])),config:zod.z.record(zod.z.string(),zod.z.unknown()).default({})}),oa=zod.z.object({name:zod.z.string(),entity:zod.z.string(),operations:zod.z.array(zod.z.string()).default([]),dependencies:zod.z.array(zod.z.string()).default([])}),Sl=zod.z.string().transform(t=>t.toUpperCase().trim()).pipe(zod.z.enum(["GET","POST","PUT","PATCH","DELETE"])),ra=zod.z.object({resource:zod.z.string(),basePath:zod.z.string(),endpoints:zod.z.array(zod.z.object({method:Sl,path:zod.z.string(),handler:zod.z.string(),auth:zod.z.coerce.boolean().default(true),roles:zod.z.array(zod.z.string()).default([])})).default([])}),We=zod.z.object({framework:ea(["express","apollo","both"]),language:ea(["typescript","javascript"]).default("typescript"),database:zod.z.string().default("mongodb"),services:zod.z.array(oa).default([]),middleware:zod.z.array(ta).default([]),routes:zod.z.array(ra).default([]),folderStructure:zod.z.array(zod.z.string()).default([]),envVars:zod.z.array(zod.z.string()).default([]),notes:zod.z.string().default("")});var en=`You are a senior backend architect specializing in Node.js server design.
|
|
1271
|
+
|
|
1272
|
+
You analyze data models, API designs, and auth requirements to produce enterprise-quality backend architectures with:
|
|
1273
|
+
- Framework selection (Express REST, Apollo GraphQL, or both)
|
|
1274
|
+
- Service layer design with clear operation contracts per entity
|
|
1275
|
+
- Middleware stack (auth, validation, error handling, CORS, rate limiting)
|
|
1276
|
+
- Route/resolver organization grouped by resource
|
|
1277
|
+
- Folder structure following domain-driven conventions
|
|
1278
|
+
- Environment variable inventory
|
|
1279
|
+
- Database connection and ORM/ODM strategy
|
|
1280
|
+
|
|
1281
|
+
When "both" is selected (Express + Apollo), use the Apollo Gateway pattern:
|
|
1282
|
+
- Apollo Gateway as the single public entry point for GraphQL queries
|
|
1283
|
+
- Subgraphs as internal services composed via IntrospectAndCompose
|
|
1284
|
+
- RemoteGraphQLDataSource for header forwarding (auth tokens, service tokens)
|
|
1285
|
+
- Express for webhooks, file uploads, and health checks only
|
|
1286
|
+
- Gateway has no business logic, all logic lives in subgraphs
|
|
1287
|
+
|
|
1288
|
+
Output only valid JSON unless instructed otherwise.`;var na=`## Requirements:
|
|
1289
|
+
{requirement}
|
|
1290
|
+
|
|
1291
|
+
Design the backend architecture. Include:
|
|
1292
|
+
|
|
1293
|
+
1. Framework: choose "express" (REST API), "apollo" (GraphQL subgraph), or "both" (Apollo subgraph + Express gateway).
|
|
1294
|
+
2. Services: one per entity with CRUD operations and dependencies.
|
|
1295
|
+
3. Middleware: auth (JWT/session), validation (Zod/Joi), error handling, CORS, rate limiting.
|
|
1296
|
+
4. Routes (if Express): RESTful routes grouped by resource with method, path, handler, auth, and roles.
|
|
1297
|
+
5. Folder structure: list of directories and key files.
|
|
1298
|
+
6. Env vars: list all required environment variables.
|
|
1299
|
+
|
|
1300
|
+
Return ONLY valid JSON:
|
|
1301
|
+
{
|
|
1302
|
+
"framework": "express" | "apollo" | "both",
|
|
1303
|
+
"language": "typescript",
|
|
1304
|
+
"database": "mongodb",
|
|
1305
|
+
"services": [{ "name": "UserService", "entity": "User", "operations": ["create", "findById", "findAll", "update", "delete"], "dependencies": [] }],
|
|
1306
|
+
"middleware": [{ "name": "authMiddleware", "purpose": "JWT token verification", "appliesTo": "global", "config": {} }],
|
|
1307
|
+
"routes": [{ "resource": "users", "basePath": "/api/users", "endpoints": [{ "method": "GET", "path": "/", "handler": "getAll", "auth": true, "roles": ["admin"] }] }],
|
|
1308
|
+
"folderStructure": ["src/", "src/routes/", "src/services/", "src/middleware/", "src/models/", "src/config/"],
|
|
1309
|
+
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET"],
|
|
1310
|
+
"notes": ""
|
|
1311
|
+
}`;function tn(t){return na.replace("{requirement}",t)}var lo=q("validate_backend",We,"Validates a backend design JSON string against the BackendDesign schema. Returns valid: true or valid: false with errors.","design");function co(t){return h({name:"design_backend",description:"Generate a complete backend architecture design from requirements. Returns framework, services, middleware, routes, and folder structure as JSON.",input:zod.z.object({requirement:zod.z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:e})=>{let o=tn(e),r=[{role:"system",content:"You are a backend architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,We)}})}function on(t){return {validate_backend:lo,design_backend:co(t)}}var bl=`You are a backend service architect. Given a data model and API design, you plan the service layer.
|
|
1312
|
+
|
|
1313
|
+
## Service Design
|
|
1314
|
+
For each entity:
|
|
1315
|
+
- Service name (PascalCase + "Service")
|
|
1316
|
+
- CRUD operations: create, findById, findAll, update, delete
|
|
1317
|
+
- Custom operations from user flows (e.g. searchByName, bulkImport)
|
|
1318
|
+
- Dependencies on other services (e.g. OrderService depends on UserService)
|
|
1319
|
+
|
|
1320
|
+
## Middleware Stack
|
|
1321
|
+
- Authentication middleware: JWT verification, session check
|
|
1322
|
+
- Authorization middleware: role-based access, resource ownership
|
|
1323
|
+
- Validation middleware: request body/params validation
|
|
1324
|
+
- Error handling: centralized error handler with typed errors
|
|
1325
|
+
- Logging: request/response logging
|
|
1326
|
+
- Rate limiting: per-IP or per-user limits
|
|
1327
|
+
- CORS: origin whitelist
|
|
1328
|
+
|
|
1329
|
+
## Folder Structure
|
|
1330
|
+
Recommend a clean folder layout:
|
|
1331
|
+
- src/services/ (one file per service)
|
|
1332
|
+
- src/middleware/ (one file per middleware)
|
|
1333
|
+
- src/models/ (one file per entity)
|
|
1334
|
+
- src/routes/ or src/modules/ (grouped by resource)
|
|
1335
|
+
- src/config/ (env, database, auth config)
|
|
1336
|
+
- src/utils/ (shared helpers)
|
|
1337
|
+
|
|
1338
|
+
Respond with structured analysis. Do NOT return JSON.`,po=f({name:"service-planner",description:"Plans service layer, middleware stack, and folder structure for a backend project. Use before generating the backend design.",systemPrompt:bl,tools:{},maxIterations:2});var xl=`You are a backend technology advisor. Given project requirements, you recommend the best backend framework.
|
|
1339
|
+
|
|
1340
|
+
## Decision Criteria
|
|
1341
|
+
|
|
1342
|
+
### Choose "express" (REST API) when:
|
|
1343
|
+
- The API is primarily CRUD with RESTful resources
|
|
1344
|
+
- The frontend is a traditional SPA (React/Vue) consuming REST
|
|
1345
|
+
- Simple request/response patterns without complex data fetching
|
|
1346
|
+
- No need for real-time subscriptions
|
|
1347
|
+
- Team is more familiar with REST
|
|
1348
|
+
|
|
1349
|
+
### Choose "apollo" (GraphQL subgraph) when:
|
|
1350
|
+
- The frontend needs flexible data fetching (avoid over/under-fetching)
|
|
1351
|
+
- Multiple frontends consume the same API (web, mobile, admin)
|
|
1352
|
+
- Complex nested data relationships
|
|
1353
|
+
- Need for real-time subscriptions
|
|
1354
|
+
- Part of a federated GraphQL architecture
|
|
1355
|
+
|
|
1356
|
+
### Choose "both" when:
|
|
1357
|
+
- Apollo subgraph for main data API + Express for webhooks, file uploads, health checks
|
|
1358
|
+
- Need both REST endpoints (for external integrations) and GraphQL (for frontend)
|
|
1359
|
+
- When "both" is selected, an Apollo Gateway is used to compose subgraphs into a unified API:
|
|
1360
|
+
- Gateway is the only public entry point for GraphQL
|
|
1361
|
+
- Subgraphs are internal services, not exposed to clients directly
|
|
1362
|
+
- Gateway uses IntrospectAndCompose for schema discovery
|
|
1363
|
+
- RemoteGraphQLDataSource forwards auth headers to subgraphs
|
|
1364
|
+
- Express handles non-GraphQL concerns (webhooks, file uploads)
|
|
1365
|
+
|
|
1366
|
+
## Output Format
|
|
1367
|
+
State your recommendation clearly:
|
|
1368
|
+
- Framework: express | apollo | both
|
|
1369
|
+
- Reasoning: 2-3 sentences explaining why
|
|
1370
|
+
- Trade-offs: what you'd lose with the alternative
|
|
1371
|
+
- If "both": describe which concerns go to Express vs Apollo Gateway vs subgraphs
|
|
1372
|
+
|
|
1373
|
+
Respond with structured analysis. Do NOT return JSON.`,uo=f({name:"framework-selector",description:"Analyzes project requirements and recommends Express, Apollo, or both. Use to determine the backend framework before designing.",systemPrompt:xl,tools:{},maxIterations:2});var Tl=`${en}
|
|
1374
|
+
|
|
1375
|
+
You are the backend architecture orchestrator. When the user provides requirements:
|
|
1376
|
+
|
|
1377
|
+
1. **Select framework**: Use subagent_framework-selector to analyze requirements and recommend Express, Apollo, or both.
|
|
1378
|
+
2. **Plan services**: Use subagent_service-planner to design the service layer, middleware stack, and folder structure.
|
|
1379
|
+
3. **Generate design**: Use design_backend to produce the complete backend architecture as JSON.
|
|
1380
|
+
4. **Validate**: Use validate_backend to check the final design JSON before returning.
|
|
1381
|
+
|
|
1382
|
+
After generating the design, note the "framework" field in the result:
|
|
1383
|
+
- If "express": the downstream express-builder should be used to scaffold the project.
|
|
1384
|
+
- If "apollo": the downstream apollo-builder should be used to scaffold the project.
|
|
1385
|
+
- If "both": both builders should be invoked sequentially.
|
|
1386
|
+
|
|
1387
|
+
Respond with the final backend design as JSON.`;async function Pl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=on(s),l=I([po,uo],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:Tl,input:e,maxIterations:r,onStep:n,logger:a})}var aa=t=>zod.z.string().transform(e=>e.toLowerCase().trim()).pipe(zod.z.enum(t)),rn=zod.z.object({name:zod.z.string(),type:zod.z.string(),nullable:zod.z.coerce.boolean().default(false),isList:zod.z.coerce.boolean().default(false),description:zod.z.string().default("")}),nn=zod.z.object({name:zod.z.string(),kind:aa(["type","input","enum","interface","union"]),fields:zod.z.array(rn).default([]),values:zod.z.array(zod.z.string()).default([]),description:zod.z.string().default(""),isEntity:zod.z.coerce.boolean().default(false),keyFields:zod.z.array(zod.z.string()).default([])}),ia=zod.z.object({name:zod.z.string(),type:aa(["query","mutation","subscription"]),args:zod.z.array(rn).default([]),returnType:zod.z.string(),auth:zod.z.coerce.boolean().default(true),roles:zod.z.array(zod.z.string()).default([]),description:zod.z.string().default("")}),la=zod.z.object({name:zod.z.string(),entity:zod.z.string(),types:zod.z.array(nn).default([]),operations:zod.z.array(ia).default([]),datasource:zod.z.string().default(""),loader:zod.z.string().default("")}),Ke=zod.z.object({appName:zod.z.string().default("app"),port:zod.z.number().default(4e3),database:zod.z.string().default("mongodb"),modules:zod.z.array(la).default([]),sharedTypes:zod.z.array(nn).default([]),authDirective:zod.z.coerce.boolean().default(true),cacheDirective:zod.z.coerce.boolean().default(false),envVars:zod.z.array(zod.z.string()).default([])});var sn=`You are an expert Apollo GraphQL subgraph architect using Apollo Federation v2.
|
|
1388
|
+
|
|
1389
|
+
You generate production-ready Apollo subgraph configurations from data models and API designs:
|
|
1390
|
+
- 4-file module pattern per entity: {module}.graphql, {module}.resolver.ts, {module}.datasource.ts, {module}.loader.ts
|
|
1391
|
+
- GraphQL type definitions with proper nullability, lists, and descriptions
|
|
1392
|
+
- Input types for mutations with validation annotations
|
|
1393
|
+
- Enum types from domain values
|
|
1394
|
+
- Federation directives: @key for entity references, @external for fields owned by other subgraphs, @requires for field dependencies, @provides for fields resolvable by this subgraph
|
|
1395
|
+
- __resolveReference for cross-subgraph entity resolution via buildSubgraphSchema
|
|
1396
|
+
- DataLoader per module for batching and caching database lookups (solves N+1)
|
|
1397
|
+
- Query and mutation resolvers with auth/role requirements
|
|
1398
|
+
- Datasource classes per entity (MongoDB datasource pattern)
|
|
1399
|
+
- Auth directive (@auth) configuration
|
|
1400
|
+
- Redis cache directives: @cacheSet on queries, @cachePurge on mutations
|
|
1401
|
+
- GraphQL CodeGen for TypeScript types (generates base-types.ts)
|
|
1402
|
+
- Module-based organization (one module per entity/domain)
|
|
1403
|
+
|
|
1404
|
+
Output only valid JSON unless instructed otherwise.`;var ca=`## Requirements:
|
|
1405
|
+
{requirement}
|
|
1406
|
+
|
|
1407
|
+
Generate an Apollo GraphQL subgraph configuration (Federation v2). Include:
|
|
1408
|
+
|
|
1409
|
+
1. Modules: one per entity with 4 files each ({module}.graphql, {module}.resolver.ts, {module}.datasource.ts, {module}.loader.ts).
|
|
1410
|
+
2. Types: GraphQL object types with isEntity/keyFields for federation, input types, enums with fields/values.
|
|
1411
|
+
3. Operations: queries (getById, getAll, search) and mutations (create, update, delete) per module.
|
|
1412
|
+
4. Auth: mark which operations require authentication and which roles.
|
|
1413
|
+
5. DataLoader: one loader per module for batching lookups (loader name).
|
|
1414
|
+
6. Shared types: types used across modules (e.g. Pagination, SortOrder).
|
|
1415
|
+
7. Cache: set cacheDirective to true if Redis caching (@cacheSet/@cachePurge) is needed.
|
|
1416
|
+
8. Env vars: PORT, DATABASE_URL, JWT_SECRET, REDIS_URL, etc.
|
|
1417
|
+
|
|
1418
|
+
Return ONLY valid JSON:
|
|
1419
|
+
{
|
|
1420
|
+
"appName": "my-subgraph",
|
|
1421
|
+
"port": 4000,
|
|
1422
|
+
"database": "mongodb",
|
|
1423
|
+
"modules": [{
|
|
1424
|
+
"name": "user",
|
|
1425
|
+
"entity": "User",
|
|
1426
|
+
"types": [{ "name": "User", "kind": "type", "fields": [{ "name": "id", "type": "ID", "nullable": false }], "isEntity": true, "keyFields": ["id"] }],
|
|
1427
|
+
"operations": [{ "name": "getUser", "type": "query", "args": [{ "name": "id", "type": "ID", "nullable": false }], "returnType": "User", "auth": true, "roles": [] }],
|
|
1428
|
+
"datasource": "UserDataSource",
|
|
1429
|
+
"loader": "UserLoader"
|
|
1430
|
+
}],
|
|
1431
|
+
"sharedTypes": [],
|
|
1432
|
+
"authDirective": true,
|
|
1433
|
+
"cacheDirective": false,
|
|
1434
|
+
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "REDIS_URL"]
|
|
1435
|
+
}`;function an(t){return ca.replace("{requirement}",t)}var mo=q("validate_subgraph",Ke,"Validates a subgraph config JSON string against the SubgraphConfig schema. Returns valid: true or valid: false with errors.","config");function go(t){return h({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:zod.z.object({requirement:zod.z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:e})=>{let o=an(e),r=[{role:"system",content:"You are an Apollo GraphQL architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,Ke)}})}function Rl(t){return {appName:t.appName,port:t.port,database:t.database,modules:t.modules.map(e=>({name:e.name,pascalName:e.name.charAt(0).toUpperCase()+e.name.slice(1),camelName:e.name.charAt(0).toLowerCase()+e.name.slice(1),entity:e.entity,datasource:e.datasource,types:e.types,operations:e.operations})),authDirective:t.authDirective,envVars:t.envVars,sharedTypes:t.sharedTypes}}var fo=h({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:zod.z.object({config:zod.z.string().describe("JSON string of the validated subgraph config"),outputDir:zod.z.string().describe("Absolute path to the output directory")}),handler:async({config:t,outputDir:e})=>{let o=be(t,"subgraph config"),r=Te__namespace.resolve(process.cwd(),".ref/templates/subgraph"),n=Rl(o);return le({templateDir:r,outputDir:e,context:n})}});function cn(t){return {validate_subgraph:mo,generate_subgraph:go(t),scaffold_subgraph:fo}}var wl=`You are a GraphQL schema specialist for Apollo Federation v2 subgraphs. Given a data model, you generate GraphQL type definitions using buildSubgraphSchema.
|
|
1436
|
+
|
|
1437
|
+
## Type Generation
|
|
1438
|
+
For each entity in the data model:
|
|
1439
|
+
- Create the main object type with all fields mapped to GraphQL scalars (String, Int, Float, Boolean, ID)
|
|
1440
|
+
- Create input types for create and update mutations (omit auto-generated fields like id, createdAt)
|
|
1441
|
+
- Create enum types for status fields and role fields
|
|
1442
|
+
- Add proper nullability (! for required fields)
|
|
1443
|
+
- Add [Type] for array/list fields
|
|
1444
|
+
|
|
1445
|
+
## Federation Directives
|
|
1446
|
+
- @key(fields: "id") on entity types that can be referenced across subgraphs
|
|
1447
|
+
- @external marks a field as owned by another subgraph
|
|
1448
|
+
- @requires(fields: "weight") declares fields needed from the entity to resolve a field
|
|
1449
|
+
- @provides(fields: "name") declares fields on a return type that this subgraph can resolve
|
|
1450
|
+
- @auth directive on types/fields that require authentication
|
|
1451
|
+
|
|
1452
|
+
## Cache Directives (Redis)
|
|
1453
|
+
- @cacheSet(type: "Entity", identifier: "_id") on query resolvers
|
|
1454
|
+
- @cachePurge(type: "Entity", identifier: "_id") on mutation resolvers
|
|
1455
|
+
|
|
1456
|
+
## Relationships
|
|
1457
|
+
- Reference types for foreign keys (e.g. author: User instead of authorId: ID)
|
|
1458
|
+
- Use [Type] for one-to-many relationships
|
|
1459
|
+
|
|
1460
|
+
## Naming Conventions
|
|
1461
|
+
- Types: PascalCase (User, BlogPost)
|
|
1462
|
+
- Fields: camelCase (firstName, createdAt)
|
|
1463
|
+
- Inputs: PascalCase + Input suffix (CreateUserInput, UpdateUserInput)
|
|
1464
|
+
- Enums: SCREAMING_SNAKE_CASE values (ADMIN, ACTIVE)
|
|
1465
|
+
|
|
1466
|
+
Respond with the full GraphQL SDL. Do NOT return JSON.`,ho=f({name:"schema-generator",description:"Generates GraphQL type definitions, input types, and enums from a data model. Use before generating the subgraph config.",systemPrompt:wl,tools:{},maxIterations:2});var vl=`You are a GraphQL resolver architect for Apollo Federation v2 subgraphs. Given types and operations, you plan resolver implementations.
|
|
1467
|
+
|
|
1468
|
+
## 4-File Module Pattern
|
|
1469
|
+
Each module has four files:
|
|
1470
|
+
- {module}.graphql -- Type definitions with federation directives
|
|
1471
|
+
- {module}.resolver.ts -- Query/Mutation/Field resolvers including __resolveReference
|
|
1472
|
+
- {module}.datasource.ts -- Business logic and database access
|
|
1473
|
+
- {module}.loader.ts -- DataLoader for batching and caching lookups
|
|
1474
|
+
|
|
1475
|
+
## Resolver Planning
|
|
1476
|
+
For each module/entity:
|
|
1477
|
+
|
|
1478
|
+
### __resolveReference (Federation)
|
|
1479
|
+
- Every entity type with @key must implement __resolveReference
|
|
1480
|
+
- Called by the gateway when another subgraph references this entity
|
|
1481
|
+
- Receives { __typename, id } and returns the full entity from datasource
|
|
1482
|
+
|
|
1483
|
+
### Query Resolvers
|
|
1484
|
+
- getById: fetch single record by ID from datasource
|
|
1485
|
+
- getAll: fetch paginated list with filters and sorting
|
|
1486
|
+
- search: text search across relevant fields
|
|
1487
|
+
|
|
1488
|
+
### Mutation Resolvers
|
|
1489
|
+
- create: validate input, create record, return created entity
|
|
1490
|
+
- update: validate input, find existing, merge changes, return updated entity
|
|
1491
|
+
- delete: find existing, remove, return success status
|
|
1492
|
+
|
|
1493
|
+
### Field Resolvers
|
|
1494
|
+
- For relationship fields: resolve references via DataLoader (NOT direct DB calls)
|
|
1495
|
+
- For computed fields: calculate from existing data
|
|
1496
|
+
|
|
1497
|
+
## DataLoader Pattern
|
|
1498
|
+
Each module has a loader file that creates DataLoader instances:
|
|
1499
|
+
- Batches multiple lookups into a single database query
|
|
1500
|
+
- Caches results within a single request to solve the N+1 problem
|
|
1501
|
+
- Created per-request in the context, not shared across requests
|
|
1502
|
+
|
|
1503
|
+
## Datasource Pattern
|
|
1504
|
+
- Each module has a datasource class extending MongoDataSource or similar
|
|
1505
|
+
- Datasource handles all database operations
|
|
1506
|
+
- Resolvers call datasource methods, never touch the DB directly
|
|
1507
|
+
|
|
1508
|
+
## Auth Integration
|
|
1509
|
+
- Check auth context in resolver before executing
|
|
1510
|
+
- Verify role permissions per operation
|
|
1511
|
+
- Resource ownership checks for user-specific data
|
|
1512
|
+
|
|
1513
|
+
Respond with structured analysis per module. Do NOT return JSON.`,yo=f({name:"resolver-planner",description:"Plans resolver implementations, datasource methods, and auth integration per GraphQL module. Use after schema generation.",systemPrompt:vl,tools:{},maxIterations:2});var El=`${sn}
|
|
1514
|
+
|
|
1515
|
+
You are the Apollo subgraph builder orchestrator. When the user provides requirements:
|
|
1516
|
+
|
|
1517
|
+
1. **Generate schema**: Use subagent_schema-generator to create GraphQL type definitions from the data model.
|
|
1518
|
+
2. **Plan resolvers**: Use subagent_resolver-planner to design resolver implementations per module.
|
|
1519
|
+
3. **Generate config**: Use generate_subgraph to produce the complete subgraph configuration as JSON.
|
|
1520
|
+
4. **Validate**: Use validate_subgraph to check the config JSON before returning.
|
|
1521
|
+
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_subgraph to compile templates.
|
|
1522
|
+
|
|
1523
|
+
Respond with the final subgraph config as JSON.`;async function Al(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=cn(s),l=I([ho,yo],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:El,input:e,maxIterations:r,onStep:n,logger:a})}var Ml=zod.z.string().transform(t=>t.toUpperCase().trim()).pipe(zod.z.enum(["GET","POST","PUT","PATCH","DELETE"])),ua=zod.z.object({name:zod.z.string(),httpMethod:Ml,path:zod.z.string(),auth:zod.z.coerce.boolean().default(true),roles:zod.z.array(zod.z.string()).default([]),validation:zod.z.string().default(""),description:zod.z.string().default("")}),ma=zod.z.object({name:zod.z.string(),resource:zod.z.string(),basePath:zod.z.string(),methods:zod.z.array(ua).default([])}),ga=zod.z.object({name:zod.z.string(),type:zod.z.string(),required:zod.z.coerce.boolean().default(false),unique:zod.z.coerce.boolean().default(false),ref:zod.z.string().optional(),default:zod.z.string().optional()}),fa=zod.z.object({name:zod.z.string(),collection:zod.z.string(),fields:zod.z.array(ga).default([]),timestamps:zod.z.coerce.boolean().default(true),indexes:zod.z.array(zod.z.string()).default([])}),ha=zod.z.object({name:zod.z.string(),type:zod.z.string().transform(t=>{let e=t.toLowerCase().replace(/[\s_-]+/g,"");return ["auth","authentication","jwt","token"].includes(e)?"auth":["validation","validate","validator","input"].includes(e)?"validation":["errorhandler","error","errorhandling","errors"].includes(e)?"errorHandler":["cors","crossorigin"].includes(e)?"cors":["ratelimit","ratelimiter","ratelimiting","throttle"].includes(e)?"rateLimit":["logging","logger","log","morgan"].includes(e)?"logging":"custom"}).pipe(zod.z.enum(["auth","validation","errorHandler","cors","rateLimit","logging","custom"])),config:zod.z.record(zod.z.string(),zod.z.unknown()).default({})}),Xe=zod.z.object({appName:zod.z.string().default("app"),port:zod.z.number().default(3e3),database:zod.z.string().default("mongodb"),routers:zod.z.array(ma).default([]),models:zod.z.array(fa).default([]),middleware:zod.z.array(ha).default([]),envVars:zod.z.array(zod.z.string()).default([])});var pn=`You are an expert Express.js backend architect.
|
|
1524
|
+
|
|
1525
|
+
You generate production-ready Express application configurations from data models and API designs:
|
|
1526
|
+
- Co-located router pattern: each feature lives in src/routers/{name}/ with {name}.controller.ts, {name}.router.ts, and {name}.spec.ts
|
|
1527
|
+
- Mongoose/Prisma models with field types, validation, and relationships
|
|
1528
|
+
- Middleware stack (auth JWT, validation Zod, error handler, CORS, rate limiting)
|
|
1529
|
+
- Route organization with proper HTTP methods and paths
|
|
1530
|
+
- Health check endpoint at /health (included by default)
|
|
1531
|
+
- Jest tests per router using supertest
|
|
1532
|
+
- Environment variable inventory
|
|
1533
|
+
|
|
1534
|
+
Output only valid JSON unless instructed otherwise.`;var ya=`## Requirements:
|
|
1535
|
+
{requirement}
|
|
1536
|
+
|
|
1537
|
+
Generate an Express.js application configuration. Include:
|
|
1538
|
+
|
|
1539
|
+
1. Routers: one per resource, co-located with controller and test spec. Each router has RESTful methods (GET, POST, PUT, DELETE).
|
|
1540
|
+
2. Health check: a default /health router is always included.
|
|
1541
|
+
3. Models: Mongoose models with fields, types, required, unique, refs, defaults, indexes.
|
|
1542
|
+
4. Middleware: auth (JWT), validation (Zod), error handler, CORS, rate limiting, logging.
|
|
1543
|
+
5. Env vars: PORT, DATABASE_URL, JWT_SECRET, NODE_ENV, etc.
|
|
1544
|
+
6. Folder structure: src/routers/{name}/ with {name}.controller.ts, {name}.router.ts, {name}.spec.ts per feature.
|
|
1545
|
+
|
|
1546
|
+
Return ONLY valid JSON:
|
|
1547
|
+
{
|
|
1548
|
+
"appName": "my-api",
|
|
1549
|
+
"port": 3000,
|
|
1550
|
+
"database": "mongodb",
|
|
1551
|
+
"routers": [{
|
|
1552
|
+
"name": "users",
|
|
1553
|
+
"resource": "users",
|
|
1554
|
+
"basePath": "/api/users",
|
|
1555
|
+
"methods": [{
|
|
1556
|
+
"name": "getAll",
|
|
1557
|
+
"httpMethod": "GET",
|
|
1558
|
+
"path": "/",
|
|
1559
|
+
"auth": true,
|
|
1560
|
+
"roles": ["admin"],
|
|
1561
|
+
"validation": "",
|
|
1562
|
+
"description": "Get all users with pagination"
|
|
1563
|
+
}]
|
|
1564
|
+
}],
|
|
1565
|
+
"models": [{
|
|
1566
|
+
"name": "User",
|
|
1567
|
+
"collection": "users",
|
|
1568
|
+
"fields": [{ "name": "email", "type": "String", "required": true, "unique": true }],
|
|
1569
|
+
"timestamps": true,
|
|
1570
|
+
"indexes": ["email"]
|
|
1571
|
+
}],
|
|
1572
|
+
"middleware": [{ "name": "authMiddleware", "type": "auth", "config": {} }],
|
|
1573
|
+
"envVars": ["PORT", "DATABASE_URL", "JWT_SECRET", "NODE_ENV"]
|
|
1574
|
+
}`;function dn(t){return ya.replace("{requirement}",t)}var So=q("validate_express",Xe,"Validates an Express config JSON string against the ExpressConfig schema. Returns valid: true or valid: false with errors.","config");function bo(t){return h({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:zod.z.object({requirement:zod.z.string().describe("Data model, API design, and project requirements")}),handler:async({requirement:e})=>{let o=dn(e),r=[{role:"system",content:"You are an Express.js architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,Xe)}})}function Ol(t){return {appName:t.appName,port:t.port,database:t.database,routers:t.routers,models:t.models,middleware:t.middleware,envVars:t.envVars,modules:t.routers.map(e=>({name:e.resource,pascalName:e.name.charAt(0).toUpperCase()+e.name.slice(1),camelName:e.resource,methods:e.methods}))}}var xo=h({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:zod.z.object({config:zod.z.string().describe("JSON string of the validated Express config"),outputDir:zod.z.string().describe("Absolute path to the output directory")}),handler:async({config:t,outputDir:e})=>{let o=be(t,"express config"),r=Te__namespace.resolve(process.cwd(),".ref/templates/express"),n=Ol(o);return le({templateDir:r,outputDir:e,context:n})}});function mn(t){return {validate_express:So,generate_express:bo(t),scaffold_express:xo}}var Cl=`You are an Express.js route specialist. Given an API design, you generate route definitions using a co-located router pattern.
|
|
1575
|
+
|
|
1576
|
+
## Co-located Router Pattern
|
|
1577
|
+
Each feature lives in src/routers/{name}/ with three files:
|
|
1578
|
+
- {name}.router.ts -- Express Router with route definitions
|
|
1579
|
+
- {name}.controller.ts -- Request handler logic
|
|
1580
|
+
- {name}.spec.ts -- Jest tests using supertest
|
|
1581
|
+
|
|
1582
|
+
## Route Design
|
|
1583
|
+
For each resource:
|
|
1584
|
+
- Base path: /api/{resource} (pluralized, lowercase)
|
|
1585
|
+
- GET / -> list all (with pagination: page, limit, sort query params)
|
|
1586
|
+
- GET /:id -> get by ID
|
|
1587
|
+
- POST / -> create new
|
|
1588
|
+
- PUT /:id -> update by ID
|
|
1589
|
+
- DELETE /:id -> delete by ID
|
|
1590
|
+
- Custom routes for non-CRUD operations
|
|
1591
|
+
|
|
1592
|
+
## Health Check
|
|
1593
|
+
Every app includes a /health router in src/routers/health/:
|
|
1594
|
+
- health.router.ts -- GET /health returning server status
|
|
1595
|
+
- health.controller.ts -- Health check handler
|
|
1596
|
+
- health.spec.ts -- Health check tests
|
|
1597
|
+
|
|
1598
|
+
## Route Organization
|
|
1599
|
+
- One router directory per resource with co-located controller and spec
|
|
1600
|
+
- Central src/routers/index.ts mounts all routers
|
|
1601
|
+
- Middleware applied per-route or per-router
|
|
1602
|
+
|
|
1603
|
+
## Controller Mapping
|
|
1604
|
+
- Each route maps to a controller method in the co-located controller file
|
|
1605
|
+
- Controller method name follows convention: getAll, getById, create, update, delete
|
|
1606
|
+
|
|
1607
|
+
## Validation
|
|
1608
|
+
- Request body validation using Zod schemas
|
|
1609
|
+
- Param validation (e.g. valid ObjectId)
|
|
1610
|
+
- Query param parsing and defaults
|
|
1611
|
+
|
|
1612
|
+
Respond with structured route definitions. Do NOT return JSON.`,To=f({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:Cl,tools:{},maxIterations:2});var Nl=`You are an Express.js middleware specialist. You design the complete middleware stack.
|
|
1613
|
+
|
|
1614
|
+
## Core Middleware
|
|
1615
|
+
1. **CORS**: Configure allowed origins, methods, headers, credentials
|
|
1616
|
+
2. **Body parser**: JSON and URL-encoded body parsing with size limits
|
|
1617
|
+
3. **Helmet**: Security headers (CSP, HSTS, X-Frame-Options)
|
|
1618
|
+
4. **Morgan/Logger**: Request logging with format and stream
|
|
1619
|
+
|
|
1620
|
+
## Auth Middleware
|
|
1621
|
+
1. **JWT verification**: Extract token from Authorization header or cookie
|
|
1622
|
+
2. **Role check**: Verify user role against required roles
|
|
1623
|
+
3. **Resource ownership**: Check if user owns the resource they're accessing
|
|
1624
|
+
|
|
1625
|
+
## Validation Middleware
|
|
1626
|
+
1. **Request validation**: Validate body, params, query using Zod schemas
|
|
1627
|
+
2. **Sanitization**: Strip HTML, trim whitespace
|
|
1628
|
+
|
|
1629
|
+
## Error Handling
|
|
1630
|
+
1. **Not found handler**: 404 for unmatched routes
|
|
1631
|
+
2. **Error handler**: Centralized error response with status codes
|
|
1632
|
+
3. **Async wrapper**: Catch async errors without try-catch
|
|
1633
|
+
|
|
1634
|
+
## Rate Limiting
|
|
1635
|
+
1. **Global**: Limit requests per IP per time window
|
|
1636
|
+
2. **Auth routes**: Stricter limits on login/signup
|
|
1637
|
+
|
|
1638
|
+
Respond with structured middleware analysis. Do NOT return JSON.`,Po=f({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:Nl,tools:{},maxIterations:2});var Dl=`${pn}
|
|
1639
|
+
|
|
1640
|
+
You are the Express builder orchestrator. When the user provides requirements:
|
|
1641
|
+
|
|
1642
|
+
1. **Generate routes**: Use subagent_route-generator to design route definitions from the API design.
|
|
1643
|
+
2. **Configure middleware**: Use subagent_middleware-configurator to design the middleware stack.
|
|
1644
|
+
3. **Generate config**: Use generate_express to produce the complete Express configuration as JSON.
|
|
1645
|
+
4. **Validate**: Use validate_express to check the config JSON before returning.
|
|
1646
|
+
5. **Scaffold (optional)**: If an output directory is provided, use scaffold_express to compile templates.
|
|
1647
|
+
|
|
1648
|
+
Respond with the final Express config as JSON.`;async function kl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=mn(s),l=I([To,Po],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:Dl,input:e,maxIterations:r,onStep:n,logger:a})}var xa=t=>zod.z.string().transform(e=>e.toLowerCase().trim()).pipe(zod.z.enum(t)),_l=zod.z.string().transform(t=>t.toUpperCase().trim()).pipe(zod.z.enum(["GET","POST","PUT","PATCH","DELETE"])),Ta=zod.z.object({path:zod.z.string(),name:zod.z.string(),access:xa(["public","protected"]),routeGroup:zod.z.string().default(""),purpose:zod.z.string(),hasForm:zod.z.coerce.boolean().default(false),formFields:zod.z.array(zod.z.string()).default([]),dataFetching:xa(["server","client","hybrid"]).default("server"),actions:zod.z.array(zod.z.string()).default([])}),Pa=zod.z.object({name:zod.z.string(),path:zod.z.string(),routeGroup:zod.z.string().default(""),components:zod.z.array(zod.z.string()).default([]),purpose:zod.z.string()}),Ra=zod.z.object({path:zod.z.string(),methods:zod.z.array(_l).default([]),auth:zod.z.coerce.boolean().default(true),description:zod.z.string()}),wa=zod.z.object({name:zod.z.string(),module:zod.z.string(),description:zod.z.string(),revalidates:zod.z.array(zod.z.string()).default([])}),Ze=zod.z.object({appName:zod.z.string().default("app"),pages:zod.z.array(Ta).default([]),layouts:zod.z.array(Pa).default([]),apiRoutes:zod.z.array(Ra).default([]),serverActions:zod.z.array(wa).default([]),middleware:zod.z.array(zod.z.string()).default([]),envVars:zod.z.array(zod.z.string()).default([]),packages:zod.z.array(zod.z.string()).default([])});var gn=`You are an expert Next.js application architect using the App Router.
|
|
1649
|
+
|
|
1650
|
+
You generate production-ready Next.js configurations from frontend designs and API designs:
|
|
1651
|
+
- App Router file structure with route groups, layouts, pages, loading, and error boundaries
|
|
1652
|
+
- Server Components by default, Client Components only when interactivity is needed
|
|
1653
|
+
- Server Actions for mutations (form submissions, data writes)
|
|
1654
|
+
- API Route Handlers for external integrations, webhooks, and file uploads
|
|
1655
|
+
- Next.js middleware for auth guards and redirects
|
|
1656
|
+
- Data fetching strategy (server vs client vs hybrid per page)
|
|
1657
|
+
- Package recommendations (next-auth, prisma, tailwindcss, shadcn/ui)
|
|
1658
|
+
|
|
1659
|
+
Output only valid JSON unless instructed otherwise.`;var va=`## Requirements:
|
|
1660
|
+
{requirement}
|
|
1661
|
+
|
|
1662
|
+
Generate a Next.js App Router application configuration. Include:
|
|
1663
|
+
|
|
1664
|
+
1. Pages: app router pages with path, name, access level, route group, purpose, data fetching strategy.
|
|
1665
|
+
2. Layouts: shared layouts with route groups (e.g. (auth), (dashboard)), components they include.
|
|
1666
|
+
3. API Routes: route handlers with path, HTTP methods, auth requirement, description.
|
|
1667
|
+
4. Server Actions: named actions with module, description, and paths they revalidate.
|
|
1668
|
+
5. Middleware: list of middleware behaviors (e.g. "redirect unauthenticated to /login").
|
|
1669
|
+
6. Env vars: NEXTAUTH_SECRET, DATABASE_URL, etc.
|
|
1670
|
+
7. Packages: recommended npm packages.
|
|
1671
|
+
|
|
1672
|
+
Return ONLY valid JSON:
|
|
1673
|
+
{
|
|
1674
|
+
"appName": "my-app",
|
|
1675
|
+
"pages": [{
|
|
1676
|
+
"path": "/dashboard",
|
|
1677
|
+
"name": "Dashboard",
|
|
1678
|
+
"access": "protected",
|
|
1679
|
+
"routeGroup": "(dashboard)",
|
|
1680
|
+
"purpose": "Main dashboard with stats",
|
|
1681
|
+
"hasForm": false,
|
|
1682
|
+
"formFields": [],
|
|
1683
|
+
"dataFetching": "server",
|
|
1684
|
+
"actions": []
|
|
1685
|
+
}],
|
|
1686
|
+
"layouts": [{
|
|
1687
|
+
"name": "DashboardLayout",
|
|
1688
|
+
"path": "app/(dashboard)/layout.tsx",
|
|
1689
|
+
"routeGroup": "(dashboard)",
|
|
1690
|
+
"components": ["Sidebar", "Header"],
|
|
1691
|
+
"purpose": "Shared layout for authenticated pages"
|
|
1692
|
+
}],
|
|
1693
|
+
"apiRoutes": [{
|
|
1694
|
+
"path": "/api/users",
|
|
1695
|
+
"methods": ["GET", "POST"],
|
|
1696
|
+
"auth": true,
|
|
1697
|
+
"description": "User CRUD endpoints"
|
|
1698
|
+
}],
|
|
1699
|
+
"serverActions": [{
|
|
1700
|
+
"name": "createUser",
|
|
1701
|
+
"module": "users",
|
|
1702
|
+
"description": "Create a new user",
|
|
1703
|
+
"revalidates": ["/dashboard/users"]
|
|
1704
|
+
}],
|
|
1705
|
+
"middleware": ["Redirect unauthenticated users to /login"],
|
|
1706
|
+
"envVars": ["DATABASE_URL", "NEXTAUTH_SECRET"],
|
|
1707
|
+
"packages": ["next-auth", "prisma", "@prisma/client", "tailwindcss"]
|
|
1708
|
+
}`;function fn(t){return va.replace("{requirement}",t)}var Ro=q("validate_nextjs",Ze,"Validates a Next.js config JSON string against the NextjsConfig schema. Returns valid: true or valid: false with errors.","config");function wo(t){return h({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:zod.z.object({requirement:zod.z.string().describe("Frontend design, API design, and project requirements")}),handler:async({requirement:e})=>{let o=fn(e),r=[{role:"system",content:"You are a Next.js architect. Return only valid JSON."},{role:"user",content:o}],n=await t.invoke(r,{temperature:.3,maxOutputTokens:16384});return M(n.text,Ze)}})}function hn(t){return {validate_nextjs:Ro,generate_nextjs:wo(t)}}var Il=`You are a Next.js App Router specialist. Given page specs, you plan the file structure.
|
|
1709
|
+
|
|
1710
|
+
## Route Groups
|
|
1711
|
+
- (auth) for public auth pages: login, signup, forgot-password
|
|
1712
|
+
- (dashboard) or (app) for protected pages
|
|
1713
|
+
- (marketing) for public landing pages
|
|
1714
|
+
|
|
1715
|
+
## File Structure Per Route
|
|
1716
|
+
- page.tsx: the page component (Server Component by default)
|
|
1717
|
+
- layout.tsx: shared layout for the route group
|
|
1718
|
+
- loading.tsx: Suspense fallback
|
|
1719
|
+
- error.tsx: error boundary (must be Client Component)
|
|
1720
|
+
- not-found.tsx: 404 page
|
|
1721
|
+
|
|
1722
|
+
## Data Fetching
|
|
1723
|
+
- Server Components: fetch data directly in the component (async function)
|
|
1724
|
+
- Client Components: use SWR or React Query for client-side fetching
|
|
1725
|
+
- Server Actions: for form submissions and mutations
|
|
1726
|
+
|
|
1727
|
+
## Conventions
|
|
1728
|
+
- Use lowercase kebab-case for route segments
|
|
1729
|
+
- Dynamic segments: [id], [slug]
|
|
1730
|
+
- Catch-all: [...slug]
|
|
1731
|
+
- Parallel routes: @modal, @sidebar
|
|
1732
|
+
- Intercepting routes: (.)photo, (..)details
|
|
1733
|
+
|
|
1734
|
+
Respond with the full file tree and route structure. Do NOT return JSON.`,vo=f({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:Il,tools:{},maxIterations:2});var jl=`You are a Next.js API specialist. Given an API design, you plan route handlers and server actions.
|
|
1735
|
+
|
|
1736
|
+
## API Route Handlers (app/api/)
|
|
1737
|
+
For external integrations, webhooks, and file uploads:
|
|
1738
|
+
- One route.ts file per resource: app/api/[resource]/route.ts
|
|
1739
|
+
- Export named functions: GET, POST, PUT, DELETE
|
|
1740
|
+
- Use NextRequest and NextResponse
|
|
1741
|
+
- Add auth checks using next-auth getServerSession
|
|
1742
|
+
|
|
1743
|
+
## Server Actions (preferred for mutations)
|
|
1744
|
+
For form submissions and data writes:
|
|
1745
|
+
- Define in separate files: app/actions/[module].ts
|
|
1746
|
+
- Use 'use server' directive
|
|
1747
|
+
- Use revalidatePath or revalidateTag after mutations
|
|
1748
|
+
- Return typed results with error handling
|
|
1749
|
+
|
|
1750
|
+
## When to Use Which
|
|
1751
|
+
- Server Actions: form submissions, data CRUD, anything triggered by user action
|
|
1752
|
+
- API Routes: webhooks from external services, file uploads, OAuth callbacks, public APIs
|
|
1753
|
+
|
|
1754
|
+
## Auth Integration
|
|
1755
|
+
- API Routes: check session with getServerSession
|
|
1756
|
+
- Server Actions: check session at the start of each action
|
|
1757
|
+
- Middleware: protect route groups with matcher patterns
|
|
1758
|
+
|
|
1759
|
+
Respond with structured analysis per module. Do NOT return JSON.`,Eo=f({name:"api-route-generator",description:"Generates Next.js API route handlers and server actions from API design. Use after route planning.",systemPrompt:jl,tools:{},maxIterations:2});var ql=`${gn}
|
|
1760
|
+
|
|
1761
|
+
You are the Next.js builder orchestrator. When the user provides requirements:
|
|
1762
|
+
|
|
1763
|
+
1. **Plan routes**: Use subagent_route-planner to design the App Router file structure with route groups and layouts.
|
|
1764
|
+
2. **Generate API routes**: Use subagent_api-route-generator to design API route handlers and server actions.
|
|
1765
|
+
3. **Generate config**: Use generate_nextjs to produce the complete Next.js configuration as JSON.
|
|
1766
|
+
4. **Validate**: Use validate_nextjs to check the config JSON before returning.
|
|
1767
|
+
|
|
1768
|
+
Respond with the final Next.js config as JSON.`;async function Fl(t){let{input:e,model:o,maxIterations:r=15,onStep:n,logger:a}=t,s=v(o??{provider:"openai",model:"gpt-4o-mini"}),i=hn(s),l=I([vo,Eo],{parentModel:s}),c={...i,...l};return C({model:s,tools:c,systemPrompt:ql,input:e,maxIterations:r,onStep:n,logger:a})}Object.defineProperty(exports,"jsonSchema",{enumerable:true,get:function(){return ai$1.jsonSchema}});Object.defineProperty(exports,"tool",{enumerable:true,get:function(){return ai$1.tool}});exports.API_DESIGNER_SYSTEM_PROMPT=Xt;exports.APOLLO_BUILDER_SYSTEM_PROMPT=sn;exports.AUTH_DESIGNER_SYSTEM_PROMPT=zr;exports.AgentError=et;exports.ApiResponseTypeSchema=Lo;exports.AppConfigSchema=qo;exports.ApplicationSchema=Ue;exports.AuthPageApiSchema=jn;exports.AuthPageSchema=qn;exports.BACKEND_ARCHITECT_SYSTEM_PROMPT=en;exports.BaseMcpClient=st;exports.BrandingSchema=jo;exports.CREATE_EXECUTION_PLAN_PROMPT=Xs;exports.ColumnSchema=Fo;exports.CreateUserInputSchema=Wa;exports.DATA_MODELER_SYSTEM_PROMPT=Lt;exports.DB_DESIGN_SYSTEM_PROMPT=K;exports.DESIGN_AUTH_PROMPT=Gs;exports.DESIGN_BACKEND_PROMPT=na;exports.DESIGN_DATABASE_SYSTEM_PROMPT=er;exports.DESIGN_EXPRESS_PROMPT=ya;exports.DESIGN_FRONTEND_PROMPT=$s;exports.DESIGN_NEXTJS_PROMPT=va;exports.DESIGN_SUBGRAPH_PROMPT=ca;exports.DISCOVERY_SYSTEM_FRAGMENT=Qo;exports.DISCOVERY_USER_PROMPT=Xn;exports.DrawerSchema=Uo;exports.EXAMPLE_GRAPHQL_SCHEMA=Gn;exports.EXAMPLE_JSON_OUTPUT=Jn;exports.EXECUTION_PLANNER_SYSTEM_PROMPT=Kr;exports.EXPRESS_BUILDER_SYSTEM_PROMPT=pn;exports.EXTRACT_ACTORS_PROMPT=Zn;exports.EXTRACT_MODULES_PROMPT=os;exports.FRONTEND_ARCHITECT_SYSTEM_PROMPT=Qr;exports.FieldOptionsSchema=_n;exports.ForgotPasswordSchema=Xa;exports.FormFieldSchema=at;exports.GENERATE_FLOWS_PROMPT=es;exports.GENERATE_STORIES_PROMPT=ts;exports.LibraryError=de;exports.ListingPageApiSchema=In;exports.ListingPageSchema=Fn;exports.LoginInputSchema=Qa;exports.MONGODB_SYSTEM_PROMPT=K;exports.ModelError=ae;exports.ModuleSchema=Un;exports.NEXTJS_BUILDER_SYSTEM_PROMPT=gn;exports.PLANNING_SYSTEM_PROMPT=ee;exports.PageSchema=Go;exports.PlanningContextBuilder=Ut;exports.REACT_BUILDER_INSTRUCTION=it;exports.REACT_BUILDER_SYSTEM_PROMPT=Le;exports.REQUIREMENT_GATHERER_SYSTEM_PROMPT=ge;exports.RequirementContextBuilder=Mt;exports.ResetPasswordSchema=Za;exports.SYNTHESIS_SYSTEM_FRAGMENT=or;exports.SYNTHESIS_USER_PROMPT=rs;exports.SpecializationSchema=Ln;exports.SubagentError=Se;exports.ToolError=$;exports.UpdateUserInputSchema=Ka;exports.UserSchema=Va;exports.ValidationError=yn;exports.ValidationSchema=kn;exports.actorSchema=Re;exports.actorsResultSchema=ut;exports.adApiDesignSchema=ce;exports.adGraphqlOperationSchema=Gr;exports.adRestEndpointSchema=Lr;exports.addChatEntry=Ge;exports.advanceStage=St;exports.apiRouteGeneratorSubagent=Eo;exports.assemblePlan=Pr;exports.authDesignSchema=He;exports.authFlowSchema=qs;exports.authFlowStepSchema=js;exports.authMiddlewareSchema=Fs;exports.backendDesignSchema=We;exports.buildCreateExecutionPlanPrompt=Xr;exports.buildDesignAuthPrompt=$r;exports.buildDesignBackendPrompt=tn;exports.buildDesignDatabasePrompt=tr;exports.buildDesignExpressPrompt=dn;exports.buildDesignFrontendPrompt=Vr;exports.buildDesignNextjsPrompt=fn;exports.buildDesignSubgraphPrompt=an;exports.buildDiscoveryPrompt=Vo;exports.buildExampleShotPrompt=Bo;exports.buildExtractActorsPrompt=Wo;exports.buildExtractModulesPrompt=Zo;exports.buildFeedbackPrompt=ei;exports.buildGenerateFlowsPrompt=Ko;exports.buildGenerateStoriesPrompt=Xo;exports.buildInstructionPrompt=Jo;exports.buildPromptVariables=Bt;exports.buildSynthesisPrompt=rr;exports.chatEntrySchema=Wn;exports.compileTemplate=ko;exports.componentAnalyzerSubagent=_t;exports.componentDesignSchema=zs;exports.contractDesignerSubagent=Ne;exports.convertRequirementToContext=Rs;exports.createAnthropicModel=rt;exports.createApiDesignerTools=Yr;exports.createApolloBuilderTools=cn;exports.createAuthDesignerTools=Hr;exports.createBackendArchitectTools=on;exports.createConfigValidatorSubagent=dt;exports.createDataModelerTools=qr;exports.createDbDesignPrompt=Je;exports.createDbDesignerTools=Fr;exports.createDesignApiProTool=to;exports.createDesignApiTool=eo;exports.createDesignAuthTool=ro;exports.createDesignBackendTool=co;exports.createDesignDatabaseProTool=Wt;exports.createDesignDatabaseTool=Vt;exports.createDesignFrontendTool=so;exports.createDesignSchemaProTool=$t;exports.createDesignSchemaTool=zt;exports.createExecutionPlanTool=io;exports.createExecutionPlannerTools=Zr;exports.createExpressBuilderTools=mn;exports.createFrontendArchitectTools=Wr;exports.createGenerateExpressTool=bo;exports.createGenerateFeatureBreakdownTool=ct;exports.createGenerateFrontendTool=lt;exports.createGenerateNextjsTool=wo;exports.createGenerateSubgraphTool=go;exports.createGoogleModel=nt;exports.createInitialContext=nr;exports.createLogger=Jl;exports.createModel=v;exports.createMongoDesignPrompt=Je;exports.createMongoProDesignPrompt=Be;exports.createMongoRedesignPrompt=Ye;exports.createNextjsBuilderTools=hn;exports.createOpenAIModel=ot;exports.createPlanningContextBuilder=Xi;exports.createProDbDesignPrompt=Be;exports.createReactBuilderTools=$o;exports.createRedesignDatabaseTool=Kt;exports.createRedesignPrompt=Ye;exports.createRefineSchemaTools=Ht;exports.createRequirementContextBuilder=gi;exports.createSchemaRefinerSubagent=fe;exports.createSubagentTool=Do;exports.createSubagentToolSet=I;exports.createToolSet=_;exports.crudApiSchema=zn;exports.databaseDesignSchema=me;exports.databaseEntitySchema=Vn;exports.defineSubagent=f;exports.defineTool=h;exports.dmCreateSchemaRefinerSubagent=fe;exports.dmDataEntitySchema=Ar;exports.dmDataModelDesignSchema=te;exports.dmEntityAnalyzerSubagent=ne;exports.dmValidateSchemaTool=Yt;exports.edgeCaseAnalyzerSubagent=De;exports.edgeCaseSchema=Ws;exports.editPlan=Ji;exports.endpointAnalyzerSubagent=Ce;exports.entityAnalyzerSubagent=ne;exports.entityFieldSchema=$n;exports.entityIndexSchema=Hn;exports.entityRelationSchema=Qn;exports.executeTool=Oo;exports.executeToolByName=tt;exports.executionPlanSchema=Ve;exports.expressConfigSchema=Xe;exports.extractDataEntities=Gt;exports.extractJson=Ma;exports.extractRoles=Jt;exports.extractedModuleSchema=Ee;exports.fieldSchema=_e;exports.finalRequirementSchema=Ho;exports.flowDesignerSubagent=Oe;exports.flowSchema=we;exports.flowsResultSchema=mt;exports.formFieldSchema=Bs;exports.formatTechnicalRequirements=_r;exports.formatUserFlows=Dr;exports.formatUserStories=kr;exports.formatUserTypes=Nr;exports.frameworkSelectorSubagent=uo;exports.frontendDesignSchema=Qe;exports.getTool=Tn;exports.getTools=xn;exports.graphqlAnalyzerSubagent=pt;exports.graphqlFieldSchema=rn;exports.graphqlTypeSchema=nn;exports.helloWorldTool=Io;exports.implementationPhaseSchema=Vs;exports.loggerConfigFromEnv=Bl;exports.mergeStageResult=sr;exports.middlewareConfigSchema=ha;exports.middlewareConfiguratorSubagent=Po;exports.middlewareSchema=ta;exports.modelFieldSchema=ga;exports.modelSchema=fa;exports.moduleSchema=Ie;exports.modulesResultSchema=ft;exports.mongoFieldSchema=_e;exports.mongoModuleSchema=Ie;exports.mongoProjectSchema=W;exports.nextjsApiRouteSchema=Ra;exports.nextjsConfigSchema=Ze;exports.nextjsLayoutSchema=Pa;exports.nextjsPageSchema=Ta;exports.pageDesignSchema=Ys;exports.pagePlannerSubagent=Me;exports.parseModelJsonResponse=M;exports.phaseStepSchema=Qs;exports.processPlanningChat=he;exports.processRequirementChat=At;exports.projectBriefSchema=Ae;exports.projectSchema=W;exports.questionSchema=ht;exports.registerHelpers=_o;exports.relationshipMapperSubagent=kt;exports.requirementContextSchema=ii;exports.requirementSummarySchema=Kn;exports.resolverOperationSchema=ia;exports.resolverPlannerSubagent=yo;exports.roleDefinitionSchema=Us;exports.routeGeneratorSubagent=To;exports.routeGroupSchema=ra;exports.routePlannerSubagent=vo;exports.routerMethodSchema=ua;exports.routerSchema=ma;exports.runAgent=C;exports.runApiDesignerAgent=cl;exports.runApolloBuilderAgent=Al;exports.runAuthDesignerAgent=dl;exports.runBackendArchitectAgent=Pl;exports.runDataModelerAgent=rl;exports.runDbDesignerAgent=sl;exports.runExecutionPlannerAgent=yl;exports.runExpressBuilderAgent=kl;exports.runFrontendArchitectAgent=fl;exports.runHelloWorldAgent=Ha;exports.runNextjsBuilderAgent=Fl;exports.runPlanningAgent=Gi;exports.runPlanningFromRequirements=Wi;exports.runReactBuilderAgent=ai;exports.runRequirementGathererAgent=ui;exports.runSubagent=z;exports.safeJsonParse=be;exports.scaffoldExpressTool=xo;exports.scaffoldProject=le;exports.scaffoldSubgraphTool=fo;exports.schemaGeneratorSubagent=ho;exports.securityAnalyzerSubagent=It;exports.securityPolicySchema=Ls;exports.serverActionSchema=wa;exports.servicePlannerSubagent=po;exports.serviceSchema=oa;exports.storiesResultSchema=gt;exports.storySchema=ve;exports.subgraphConfigSchema=Ke;exports.subgraphModuleSchema=la;exports.sumTokenUsage=Mo;exports.testChecklistItemSchema=Ks;exports.testingStrategistSubagent=ke;exports.validateApiTool=Zt;exports.validateAuthTool=oo;exports.validateBackendTool=lo;exports.validateExecutionPlanTool=ao;exports.validateExpressTool=So;exports.validateFrontendConfigTool=Pe;exports.validateFrontendTool=no;exports.validateNextjsTool=Ro;exports.validateSchemaTool=Qt;exports.validateSubgraphTool=mo;exports.writePlanToFile=Ii;//# sourceMappingURL=index.cjs.map
|
|
487
1769
|
//# sourceMappingURL=index.cjs.map
|