Skip to content

Commit eb94952

Browse files
committed
Update prompt schema to use library to parse to zod. include any params
1 parent 9ec9b9e commit eb94952

File tree

8 files changed

+1106
-43
lines changed

8 files changed

+1106
-43
lines changed

backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"express": "4.19.2",
3939
"gpt-tokenizer": "2.8.1",
4040
"ignore": "5.3.2",
41+
"json-schema-to-zod": "2.6.1",
4142
"lodash": "*",
4243
"openai": "^4.78.1",
4344
"pino": "9.4.0",

backend/src/__tests__/dynamic-agent-loader.test.ts

Lines changed: 105 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mock.module('../util/file-resolver', () => ({
2424
return 'Help brainstorm ideas.'
2525
}
2626
return 'Mock content'
27-
}
27+
},
2828
}))
2929

3030
// Mock fs module to avoid file system access in tests
@@ -136,7 +136,7 @@ describe('Dynamic Agent Loader', () => {
136136
}
137137

138138
const result = await dynamicAgentService.loadAgents(fileContext)
139-
139+
140140
expect(result.validationErrors).toHaveLength(0)
141141
expect(result.templates).toHaveProperty('brainstormer')
142142
expect(result.templates.brainstormer.name).toBe('Brainy')
@@ -150,7 +150,7 @@ describe('Dynamic Agent Loader', () => {
150150
}
151151

152152
const result = await dynamicAgentService.loadAgents(fileContext)
153-
153+
154154
expect(result.validationErrors).toHaveLength(0)
155155
expect(Object.keys(result.templates)).toHaveLength(0)
156156
})
@@ -162,9 +162,11 @@ describe('Dynamic Agent Loader', () => {
162162
}
163163

164164
const result = await dynamicAgentService.loadAgents(fileContext)
165-
165+
166166
expect(result.validationErrors).toHaveLength(1)
167-
expect(result.validationErrors[0].message).toContain('Invalid spawnable agents: nonexistent_agent')
167+
expect(result.validationErrors[0].message).toContain(
168+
'Invalid spawnable agents: nonexistent_agent'
169+
)
168170
})
169171

170172
it('should handle invalid JSON', async () => {
@@ -174,9 +176,11 @@ describe('Dynamic Agent Loader', () => {
174176
}
175177

176178
const result = await dynamicAgentService.loadAgents(fileContext)
177-
179+
178180
expect(result.validationErrors).toHaveLength(1)
179-
expect(result.validationErrors[0].message).toContain('Error in agent template')
181+
expect(result.validationErrors[0].message).toContain(
182+
'Error in agent template'
183+
)
180184
})
181185

182186
it('should merge static and dynamic templates', async () => {
@@ -186,8 +190,101 @@ describe('Dynamic Agent Loader', () => {
186190
}
187191

188192
const result = await dynamicAgentService.loadAgents(fileContext)
189-
193+
190194
// Should have dynamic templates
191195
expect(result.templates).toHaveProperty('custom_agent') // Dynamic
192196
})
197+
198+
it('should handle agents with JSON schemas', async () => {
199+
// Create a new service instance to avoid global state issues
200+
const testService =
201+
new (require('../templates/dynamic-agent-service').DynamicAgentService)()
202+
203+
// Mock fs for this specific test
204+
const mockFs = mock.module('fs', () => ({
205+
existsSync: () => true,
206+
readdirSync: () => ['schema-agent.json'],
207+
readFileSync: () =>
208+
JSON.stringify({
209+
id: 'schema_agent',
210+
version: '1.0.0',
211+
override: false,
212+
name: 'Schema Agent',
213+
description: 'Agent with JSON schemas',
214+
model: 'anthropic/claude-4-sonnet-20250522',
215+
systemPrompt: 'Test system prompt',
216+
userInputPrompt: 'Test user prompt',
217+
agentStepPrompt: 'Test step prompt',
218+
promptSchema: {
219+
prompt: {
220+
type: 'string',
221+
description: 'A test prompt',
222+
},
223+
params: {
224+
type: 'object',
225+
properties: {
226+
temperature: { type: 'number', minimum: 0, maximum: 1 },
227+
},
228+
},
229+
},
230+
}),
231+
}))
232+
233+
const fileContext = {
234+
...mockFileContext,
235+
projectRoot: '/test/schema',
236+
}
237+
238+
const result = await testService.loadAgents(fileContext)
239+
240+
expect(result.validationErrors).toHaveLength(0)
241+
expect(result.templates).toHaveProperty('schema_agent')
242+
expect(result.templates.schema_agent.promptSchema.prompt).toBeDefined()
243+
expect(result.templates.schema_agent.promptSchema.params).toBeDefined()
244+
})
245+
246+
it('should return validation errors for invalid schemas', async () => {
247+
// Create a new service instance to avoid global state issues
248+
const testService =
249+
new (require('../templates/dynamic-agent-service').DynamicAgentService)()
250+
251+
// Mock fs for this specific test
252+
const mockFs = mock.module('fs', () => ({
253+
existsSync: () => true,
254+
readdirSync: () => ['invalid-schema-agent.json'],
255+
readFileSync: () =>
256+
JSON.stringify({
257+
id: 'invalid_schema_agent',
258+
version: '1.0.0',
259+
override: false,
260+
name: 'Invalid Schema Agent',
261+
description: 'Agent with invalid schemas',
262+
model: 'anthropic/claude-4-sonnet-20250522',
263+
systemPrompt: 'Test system prompt',
264+
userInputPrompt: 'Test user prompt',
265+
agentStepPrompt: 'Test step prompt',
266+
promptSchema: {
267+
prompt: {
268+
type: 'number', // Invalid - should allow strings
269+
},
270+
},
271+
}),
272+
}))
273+
274+
const fileContext = {
275+
...mockFileContext,
276+
projectRoot: '/test/invalid-schema',
277+
}
278+
279+
const result = await testService.loadAgents(fileContext)
280+
281+
expect(result.validationErrors).toHaveLength(1)
282+
expect(result.validationErrors[0].message).toContain(
283+
'Invalid promptSchema.prompt'
284+
)
285+
expect(result.validationErrors[0].message).toContain(
286+
'Schema must allow string or undefined values'
287+
)
288+
expect(result.templates).not.toHaveProperty('invalid_schema_agent')
289+
})
193290
})

0 commit comments

Comments
 (0)