forked from EduCraft/curriculum-project-hub
refactor(hub): 手搓 agent loop 换成 Vercel AI SDK
将 provider/runner/tools 三件手搓轮子替换为 AI SDK v7 的 generateText + tool:
- 删 openrouter-provider.ts(翻译层消失)、provider.ts 自定义消息类型
- runner.ts 循环体改为 generateText({stopWhen: stepCountIs}),保留 RunRequest/RunResult 公共签名
- tools.ts ToolRegistry 改为 ToolFactory + build(ctx, names?) 按 role 白名单构建 tools record
- workspace/cph/feishu 工具改写为 tool() 定义,execute 闭包捕获 per-run ToolContext
- transcript.ts 改为 ModelMessage[] JSONL(0.0.0 cutover,无迁移)
- server.ts/trigger.ts 接 modelFactory + toolWhitelist
- 测试:helpers 写 MockLanguageModel implements LanguageModelV4;5 个测试改写 + 新增 runner.test.ts
- 移除未使用的 openai 依赖
- ADR-0017 Consequences 同步:loop 委托给 AI SDK,provider seam 是 LanguageModel
tsc 干净,54 tests 全过。
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { runAgent } from "../../src/agent/runner.js";
|
||||
import { ToolRegistry } from "../../src/agent/tools.js";
|
||||
import { readFileTool } from "../../src/agent/workspace.js";
|
||||
import { createMockModelFactory } from "../integration/helpers.js";
|
||||
|
||||
describe("runAgent with AI SDK tool loop", () => {
|
||||
it("executes SDK tools and returns the final assistant response", async () => {
|
||||
const ws = await mkdtemp(join(tmpdir(), "hub-runner-"));
|
||||
try {
|
||||
await writeFile(join(ws, "lesson.txt"), "hello lesson", "utf8");
|
||||
const tools = new ToolRegistry();
|
||||
tools.register("read_file", readFileTool);
|
||||
const { modelFactory, models } = createMockModelFactory([
|
||||
{
|
||||
toolCalls: [{ toolCallId: "call-1", toolName: "read_file", input: { path: "lesson.txt" } }],
|
||||
},
|
||||
{ text: "done", finishReason: "stop" },
|
||||
]);
|
||||
|
||||
const result = await runAgent(modelFactory, tools, {
|
||||
prompt: "read lesson.txt",
|
||||
model: "mock-model",
|
||||
project: { projectId: "p", boundChatId: "c", workspaceDir: ws },
|
||||
systemPrompt: "system",
|
||||
maxIterations: 5,
|
||||
});
|
||||
|
||||
expect(result.status).toBe("completed");
|
||||
expect(result.messages.at(-1)).toMatchObject({ role: "assistant" });
|
||||
expect(models.get("mock-model")?.calls).toHaveLength(2);
|
||||
} finally {
|
||||
await rm(ws, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user