← Public packages
@kentcdodds/ai
Kody tool-using agent turns with Vercel AI SDK and Cloudflare AI Gateway.
src/app.ts
51 lines · 2.0 KB · TypeScriptimport { agentTurnStream } from './index.ts'
import type { AgentTurnInput, AgentTurnStreamEvent } from './types.ts'
const html =
'<!doctype html><html><head><title>Kody AI</title></head><body><h1>Kody AI</h1><form method="post"><textarea name="prompt"></textarea><button>Send</button></form></body></html>'
function json(value: unknown, init: ResponseInit = {}) {
return new Response(JSON.stringify(value), {
...init,
headers: {
'content-type': 'application/json; charset=utf-8',
...(init.headers || {}),
},
})
}
async function readTurnInput(request: Request): Promise<AgentTurnInput> {
const contentType = (request.headers.get('content-type') || '').toLowerCase()
if (
contentType.includes('application/x-www-form-urlencoded') ||
contentType.includes('multipart/form-data')
) {
const form = await request.formData().catch(() => null)
const prompt = form ? String(form.get('prompt') ?? '').trim() : ''
return prompt ? { messages: [{ role: 'user', content: prompt }] } : { messages: [] }
}
const body = (await request.json().catch(() => ({}))) as AgentTurnInput
return body?.messages ? body : { messages: [] }
}
/**
* Hosted AI chat app: GET serves a minimal HTML form; POST runs one buffered agent turn.
* @example
* import app from 'kody:@kentcdodds/ai/app'
* const response = await app(new Request('https://example/', { method: 'POST', body: JSON.stringify({ messages: [{ role: 'user', content: 'Hello' }] }) }))
* // => Response JSON { ok: true, events: [...] }
*/
export default async function fetch(request: Request): Promise<Response> {
if (request.method === 'GET' || request.method === 'HEAD') {
return new Response(request.method === 'HEAD' ? null : html, {
headers: { 'content-type': 'text/html; charset=utf-8' },
})
}
if (request.method === 'POST') {
const body = await readTurnInput(request)
const events: AgentTurnStreamEvent[] = []
for await (const event of agentTurnStream(body)) events.push(event)
return json({ ok: true, events })
}
return json({ error: 'Method not allowed' }, { status: 405 })
}