feat: initial release v0.3.0
This commit is contained in:
230
tests/unit/assistant-platform/skills-api-config-template.test.ts
Normal file
230
tests/unit/assistant-platform/skills-api-config-template.test.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { AssistantRuntimeContext } from '@/lib/assistant-platform'
|
||||
|
||||
const saveModelTemplateConfigurationMock = vi.hoisted(() =>
|
||||
vi.fn(async () => ({ modelKey: 'openai-compatible:oa-1::veo3.1' })),
|
||||
)
|
||||
|
||||
vi.mock('@/lib/user-api/model-template/save', () => ({
|
||||
saveModelTemplateConfiguration: saveModelTemplateConfigurationMock,
|
||||
}))
|
||||
|
||||
import { apiConfigTemplateSkill } from '@/lib/assistant-platform/skills/api-config-template'
|
||||
|
||||
function buildRuntimeContext(): AssistantRuntimeContext {
|
||||
return {
|
||||
userId: 'user-1',
|
||||
assistantId: 'api-config-template',
|
||||
context: {
|
||||
providerId: 'openai-compatible:oa-1',
|
||||
},
|
||||
analysisModelKey: 'openrouter::gpt-5-mini',
|
||||
resolvedModel: {
|
||||
providerId: 'openrouter',
|
||||
providerKey: 'openrouter',
|
||||
modelId: 'gpt-5-mini',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe('assistant-platform api-config-template skill', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('returns invalid when template fails schema validation', async () => {
|
||||
const tools = apiConfigTemplateSkill.tools?.(buildRuntimeContext())
|
||||
expect(tools).toBeTruthy()
|
||||
const saveTool = tools?.saveModelTemplate
|
||||
expect(saveTool).toBeTruthy()
|
||||
if (!saveTool?.execute) {
|
||||
throw new Error('saveModelTemplate.execute is required for test')
|
||||
}
|
||||
|
||||
const result = await saveTool.execute({
|
||||
modelId: 'veo3.1',
|
||||
name: 'Veo 3.1',
|
||||
type: 'video',
|
||||
compatMediaTemplate: {
|
||||
version: 1,
|
||||
mediaType: 'video',
|
||||
mode: 'async',
|
||||
create: {
|
||||
method: 'POST',
|
||||
path: '/v2/videos/generations',
|
||||
},
|
||||
response: {
|
||||
taskIdPath: '$.task_id',
|
||||
},
|
||||
},
|
||||
}, {} as never)
|
||||
|
||||
expect(result.status).toBe('invalid')
|
||||
expect(result.code).toBe('MODEL_TEMPLATE_INVALID')
|
||||
expect(saveModelTemplateConfigurationMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('saves template when payload is valid', async () => {
|
||||
const tools = apiConfigTemplateSkill.tools?.(buildRuntimeContext())
|
||||
expect(tools).toBeTruthy()
|
||||
const saveTool = tools?.saveModelTemplate
|
||||
expect(saveTool).toBeTruthy()
|
||||
if (!saveTool?.execute) {
|
||||
throw new Error('saveModelTemplate.execute is required for test')
|
||||
}
|
||||
|
||||
const result = await saveTool.execute({
|
||||
modelId: 'veo3.1',
|
||||
name: 'Veo 3.1',
|
||||
type: 'video',
|
||||
compatMediaTemplate: {
|
||||
version: 1,
|
||||
mediaType: 'video',
|
||||
mode: 'async',
|
||||
create: {
|
||||
method: 'POST',
|
||||
path: '/v2/videos/generations',
|
||||
contentType: 'application/json',
|
||||
bodyTemplate: {
|
||||
model: '{{model}}',
|
||||
prompt: '{{prompt}}',
|
||||
},
|
||||
},
|
||||
status: {
|
||||
method: 'GET',
|
||||
path: '/v2/videos/generations/{{task_id}}',
|
||||
},
|
||||
response: {
|
||||
taskIdPath: '$.task_id',
|
||||
statusPath: '$.status',
|
||||
outputUrlPath: '$.video_url',
|
||||
},
|
||||
polling: {
|
||||
intervalMs: 3000,
|
||||
timeoutMs: 180000,
|
||||
doneStates: ['done'],
|
||||
failStates: ['failed'],
|
||||
},
|
||||
},
|
||||
}, {} as never)
|
||||
|
||||
expect(result.status).toBe('saved')
|
||||
expect(result.savedModelKey).toBe('openai-compatible:oa-1::veo3.1')
|
||||
expect(saveModelTemplateConfigurationMock).toHaveBeenCalledWith({
|
||||
userId: 'user-1',
|
||||
providerId: 'openai-compatible:oa-1',
|
||||
modelId: 'veo3.1',
|
||||
name: 'Veo 3.1',
|
||||
type: 'video',
|
||||
template: expect.objectContaining({
|
||||
mediaType: 'video',
|
||||
}),
|
||||
source: 'ai',
|
||||
})
|
||||
})
|
||||
|
||||
it('saves multiple templates when batch payload is valid', async () => {
|
||||
const tools = apiConfigTemplateSkill.tools?.(buildRuntimeContext())
|
||||
expect(tools).toBeTruthy()
|
||||
const batchTool = tools?.saveModelTemplates
|
||||
expect(batchTool).toBeTruthy()
|
||||
if (!batchTool?.execute) {
|
||||
throw new Error('saveModelTemplates.execute is required for test')
|
||||
}
|
||||
|
||||
const result = await batchTool.execute({
|
||||
models: [
|
||||
{
|
||||
modelId: 'veo3-fast',
|
||||
name: 'Veo 3 Fast',
|
||||
type: 'video',
|
||||
compatMediaTemplate: {
|
||||
version: 1,
|
||||
mediaType: 'video',
|
||||
mode: 'async',
|
||||
create: {
|
||||
method: 'POST',
|
||||
path: '/video/create',
|
||||
contentType: 'application/json',
|
||||
bodyTemplate: {
|
||||
model: '{{model}}',
|
||||
prompt: '{{prompt}}',
|
||||
images: ['{{image}}'],
|
||||
},
|
||||
},
|
||||
status: {
|
||||
method: 'GET',
|
||||
path: '/video/query?id={{task_id}}',
|
||||
},
|
||||
response: {
|
||||
taskIdPath: '$.id',
|
||||
statusPath: '$.status',
|
||||
outputUrlPath: '$.video_url',
|
||||
},
|
||||
polling: {
|
||||
intervalMs: 5000,
|
||||
timeoutMs: 600000,
|
||||
doneStates: ['completed'],
|
||||
failStates: ['failed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
modelId: 'veo3.1-fast',
|
||||
name: 'Veo 3.1 Fast',
|
||||
type: 'video',
|
||||
compatMediaTemplate: {
|
||||
version: 1,
|
||||
mediaType: 'video',
|
||||
mode: 'async',
|
||||
create: {
|
||||
method: 'POST',
|
||||
path: '/video/create',
|
||||
contentType: 'application/json',
|
||||
bodyTemplate: {
|
||||
model: '{{model}}',
|
||||
prompt: '{{prompt}}',
|
||||
images: ['{{image}}'],
|
||||
},
|
||||
},
|
||||
status: {
|
||||
method: 'GET',
|
||||
path: '/video/query?id={{task_id}}',
|
||||
},
|
||||
response: {
|
||||
taskIdPath: '$.id',
|
||||
statusPath: '$.status',
|
||||
outputUrlPath: '$.video_url',
|
||||
},
|
||||
polling: {
|
||||
intervalMs: 5000,
|
||||
timeoutMs: 600000,
|
||||
doneStates: ['completed'],
|
||||
failStates: ['failed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}, {} as never)
|
||||
|
||||
expect(result.status).toBe('saved')
|
||||
expect(result.savedModelKeys).toHaveLength(2)
|
||||
expect(saveModelTemplateConfigurationMock).toHaveBeenCalledTimes(2)
|
||||
expect(saveModelTemplateConfigurationMock).toHaveBeenNthCalledWith(1, expect.objectContaining({
|
||||
modelId: 'veo3-fast',
|
||||
name: 'Veo 3 Fast',
|
||||
providerId: 'openai-compatible:oa-1',
|
||||
userId: 'user-1',
|
||||
type: 'video',
|
||||
source: 'ai',
|
||||
}))
|
||||
expect(saveModelTemplateConfigurationMock).toHaveBeenNthCalledWith(2, expect.objectContaining({
|
||||
modelId: 'veo3.1-fast',
|
||||
name: 'Veo 3.1 Fast',
|
||||
providerId: 'openai-compatible:oa-1',
|
||||
userId: 'user-1',
|
||||
type: 'video',
|
||||
source: 'ai',
|
||||
}))
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user