first commit

This commit is contained in:
Ramnique Singh 2025-10-28 13:17:06 +05:30
parent 476654af80
commit 6014437479
20 changed files with 2231 additions and 0 deletions

View file

@ -0,0 +1,130 @@
import { Message } from "../entities/message.js";
import { z } from "zod";
import { Node, NodeInputT, NodeOutputT } from "./node.js";
import { openai } from "@ai-sdk/openai";
import { generateText, ModelMessage, stepCountIs, streamText } from "ai";
import { Agent } from "../entities/agent.js";
import { WorkDir } from "../config/config.js";
import fs from "fs";
import path from "path";
function convertFromMessages(messages: z.infer<typeof Message>[]): ModelMessage[] {
const result: ModelMessage[] = [];
for (const msg of messages) {
switch (msg.role) {
case "assistant":
if (typeof msg.content === 'string') {
result.push({
role: "assistant",
content: msg.content,
});
} else {
result.push({
role: "assistant",
content: msg.content.map(part => {
switch (part.type) {
case 'text':
return part;
case 'reasoning':
return part;
case 'tool-call':
return {
type: 'tool-call',
toolCallId: part.toolCallId,
toolName: part.toolName,
input: part.arguments,
};
}
}),
});
}
break;
case "system":
result.push({
role: "system",
content: msg.content,
});
break;
case "user":
result.push({
role: "user",
content: msg.content,
});
break;
}
}
return result;
}
export class AgentNode implements Node {
private id: string;
constructor(id: string) {
this.id = id;
}
private loadAgent(id: string): z.infer<typeof Agent> {
const agentPath = path.join(WorkDir, "agents", `${id}.json`);
const agent = fs.readFileSync(agentPath, "utf8");
return Agent.parse(JSON.parse(agent));
}
async* execute(input: NodeInputT): NodeOutputT {
const agent = this.loadAgent(this.id);
const { fullStream } = await streamText({
model: openai(agent.model),
messages: convertFromMessages(input),
system: agent.instructions,
stopWhen: stepCountIs(1),
});
for await (const event of fullStream) {
switch (event.type) {
case "reasoning-start":
yield {
type: "reasoning-start",
};
break;
case "reasoning-delta":
yield {
type: "reasoning-delta",
delta: event.text,
};
break;
case "reasoning-end":
yield {
type: "reasoning-end",
};
break;
case "text-start":
yield {
type: "text-start",
};
break;
case "text-delta":
yield {
type: "text-delta",
delta: event.text,
};
break;
case "tool-call":
yield {
type: "tool-call",
toolCallId: event.toolCallId,
toolName: event.toolName,
input: event.input,
};
break;
case "finish":
yield {
type: "usage",
usage: event.totalUsage,
};
break;
default:
// console.warn("Unknown event type", event);
continue;
}
}
}
}