- PiAgentRuntime 改用 pi-durable Harness:每个 run 一个 JSONL 存储目录 sessionDir/<runId>/ + root 对话; 系统提示 / 能力工具 / 白名单与预算钩子装在每次运行自己的扩展里;watchEvents 翻译成 AgentRunEvent - 挂起(工具内 close)立即封口,调用保持未完成,重开后 resume 重放;replayGate 用调用级 memo - 旧格式 <runId>.jsonl 打开时抛 LegacySessionError;skills 加载与 <skill> 块格式内置(源自 pi-agent-core,MIT) - tool_call_end 新增可选 durationMs;用量取 pi.usage 合计(整段会话总量) - Azure provider 改名 azure,迁移 0093 改存量;移除 pi-agent-core,锁 pi-durable/pi-ai/chord 1.1.0 - 文档:ADR-003、pi-providers、runbook、agent README、CHANGELOG Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
52 lines
2.2 KiB
TypeScript
52 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { describeSettings, resolveAgentSettings } from "../src/index.ts";
|
|
import { compactionFromSettings, resolveModelFromSettings } from "../src/pi/model.ts";
|
|
|
|
describe("AgentSettings → pi-ai", () => {
|
|
it("anthropic:baseUrl 去掉 /v1,上下文预算即 contextWindow,apiKey 只在 resolve 时给出", async () => {
|
|
const s = resolveAgentSettings({
|
|
provider: "anthropic",
|
|
baseUrl: "https://proxy.local/v1/",
|
|
apiKey: "sk-ant-secret-value",
|
|
model: "claude-sonnet-4-5",
|
|
thinkingLevel: "high",
|
|
contextBudgetTokens: 100_000,
|
|
});
|
|
const { models, model } = resolveModelFromSettings(s);
|
|
expect(model).toMatchObject({
|
|
api: "anthropic-messages",
|
|
baseUrl: "https://proxy.local",
|
|
id: "claude-sonnet-4-5",
|
|
contextWindow: 100_000,
|
|
reasoning: true,
|
|
});
|
|
expect(JSON.stringify(model)).not.toContain("sk-ant-secret-value");
|
|
const auth = await models.getAuth(model);
|
|
expect(JSON.stringify(auth)).toContain("sk-ant-secret-value");
|
|
expect(JSON.stringify(describeSettings(s))).not.toContain("sk-ant-secret-value");
|
|
expect(s.subagentsEnabled).toBe(false);
|
|
});
|
|
|
|
it("openai-compatible 需要带 /v1 的 baseUrl;压缩模式映射", () => {
|
|
const base = { provider: "openai-compatible" as const, apiKey: "k", model: "qwen3" };
|
|
expect(() => resolveModelFromSettings(resolveAgentSettings(base))).toThrow(/baseUrl/);
|
|
const s = resolveAgentSettings({
|
|
...base,
|
|
baseUrl: "http://llm.local/v1",
|
|
contextBudgetTokens: 32_000,
|
|
compaction: { mode: "threshold", threshold: 0.75 },
|
|
});
|
|
const { model } = resolveModelFromSettings(s);
|
|
expect(model).toMatchObject({ api: "openai-completions", baseUrl: "http://llm.local/v1", reasoning: false });
|
|
expect(compactionFromSettings(s, 32_000)).toEqual({
|
|
enabled: true,
|
|
reserveTokens: 8000,
|
|
keepRecentTokens: 8000,
|
|
backgroundTokens: 0,
|
|
});
|
|
const manual = resolveAgentSettings({ ...s, compaction: { mode: "manual", threshold: 0.8 } });
|
|
expect(compactionFromSettings(manual, 32_000).enabled).toBe(false);
|
|
expect(() => resolveAgentSettings({ ...base, model: "" })).toThrow();
|
|
});
|
|
});
|