sweagent 0.0.1
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/LICENSE +21 -0
- package/README.md +755 -0
- package/dist/index.cjs +487 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1816 -0
- package/dist/index.d.ts +1816 -0
- package/dist/index.js +487 -0
- package/dist/index.js.map +1 -0
- package/package.json +107 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import {z}from'zod';import {tool,generateText}from'ai';export{jsonSchema,tool}from'ai';import {createOpenAI}from'@ai-sdk/openai';import {createAnthropic}from'@ai-sdk/anthropic';import {createGoogleGenerativeAI}from'@ai-sdk/google';import {Client}from'@modelcontextprotocol/sdk/client';import {createRequire}from'module';import k from'path';import {pathToFileURL}from'url';var M=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}`);}},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 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 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 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=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=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=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:z.object({prompt: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=createRequire(import.meta.url).resolve("@modelcontextprotocol/sdk/client");return k.dirname(k.dirname(k.dirname(k.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.join(Fe,"dist","esm","client","streamableHttp.js"),r=await import(pathToFileURL(o).href),n=e?{headers:new Headers(e)}:void 0;return new r.StreamableHTTPClientTransport(new URL(t),n?{requestInit:n}:void 0)}async function Ge(t,e){let o=k.join(Fe,"dist","esm","client","stdio.js"),r=await import(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({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:z.object({name: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=z.object({fieldName:z.string().describe("fieldName must be in camelCase"),fieldType:z.enum(["string","number","boolean","Types.ObjectId","Date","object","email","password","enum"]),isArray:z.boolean(),isRequired:z.boolean(),isUnique:z.boolean(),values:z.array(z.string()).describe("Enum values if fieldType is enum, else empty array"),defaultVal:z.union([z.string(),z.boolean(),z.number(),z.null()]).optional(),relationTo:z.string().optional().describe("Module name for relations"),relationType:z.enum(["one-to-one","many-to-one",""]).optional(),isPrivate:z.boolean().describe("True if password field, else false")});var ge=z.object({moduleName:z.string().describe("camelCase, single word, never auth/authentication"),isUserModule:z.boolean(),authMethod:z.enum(["EMAIL_AND_PASSWORD","PHONE_AND_OTP",""]).optional(),emailField:z.string().optional(),passwordField:z.string().optional(),phoneField:z.string().optional(),roleField:z.string().optional(),permissions:z.record(z.string(),z.array(z.enum(["CREATE","READ","UPDATE","DELETE"]))).optional().describe("Permissions per role"),fields:z.array(ue)});var A=z.object({projectName:z.string().describe("projectName must be in kebab-case"),projectDescription:z.string(),modules:z.array(ge),author: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
|
+
You MUST follow this 5-phase analysis process before generating the schema:
|
|
7
|
+
|
|
8
|
+
### PHASE 1: Entity Discovery
|
|
9
|
+
Systematically extract all entities from the provided requirements:
|
|
10
|
+
|
|
11
|
+
1. **From dataInvolved fields**: Every item in user stories' dataInvolved[] array indicates a potential entity or field
|
|
12
|
+
- Pattern: "User Profile" \u2192 user collection with profile fields
|
|
13
|
+
- Pattern: "Order Items" \u2192 order collection + item collection with relationship
|
|
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:z.object({schema: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 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:z.object({requirement: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=z.object({projectName:z.string(),projectGoal:z.string(),projectDescription:z.string().optional(),actors:z.array(z.object({id:z.string(),name:z.string(),description:z.string(),goals:z.array(z.string())})),flows:z.array(z.object({id:z.string(),actorId:z.string(),name:z.string(),description:z.string(),trigger:z.string(),outcome:z.string()})),stories:z.array(z.object({id:z.string(),flowId:z.string(),actor:z.string(),action:z.string(),benefit:z.string(),preconditions:z.array(z.string()),postconditions:z.array(z.string()),dataInvolved:z.array(z.string())})),technicalRequirements:z.object({authentication:z.enum(["none","email","oauth","phone","email_and_phone"]),authorization:z.boolean(),roles:z.array(z.string()).optional(),integrations:z.array(z.string()).optional(),realtime:z.boolean().optional(),fileUpload:z.boolean().optional(),search:z.boolean().optional()}).optional()});function 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:z.object({existingSchema:z.string().describe("Current project schema as JSON string"),feedback: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=z.object({brandName:z.string().describe("The brand's display name"),primaryColor:z.string().describe("The brand's primary color code (e.g., #FFFFFF)"),secondaryColor:z.string().describe("The brand's secondary color code (e.g., #000000)"),logo:z.url().describe("URL pointing to the brand's logo")});var ve=z.object({name:z.string().describe("Application name"),description:z.string().describe("Brief description of the application"),author:z.string().describe("Author or owner of the application").default("sijeeshmiziha (HubSpire)"),branding:Re.describe("Branding information for the application"),apiEndpoint:z.url().describe("URL endpoint for the app's API calls")});var Ze=z.object({minLength:z.number().optional().describe("Minimum length requirement"),zodString:z.string().describe("Raw Zod string validation (e.g. regex)")}),Xe=z.object({hookName:z.string().optional().describe("Name of the hook for dynamic field options"),queryString:z.string().optional().describe("Optional query string for fetching field options"),labelKey:z.string().optional().describe("Key used as label when displaying options"),valueKey:z.string().optional().describe("Key used as value for a field when selecting options"),values:z.array(z.string()).optional().describe("Static list of possible field values")}),re=z.object({name:z.string().describe("The field's key or identifier"),type:z.enum(["text","email","password","number","multiSelect","textarea","hidden","select","date","image"]).describe('Type of input field. If it has options, it should not be "hidden". If the field is required, it should not be hidden unless it serves as the current user.'),required:z.boolean().optional().describe("Whether this field must be filled"),validation:Ze.optional().describe("Optional field validation requirements"),defaultValue:z.union([z.string(),z.number(),z.boolean()]).optional().describe("Default value can be string, number, or boolean"),options:Xe.optional().describe("Additional dynamic or static options for this field")}),Ae=z.object({field:z.string().describe("Key or name of the data field in the table"),label:z.string().describe("User-friendly label to show on the table header")});var Me=z.object({type:z.string().describe("Indicates the response type (e.g., 'object')"),properties:z.record(z.string(),z.object({type:z.string().describe("Property type as returned by the API")})).describe("Key-value record describing each field in the response")}).optional().describe("Describes the expected structure of an API response"),et=z.object({type:z.enum(["list","create","update","delete","getById"]).describe("Type of API call for CRUD operations"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useGetAllUserQuery, useCreateUserMutation)"),queryString:z.string().describe("Actual GraphQL query string"),responseType:Me.describe("Optional schema describing shape of the API response")}),tt=z.object({type:z.enum(["login","currentUser","forgotPassword","resetPassword"]).describe("Type of API call"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useLoginMutation)"),queryString:z.string().describe("Actual GraphQL query string"),responseType:Me.describe("Optional schema describing shape of the API response")}),Pe=z.object({title:z.string().describe("Title displayed on the drawer"),graphqlHook:z.string().describe("Name of the GraphQL hook (e.g. useCreateUserMutation, useDeleteOneUserMutation)"),fields:z.array(re).describe("List of fields displayed within the drawer")}),ot=z.object({name:z.enum(["LoginPage","ForgotPasswordPage","ResetPasswordPage"]).describe("Internal name of the auth page"),type:z.enum(["EmailPassword","ForgotPassword","ResetPassword"]).describe("Type of authentication page"),route:z.string().describe("URL route for this page (e.g., '/login')"),isPrivate:z.boolean().describe("Whether this page requires an authenticated session"),api:z.array(tt).describe("List of API calls involved in this page"),fields:z.array(re).optional().describe("Optional form fields needed on this auth page")}),rt=z.object({type:z.literal("Listing").describe("Indicates that this page is a listing-type page"),name:z.string().describe("Internal name of the listing page"),route:z.string().describe("URL route for this listing page"),isPrivate:z.boolean().describe("Whether this page is private (requires auth)"),api:z.array(et).describe("List of API calls that power this listing page"),columns:z.array(Ae).describe("Table columns displayed on the listing page"),actions:z.array(z.string()).describe("List of possible actions on each row (e.g., create, edit, delete, view)"),drawerCreate:Pe.describe("Drawer configuration for creating new records"),drawerUpdate:Pe.describe("Drawer configuration for editing existing records")}),Ce=z.discriminatedUnion("type",[ot,rt]);var nt=z.object({name:z.string().describe("Name of the module"),pages:z.array(Ce).describe("Pages included within this module")}),$=z.object({app:ve.describe("Overall application configuration"),modules: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=z.object({email:z.email().describe("User's email address, must be valid format"),password:z.string().min(8).describe("User's password, minimum length of 8")}),at=z.object({_id:z.string().describe("Unique identifier of the specialization, type: string"),title:z.string().describe("Display title for the specialization, type: string")}),Ut=z.object({_id:z.string().describe("Unique ID of the user, type: string"),firstName:z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:z.email().describe("Email address in valid format, type: string"),phoneNumber:z.string().min(10).describe("User's phone number, at least 10 digits, type: string"),profileImage:z.string().optional().describe("Optional URL to user's profile image, type: string, optional"),role:z.enum(["ADMIN","TRAINER","CLIENT"]).describe("User's role in the system (ADMIN, TRAINER, CLIENT)"),rate:z.number().min(1).optional().describe("User's rate (e.g., hourly, etc.), type: number, optional"),specializations:z.array(at).optional().describe("Array of specialization objects, optional"),languages:z.array(z.string()).optional().describe("Array of languages the user speaks, type: string[], optional"),about:z.string().min(20).max(500).optional().describe("Brief bio or description (20-500 chars), type: string, optional"),gender:z.string().optional().describe("User's gender, type: string, optional"),timezone:z.string().optional().describe("User's timezone, type: string, optional"),averageRating:z.number().optional().describe("Average rating for this user, type: number, optional")}),kt=z.object({firstName:z.string().min(2).max(30).describe("First name, 2-30 characters, type: string"),lastName:z.string().min(2).max(30).describe("Last name, 2-30 characters, type: string"),email:z.email().describe("Valid email for the new user, type: string"),phoneNumber:z.string().min(10).describe("Phone number (at least 10 digits), type: string"),password:z.string().min(8).describe("Password with min length 8, type: string"),role:z.enum(["ADMIN","TRAINER","CLIENT"]).describe("Role of the new user (ADMIN, TRAINER, CLIENT)"),rate:z.number().min(1).optional().describe("Rate for the new user, type: number, optional"),specializationIds:z.array(z.string()).min(1).optional().describe("Array of specialization IDs, optional"),languages:z.array(z.string()).min(1).optional().describe("List of languages user speaks, optional"),about:z.string().min(20).max(500).optional().describe("User's about/bio field, 20-500 chars, optional")}),_t=z.object({_id:z.string().describe("ID of the user to be updated, type: string"),firstName:z.string().min(2).max(30).optional().describe("Updated first name, type: string, optional"),lastName:z.string().min(2).max(30).optional().describe("Updated last name, type: string, optional"),email:z.email().optional().describe("Updated email, type: string, optional"),phoneNumber:z.string().min(10).optional().describe("Updated phone number, at least 10 digits, optional"),rate:z.number().min(1).optional().describe("Updated rate, type: number, optional"),specializationIds:z.array(z.string()).min(1).optional().describe("Updated array of specialization IDs, optional"),languages:z.array(z.string()).min(1).optional().describe("Updated list of languages, optional"),about:z.string().min(20).max(500).optional().describe("Updated about/bio (20-500 chars), optional")}),jt=z.object({email:z.email().describe("Email to initiate the password reset process, type: string")}),Lt=z.object({type:z.enum(["EMAIL","SMS"]).describe("How the reset code was sent (EMAIL or SMS)"),resetTicket:z.string().describe("Token/ticket to validate the reset request, type: string"),newPassword:z.string().min(8).describe("The new password, min length 8, type: string")});var B=`You are an expert GraphQL-to-frontend configuration converter. Transform the provided GraphQL schema into a structured JSON configuration for rapid app development.
|
|
303
|
+
|
|
304
|
+
**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
|
+
|
|
306
|
+
Strict guidelines:
|
|
307
|
+
- Use every available CRUD GraphQL query and mutation from the project schema.
|
|
308
|
+
- Map GraphQL types to frontend modules and pages.
|
|
309
|
+
- EmailAddress \u2192 "type": "email" with validation; DateTime \u2192 "type": "date"; enums \u2192 select with options.values.
|
|
310
|
+
- Relationships \u2192 multiSelect with query-based options where appropriate.
|
|
311
|
+
- Add isPrivate: true for authenticated operations.
|
|
312
|
+
- Maintain camelCase. Ensure valid JSON syntax.`;var ne=`
|
|
313
|
+
Act as an expert GraphQL-to-frontend configuration converter. Transform the provided schema into a structured JSON configuration for rapid app development.
|
|
314
|
+
|
|
315
|
+
**Conversion Process**
|
|
316
|
+
|
|
317
|
+
1. Schema Analysis:
|
|
318
|
+
- Identify all modules using 100% of available CRUD operations
|
|
319
|
+
- Catalog all Query/Mutation operations with arguments
|
|
320
|
+
- Map GraphQL types to frontend modules
|
|
321
|
+
- Detect @auth directives and role requirements
|
|
322
|
+
- Analyze relationships through nested types
|
|
323
|
+
|
|
324
|
+
2. Field Mapping:
|
|
325
|
+
- EmailAddress \u2192 "type": "email" with Zod email validation
|
|
326
|
+
- DateTime \u2192 "type": "date"
|
|
327
|
+
- Enums \u2192 dropdowns with options.values
|
|
328
|
+
- Relationships \u2192 multiSelect with query-based options
|
|
329
|
+
|
|
330
|
+
3. API Operations:
|
|
331
|
+
- For each Query/Mutation: determine CRUD type, generate query string with variables, map to React Hook, define response type shape
|
|
332
|
+
|
|
333
|
+
4. Validation:
|
|
334
|
+
- Generate Zod schemas from @required directives, scalar types (Password \u2192 min 8 chars), custom directives
|
|
335
|
+
- Include validation error messages
|
|
336
|
+
|
|
337
|
+
5. Security:
|
|
338
|
+
- Add isPrivate: true for authenticated operations
|
|
339
|
+
- Implement role checks from @auth directives
|
|
340
|
+
|
|
341
|
+
6. Output:
|
|
342
|
+
- Generate complete CRUD pages with table column mappings, validated Create/Update forms, API hooks
|
|
343
|
+
- Include Zod validation strings, maintain camelCase, valid JSON only
|
|
344
|
+
`.trim();function Ie(){return ne}var it=`
|
|
345
|
+
type Query {
|
|
346
|
+
getCurrentUser: User
|
|
347
|
+
getAllUser(limit: Int, offset: Int): [User]!
|
|
348
|
+
}
|
|
349
|
+
type Mutation {
|
|
350
|
+
login(data: LoginInput!): Login!
|
|
351
|
+
createUser(data: CreateUserInput!): User!
|
|
352
|
+
}
|
|
353
|
+
type User {
|
|
354
|
+
_id: ID!
|
|
355
|
+
firstName: String!
|
|
356
|
+
lastName: String!
|
|
357
|
+
email: String!
|
|
358
|
+
role: Role!
|
|
359
|
+
}
|
|
360
|
+
enum Role { ADMIN TRAINER CLIENT }
|
|
361
|
+
input LoginInput { email: String! password: String! }
|
|
362
|
+
input CreateUserInput { firstName: String! lastName: String! email: String! role: Role! }
|
|
363
|
+
`.trim(),st=`{
|
|
364
|
+
"app": {
|
|
365
|
+
"name": "my-app",
|
|
366
|
+
"description": "App description",
|
|
367
|
+
"author": "Author",
|
|
368
|
+
"branding": {
|
|
369
|
+
"brandName": "MyBrand",
|
|
370
|
+
"primaryColor": "#333",
|
|
371
|
+
"secondaryColor": "#fff",
|
|
372
|
+
"logo": "https://example.com/logo.png"
|
|
373
|
+
},
|
|
374
|
+
"apiEndpoint": "http://localhost:4000/graphql"
|
|
375
|
+
},
|
|
376
|
+
"modules": [
|
|
377
|
+
{
|
|
378
|
+
"name": "auth",
|
|
379
|
+
"pages": [
|
|
380
|
+
{
|
|
381
|
+
"name": "LoginPage",
|
|
382
|
+
"type": "EmailPassword",
|
|
383
|
+
"route": "/login",
|
|
384
|
+
"isPrivate": false,
|
|
385
|
+
"api": [
|
|
386
|
+
{ "type": "login", "graphqlHook": "useLoginMutation", "queryString": "mutation Login($data: LoginInput!) { login(data: $data) { accessToken } }" }
|
|
387
|
+
]
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"name": "user",
|
|
393
|
+
"pages": [
|
|
394
|
+
{
|
|
395
|
+
"type": "Listing",
|
|
396
|
+
"name": "UserListPage",
|
|
397
|
+
"route": "/users",
|
|
398
|
+
"isPrivate": true,
|
|
399
|
+
"api": [
|
|
400
|
+
{ "type": "list", "graphqlHook": "useGetAllUserQuery", "queryString": "query GetAllUser { getAllUser { _id firstName email } }" },
|
|
401
|
+
{ "type": "create", "graphqlHook": "useCreateUserMutation", "queryString": "mutation CreateUser($data: CreateUserInput!) { createUser(data: $data) { _id } }" }
|
|
402
|
+
],
|
|
403
|
+
"columns": [{ "field": "firstName", "label": "First Name" }, { "field": "email", "label": "Email" }],
|
|
404
|
+
"actions": ["create", "edit", "delete"],
|
|
405
|
+
"drawerCreate": { "title": "Create User", "graphqlHook": "useCreateUserMutation", "fields": [{ "name": "firstName", "type": "text", "required": true }, { "name": "email", "type": "email", "required": true }] },
|
|
406
|
+
"drawerUpdate": { "title": "Edit User", "graphqlHook": "useUpdateUserMutation", "fields": [{ "name": "firstName", "type": "text" }, { "name": "email", "type": "email" }] }
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}`;function Ee(){return `
|
|
412
|
+
**Reference Conversion Example**
|
|
413
|
+
|
|
414
|
+
EXAMPLE GRAPHQL INPUT:
|
|
415
|
+
\`\`\`graphql
|
|
416
|
+
${it}
|
|
417
|
+
\`\`\`
|
|
418
|
+
|
|
419
|
+
EXPECTED JSON OUTPUT:
|
|
420
|
+
\`\`\`json
|
|
421
|
+
${st}
|
|
422
|
+
\`\`\`
|
|
423
|
+
`.trim()}function qt(t,e){return `
|
|
424
|
+
Review the user feedback carefully to understand the required updates.
|
|
425
|
+
|
|
426
|
+
The user feedback for updating the generated Frontend Config JSON is provided below:
|
|
427
|
+
"""
|
|
428
|
+
${t}
|
|
429
|
+
"""
|
|
430
|
+
|
|
431
|
+
Now, generate the Frontend Config JSON for this project based on the provided feedback.
|
|
432
|
+
|
|
433
|
+
**Project GRAPHQL SCHEMA INPUT:**
|
|
434
|
+
\`\`\`graphql
|
|
435
|
+
${e}
|
|
436
|
+
\`\`\`
|
|
437
|
+
|
|
438
|
+
Update the Frontend Config JSON to incorporate the requested changes. Return ONLY valid JSON, no markdown code blocks.
|
|
439
|
+
`.trim()}var j=h({name:"validate_frontend_config",description:"Validates a frontend configuration JSON string against the ApplicationSchema. Returns valid: true or valid: false with errors array.",input:z.object({config:z.string().describe("JSON string of the frontend application config to validate")}),handler:async({config:t})=>{try{let e=JSON.parse(t);return $.parse(e),{valid:!0}}catch(e){return e instanceof 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 zt(t){let e=t.trim(),o=/```(?:json)?\s*([\s\S]*?)```/.exec(e);return o?.[1]?o[1].trim():e}function Ft(t,e){let o=Ie(),r=Ee(),n=e?`
|
|
440
|
+
**Project context:**
|
|
441
|
+
- name: ${e.projectName??"project"}
|
|
442
|
+
- description: ${e.projectDescription??""}
|
|
443
|
+
- modules: ${e.modules??""}
|
|
444
|
+
- apiEndpoint: ${e.apiEndpoint??"http://localhost:4000/graphql"}
|
|
445
|
+
`:"";return `${o}
|
|
446
|
+
|
|
447
|
+
${r}
|
|
448
|
+
${n}
|
|
449
|
+
|
|
450
|
+
**Current Project GraphQL Schema:**
|
|
451
|
+
\`\`\`graphql
|
|
452
|
+
${t}
|
|
453
|
+
\`\`\`
|
|
454
|
+
|
|
455
|
+
Generate the Frontend Config JSON. Use every available CRUD GraphQL query and mutation. Return ONLY valid JSON.`}function ae(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:z.object({graphqlSchema:z.string().describe("The GraphQL schema string to convert"),appInfo:z.object({projectName:z.string().optional(),projectDescription:z.string().optional(),modules:z.string().optional(),apiEndpoint:z.string().optional()}).optional().describe("Optional project/app context")}),handler:async({graphqlSchema:e,appInfo:o})=>{let r=Ft(e,o),n=[{role:"system",content:B},{role:"user",content:r}],i=await t.invoke(n,{temperature:.2,maxOutputTokens:16384}),s=zt(i.text),a=JSON.parse(s);return $.parse(a)}})}function ie(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:z.object({graphqlSchema:z.string().describe("The GraphQL schema string to analyze")}),handler:async({graphqlSchema:e})=>{let o=`${ne}
|
|
456
|
+
|
|
457
|
+
**Schema to analyze:**
|
|
458
|
+
\`\`\`graphql
|
|
459
|
+
${e}
|
|
460
|
+
\`\`\`
|
|
461
|
+
|
|
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 De(t){return {validate_frontend_config:j,generate_frontend:ae(t),generate_feature_breakdown:ie(t)}}var $t=`You are an expert at analyzing GraphQL schemas. Your job is to:
|
|
463
|
+
|
|
464
|
+
1. **Types**: List all object types, enums, scalars, and input types.
|
|
465
|
+
2. **Queries**: List every Query field with arguments and return type.
|
|
466
|
+
3. **Mutations**: List every Mutation field with arguments and return type.
|
|
467
|
+
4. **Relationships**: Identify types that reference other types (e.g. User has role: Role, or Order has customer: User).
|
|
468
|
+
5. **Auth/directives**: Note any @auth, @directive usage that affects access control.
|
|
469
|
+
|
|
470
|
+
Respond with a clear, structured analysis (headings and bullet points). The user will use this to generate a frontend configuration.`,se=v({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:$t,tools:{},maxIterations:2});var Bt=`You are a frontend configuration validator. Your job is to:
|
|
471
|
+
|
|
472
|
+
1. Validate the provided frontend config JSON using the validate_frontend_config tool.
|
|
473
|
+
2. Compare the config against the GraphQL schema (if provided) and check that all CRUD operations are covered.
|
|
474
|
+
3. Report any missing modules, pages, or API hooks.
|
|
475
|
+
|
|
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 le(){return v({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:Bt,tools:{validate_frontend_config:j},maxIterations:5})}var Gt=`${B}
|
|
477
|
+
|
|
478
|
+
You are the React frontend builder orchestrator. When the user provides a GraphQL schema and asks for a frontend configuration:
|
|
479
|
+
|
|
480
|
+
1. **Analyze (optional)**: For complex schemas, use subagent_graphql-analyzer with a prompt that includes the schema to get a structured analysis of types, queries, and mutations.
|
|
481
|
+
2. **Generate**: Use generate_frontend with the GraphQL schema (and optional appInfo) to produce the frontend config JSON.
|
|
482
|
+
3. **Validate (optional)**: Use subagent_config-validator with the generated config (and schema) to check structure and completeness.
|
|
483
|
+
4. **Validate directly**: You can use validate_frontend_config to check any config JSON.
|
|
484
|
+
5. **Feature breakdown**: Use generate_feature_breakdown to get a module/operation breakdown before generating.
|
|
485
|
+
|
|
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 Jt(t){let{input:e,model:o,maxIterations:r=15,onStep:n}=t,i=R(o??{provider:"openai",model:"gpt-4o-mini"}),s=De(i),a=le(),p=U([se,a],{parentModel:i}),m={...s,...p};return w({model:i,tools:m,systemPrompt:Gt,input:e,maxIterations:r,onStep:n})}export{Y as AgentError,Me as ApiResponseTypeSchema,ve as AppConfigSchema,$ as ApplicationSchema,tt as AuthPageApiSchema,ot as AuthPageSchema,K as BaseMcpClient,Re as BrandingSchema,Ae as ColumnSchema,kt as CreateUserInputSchema,P as DB_DESIGN_SYSTEM_PROMPT,Pe as DrawerSchema,it as EXAMPLE_GRAPHQL_SCHEMA,st as EXAMPLE_JSON_OUTPUT,Xe as FieldOptionsSchema,jt as ForgotPasswordSchema,re as FormFieldSchema,M as LibraryError,et as ListingPageApiSchema,rt as ListingPageSchema,Nt as LoginInputSchema,C as ModelError,nt as ModuleSchema,Ce as PageSchema,ne as REACT_BUILDER_INSTRUCTION,B as REACT_BUILDER_SYSTEM_PROMPT,Lt as ResetPasswordSchema,at as SpecializationSchema,D as SubagentError,x as ToolError,_t as UpdateUserInputSchema,Ut as UserSchema,Ne as ValidationError,Ze as ValidationSchema,Ee as buildExampleShotPrompt,qt as buildFeedbackPrompt,Ie as buildInstructionPrompt,We as buildPromptVariables,V as createAnthropicModel,le as createConfigValidatorSubagent,fe as createDbDesignPrompt,we as createDbDesignerTools,X as createDesignDatabaseProTool,Z as createDesignDatabaseTool,ie as createGenerateFeatureBreakdownTool,ae as createGenerateFrontendTool,W as createGoogleModel,Ht as createLogger,R as createModel,Q as createOpenAIModel,be as createProDbDesignPrompt,De as createReactBuilderTools,ee as createRedesignDatabaseTool,Se as createRedesignPrompt,oe as createSchemaRefinerSubagent,de as createSubagentTool,U as createSubagentToolSet,I as createToolSet,v as defineSubagent,h as defineTool,te as entityAnalyzerSubagent,ce as executeTool,H as executeToolByName,he as extractDataEntities,ye as extractRoles,ue as fieldSchema,Ve as formatTechnicalRequirements,He as formatUserFlows,Qe as formatUserStories,Ye as formatUserTypes,je as getTool,_e as getTools,se as graphqlAnalyzerSubagent,me as helloWorldTool,ge as moduleSchema,A as projectSchema,w as runAgent,Dt as runDbDesignerAgent,vt as runHelloWorldAgent,Jt as runReactBuilderAgent,pe as runSubagent,ke as sumTokenUsage,j as validateFrontendConfigTool,_ as validateSchemaTool};//# sourceMappingURL=index.js.map
|
|
487
|
+
//# sourceMappingURL=index.js.map
|