Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions desktop/renderer/src/browser-openclaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function createBrowserOpenClawMock(): OpenClawAPI {
{ id: "main", name: "Assistant" },
{ id: "master-archive", name: "Master Archive" },
{ id: "painter", name: "Van Gogh" },
{ id: "dr-pulse", name: "Dr. Pulse" },
{ id: "intel-analyst", name: "Intel Analyst" },
];
const browserAgentsSnapshot = () => ({
Expand Down
25 changes: 14 additions & 11 deletions desktop/renderer/src/i18n/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -794,17 +794,20 @@ export default {
"agent.painter.task.3.title": "Create pixel emoji stickers",
"agent.painter.task.3.desc": "Generate cute retro pixel-style emoji stickers.",

"agent.master.name": "Life Master",
"agent.master.desc": "Life planning, meals & travel arrangements",
"agent.master.tag.1": "Life Planning",
"agent.master.tag.2": "Meal Suggestions",
"agent.master.tag.3": "Travel Plans",
"agent.master.task.1.title": "Plan my weekend trip",
"agent.master.task.1.desc": "Customize a two-day itinerary based on weather and preferences.",
"agent.master.task.2.title": "Recommend healthy recipes",
"agent.master.task.2.desc": "Suggest balanced meal plans matching your taste preferences.",
"agent.master.task.3.title": "Create a study plan",
"agent.master.task.3.desc": "Break down an efficient daily study schedule by goals and time.",
"agent.drPulse.name": "Dr. Pulse",
"agent.drPulse.desc": "Evidence-led Windows diagnostics, guided tuning & scenario preparation",
"agent.drPulse.tag.1": "System Health",
"agent.drPulse.tag.2": "Guided Tuning",
"agent.drPulse.tag.3": "Scenario Prep",
"agent.drPulse.task.1.title": "Diagnose my Windows PC before proposing repairs",
"agent.drPulse.task.1.desc":
"Run read-only health checks, show the evidence, and prepare a scoped, reversible repair plan.",
"agent.drPulse.task.2.title": "Tune this Windows setting or peripheral",
"agent.drPulse.task.2.desc":
"Translate the request into supported steps, explain impact and rollback, and wait for approval.",
"agent.drPulse.task.3.title": "Prepare my PC for deep work or a video call",
"agent.drPulse.task.3.desc":
"Inspect readiness, propose supported app and system adjustments, and apply only confirmed changes.",

"agent.intelAnalyst.name": "Intel Analyst",
"agent.intelAnalyst.desc":
Expand Down
22 changes: 11 additions & 11 deletions desktop/renderer/src/i18n/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,17 +755,17 @@ export default {
"agent.painter.task.3.title": "制作像素表情包",
"agent.painter.task.3.desc": "生成可爱复古的像素风格表情贴纸。",

"agent.master.name": "大师",
"agent.master.desc": "生活规划、饮食与出行安排",
"agent.master.tag.1": "生活规划",
"agent.master.tag.2": "饮食建议",
"agent.master.tag.3": "出行安排",
"agent.master.task.1.title": "帮我规划周末行程",
"agent.master.task.1.desc": "根据天气和偏好定制两天出行方案。",
"agent.master.task.2.title": "推荐健康食谱",
"agent.master.task.2.desc": "结合营养均衡和口味偏好推荐三餐搭配。",
"agent.master.task.3.title": "制定学习计划",
"agent.master.task.3.desc": "按目标和时间拆解高效的每日学习安排。",
"agent.drPulse.name": "系统神医",
"agent.drPulse.desc": "循证 Windows 诊断、引导式调优与场景准备",
"agent.drPulse.tag.1": "系统体检",
"agent.drPulse.tag.2": "引导调优",
"agent.drPulse.tag.3": "场景准备",
"agent.drPulse.task.1.title": "先诊断我的 Windows 电脑,再提出修复方案",
"agent.drPulse.task.1.desc": "执行只读健康检查、展示证据,并制定范围明确、可回退的修复计划。",
"agent.drPulse.task.2.title": "调整这项 Windows 设置或外设",
"agent.drPulse.task.2.desc": "把需求转为当前工具支持的步骤,说明影响和回退方式,确认后再执行。",
"agent.drPulse.task.3.title": "为深度工作或视频会议准备电脑",
"agent.drPulse.task.3.desc": "检查就绪状态,提出应用与系统调整建议,仅执行已确认的更改。",

"agent.intelAnalyst.name": "前哨智囊",
"agent.intelAnalyst.desc": "个人情报简报、趋势监控与循证深度研究",
Expand Down
23 changes: 21 additions & 2 deletions desktop/renderer/src/stores/agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,21 @@ describe("agent store", () => {
expect(store.agents.map((agent) => agent.id)).toEqual(["main", "custom"]);
});

it("hides the Singer compatibility alias from the sidebar", async () => {
it("hides legacy compatibility aliases from the sidebar", async () => {
const store = useAgentStore();
agentsList.mockResolvedValueOnce({
agents: [
{ id: "main", name: "Assistant" },
{ id: "dr-pulse", name: "Dr. Pulse" },
{ id: "master", name: "Dr. Pulse" },
{ id: "creative-muse", name: "Creative Muse" },
{ id: "singer", name: "Creative Muse" },
],
});

await store.fetchAgents();

expect(store.agents.map((agent) => agent.id)).toEqual(["main", "creative-muse"]);
expect(store.agents.map((agent) => agent.id)).toEqual(["main", "dr-pulse", "creative-muse"]);
});

it("adds Master Archive to OpenClaw before showing it in the sidebar", async () => {
Expand Down Expand Up @@ -100,6 +102,23 @@ describe("agent store", () => {
expect(store.marketAgents.some((entry) => entry.id === "growth-hacker")).toBe(false);
});

it("presents the Dr. Pulse safety-first Windows scenarios", () => {
const store = useAgentStore();

expect(store.marketAgents.find((entry) => entry.id === "dr-pulse")).toMatchObject({
name: "Dr. Pulse",
description: "Evidence-led Windows diagnostics, guided tuning & scenario preparation",
tags: ["System Health", "Guided Tuning", "Scenario Prep"],
isAdded: false,
});
expect(store.marketAgents.find((entry) => entry.id === "dr-pulse")?.quickTasks).toEqual([
expect.objectContaining({ title: "Diagnose my Windows PC before proposing repairs" }),
expect.objectContaining({ title: "Tune this Windows setting or peripheral" }),
expect.objectContaining({ title: "Prepare my PC for deep work or a video call" }),
]);
expect(store.marketAgents.some((entry) => entry.id === "master")).toBe(false);
});

it("presents the Creative Muse platform content scenarios", () => {
const store = useAgentStore();

Expand Down
7 changes: 7 additions & 0 deletions desktop/renderer/src/stores/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,13 @@ describe("useChatStore — draft sessions", () => {
expect(store.sessionKey).toMatch(/^agent:singer:session-/);
expect(store.currentSessionAgentId).toBe("creative-muse");
});

it("attributes historical Master session keys to Dr. Pulse", () => {
const store = useChatStore();
store.newSession("master");
expect(store.sessionKey).toMatch(/^agent:master:session-/);
expect(store.currentSessionAgentId).toBe("dr-pulse");
});
});

describe("useChatStore — attachments", () => {
Expand Down
22 changes: 22 additions & 0 deletions desktop/renderer/src/stores/sessions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,28 @@ describe("useSessionStore", () => {
});
});

it("keeps historical Master sessions visible under Dr. Pulse", () => {
storage["openclaw-sessions"] = JSON.stringify([
{
key: "agent:master:legacy",
title: "Legacy system check",
createdAt: 1,
updatedAt: 1,
preview: "diagnose",
agentId: "master",
},
]);
setActivePinia(createPinia());

const store = useSessionStore();

expect(store.sessions[0]).toMatchObject({
key: "agent:master:legacy",
agentId: "dr-pulse",
title: "Legacy system check",
});
});

it("removes a persisted reserved warm-up session on load", () => {
storage["openclaw-sessions"] = JSON.stringify([
{
Expand Down
13 changes: 13 additions & 0 deletions desktop/src/agent-catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getAgentOwnedSkillIds,
isKnownSkillId,
matchesSkill,
canonicalAgentId,
resolveSkillFilterNames,
sanitizeAgentSkillIds,
SKILL_MATCH_NAMES,
Expand Down Expand Up @@ -146,6 +147,18 @@ describe("agent catalog skills binding", () => {
});
});

it("replaces Master with the dedicated Dr. Pulse persona", () => {
expect(AGENT_CATALOG.some((agent) => agent.id === "master")).toBe(false);
expect(AGENT_CATALOG.find((agent) => agent.id === "dr-pulse")).toMatchObject({
name: "Dr. Pulse",
avatar: "dr-pulse-avatar.png",
image: "Diviner.png",
workspaceDirName: "workspace-dr-pulse",
personaProfile: "dr-pulse",
});
expect(canonicalAgentId("master")).toBe("dr-pulse");
});

it("replaces Singer with the dedicated Creative Muse persona", () => {
expect(AGENT_CATALOG.some((agent) => agent.id === "singer")).toBe(false);
expect(AGENT_CATALOG.find((agent) => agent.id === "creative-muse")).toMatchObject({
Expand Down
23 changes: 13 additions & 10 deletions desktop/src/agent-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export interface AgentCatalogEntry {
skills: readonly string[];
ownedSkills?: readonly string[];
workspaceDirName?: string;
personaProfile?: "master-archive" | "code-geek" | "intel-analyst" | "creative-muse";
personaProfile?: "master-archive" | "code-geek" | "dr-pulse" | "intel-analyst" | "creative-muse";
}

export const AGENT_CATALOG: readonly AgentCatalogEntry[] = [
Expand Down Expand Up @@ -142,20 +142,22 @@ export const AGENT_CATALOG: readonly AgentCatalogEntry[] = [
skills: catalogSkills(),
},
{
id: "master",
name: "Master",
nameKey: "agent.master.name",
descKey: "agent.master.desc",
avatar: "master-avatar.png",
id: "dr-pulse",
name: "Dr. Pulse",
nameKey: "agent.drPulse.name",
descKey: "agent.drPulse.desc",
avatar: "dr-pulse-avatar.png",
image: "Diviner.png",
tagKeys: ["agent.master.tag.1", "agent.master.tag.2", "agent.master.tag.3"],
tagKeys: ["agent.drPulse.tag.1", "agent.drPulse.tag.2", "agent.drPulse.tag.3"],
taskKeys: [
{ titleKey: "agent.master.task.1.title", descKey: "agent.master.task.1.desc" },
{ titleKey: "agent.master.task.2.title", descKey: "agent.master.task.2.desc" },
{ titleKey: "agent.master.task.3.title", descKey: "agent.master.task.3.desc" },
{ titleKey: "agent.drPulse.task.1.title", descKey: "agent.drPulse.task.1.desc" },
{ titleKey: "agent.drPulse.task.2.title", descKey: "agent.drPulse.task.2.desc" },
{ titleKey: "agent.drPulse.task.3.title", descKey: "agent.drPulse.task.3.desc" },
],
installedByDefault: false,
skills: catalogSkills(),
workspaceDirName: "workspace-dr-pulse",
personaProfile: "dr-pulse",
},
{
id: "intel-analyst",
Expand Down Expand Up @@ -290,6 +292,7 @@ export function getAgentOwnedSkillIds(agentId: string): readonly string[] {
}

export const LEGACY_AGENT_ID_ALIASES: Readonly<Record<string, string>> = {
master: "dr-pulse",
singer: "creative-muse",
};

Expand Down
Loading
Loading