You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import { streamText, Message, createDataStream } from "ai";
|
|
import { Hono } from "hono";
|
|
import { stream } from "hono/streaming";
|
|
import { processPendingToolCalls } from "./util.js";
|
|
import { agentsById, openrouter } from "./agentRegistry.js";
|
|
|
|
const app = new Hono();
|
|
|
|
app.post("/api/chat/:agent_id", async (c) => {
|
|
const input: { messages: Message[] } = await c.req.json();
|
|
const agentId = c.req.param("agent_id");
|
|
const agent = agentsById[agentId];
|
|
if (!agent) {
|
|
c.status(404);
|
|
return c.json({ error: `No such agent: ${agentId}` });
|
|
}
|
|
|
|
const dataStream = createDataStream({
|
|
execute: async (dataStreamWriter) => {
|
|
// dataStreamWriter.writeData('initialized call');
|
|
|
|
// Process any pending tool calls in the messages
|
|
// This modifies the messages array in place
|
|
await processPendingToolCalls(input.messages, dataStreamWriter);
|
|
|
|
const result = streamText({
|
|
model: openrouter(agent.modelName),
|
|
maxSteps: 5,
|
|
messages: [
|
|
{ role: "system", content: agent.systemMessage },
|
|
...Object.values(agentsById).map((agent) => ({
|
|
role: "system" as const,
|
|
content: `Agent ${JSON.stringify({
|
|
id: agent.id,
|
|
name: agent.name,
|
|
description: agent.description,
|
|
skills: agent.skills,
|
|
})}`,
|
|
})),
|
|
...input.messages,
|
|
],
|
|
tools: agent.tools,
|
|
onError: (error) => {
|
|
console.error("Error in streamText:", error);
|
|
},
|
|
});
|
|
|
|
result.mergeIntoDataStream(dataStreamWriter);
|
|
},
|
|
onError: (error) => {
|
|
// Error messages are masked by default for security reasons.
|
|
// If you want to expose the error message to the client, you can do so here:
|
|
return error instanceof Error ? error.message : String(error);
|
|
},
|
|
});
|
|
|
|
// Mark the response as a v1 data stream:
|
|
c.header("X-Vercel-AI-Data-Stream", "v1");
|
|
c.header("Content-Type", "text/plain; charset=utf-8");
|
|
|
|
return stream(c, (stream) =>
|
|
stream.pipe(dataStream.pipeThrough(new TextEncoderStream()))
|
|
);
|
|
});
|
|
|
|
export default app;
|