100 lines
3.9 KiB
TypeScript
100 lines
3.9 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
|
|
let runtimeRoot = "";
|
|
let readState: (typeof import("../src/lib/boss-data"))["readState"];
|
|
let getProjectAgentControls: (typeof import("../src/lib/boss-data"))["getProjectAgentControls"];
|
|
let recordMasterAgentEvolutionSignal: (typeof import("../src/lib/master-agent-evolution"))["recordMasterAgentEvolutionSignal"];
|
|
let listMasterAgentEvolutionProposals: (typeof import("../src/lib/master-agent-evolution"))["listMasterAgentEvolutionProposals"];
|
|
let setMasterAgentEvolutionMode: (typeof import("../src/lib/master-agent-evolution"))["setMasterAgentEvolutionMode"];
|
|
|
|
async function setup() {
|
|
if (runtimeRoot) {
|
|
return;
|
|
}
|
|
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-master-agent-evolution-engine-"));
|
|
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
|
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
|
const [data, evolution] = await Promise.all([
|
|
import("../src/lib/boss-data.ts"),
|
|
import("../src/lib/master-agent-evolution.ts"),
|
|
]);
|
|
readState = data.readState;
|
|
getProjectAgentControls = data.getProjectAgentControls;
|
|
recordMasterAgentEvolutionSignal = evolution.recordMasterAgentEvolutionSignal;
|
|
listMasterAgentEvolutionProposals = evolution.listMasterAgentEvolutionProposals;
|
|
setMasterAgentEvolutionMode = evolution.setMasterAgentEvolutionMode;
|
|
}
|
|
|
|
test.after(async () => {
|
|
if (runtimeRoot) {
|
|
await rm(runtimeRoot, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test.beforeEach(async () => {
|
|
await setup();
|
|
await rm(runtimeRoot, { recursive: true, force: true });
|
|
await mkdir(runtimeRoot, { recursive: true });
|
|
});
|
|
|
|
test("recording repeated deterministic questions creates a pending fast_path_rule proposal in controlled mode", async () => {
|
|
await setMasterAgentEvolutionMode("controlled");
|
|
|
|
const result = await recordMasterAgentEvolutionSignal({
|
|
kind: "repeated_question",
|
|
projectId: "master-agent",
|
|
account: "17600003315",
|
|
requestText: "当前主节点在线吗",
|
|
});
|
|
|
|
assert.equal(result.signal.kind, "repeated_question");
|
|
assert.equal(result.proposal?.proposalType, "fast_path_rule");
|
|
assert.equal(result.proposal?.status, "pending_review");
|
|
|
|
const proposals = await listMasterAgentEvolutionProposals();
|
|
assert.equal(proposals[0]?.proposalType, "fast_path_rule");
|
|
assert.equal(proposals[0]?.status, "pending_review");
|
|
});
|
|
|
|
test("autonomous mode auto applies low risk fast path proposals as evolution rules", async () => {
|
|
await setMasterAgentEvolutionMode("autonomous");
|
|
|
|
const result = await recordMasterAgentEvolutionSignal({
|
|
kind: "repeated_question",
|
|
projectId: "master-agent",
|
|
account: "17600003315",
|
|
requestText: "当前主节点在线吗",
|
|
});
|
|
|
|
assert.equal(result.proposal?.status, "auto_applied");
|
|
const state = await readState();
|
|
assert.equal(state.masterAgentEvolutionRules.length, 1);
|
|
assert.equal(state.masterAgentEvolutionRules[0]?.ruleType, "fast_path_rule");
|
|
});
|
|
|
|
test("autonomous mode auto applies backend fallback proposals into master-agent backend override", async () => {
|
|
await setMasterAgentEvolutionMode("autonomous");
|
|
|
|
const result = await recordMasterAgentEvolutionSignal({
|
|
kind: "backend_fallback",
|
|
projectId: "master-agent",
|
|
account: "17600003315",
|
|
requestText: "Hermes 不可用时自动回退到 Claw",
|
|
metadataJson: {
|
|
failedBackendId: "hermes-runtime",
|
|
fallbackToBackendId: "claw-runtime",
|
|
},
|
|
});
|
|
|
|
assert.equal(result.proposal?.status, "auto_applied");
|
|
const state = await readState();
|
|
const controls = await getProjectAgentControls("master-agent", "17600003315");
|
|
assert.equal(state.masterAgentEvolutionRules.length, 1);
|
|
assert.equal(state.masterAgentEvolutionRules[0]?.ruleType, "routing_preference_patch");
|
|
assert.equal(controls?.backendOverride ?? null, "claw-runtime");
|
|
});
|