Files
UHD_Media_Tool/spikes/pi/fake-run.ts
T

51 lines
2.9 KiB
TypeScript

// Fake model drives AgentHarness through 2 whitelisted tools; streams events.
import { createModels, fauxProvider } from "@earendil-works/pi-ai";
import { AgentHarness, BACKGROUND_CONTEXT, MemorySessionRepo } from "@earendil-works/pi-agent-core";
import { downloadSubmit, inventoryQuery, script, submitted } from "./common.ts";
const faux = fauxProvider({ provider: "umt-fake" });
const models = createModels();
models.setProvider(faux.provider);
faux.setResponses(script);
const repo = new MemorySessionRepo();
const session = await repo.create({ id: "spike-1" }, BACKGROUND_CONTEXT);
const { harness } = await AgentHarness.create({
session, models, model: faux.getModel(),
systemPrompt: "你是媒体库自动化助手,只能使用提供的工具。",
tools: [inventoryQuery, downloadSubmit], // explicit whitelist; no discovery
toolContext: { actorId: "user:1", grants: ["download.submit"] },
thinkingLevel: "off",
compaction: { enabled: true, reserveTokens: 4096, keepRecentTokens: 8000 },
retry: { enabled: true, maxRetries: 2, baseDelayMs: 100 },
toolExecution: "sequential",
}, BACKGROUND_CONTEXT);
// Server-side authorization gate in addition to the whitelist.
harness.hooks.on("before_tool", (ev) => {
console.log(` [hook before_tool] ${ev.toolName} args=${JSON.stringify(ev.args)}`);
return undefined;
});
const types = ["run_start", "turn_start", "message_update", "tool_start", "tool_update", "tool_end", "turn_end", "run_end", "usage", "fault", "handler_error"] as const;
for (const t of types) harness.events.on(t as any, (e: any) => {
if (e.type === "message_update") {
if (e.event.type === "text_delta") process.stdout.write(` [text_delta] ${JSON.stringify(e.event.delta)}\n`);
else if (e.event.type === "toolcall_end") console.log(` [toolcall_end] ${e.event.toolCall.name}`);
return;
}
if (e.type === "tool_end") return console.log(`[tool_end] ${e.toolName} isError=${e.isError} -> ${JSON.stringify(e.result.content[0]?.text)}`);
if (e.type === "tool_start") return console.log(`[tool_start] ${e.toolName} ${JSON.stringify(e.args)}`);
if (e.type === "usage") return console.log(`[usage] in=${e.row?.usage?.input ?? "?"} totals.input=${e.totals.input} output=${e.totals.output}`);
if (e.type === "run_end") return console.log(`[run_end] status=${e.status}${e.error ? " error=" + JSON.stringify(e.error) : ""}`);
console.log(`[${e.type}]${e.lane ? " lane=" + e.lane : ""}`);
});
const lane = await harness.lane("main", BACKGROUND_CONTEXT);
const result = await lane.prompt("把《Dune》1080p 收进来", undefined, BACKGROUND_CONTEXT);
console.log("RESULT", JSON.stringify(result));
console.log("SUBMITTED", JSON.stringify(submitted), "fake calls:", faux.state.callCount);
const entries = await lane.findEntries(undefined, BACKGROUND_CONTEXT);
console.log("TRANSCRIPT roles:", entries.map((e: any) => e.type === "message" ? e.message.role : e.type).join(","));
await harness.close(BACKGROUND_CONTEXT);