Refresh config pages in realtime
This commit is contained in:
47
tests/config-pages-realtime-refresh.test.ts
Normal file
47
tests/config-pages-realtime-refresh.test.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
|
||||
async function readSource(relativePath: string) {
|
||||
return readFile(new URL(`../${relativePath}`, import.meta.url), "utf8");
|
||||
}
|
||||
|
||||
test("ai accounts page refreshes when AI account state changes", async () => {
|
||||
const source = await readSource("src/app/me/ai-accounts/page.tsx");
|
||||
|
||||
assert.match(source, /import \{ RealtimeRefresh \}/, "expected ai accounts page to import RealtimeRefresh");
|
||||
assert.match(source, /<RealtimeRefresh/, "expected ai accounts page to render RealtimeRefresh");
|
||||
assert.match(
|
||||
source,
|
||||
/events=\{\["ai_accounts\.updated"\]\}/,
|
||||
"expected ai accounts page to refresh on ai_accounts.updated",
|
||||
);
|
||||
});
|
||||
|
||||
test("storage page refreshes when storage config changes", async () => {
|
||||
const source = await readSource("src/app/me/storage/page.tsx");
|
||||
|
||||
assert.match(source, /import \{ RealtimeRefresh \}/, "expected storage page to import RealtimeRefresh");
|
||||
assert.match(source, /<RealtimeRefresh/, "expected storage page to render RealtimeRefresh");
|
||||
assert.match(
|
||||
source,
|
||||
/events=\{\["storage\.updated"\]\}/,
|
||||
"expected storage page to refresh on storage.updated",
|
||||
);
|
||||
});
|
||||
|
||||
test("master agent settings pages refresh when master agent config changes", async () => {
|
||||
for (const relativePath of [
|
||||
"src/app/me/master-agent/page.tsx",
|
||||
"src/app/me/master-agent/takeover/page.tsx",
|
||||
]) {
|
||||
const source = await readSource(relativePath);
|
||||
assert.match(source, /import \{ RealtimeRefresh \}/, `expected ${relativePath} to import RealtimeRefresh`);
|
||||
assert.match(source, /<RealtimeRefresh/, `expected ${relativePath} to render RealtimeRefresh`);
|
||||
assert.match(
|
||||
source,
|
||||
/events=\{\["master_agent\.settings\.updated"\]\}/,
|
||||
`expected ${relativePath} to refresh on master_agent.settings.updated`,
|
||||
);
|
||||
}
|
||||
});
|
||||
152
tests/config-state-events.test.ts
Normal file
152
tests/config-state-events.test.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
|
||||
let runtimeRoot = "";
|
||||
let readState: (typeof import("../src/lib/boss-data"))["readState"];
|
||||
let writeState: (typeof import("../src/lib/boss-data"))["writeState"];
|
||||
let saveAiAccount: (typeof import("../src/lib/boss-data"))["saveAiAccount"];
|
||||
let upsertAttachmentStorageConfig: (typeof import("../src/lib/boss-data"))["upsertAttachmentStorageConfig"];
|
||||
let updateMasterAgentPromptPolicy: (typeof import("../src/lib/boss-data"))["updateMasterAgentPromptPolicy"];
|
||||
let createUserMasterMemory: (typeof import("../src/lib/boss-data"))["createUserMasterMemory"];
|
||||
let updateProjectAgentControls: (typeof import("../src/lib/boss-data"))["updateProjectAgentControls"];
|
||||
let subscribeBossEvents: (typeof import("../src/lib/boss-events"))["subscribeBossEvents"];
|
||||
|
||||
async function setup() {
|
||||
if (runtimeRoot) return;
|
||||
|
||||
runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-config-events-"));
|
||||
process.env.BOSS_RUNTIME_ROOT = runtimeRoot;
|
||||
process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json");
|
||||
|
||||
const [data, events] = await Promise.all([
|
||||
import("../src/lib/boss-data.ts"),
|
||||
import("../src/lib/boss-events.ts"),
|
||||
]);
|
||||
|
||||
readState = data.readState;
|
||||
writeState = data.writeState;
|
||||
saveAiAccount = data.saveAiAccount;
|
||||
upsertAttachmentStorageConfig = data.upsertAttachmentStorageConfig;
|
||||
updateMasterAgentPromptPolicy = data.updateMasterAgentPromptPolicy;
|
||||
createUserMasterMemory = data.createUserMasterMemory;
|
||||
updateProjectAgentControls = data.updateProjectAgentControls;
|
||||
subscribeBossEvents = events.subscribeBossEvents;
|
||||
}
|
||||
|
||||
async function resetConfigState() {
|
||||
const state = await readState();
|
||||
state.aiAccounts = [];
|
||||
state.aiAccountSwitchHistory = [];
|
||||
state.userAttachmentStorageConfigs = [];
|
||||
state.masterAgentPromptPolicy = undefined;
|
||||
state.userMasterPrompts = [];
|
||||
state.masterAgentMemories = [];
|
||||
const masterAgentProject = state.projects.find((project) => project.id === "master-agent");
|
||||
if (masterAgentProject) {
|
||||
masterAgentProject.agentControls = undefined;
|
||||
}
|
||||
await writeState(state);
|
||||
}
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await setup();
|
||||
await resetConfigState();
|
||||
});
|
||||
|
||||
test.after(async () => {
|
||||
if (runtimeRoot) {
|
||||
await rm(runtimeRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("saveAiAccount publishes ai account refresh event", async () => {
|
||||
const events: Array<{ event: string }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event) => {
|
||||
events.push({ event });
|
||||
});
|
||||
|
||||
await saveAiAccount({
|
||||
label: "主 GPT",
|
||||
role: "primary",
|
||||
provider: "openai_api",
|
||||
displayName: "OpenAI 主账号",
|
||||
apiKey: "sk-test-primary",
|
||||
setActive: true,
|
||||
});
|
||||
unsubscribe();
|
||||
|
||||
assert.equal(events.at(-1)?.event, "ai_accounts.updated");
|
||||
});
|
||||
|
||||
test("upsertAttachmentStorageConfig publishes storage refresh event", async () => {
|
||||
const events: Array<{ event: string }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event) => {
|
||||
events.push({ event });
|
||||
});
|
||||
|
||||
await upsertAttachmentStorageConfig({
|
||||
account: "17600003315",
|
||||
mode: "server_file",
|
||||
updatedAt: "2026-04-07T10:20:00.000Z",
|
||||
});
|
||||
unsubscribe();
|
||||
|
||||
assert.equal(events.at(-1)?.event, "storage.updated");
|
||||
});
|
||||
|
||||
test("master agent prompt policy publishes master agent settings refresh event", async () => {
|
||||
const events: Array<{ event: string; payload: { projectId?: string } }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event, payload) => {
|
||||
events.push({ event, payload });
|
||||
});
|
||||
|
||||
await updateMasterAgentPromptPolicy({
|
||||
globalPrompt: "保持简洁并只输出有效内容。",
|
||||
updatedBy: "17600003315",
|
||||
});
|
||||
unsubscribe();
|
||||
|
||||
assert.equal(events.at(-1)?.event, "master_agent.settings.updated");
|
||||
assert.equal(events.at(-1)?.payload.projectId, "master-agent");
|
||||
});
|
||||
|
||||
test("master agent memory writes publish master agent settings refresh event", async () => {
|
||||
const events: Array<{ event: string; payload: { projectId?: string } }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event, payload) => {
|
||||
events.push({ event, payload });
|
||||
});
|
||||
|
||||
await createUserMasterMemory({
|
||||
account: "17600003315",
|
||||
scope: "global",
|
||||
title: "用户偏好",
|
||||
content: "群聊里默认一键通过。",
|
||||
memoryType: "user_preference",
|
||||
});
|
||||
unsubscribe();
|
||||
|
||||
assert.equal(events.at(-1)?.event, "master_agent.settings.updated");
|
||||
assert.equal(events.at(-1)?.payload.projectId, "master-agent");
|
||||
});
|
||||
|
||||
test("master agent takeover changes publish master agent settings refresh event", async () => {
|
||||
const events: Array<{ event: string; payload: { projectId?: string } }> = [];
|
||||
const unsubscribe = subscribeBossEvents((event, payload) => {
|
||||
events.push({ event, payload });
|
||||
});
|
||||
|
||||
await updateProjectAgentControls(
|
||||
"master-agent",
|
||||
{
|
||||
globalTakeoverEnabled: true,
|
||||
},
|
||||
"17600003315",
|
||||
);
|
||||
unsubscribe();
|
||||
|
||||
assert.equal(events.at(-1)?.event, "master_agent.settings.updated");
|
||||
assert.equal(events.at(-1)?.payload.projectId, "master-agent");
|
||||
});
|
||||
Reference in New Issue
Block a user