[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83014":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":16,"starSnapshotCount":16,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},83014,"sakura","Rvosy\u002Fsakura","Rvosy","一个通用桌宠Agent框架, 可以主动根据屏幕内容做出反应","",null,"Python",89,3,70,1,0,8,1.81,false,"main",true,[],"2026-06-12 02:04:30","[English](README.en.md)\n\n# Sakura Desktop Pet\n\n最近推完水晶社的新作，~~推完自动变成学姐的狗~~，已经变成学姐的形状了，夜里辗转反侧怎么都睡不着，所以起来开发了这个桌宠Agent框架\n\n这个框架有一大特色就是 **她会主动找你**。传统聊天机器人只有在你先开口时才会回应，就像一扇需要你敲门才会开的锁。Sakura 更接近一个坐在你旁边的人——你不需要一直和她说话，但她知道你在做什么，偶尔觉得该说点什么的时候会自己开口。\n\n比如你正在打游戏，她瞥见屏幕上的死亡提示，凑过来说「已经第三回了…要不要帮你查下攻略？」同意后就真的打开浏览器搜了一圈，把要点贴进备忘录。\n\n或者是你在浏览其他角色的图片时，会吃醋地说「又在看别人了啊…」要求你多看看她的立绘，偶尔还会因为你太久没看她而生气地说「都不理我了啊…」\n\n所以这个框架实现的是一个一直在角落、会观察、会偶尔插话的角色。她的对话风格、表情、语音都由角色卡驱动，而工具能力（浏览器操作、屏幕截图、文件读取、Web 搜索、提醒、长期记忆等）则来自内置的 Agent 引擎。\n\n把它想成一个定制角色的桌面 Agent。\n\n![Sakura 桌宠预览](_pet_style_preview.png)\n\n## 🚀 新手教程（零基础也能用）\n\n**不需要会编程。** 推荐直接使用 **Release 里的 `0.9.3` 版本**，不要只下载 GitHub 页面上的源码压缩包。源码包缺少预置 `runtime`，新手会更容易卡在 Python 和依赖安装上喵~\n\n> **平台提醒：** Windows 版本是当前主要测试目标。macOS 包会在 Release 中构建出来，但 **Mac 目前没有经过实际机器测试**，可能遇到权限、启动脚本或依赖问题；如果你用 Mac，请把它当作实验版本。\n\n### 第一步：下载发布包\n\n打开 [Releases 页面](https:\u002F\u002Fgithub.com\u002FRvosy\u002Fsakura\u002Freleases)，务必下载 `0.9.3` 及之后的版本, 之前的版本有重大BUG\n\nRelease 里常见的文件含义如下：\n\n| 文件名 | 是什么 | 适合谁下载 |\n|:-:|---|---|\n| `sakura-v0.9.3-windows-x64.zip` | Windows 完整包，包含项目文件和 `runtime` | **Windows 新手首选** |\n| `runtime-windows-x64.zip` | 只有 Windows 预置 Python 运行环境 | 拉源码、缺 `runtime` 的用户 |\n\n> 如果你只是想运行桌宠，下载 `sakura-v0.9.3-windows-x64.zip` 这种 **完整包**。`runtime` 包不是完整程序，单独下载后不能直接启动。\n\n### 第二步：安装依赖\n\n解压完整包后，进入解压出来的项目目录。`runtime` 文件夹自带了 Python，但依赖包还是要装一次：\n\n- **Windows 用户：** 双击 `install.bat`，等待完成（约 5-15 分钟）。\n- **Mac 用户：** 可尝试双击 `install.command`，或在终端进入项目目录后运行 `bash scripts\u002Finstall.sh`。但 Mac 没有实机测试过，遇到问题请优先反馈日志。\n- **Linux 用户：** 当前没有正式发布包；如果从源码运行，进入项目目录后运行 `bash scripts\u002Finstall.sh`。\n\n> 如果是直接拉取的源码，需要先从 Release 页面下载对应平台的预编译依赖包（`sakura-runtime-*.zip`），把里面的 `runtime` 文件夹放到项目根目录，再运行安装脚本。\n> 不管下载的是 Release 完整包还是 GitHub 源码，这一步都要做。装完命令行窗口会自动关闭。\n\n### 第三步：获取 API Key\n\n桌宠需要一个「AI 大脑」才能说话，你需要一个 API Key。就像给手机插 SIM 卡才能上网一样。\n\n1. **获取 API Key。** 可以从以下任一渠道获得：\n   - 国内中转站如 [GemAI](https:\u002F\u002Fapi.gemai.cc\u002Fregister?aff=rwbQ) (有便宜且按次计费的 gemini-flash 系列模型)\n   - 其他任何兼容 OpenAI 接口格式的服务\n\n> **🚫 目前不要使用 DeepSeek 系列模型！**\n>\n> Sakura 的很多功能（屏幕观察、图像识别等）直接依赖模型的多模态能力（视觉理解），而 DeepSeek 系列模型不具备多模态能力，使用后会导致桌宠无法正常观察屏幕、识别图像等功能失效。\n>\n> 请选择支持视觉\u002F多模态的模型，例如 Gemini Flash 等。\n\n### 第四步：一键启动\n\n- **Windows 用户：** 双击项目根目录的 **`start.bat`**\n- **Mac 用户：** 可尝试双击 `start.command`，或在终端里运行 `bash scripts\u002Fstart.sh`。再次提醒：Mac 没有实机测试过。\n- **Linux 用户：** 在终端里运行 `bash scripts\u002Fstart.sh`\n- **右键** 桌宠或托盘图标可以打开菜单（设置、聊天记录等）\n\n\n### 第五步：获取角色包\n\n#### 获取渠道\n\n暂时只有百度网盘\n\n- **[百度网盘](https:\u002F\u002Fpan.baidu.com\u002Fs\u002F5ZXvAi6n6i7-OJAYeWDpprg)**：包含所有已发布的角色包.\n\n#### 安装方式\n\n1. 下载角色包\n2. 设置页选择导入\n\n### 如何更新版本?\n\n如果你已经装过旧版，推荐按下面方式更新：\n\n1. 关闭正在运行的 Sakura。\n2. 下载同平台的最新**完整包**，例如 Windows 用户下载 `sakura-v0.9.3-windows-x64.zip`。\n3. 解压新包，把新包里的文件复制到旧 Sakura 目录，遇到同名文件选择 **覆盖\u002F替换**。\n4. 如果启动失败, 再运行一次安装脚本：Windows 双击 `install.bat`；Mac\u002FLinux 运行 `bash scripts\u002Finstall.sh`。\n5. 启动 Sakura：Windows 双击 `start.bat`；Mac 可尝试 `start.command` 或 `bash scripts\u002Fstart.sh`。\n\n\n以下内容面向想深入了解架构或做开发的用户。如果你是纯用来玩的，到这里就够啦~\n\n---\n\n\n## 设计思路\n\nSakura 现在采用更直接的运行时结构：UI 负责收集用户输入、截图、确认面板和主动事件，`ChatWorker` \u002F `ChatPipeline` 负责把这些上下文整理成一次运行请求，真正的对话决策和工具循环都交给 `AgentRuntime`。\n\n`AgentRuntime` 直接使用 OpenAI 兼容接口的原生 `tool_calls` 协议。模型可以在同一轮对话里决定是否调用工具，工具结果会以 tool role 回填给模型，再由模型产出最终角色回复。这样不再需要额外的路由拆分模块，链路更短，也更容易保证提醒、主动关怀、工具确认后的回复都进入同一套字幕和语音播放流程。\n\n最终回复仍然统一按分段 JSON 组织：每段包含日文原文、中文字幕、语气和立绘标识。UI 只消费这份结构，同步驱动字幕、表情切换和 TTS 播放；如果模型输出格式不合格，运行时会尝试一次格式修复，避免坏 JSON 直接进入界面。\n\n## 核心功能\n\n- **角色包驱动。** `CharacterRegistry` 扫描 `characters\u002F*\u002Fcharacter.json`，校验角色卡、立绘和语音参考资源。\n\n- **分段双语回复。** 模型返回 JSON 片段，每段包含日文、中文和语气标签，UI 同步显示字幕、切换立绘、播放语音。\n\n- **语气联动表情和语音。** 语气同时驱动立绘切换和 TTS 参考音频选择，支持 GPT-SoVITS 权重切换。\n\n- **原生工具调用循环。** `AgentRuntime` 使用 OpenAI 兼容 `tool_calls` 协议执行工具，支持多步工具调用、工具结果回填、调用次数限制和最终回复格式修复。\n\n- **统一工具注册与权限控制。** `ToolRegistry` 统一管理内置工具、插件工具和 MCP 工具，并按工具组、能力开关、风险等级和确认策略决定是否暴露或执行。\n\n- **按需\u002F自主屏幕观察。** 模型可在对话中请求当前屏幕截图，或自动决定是否获取屏幕信息。\n\n- **视觉观察记录。** 截图和主动屏幕观察会被整理成摘要、可见文本和关键元素，写入 `data\u002Fvisual_observations\u002F`，再作为上下文交给 Agent。\n\n- **主动关怀与提醒事件。** 周期性主动事件、提醒触发和用户确认后的动作都走同一套 `ChatPipeline -> AgentRuntime -> UI` 链路，确保回复能正常进入字幕、表情和语音播放。\n\n- **受控浏览器 + 桌面操作。** 通过 MCP Playwright \u002F Windows MCP 工具支持浏览器和本地桌面交互。\n\n- **长期记忆与候选确认。** 长期记忆先写候选，用户确认后才写入正式记忆。支持自动记忆整理。\n\n- **MCP 扩展。** `data\u002Fconfig\u002Fmcp.yaml` 注册 stdio\u002FSSE MCP Server，支持运行时开关。内置 Web 搜索 MCP Server。\n\n- **历史回看与回溯、立绘缩放与动效、上下文修剪、调试日志。**\n\n## 启动流程\n\n运行 `python main.py` 后：\n\n1. 创建 `QApplication`\n2. `AppSettingsService` 从 `data\u002Fconfig\u002Fapi.yaml` 加载 API 配置\n3. `CharacterRegistry` 扫描角色包\n4. 加载角色人格卡和可用语气\u002F立绘\n5. `AppBuilder` 组装 `AppContext`——包括工具注册表、记忆库、提醒库、MCP、插件、TTS\n6. 后台线程装配耗时服务（MCP 工具、插件、TTS Provider）\n7. 显示 `PetWindow`\n\n```mermaid\nflowchart LR\n    A[\"main.py\"] --> B[\"data\u002Fconfig\u002F*.yaml\u003Cbr\u002F>配置\"]\n    A --> C[\"CharacterRegistry\"]\n    C --> D[\"characters\u002Fsakura\u002Fcharacter.json\u003Cbr\u002F>角色包\"]\n    A --> E[\"OpenAICompatibleClient\u003Cbr\u002F>API 客户端\"]\n    B --> E\n    A --> I[\"TTSProvider\"]\n    A --> J[\"AppBuilder\"]\n    J --> K[\"AppContext\"]\n    K --> L[\"PetWindow\"]\n    I --> L\n    L --> M[\"ChatWorker\u003Cbr\u002F>后台线程\"]\n    M --> N[\"ChatPipeline\u003Cbr\u002F>运行管线\"]\n    N --> S[\"AgentRuntime\u003Cbr\u002F>原生 tool_calls 循环\"]\n    S --> T[\"ToolRegistry\"]\n    T --> U[\"内置工具 + MCP 工具 + 插件工具\"]\n    S --> V[\"ChatReply\u003Cbr\u002F>分段 JSON 回复\"]\n    V --> L\n    L --> W[\"字幕 \u002F 立绘 \u002F TTS\"]\n```\n\n## 项目结构\n\n```text\n.\n├── main.py                             # 应用入口\n├── app\u002F\n│   ├── agent\u002F                          # Agent 决策层\n│   │   ├── actions.py                  # 动作\u002F事件\u002F待确认数据结构\n│   │   ├── builtin_tools.py            # 内置工具（待办\u002F提醒\u002F笔记\u002F记忆等）\n│   │   ├── memory.py \u002F reminders.py    # 长期记忆 \u002F 提醒\n│   │   ├── memory_curator.py           # 自动记忆整理（含后台 Worker）\n│   │   ├── memory_curation_worker.py   # 自动记忆整理 Qt Worker\n│   │   ├── runtime.py                  # AgentRuntime（决策\u002F工具循环）\n│   │   ├── runtime_limits.py           # 运行时限制常量\n│   │   ├── screen_policy.py            # 屏幕观察策略\n│   │   ├── screen_tools.py             # 屏幕观察工具\n│   │   ├── screen_observation.py       # 屏幕观察入口\n│   │   ├── proactive_care.py           # 主动关怀\n│   │   ├── tool_policy.py              # 工具路由策略\n│   │   ├── tool_registry.py            # 兼容层（→ app\u002Fagent\u002Ftools\u002F）\n│   │   ├── tools\u002F                      # 统一工具注册系统\n│   │   │   ├── registry.py             # ToolRegistry \u002F Tool \u002F ToolMetadata\n│   │   │   ├── permission_policy.py    # ToolPermissionPolicy\n│   │   │   └── builtin\u002Fprovider.py     # BuiltinToolProvider\n│   │   └── mcp\u002F                        # MCP 工具（桥接\u002F配置\u002FProvider）\n│   ├── core\u002F                           # 应用核心\n│   │   ├── app_context.py              # AppContext 依赖容器\n│   │   ├── bootstrap.py                # 启动装配\n│   │   ├── builder\u002F                    # AppBuilder \u002F ServiceContainer \u002F Lifecycle\n│   │   ├── contracts\u002F                  # 核心接口契约\n│   │   ├── chat_pipeline.py            # ChatPipeline 对话编排\n│   │   ├── chat_worker.py              # Qt 后台线程 Worker\n│   │   ├── debug_log.py                # 调试日志（自动脱敏）\n│   │   ├── extensions.py               # 扩展注册表\n│   │   ├── plugin_manager.py           # SakuraPluginManager（兼容层 → app\u002Fplugins\u002F）\n│   │   └── runtime\u002F                    # 运行时编排\n│   ├── config\u002F                         # 配置管理\n│   │   ├── models.py                   # 配置数据模型\n│   │   ├── defaults.py                 # 默认值\n│   │   ├── settings_service.py         # YAML 配置读写\n│   │   ├── migrations.py               # .env → YAML 迁移\n│   │   ├── character_loader.py         # 角色包加载\n│   │   └── yaml_config.py              # YAML 通用工具\n│   ├── llm\u002F                            # LLM 客户端\n│   │   ├── api_client.py               # OpenAI 兼容客户端\n│   │   ├── chat_reply.py               # 分段回复解析\n│   │   ├── context_trimming.py         # 上下文修剪\n│   │   ├── prompt_templates.py         # 提示词模板\n│   │   └── prompts\u002F                    # 提示词块\u002F渲染\n│   ├── plugins\u002F                        # 插件系统（原生）\n│   │   ├── models.py                   # PluginManifest \u002F PluginSpec \u002F Contribution\n│   │   ├── discovery.py                # PluginDiscovery\n│   │   ├── capabilities.py             # PluginCapabilityRegistry\n│   │   ├── manager.py                  # PluginManager\n│   │   └── adapters.py                 # SDK 兼容适配\n│   ├── storage\u002F                        # 存储层\n│   │   ├── paths.py                    # StoragePaths 统一路径\n│   │   ├── chat_history.py             # 聊天历史（JSONL）\n│   │   └── visual_observation.py       # 视觉观察记录（JSONL）\n│   ├── ui\u002F                             # UI 组件\n│   │   ├── pet_window.py               # 桌宠主窗口\n│   │   ├── settings_dialog.py          # 设置对话框\n│   │   ├── history_window.py           # 历史回看\n│   │   ├── portrait_controller.py      # 立绘控制器\n│   │   ├── subtitle_controller.py      # 字幕控制器\n│   │   ├── tool_confirmation_panel.py  # 工具确认面板\n│   │   ├── portrait_utils.py           # 立绘工具函数\n│   │   └── ...（其余 UI 组件）\n│   └── voice\u002F                          # 语音\n│       ├── tts.py                      # GPT-SoVITS \u002F Null Provider\n│       └── playback_controller.py      # 语音播放控制器\n├── sdk\u002F                                # Shinsekai 兼容层（已废弃，新插件用 app\u002Fplugins\u002F）\n│   ├── plugin.py                       # PluginBase\n│   ├── register.py                     # PluginCapabilityRegistry\n│   ├── types.py                        # 贡献点类型\n│   └── tool_registry.py                # 已废弃工具装饰器\n├── plugins\u002F                            # 本地插件\n│   └── playwright_browser\u002F             # Playwright 浏览器插件\n├── characters\u002Fsakura\u002F                  # 角色资源\n├── data\u002F                               # 本地数据\n│   ├── config\u002F                         # YAML 配置（api.yaml \u002F system_config.yaml 等）\n│   ├── chat_history\u002F                   # 聊天记录\n│   ├── memory\u002F                         # 长期记忆\n│   └── visual_observations\u002F            # 视觉观察记录\n├── tests\u002F                              # pytest 测试\n│   ├── unit\u002F                           # 单元测试（配置 \u002F LLM \u002F 工具 \u002F 运行时等）\n│   ├── integration\u002F                    # 集成测试（AgentRuntime \u002F ChatPipeline 等）\n│   └── ui\u002F                             # UI 测试\n├── docs\u002F                               # 文档\n│   ├── ARCHITECTURE.md                 # 架构说明\n│   ├── MIGRATION.md                    # 迁移指南\n│   └── SAKURA_PLUGIN_SDK.md            # 插件开发指南\n└── tools\u002Fmcp\u002F                          # MCP Server 运行时\n```\n\n## 可选：语音配置\n\n语音默认关闭。需要自行启动兼容以下接口的本地 GPT-SoVITS API：\n\n- `POST \u002Ftts`\n- `GET \u002Fset_gpt_weights`\n- `GET \u002Fset_sovits_weights`\n\n在 `data\u002Fconfig\u002Fapi.yaml` 或设置窗口中启用：\n\n```yaml\ntts:\n  provider: gpt-sovits\n  enabled: true\n  gpt_sovits:\n    api_url: http:\u002F\u002F127.0.0.1:9880\u002Ftts\n    ref_lang: ja\n    text_lang: ja\n    timeout_seconds: 60\n```\n\n## 配置项\n\n所有配置集中在 `data\u002Fconfig\u002F` 下的 YAML 文件中。\n\n| YAML 路径 | 作用 | 默认值 |\n|---|---|---|\n| `api.yaml: llm.base_url` | API 地址 | `https:\u002F\u002Fapi.openai.com\u002Fv1` |\n| `api.yaml: llm.api_key` | API Key | 空 |\n| `api.yaml: llm.model` | 模型名称 | `gpt-4.1-mini` |\n| `api.yaml: llm.timeout_seconds` | 超时时间 | `60` |\n| `api.yaml: tts.enabled` | 启用 TTS | `false` |\n| `api.yaml: tts.gpt_sovits.api_url` | TTS 接口 | `http:\u002F\u002F127.0.0.1:9880\u002Ftts` |\n| `system_config.yaml: ui.subtitle_language` | 气泡语言 `ja`\u002F`zh` | `ja` |\n| `system_config.yaml: ui.portrait_scale_percent` | 立绘缩放 | `100` |\n| `system_config.yaml: proactive_care.enabled` | 主动关怀 | `false` |\n| `system_config.yaml: proactive_care.check_interval_minutes` | 检查间隔 | `20` |\n| `system_config.yaml: proactive_care.cooldown_minutes` | 冷却时间 | `10` |\n| `system_config.yaml: memory_curation.enabled` | 自动记忆整理 | `true` |\n| `system_config.yaml: mcp.windows_enabled` | Windows MCP | `false` |\n| `system_config.yaml: debug.enabled` | 调试日志 | `false` |\n| `characters.yaml: current_character_id` | 当前角色 | `sakura` |\n\n## 测试\n\n```powershell\npython -m pytest\n```\n## Star History\n\n\u003Ca href=\"https:\u002F\u002Fwww.star-history.com\u002F?repos=Rvosy%2Fsakura&type=date&legend=top-left\">\n \u003Cpicture>\n   \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"https:\u002F\u002Fapi.star-history.com\u002Fchart?repos=Rvosy\u002Fsakura&type=date&theme=dark&legend=top-left\" \u002F>\n   \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"https:\u002F\u002Fapi.star-history.com\u002Fchart?repos=Rvosy\u002Fsakura&type=date&legend=top-left\" \u002F>\n   \u003Cimg alt=\"Star History Chart\" src=\"https:\u002F\u002Fapi.star-history.com\u002Fchart?repos=Rvosy\u002Fsakura&type=date&legend=top-left\" \u002F>\n \u003C\u002Fpicture>\n\u003C\u002Fa>\n\n## 许可证\n","Sakura 是一个通用桌宠Agent框架，能够根据屏幕内容主动与用户互动。其核心功能包括基于屏幕观察的主动对话、情绪表达以及执行如浏览器操作、Web搜索等任务的能力，这些都由角色卡驱动并通过内置的Agent引擎实现。该框架特别适用于需要陪伴感或希望桌面助手能更自然地融入日常使用的场景，例如游戏时提供攻略帮助或浏览网页时进行互动。项目使用Python开发，主要针对Windows平台进行了优化，并且无需编程基础即可上手使用。",2,"2026-06-04 02:30:20","CREATED_QUERY"]