feat: split assistant persona from worker persona

This commit is contained in:
zenord
2026-08-18 22:49:05 +08:00
parent ffedf616e3
commit 2409922d55
8 changed files with 69 additions and 5 deletions
+6
View File
@@ -27,6 +27,12 @@ test("parses Config v3 defaults for one Bot, agent, and platform", () => {
assert.equal(config.runtime.acp.promptTimeoutMs, 14_400_000);
assert.equal(config.runtime.acp.maxAssistantSessions, 4);
assert.equal(config.bot.permissions.mode, "deny");
assert.equal(config.bot.assistantPersona, "");
});
test("parses optional bot.assistantPersona", () => {
const config = parseConfig(raw({ bot: { ...(raw().bot as object), assistantPersona: "像运维老同事一样讲话" } }));
assert.equal(config.bot.assistantPersona, "像运维老同事一样讲话");
});
test("explicitly rejects non-v3 configuration and unknown fields", () => {
+48
View File
@@ -0,0 +1,48 @@
import assert from "node:assert/strict";
import test from "node:test";
import { parseConfig } from "../src/config.js";
import { BotProfileResolver } from "../src/roles/role-registry.js";
function resolvedBot(botOverrides: Record<string, unknown> = {}) {
const config = parseConfig({
configVersion: 3,
bot: {
id: "test-bot", workspace: "/tmp", persona: "Worker 人格:严格的安全/运维边界。",
agent: { id: "kimi", command: "kimi", args: ["acp"], env: {} },
skills: [], permissions: { mode: "deny" },
...botOverrides
},
gateway: { platform: { type: "webhook", secret: "secret" } },
runtime: {}
});
return new BotProfileResolver(config).bot;
}
test("assistant uses assistantPersona while worker keeps persona", () => {
const bot = resolvedBot({ assistantPersona: "Assistant 人格:像运维老同事一样说人话。" });
assert.match(bot.assistantBootstrap, /Assistant 人格:像运维老同事一样说人话。/);
assert.doesNotMatch(bot.assistantBootstrap, /Worker 人格:严格的安全\/运维边界。/);
assert.match(bot.workerBootstrap, /Worker 人格:严格的安全\/运维边界。/);
assert.doesNotMatch(bot.workerBootstrap, /Assistant 人格/);
});
test("assistant falls back to persona when assistantPersona is empty", () => {
const bot = resolvedBot();
assert.match(bot.assistantBootstrap, /Worker 人格:严格的安全\/运维边界。/);
assert.match(bot.workerBootstrap, /Worker 人格:严格的安全\/运维边界。/);
});
test("assistant bootstrap carries human speaking-style rules, worker bootstrap does not", () => {
const bot = resolvedBot({ assistantPersona: "Assistant 人格" });
assert.match(bot.assistantBootstrap, /reliable colleague/);
assert.match(bot.assistantBootstrap, /conclusion, then the reason, then the next step/);
assert.match(bot.assistantBootstrap, /2-4 sentences/);
assert.match(bot.assistantBootstrap, /actionable next step/);
assert.doesNotMatch(bot.workerBootstrap, /reliable colleague/);
});
test("assistantPersona participates in the bot fingerprint", () => {
const base = resolvedBot();
const withPersona = resolvedBot({ assistantPersona: "Assistant 人格" });
assert.notEqual(base.fingerprint, withPersona.fingerprint);
});