- Add agent-run module to handle AI interactions with tools and messages. - Create routes for proxying requests to OpenAI and Anthropic APIs. - Implement flowme-life chat route for user queries and task management. - Add services for retrieving and updating life records in the database. - Implement logic for fetching today's tasks and marking tasks as done with next execution time calculation. - Introduce tests for flowme-life functionalities.
66 lines
2.5 KiB
TypeScript
66 lines
2.5 KiB
TypeScript
import { type QueryRouterServer, type App, type RouteInfo } from '@kevisual/router'
|
|
import { generateText, tool, type ModelMessage, type LanguageModel, type GenerateTextResult } from 'ai';
|
|
import z from 'zod';
|
|
import { filter } from '@kevisual/js-filter'
|
|
export const createTool = async (app: QueryRouterServer | App, message: { path: string, key: string, token?: string }) => {
|
|
const route = app.findRoute({ path: message.path, key: message.key });
|
|
if (!route) {
|
|
console.error(`未找到路径 ${message.path} 和 key ${message.key} 的路由`);
|
|
return null;
|
|
}
|
|
const _tool = tool({
|
|
description: route?.metadata?.summary || route?.description || '无描述',
|
|
inputSchema: z.object({
|
|
...route.metadata?.args
|
|
}), // 这里可以根据实际需要定义输入参数的 schema
|
|
execute: async (args: any) => {
|
|
const res = await app.run({ path: message.path, key: message.key, payload: args, token: message.token });
|
|
return res;
|
|
}
|
|
});
|
|
return _tool;
|
|
}
|
|
|
|
export const createTools = async (opts: { app: QueryRouterServer | App, token?: string }) => {
|
|
const { app, token } = opts;
|
|
const tools: Record<string, any> = {};
|
|
for (const route of app.routes) {
|
|
const id = route.id!;
|
|
const _tool = await createTool(app, { path: route.path!, key: route.key!, token });
|
|
if (_tool && id) {
|
|
tools[id] = _tool;
|
|
}
|
|
}
|
|
return tools;
|
|
}
|
|
type Route = Partial<RouteInfo>
|
|
type AgentResult = {
|
|
result: GenerateTextResult<Record<string, any>, any>,
|
|
messages: ModelMessage[],
|
|
}
|
|
export const reCallAgent = async (opts: { messages?: ModelMessage[], tools?: Record<string, any>, languageModel: LanguageModel }): Promise<AgentResult> => {
|
|
const { messages = [], tools = {}, languageModel } = opts;
|
|
const result = await generateText({
|
|
model: languageModel,
|
|
messages,
|
|
tools,
|
|
});
|
|
const step = result.steps[0]!;
|
|
if (step.finishReason === 'tool-calls') {
|
|
messages.push(...result.response.messages);
|
|
return reCallAgent({ messages, tools, languageModel });
|
|
}
|
|
return { result, messages };
|
|
}
|
|
export const runAgent = async (opts: { app: QueryRouterServer | App, messages?: ModelMessage[], routes?: Route[], query?: string, languageModel: LanguageModel, token: string }) => {
|
|
const { app, languageModel } = opts;
|
|
let messages = opts.messages || [];
|
|
|
|
let routes = opts?.routes || app.routes;
|
|
if (opts.query) {
|
|
routes = filter(routes, opts.query);
|
|
};
|
|
const tools = await createTools({ app, token: opts.token });
|
|
return await reCallAgent({ messages, tools, languageModel });
|
|
}
|