mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
The generator already resolves operations under /v1/ (40d120dbf7), and
the Python docstrings and prompts it copies say /v1/ too, but the
checked-in output still carried upstream's /api/ paths, so 771 tool
calls went to a prefix insights no longer serves. Bring the generated
tools, types and schema in line with what the generator emits for the
/v1/ mount, and move the tests that assert those paths.
Left as they are: POST /api/orders and /api/feed are customer span
names in tool examples, and the connection tool's `api/projects/2/...`
mirrors insights_connection.py's help text.
Claude-Session: https://claude.ai/code/session_01TUxvfuta1Z44KVNYuAz71F
159 lines
6.8 KiB
TypeScript
159 lines
6.8 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
import { getToolByName } from '@/shared/test-utils'
|
|
import { GENERATED_TOOLS } from '@/tools/generated/ai_observability'
|
|
import type { Context } from '@/tools/types'
|
|
|
|
function createContext(requestReturnValue: unknown): { context: Context; requestMock: ReturnType<typeof vi.fn> } {
|
|
const requestMock = vi.fn().mockResolvedValue(requestReturnValue)
|
|
|
|
const context = {
|
|
api: {
|
|
request: requestMock,
|
|
},
|
|
stateManager: {
|
|
getProjectId: vi.fn().mockResolvedValue('17'),
|
|
},
|
|
} as unknown as Context
|
|
|
|
return { context, requestMock }
|
|
}
|
|
|
|
describe('Generated llma-prompt-* tools', () => {
|
|
it('uses prompt_name (not name) in generated prompt-get schema', () => {
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-get')
|
|
|
|
const parsed = tool.schema.parse({ prompt_name: 'checkout_prompt', version: 2 })
|
|
expect(parsed).toEqual({ prompt_name: 'checkout_prompt', version: 2, content: 'full' })
|
|
expect(() => tool.schema.parse({ name: 'checkout_prompt' })).toThrow()
|
|
})
|
|
|
|
it('exposes content mode on the prompt-get schema so agents can fetch outline-only', () => {
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-get')
|
|
|
|
const parsed = tool.schema.parse({ prompt_name: 'checkout_prompt', content: 'none' })
|
|
expect(parsed).toEqual({ prompt_name: 'checkout_prompt', content: 'none' })
|
|
expect(() => tool.schema.parse({ prompt_name: 'checkout_prompt', content: 'bogus' })).toThrow()
|
|
})
|
|
|
|
it('uses prompt_name (not name) in generated prompt-update schema', () => {
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-update')
|
|
|
|
const parsed = tool.schema.parse({ prompt_name: 'checkout_prompt', prompt: { text: 'v2' }, base_version: 1 })
|
|
expect(parsed).toEqual({ prompt_name: 'checkout_prompt', prompt: { text: 'v2' }, base_version: 1 })
|
|
expect(() => tool.schema.parse({ name: 'checkout_prompt', prompt: { text: 'v2' } })).toThrow()
|
|
})
|
|
|
|
it('requires base_version on the prompt-update schema (PATCH optionality stripped)', () => {
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-update')
|
|
|
|
// The backend serializer requires base_version for optimistic concurrency, but the
|
|
// PATCH endpoint marks it optional in OpenAPI — the schema must re-require it so the
|
|
// agent can't silently omit it and hit a backend 400.
|
|
expect(() => tool.schema.parse({ prompt_name: 'checkout_prompt', prompt: { text: 'v2' } })).toThrow()
|
|
})
|
|
|
|
it('wires prompt-list to GET and preserves paginated output shape', async () => {
|
|
const paginated = {
|
|
count: 1,
|
|
next: null,
|
|
previous: null,
|
|
results: [
|
|
{
|
|
id: '2f53a52a-06f5-4025-9ea7-f763f74f17f5',
|
|
name: 'checkout_prompt',
|
|
version: 3,
|
|
prompt_size_bytes: 123,
|
|
},
|
|
],
|
|
}
|
|
const { context, requestMock } = createContext(paginated)
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-list')
|
|
|
|
const result = await tool.handler(context, { search: 'checkout' })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'GET',
|
|
path: '/v1/projects/17/llm_prompts/',
|
|
query: { search: 'checkout', content: 'none' },
|
|
})
|
|
expect(result).toEqual(paginated)
|
|
})
|
|
|
|
it('allows overriding prompt-list content mode', async () => {
|
|
const { context, requestMock } = createContext({ count: 0, next: null, previous: null, results: [] })
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-list')
|
|
|
|
await tool.handler(context, { search: 'checkout', content: 'preview' })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'GET',
|
|
path: '/v1/projects/17/llm_prompts/',
|
|
query: { search: 'checkout', content: 'preview' },
|
|
})
|
|
})
|
|
|
|
it('wires prompt-get to GET /name/{prompt_name}/ with version query', async () => {
|
|
const response = { id: '2f53a52a-06f5-4025-9ea7-f763f74f17f5', name: 'checkout_prompt', version: 2 }
|
|
const { context, requestMock } = createContext(response)
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-get')
|
|
|
|
await tool.handler(context, { prompt_name: 'checkout_prompt', version: 2 })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'GET',
|
|
path: '/v1/projects/17/llm_prompts/name/checkout_prompt/',
|
|
query: { version: 2 },
|
|
})
|
|
})
|
|
|
|
it('wires prompt-create to POST body with name and prompt', async () => {
|
|
const { context, requestMock } = createContext({ id: 'new-id' })
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-create')
|
|
|
|
await tool.handler(context, { name: 'new_prompt', prompt: { text: 'hello' } })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'POST',
|
|
path: '/v1/projects/17/llm_prompts/',
|
|
body: { name: 'new_prompt', prompt: { text: 'hello' } },
|
|
})
|
|
})
|
|
|
|
it('wires prompt-update to PATCH /name/{prompt_name}/ with publish payload', async () => {
|
|
const { context, requestMock } = createContext({ id: 'updated-id' })
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-update')
|
|
|
|
await tool.handler(context, { prompt_name: 'new_prompt', prompt: { text: 'v2' }, base_version: 1 })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'PATCH',
|
|
path: '/v1/projects/17/llm_prompts/name/new_prompt/',
|
|
body: { prompt: { text: 'v2' }, base_version: 1 },
|
|
})
|
|
})
|
|
|
|
it('uses prompt_name and new_name in generated prompt-duplicate schema', () => {
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-duplicate')
|
|
|
|
const parsed = tool.schema.parse({ prompt_name: 'original_prompt', new_name: 'copy_of_prompt' })
|
|
expect(parsed).toEqual({ prompt_name: 'original_prompt', new_name: 'copy_of_prompt' })
|
|
expect(() => tool.schema.parse({ prompt_name: 'original_prompt' })).toThrow()
|
|
})
|
|
|
|
it('wires prompt-duplicate to POST /name/{prompt_name}/duplicate/ with new_name body', async () => {
|
|
const response = { id: 'new-id', name: 'copy_of_prompt', version: 1 }
|
|
const { context, requestMock } = createContext(response)
|
|
const tool = getToolByName(GENERATED_TOOLS, 'llma-prompt-duplicate')
|
|
|
|
const result = await tool.handler(context, { prompt_name: 'original_prompt', new_name: 'copy_of_prompt' })
|
|
|
|
expect(requestMock).toHaveBeenCalledWith({
|
|
method: 'POST',
|
|
path: '/v1/projects/17/llm_prompts/name/original_prompt/duplicate/',
|
|
body: { new_name: 'copy_of_prompt' },
|
|
})
|
|
expect(result).toEqual(response)
|
|
})
|
|
})
|