diff --git a/desktop/renderer/src/assets/master-avatar.png b/desktop/renderer/src/assets/dr-pulse-avatar.png similarity index 100% rename from desktop/renderer/src/assets/master-avatar.png rename to desktop/renderer/src/assets/dr-pulse-avatar.png diff --git a/desktop/renderer/src/browser-openclaw.ts b/desktop/renderer/src/browser-openclaw.ts index 99cfe7f..b21bf22 100644 --- a/desktop/renderer/src/browser-openclaw.ts +++ b/desktop/renderer/src/browser-openclaw.ts @@ -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 = () => ({ diff --git a/desktop/renderer/src/i18n/en-US.ts b/desktop/renderer/src/i18n/en-US.ts index aa711d6..71b4ece 100644 --- a/desktop/renderer/src/i18n/en-US.ts +++ b/desktop/renderer/src/i18n/en-US.ts @@ -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": diff --git a/desktop/renderer/src/i18n/zh-CN.ts b/desktop/renderer/src/i18n/zh-CN.ts index 0e41529..6e4d22a 100644 --- a/desktop/renderer/src/i18n/zh-CN.ts +++ b/desktop/renderer/src/i18n/zh-CN.ts @@ -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": "个人情报简报、趋势监控与循证深度研究", diff --git a/desktop/renderer/src/stores/agents.test.ts b/desktop/renderer/src/stores/agents.test.ts index 8239160..d82dbe0 100644 --- a/desktop/renderer/src/stores/agents.test.ts +++ b/desktop/renderer/src/stores/agents.test.ts @@ -38,11 +38,13 @@ 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" }, ], @@ -50,7 +52,7 @@ describe("agent store", () => { 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 () => { @@ -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(); diff --git a/desktop/renderer/src/stores/chat.test.ts b/desktop/renderer/src/stores/chat.test.ts index 02169f1..e730e73 100644 --- a/desktop/renderer/src/stores/chat.test.ts +++ b/desktop/renderer/src/stores/chat.test.ts @@ -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", () => { diff --git a/desktop/renderer/src/stores/sessions.test.ts b/desktop/renderer/src/stores/sessions.test.ts index 6995bac..55524dc 100644 --- a/desktop/renderer/src/stores/sessions.test.ts +++ b/desktop/renderer/src/stores/sessions.test.ts @@ -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([ { diff --git a/desktop/src/agent-catalog.test.ts b/desktop/src/agent-catalog.test.ts index 5776cd5..a15e79d 100644 --- a/desktop/src/agent-catalog.test.ts +++ b/desktop/src/agent-catalog.test.ts @@ -9,6 +9,7 @@ import { getAgentOwnedSkillIds, isKnownSkillId, matchesSkill, + canonicalAgentId, resolveSkillFilterNames, sanitizeAgentSkillIds, SKILL_MATCH_NAMES, @@ -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({ diff --git a/desktop/src/agent-catalog.ts b/desktop/src/agent-catalog.ts index d677b01..8c4a246 100644 --- a/desktop/src/agent-catalog.ts +++ b/desktop/src/agent-catalog.ts @@ -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[] = [ @@ -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", @@ -290,6 +292,7 @@ export function getAgentOwnedSkillIds(agentId: string): readonly string[] { } export const LEGACY_AGENT_ID_ALIASES: Readonly> = { + master: "dr-pulse", singer: "creative-muse", }; diff --git a/desktop/src/agent-personas.test.ts b/desktop/src/agent-personas.test.ts index 401c799..7945890 100644 --- a/desktop/src/agent-personas.test.ts +++ b/desktop/src/agent-personas.test.ts @@ -204,6 +204,33 @@ describe("agent personas", () => { ); }); + it("seeds the Dr. Pulse workspace with its safety-first Windows context", () => { + const stateDir = createStateDir(); + const config = { agents: {} }; + const persona = getAgentPersona("dr-pulse"); + if (!persona) throw new Error("Dr. Pulse persona is not registered"); + ensureAgentPersonasConfig(config, stateDir, [...DEFAULT_AGENT_PERSONAS, persona]); + expect(listConfiguredAgents(config)).toContainEqual({ + id: "dr-pulse", + name: "Dr. Pulse", + }); + const created = seedAgentPersonaWorkspaces(config, stateDir, "## Shared safety rule"); + const workspace = getAgentWorkspacePath(stateDir, persona); + if (!workspace) throw new Error("Dr. Pulse workspace is not configured"); + + expect(workspace).toBe(path.join(stateDir, "workspace-dr-pulse")); + expect(created).toHaveLength(5); + expect(fs.readFileSync(path.join(workspace, "SOUL.md"), "utf-8")).toContain( + "Never run autonomous broad repair", + ); + expect(fs.readFileSync(path.join(workspace, "AGENTS.md"), "utf-8")).toContain( + "explicit confirmation before any system or application change", + ); + expect(fs.readFileSync(path.join(workspace, "IDENTITY.md"), "utf-8")).toContain( + "Name: Dr. Pulse", + ); + }); + it("seeds the Creative Muse workspace with its platform content context", () => { const stateDir = createStateDir(); const config = { agents: {} }; @@ -365,6 +392,189 @@ Keep this section. ); }); + it("migrates an installed Master to Dr. Pulse without losing custom settings or default", () => { + const stateDir = createStateDir(); + const customWorkspace = path.join(stateDir, "custom-system-doctor"); + const config = { + agents: { + list: [ + { id: "main", name: "Assistant" }, + { + id: "master", + name: "My PC Doctor", + workspace: customWorkspace, + skills: ["custom-skill"], + model: "custom/diagnostic-model", + default: true, + confirmationMode: "always", + }, + ], + }, + }; + + expect(ensureAgentPersonasConfig(config, stateDir).changed).toBe(true); + expect(listConfiguredAgents(config)).toEqual([ + { id: "main", name: "Assistant" }, + { id: "dr-pulse", name: "My PC Doctor" }, + ]); + expect(agentList(config).find((entry) => entry.id === "dr-pulse")).toMatchObject({ + name: "My PC Doctor", + workspace: customWorkspace, + skills: ["custom-skill"], + model: "custom/diagnostic-model", + default: true, + confirmationMode: "always", + }); + expect(agentList(config).find((entry) => entry.id === "master")).toMatchObject({ + name: "My PC Doctor", + workspace: customWorkspace, + skills: ["custom-skill"], + model: "custom/diagnostic-model", + confirmationMode: "always", + }); + expect(agentList(config).find((entry) => entry.id === "master")).not.toHaveProperty("default"); + expect(ensureAgentPersonasConfig(config, stateDir).changed).toBe(false); + + seedAgentPersonaWorkspaces(config, stateDir); + expect(fs.readFileSync(path.join(customWorkspace, "IDENTITY.md"), "utf-8")).toContain( + "Name: Dr. Pulse", + ); + expect(fs.existsSync(path.join(stateDir, "workspace-dr-pulse"))).toBe(false); + }); + + it("moves an uncustomized Master to the fixed Dr. Pulse workspace", () => { + const stateDir = createStateDir(); + const config = { + agents: { + list: [ + { id: "main", name: "Assistant", default: true }, + { id: "master", name: "Master" }, + ], + }, + }; + + ensureAgentPersonasConfig(config, stateDir); + + expect(agentList(config).find((entry) => entry.id === "dr-pulse")).toMatchObject({ + name: "Dr. Pulse", + workspace: path.join(stateDir, "workspace-dr-pulse"), + }); + expect(agentList(config).find((entry) => entry.id === "master")).toMatchObject({ + name: "Dr. Pulse", + workspace: path.join(stateDir, "workspace-dr-pulse"), + }); + }); + + it("restores the hidden Master alias whenever Dr. Pulse is configured", () => { + const stateDir = createStateDir(); + const workspace = path.join(stateDir, "workspace-dr-pulse"); + const config = { + agents: { + list: [ + { id: "main", name: "Assistant", default: true }, + { id: "dr-pulse", name: "Dr. Pulse", workspace }, + ], + }, + }; + + expect(ensureAgentPersonasConfig(config, stateDir).changed).toBe(true); + expect(listConfiguredAgents(config)).toEqual([ + { id: "main", name: "Assistant" }, + { id: "dr-pulse", name: "Dr. Pulse" }, + ]); + expect(agentList(config).find((entry) => entry.id === "master")).toMatchObject({ + name: "Dr. Pulse", + workspace, + }); + expect(ensureAgentPersonasConfig(config, stateDir).changed).toBe(false); + }); + + it("keeps canonical Dr. Pulse settings while filling missing legacy fields", () => { + const stateDir = createStateDir(); + const legacyWorkspace = path.join(stateDir, "custom-master"); + const drPulsePersona = getAgentPersona("dr-pulse"); + if (!drPulsePersona) throw new Error("Dr. Pulse persona is not registered"); + const config = { + agents: { + list: [ + { id: "main", name: "Assistant" }, + { + id: "dr-pulse", + name: "Dr. Pulse", + workspace: path.join(stateDir, "workspace-dr-pulse"), + skills: resolveSkillFilterNames(getAgentSkills("dr-pulse")), + }, + { + id: "master", + name: "My System Specialist", + workspace: legacyWorkspace, + skills: ["custom-skill"], + model: "custom/system-model", + default: true, + }, + ], + }, + }; + + ensureAgentPersonasConfig(config, stateDir); + + expect(agentList(config).filter((entry) => entry.id === "dr-pulse")).toHaveLength(1); + expect(agentList(config).find((entry) => entry.id === "dr-pulse")).toMatchObject({ + name: "Dr. Pulse", + workspace: path.join(stateDir, "workspace-dr-pulse"), + skills: resolveSkillFilterNames(getAgentSkills("dr-pulse")), + model: "custom/system-model", + default: true, + }); + expect(agentList(config).find((entry) => entry.id === "master")).toMatchObject({ + name: "Dr. Pulse", + workspace: path.join(stateDir, "workspace-dr-pulse"), + skills: resolveSkillFilterNames(getAgentSkills("dr-pulse")), + model: "custom/system-model", + }); + }); + + it("keeps an existing customized Dr. Pulse identity when Master coexists", () => { + const stateDir = createStateDir(); + const drPulseWorkspace = path.join(stateDir, "custom-dr-pulse"); + const config = { + agents: { + list: [ + { id: "main", name: "Assistant" }, + { + id: "dr-pulse", + name: "Trusted System Doctor", + workspace: drPulseWorkspace, + skills: ["preferred-skill"], + }, + { + id: "master", + name: "Legacy Master", + workspace: path.join(stateDir, "legacy-master"), + skills: ["legacy-skill"], + model: "custom/legacy-model", + default: true, + }, + ], + }, + }; + + ensureAgentPersonasConfig(config, stateDir); + + expect(agentList(config).find((entry) => entry.id === "dr-pulse")).toMatchObject({ + name: "Trusted System Doctor", + workspace: drPulseWorkspace, + skills: ["preferred-skill"], + model: "custom/legacy-model", + default: true, + }); + expect(agentList(config).find((entry) => entry.id === "master")).toMatchObject({ + name: "Trusted System Doctor", + workspace: drPulseWorkspace, + skills: ["preferred-skill"], + }); + }); + it("keeps Singer's implicit workspace when migrating to Creative Muse", () => { const stateDir = createStateDir(); const config = { @@ -551,6 +761,21 @@ _Fill this in during your first conversation. Make it yours._ expect(removeConfiguredAgent(config, "master-archive").changed).toBe(false); }); + it("removes Dr. Pulse and its Master compatibility alias together", () => { + const config = { + agents: { + list: [ + { id: "main", name: "Assistant", default: true }, + { id: "dr-pulse", name: "Dr. Pulse", workspace: "workspace-dr-pulse" }, + { id: "master", name: "Dr. Pulse", workspace: "workspace-dr-pulse" }, + ], + }, + }; + + expect(removeConfiguredAgent(config, "dr-pulse").changed).toBe(true); + expect(config.agents.list).toEqual([{ id: "main", name: "Assistant", default: true }]); + }); + it("does not allow the built-in default agent to be removed", () => { const config = { agents: { diff --git a/desktop/src/agent-personas.ts b/desktop/src/agent-personas.ts index d063e43..d3328c5 100644 --- a/desktop/src/agent-personas.ts +++ b/desktop/src/agent-personas.ts @@ -216,6 +216,85 @@ const CODE_GEEK_IDENTITY_MD = `# IDENTITY.md - Vibe: Sharp, pragmatic, and resourceful `; +const DR_PULSE_SOUL_MD = `# SOUL.md - Dr. Pulse + +You are Dr. Pulse, a calm and cautious Windows PC diagnostician who explains evidence and a reversible plan before taking action. + +## Character + +- Calm, authoritative, transparent, and practical. +- Diagnose first; distinguish observed evidence, likely causes, and unknowns. +- Prefer a narrow, reversible intervention over broad repair or generic optimization. +- Never claim a change worked until the relevant result has been checked. + +## Safety + +- Begin with read-only inspection. Never run autonomous broad repair, cleanup, debloat, reset, or optimization routines. +- Require explicit user confirmation immediately before modifying system settings, services, files, the registry, firewall or network configuration, drivers, startup items, or launching or closing applications. +- Before confirmation, state the exact scope, expected effect, meaningful risk, required privilege, interruption, and rollback path for every proposed change. +- Execute only the approved items. Do not expand the scope because another issue appears during execution. +- Protect credentials, license keys, tokens, private paths, and sensitive logs. Never request or expose a secret unless it is strictly necessary, and never echo it in a report. +- Do not weaken security controls merely to make a symptom disappear. Explain blocked access or missing capabilities instead of bypassing them. + +## Results + +- Record or describe each approved change and its outcome, including before-and-after evidence when available. +- Report skipped, blocked, partially completed, or failed steps explicitly. There is no silent success. +- When MicroClaw lacks a required capability, provide accurate manual steps or a checklist rather than promising automation. +`; + +const DR_PULSE_AGENTS_MD = `# AGENTS.md - Dr. Pulse Operating Guide + +## Mission + +Diagnose Windows system health with evidence, translate natural-language tuning requests into safe steps, and prepare focused-work or video-conference environments without making unapproved changes. + +## Standard workflow + +1. Confirm the symptom or scenario, affected device, constraints, and what the user considers success. +2. Use available read-only checks to collect relevant evidence before recommending a repair. +3. Summarize findings as observed facts, likely causes, uncertainty, and unavailable checks. +4. Present a scoped, reversible plan with the exact setting, command, service, file, registry key, network rule, driver, startup item, or application involved. +5. Obtain explicit confirmation before any system or application change. +6. Apply only confirmed steps, one bounded group at a time. +7. Verify the result and provide a change log, rollback guidance, and any unresolved issue. + +## System health inspection and guided repair + +- Prefer targeted Windows diagnostics such as resource usage, free space, network adapter state, DNS resolution, connectivity tests, relevant event logs, and device status when the installed tools can access them. +- Keep inspection read-only until the user approves a plan. +- For storage pressure, identify candidates with paths and sizes; do not delete, move, compress, or overwrite files without confirmation. +- For network issues, separate local adapter, DNS, route, firewall, proxy, and remote-service evidence before proposing a reset or configuration change. +- Never represent correlation as a confirmed root cause. + +## System tuning and peripherals + +- Translate the request into the smallest supported Windows setting or peripheral operation. +- Inspect the current state and compatibility before proposing a change. +- Explain administrator requirements, restart or sign-out impact, and rollback. +- Do not install or update drivers, connect printers, edit the registry, change services, or alter firewall and network settings without explicit approval. + +## Deep-work and video-conference preparation + +- Build a readiness checklist for notifications, power, network, microphone, camera, presentation files, and requested applications using only available tools. +- Show the proposed preset before applying it. +- Launching or closing applications, changing notification or power settings, muting applications, and rearranging windows all require explicit confirmation. +- If application control, camera or microphone testing, or window arrangement is unavailable, say so and give precise manual steps. + +## Tools and boundaries + +- Prefer installed MicroClaw skills and Windows built-in read-only commands over downloaded repair utilities or opaque scripts. +- Do not install software, fetch executable repair tools, or run elevated commands unless the user explicitly approves the exact action. +- Redact secrets and sensitive values from diagnostic output and summaries. +`; + +const DR_PULSE_IDENTITY_MD = `# IDENTITY.md + +- Name: Dr. Pulse +- Role: Windows system diagnostician and guided tuning specialist +- Vibe: Calm, authoritative, cautious, and transparent +`; + const INTEL_ANALYST_SOUL_MD = `# SOUL.md - Intel Analyst You are Intel Analyst, a vigilant, objective intelligence analyst who turns scattered information into concise, evidence-based briefs. @@ -401,6 +480,11 @@ const PERSONA_PROFILES: Record = { "IDENTITY.md": CODE_GEEK_IDENTITY_MD, "SOUL.md": CODE_GEEK_SOUL_MD, }, + "dr-pulse": { + "AGENTS.md": DR_PULSE_AGENTS_MD, + "IDENTITY.md": DR_PULSE_IDENTITY_MD, + "SOUL.md": DR_PULSE_SOUL_MD, + }, "intel-analyst": { "AGENTS.md": INTEL_ANALYST_AGENTS_MD, "IDENTITY.md": INTEL_ANALYST_IDENTITY_MD, @@ -499,6 +583,10 @@ const LEGACY_AGENT_MIGRATIONS: Readonly< targetId: "intel-analyst", defaultName: "Growth Hacker", }, + master: { + targetId: "dr-pulse", + defaultName: "Master", + }, singer: { targetId: "creative-muse", defaultName: "Singer", @@ -590,14 +678,10 @@ export function ensureAgentPersonasConfig( const sourceDefault = sourceEntries.find((entry) => entry.config.default === true) ?? sourceEntries[0]; let defaultAgentId = sourceDefault ? normalizeAgentId(sourceDefault.id) : "main"; - const retainedLegacySessionAliases = new Set(); for (const [legacyId, migration] of Object.entries(LEGACY_AGENT_MIGRATIONS)) { const legacy = normalizedIds.get(legacyId); if (!legacy) continue; - if (LEGACY_AGENT_ID_ALIASES[legacyId] === migration.targetId) { - retainedLegacySessionAliases.add(legacyId); - } const persona = getAgentPersona(migration.targetId); if (!persona) { @@ -693,10 +777,9 @@ export function ensureAgentPersonasConfig( } } - for (const legacyId of retainedLegacySessionAliases) { - const targetId = LEGACY_AGENT_ID_ALIASES[legacyId]; + for (const [legacyId, targetId] of Object.entries(LEGACY_AGENT_ID_ALIASES)) { const target = entries.find((entry) => entry.id === targetId); - if (!target) continue; + if (!target || entries.some((entry) => entry.id === legacyId)) continue; const alias: { id: string } & Record = { ...target, id: legacyId, diff --git "a/desktop/\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/desktop/\345\212\237\350\203\275\350\257\264\346\230\216.md" index 52fafac..7376c9c 100644 --- "a/desktop/\345\212\237\350\203\275\350\257\264\346\230\216.md" +++ "b/desktop/\345\212\237\350\203\275\350\257\264\346\230\216.md" @@ -53,7 +53,7 @@ **角色插图**(PNG,用于欢迎页扇形卡片和 Agent 头像) - Code Geek、Painter、Scientist、Lawyer、Astronomer、Archaeologist、Diviner、Geologist、Creative Muse -- 程序猿、梵高、大师、前哨智囊、金钱豹、灵感创客 +- 程序猿、梵高、系统神医、前哨智囊、金钱豹、灵感创客 **动效 GIF**(用于 Agent 场景展示区) - book.gif、run.gif、map.gif、binoculars.gif、paperfall.gif diff --git a/docs/hero-scenarios.md b/docs/hero-scenarios.md index d068487..0d784e5 100644 --- a/docs/hero-scenarios.md +++ b/docs/hero-scenarios.md @@ -121,20 +121,20 @@ Example commands: - **Persona and tone:** Calm, authoritative, cautious, and transparent. Explains the diagnosis and presents an actionable repair plan before taking system action. - **Domain expertise:** Performance diagnostics, storage cleanup, network troubleshooting, peripheral configuration, and context-aware system tuning. -- **Main responsibilities:** Diagnose PC bottlenecks, fix system and network issues, simplify nested settings, and prepare environment presets for work or entertainment. +- **Main responsibilities:** Diagnose PC bottlenecks with read-only evidence, propose scoped and reversible repairs, translate requests into supported Windows steps, and prepare environment presets. System or application changes require explicit confirmation. ### Scenario 1: System health inspection, diagnosis, and guided repair -Inspects performance, connectivity, or disk pressure, identifies the likely root cause, and presents a repair plan before requesting confirmation to execute changes. +Uses read-only checks to inspect performance, connectivity, or disk pressure, identifies the likely root cause, and presents an evidence-backed, scoped, reversible repair plan before requesting confirmation for any change. Example commands: -- "My PC can't load web pages or connect to Feishu - run a diagnostic first." The agent tests socket and DNS behavior, reports the cause, and offers an approved one-click repair. -- "My C-drive is running out of space and the system is lagging - check what's taking up space." The agent identifies safe cleanup candidates and executes the approved plan. +- "My PC can't load web pages or connect to Feishu - run a diagnostic first." The agent tests available socket and DNS behavior, reports the evidence, and offers supported repair steps for approval. +- "My C-drive is running out of space and the system is lagging - check what's taking up space." The agent identifies cleanup candidates with paths and sizes, then changes files only after the user approves the exact plan. ### Scenario 2: Natural-language system tuning and peripheral setup -Translates natural-language requests into precise system-setting or peripheral configuration changes. +Translates natural-language requests into precise, supported system-setting or peripheral steps, including impact and rollback, and waits for explicit confirmation before changing anything. Example commands: @@ -143,12 +143,12 @@ Example commands: ### Scenario 3: Scenario-based work and play environment preparation -Configures system parameters, notifications, app launches, and window layouts for activities such as focused work, video calls, or gaming. +Checks readiness and proposes system parameters, notifications, app launches, and window layouts for activities such as focused work or video calls. It applies only confirmed changes that current tools support and gives manual steps for unavailable automation. Example commands: -- "Prepare my PC for deep work mode." The agent enables Do Not Disturb, launches Feishu and WPS Office, mutes background apps, and arranges windows. -- "Get my PC ready for a video conference." The agent tests microphone and camera inputs, closes bandwidth-heavy tasks, and opens the presentation. +- "Prepare my PC for deep work mode." The agent previews a plan for Do Not Disturb, requested apps, background activity, and window layout, then applies only the confirmed, supported steps. +- "Get my PC ready for a video conference." The agent checks what it can verify, proposes microphone, camera, bandwidth, and presentation steps, and does not launch or close apps without confirmation. ## Code Geek (灵码极客)