# Xianren Studio(仙人工作室)代码组织与布局 > 本文档描述代码仓库的组织结构、模块职责、数据流与关键实现。**功能变更后如涉及结构、流程或数据模型,必须同步更新本文档。** 最后更新:2026-08-16 --- ## 1. 总览 技术栈:Tauri 2(Rust 壳 + WebView2) + React 18 / TypeScript / Vite / Tailwind,推理引擎为 llama.cpp 的 `llama-server` 子进程。 ``` xianren_studio/ ├── apps/desktop/ Tauri 桌面壳(Rust 命令层、tauri.conf.json、推荐模型/预制智能体/预制工作流默认 JSON、工作流执行引擎 workflow.rs、邮件发送 mail.rs、文档提取与目录扫描 knowledge.rs) ├── crates/core/ 领域核心:SQLite(模型注册表、智能体、工作流、知识库、定时计划、会话、消息、设置) ├── crates/engine/ llama-server 生命周期 + 流式/非流式聊天(本地与远程 OpenAI 兼容) ├── crates/download/ 分片断点续传下载器 ├── crates/api/ OpenAI 兼容本地 API 服务(axum) ├── ui/ React 前端 ├── scripts/ 构建 / 引擎与测试模型下载脚本 ├── docs/ 产品与技术方案、功能记录、本文档 └── AGENTS.md 开发/维护约定(含文档同步规则) ``` --- ## 2. 分层与数据流 ``` React UI(ui/src) │ Tauri invoke(api.ts 封装)+ 事件监听(onEvent) ▼ apps/desktop/src/commands.rs ← 所有 Tauri 命令(invoke_handler 注册于 lib.rs) │ ├── crates/core(SQLite:models / agents / workflows / scheduled_tasks / sessions / settings) ├── crates/engine(llama-server 子进程 / 远程 OpenAI API) ├── crates/download(下载任务) └── crates/api(本地 API 服务) ``` 前端通过 `ui/src/api.ts` 的 `api.*` 方法调用后端命令;后端通过 Tauri `emit` 向前端推送事件(见 §7 事件通道)。 --- ## 3. 前端结构(`ui/`) ``` ui/src/ ├── main.tsx 入口 ├── App.tsx 导航栏、路由(10 个页面)、全局事件订阅(引擎/下载/模型/建议/定时计划/会话) ├── api.ts Tauri invoke 封装 + 全部请求/事件 TypeScript 类型 ├── store.ts zustand 全局状态(见下) ├── styles.css 全局样式 ├── components/Icon.tsx SVG 图标库 └── pages/ ├── ChatPage.tsx 对话页(最大的页面,含会话快照、消息气泡、模型下拉、建议标签) ├── AgentsPage.tsx 智能体列表(预制/自定义分组、新建/编辑/删除/恢复预制) ├── AgentChatPage.tsx 智能体会话页(按路由加载智能体并渲染 ChatPage 智能体模式) ├── WorkflowsPage.tsx 工作流列表(预制/自定义分组、新建/删除/恢复预制) ├── WorkflowCanvasPage.tsx 工作流画布(节点拖入/拖拽/连线、滚轮缩放、空白平移、节点/连线右键菜单、导入导出、运行与结果展示) ├── KnowledgeBasePage.tsx 知识库(库管理、文档上传/预览/重切、FTS 检索与复制引用) ├── ModelsPage.tsx 模型管理(本地部署 + 在线 API 启用开关) ├── ModelPlazaPage.tsx 模型广场(HF/ModelScope 搜索与下载) ├── TasksPage.tsx 任务(下载/部署进度) ├── ToolsPage.tsx 工具(Tavily 联网搜索) ├── ServerPage.tsx 服务管理(本地 OpenAI API) └── SettingsPage.tsx 设置 ``` ### 3.1 全局状态(`store.ts`) 主要状态字段: | 字段 | 说明 | | --- | --- | | `agents` / `agentsLoaded` | 智能体列表(预制 + 自定义)与加载标记 | | `agentConversations` | 智能体 id → 会话列表(各智能体会话隔离,key 为智能体 id) | | `workflows` / `workflowsLoaded` | 工作流列表(预制 + 自定义)与加载标记 | | `scheduledTasks` | 定时计划列表(任务页) | | `models` | 模型列表(含 `enabled`、`kind`、`file_name` 等) | | `engine` | 引擎状态(running / model / port) | | `deployStates` / `deployProgress` | 各模型部署状态(loading/ready/error)与进度 | | `chatSuggestionsByMessage` | 消息 ID → 预测建议列表(全局接收,跨选项卡不丢) | | `conversations` | 会话列表 | | `tasks` | 下载/部署任务 | | `server` | 本地 API 服务状态 | ### 3.2 会话快照(`ChatPage.tsx`) 切换选项卡时 React Router 会卸载页面,因此 `ChatPage.tsx` 顶部维护了模块级 `chatSession` 对象(当前会话、所选模型、消息、输入草稿、请求参数、面板开合、工具、版本、附件),每次渲染后写回;重新挂载时用快照初始化,实现「切走再回来保持原状」。 --- ## 4. 后端命令层(`apps/desktop`) ### 4.1 `lib.rs` - `run()`:初始化数据目录(`%APPDATA%\XianrenStudio`)、日志、panic 钩子;构建 Tauri 应用并注册 `invoke_handler`。 - 注册插件:`tauri-plugin-opener`、`tauri-plugin-autostart`(开机启动,Windows 写注册表启动项)、`tauri-plugin-dialog`(原生文件/文件夹选择对话框,知识库目录来源「浏览…」使用)。 - `tauri.conf.json` 启用 `assetProtocol`(scope `**`):知识库媒体文档(图片/视频/音频)预览通过 `convertFileSrc` 直读本地文件渲染/播放。 - `setup` 末尾启动**自动加载模型**任务(`auto_load_models`:按设置列表顺序逐个部署,最后一个保持运行)。 - `setup` 末尾启动**定时计划后台调度循环**(tokio interval 每 30 秒调用 `run_due_scheduled_tasks`)。 - 数据目录:`logs/`、`models/`、`engines/`、`recommendations/`。 ### 4.2 `commands.rs`(命令分组) | 分组 | 命令 | | --- | --- | | 智能体 | `list_agents`、`add_agent`、`update_agent`、`remove_agent`、`set_agent_enabled`、`restore_preset_agents` | | 工作流 | `list_workflows`、`add_workflow`、`update_workflow`、`remove_workflow`、`set_workflow_enabled`、`restore_preset_workflows`、`run_workflow` | | 定时计划 | `list_scheduled_tasks`、`add_scheduled_task`、`update_scheduled_task`、`remove_scheduled_task`、`set_scheduled_task_enabled`、`run_scheduled_task_now` | | 邮件 | `mail_test`(用当前 SMTP 配置发送测试邮件) | | 知识库 | `list_knowledge_bases`、`add_knowledge_base`、`update_knowledge_base`、`remove_knowledge_base`、`list_kb_documents`(分页)、`get_kb_document`、`kb_import_documents`、`remove_kb_document`、`kb_clear_documents`、`kb_rechunk_document`、`kb_search`(分页) | | 知识库·目录来源 | `kb_list_sources`、`kb_add_source`、`kb_scan_sources`(后台扫描,`kb://scan-progress` 事件推送进度)、`kb_remove_source` | | 应用/设置 | `app_info`、`autostart_status`、`autostart_set`、`settings_get`、`settings_set` | | 模型 | `list_models`、`import_model`、`remove_model`、`set_model_enabled`、`scan_models`、`add_remote_model` | | 模型广场 | `search_models`、`list_model_files`、`list_recommended_models`、`import_recommendations`、`fetch_model_page` | | 会话 | `list_conversations`(可按 `agent_id` 过滤)、`create_conversation`(可选 `agent_id`,自动继承智能体系统提示词与默认模型)、`rename_conversation`、`set_conversation_pinned`、`set_conversation_favorite`、`import_conversation`、`set_conversation_tools`、`delete_conversation`、`get_messages` | | 消息 | `chat_send`、`chat_stop`、`regenerate_message`、`edit_message`、`list_message_versions`、`apply_message_version` | | 引擎 | `engine_start`、`engine_stop`、`engine_status`、`deploy_model` | | 工具 | `web_search`(Tavily)、`list_skills`、`add_skill`、`update_skill`、`remove_skill`、`set_skill_enabled`、`test_skill`、`list_mcp_servers`、`add_mcp_server`、`update_mcp_server`、`remove_mcp_server`、`set_mcp_server_enabled`、`mcp_test_server`、`mcp_list_tools`、`mcp_call_tool` | | 下载 | `download_enqueue` | | 服务 | `server_start`、`server_stop`、`server_status` | | 其他 | `report_error`、`open_path` | **聊天相关核心函数(均在 `commands.rs`):** - `chat_send`:写入用户消息 → 构建历史 → 拉起后台生成任务。 - `run_generation_and_stream`:统一生成入口(本地引擎 / 远程 API),流式转发 token、统计用量、写库、发 `chat://done`,随后触发标题生成与建议生成。 - `inject_system_prompts`:把会话/智能体系统提示词(`conversations.system_prompt`)与工具说明统一注入消息历史最前;`chat_send` / `regenerate_message` / `edit_message` 三条链路共用。 - `maybe_generate_suggestions` → `call_suggestion_model` → `parse_suggestions`:回答完成后预测用户接下来可能说的话。统一要求模型输出 JSON 数组;最多重试 3 次;过滤元信息行与回答原文片段;每条 ≤ 30 字。 - `maybe_generate_conversation_title`:首轮对话自动生成标题。 - `create_conversation`:先在指定作用域(普通对话或某智能体)查找空会话(`find_empty_conversation`)复用,没有才新建;智能体会话写入该智能体的系统提示词与默认模型。 - `seed_preset_agents`:启动时首次写入 `default_agents.json` 中的预制智能体(`settings.preset_agents_seeded` 标记只执行一次);`restore_preset_agents` 命令可随时补齐缺失预制体。 - `run_workflow`:加载工作流节点/连线 → 交给 `workflow.rs` 执行引擎按拓扑顺序运行;LLM 节点经 `resolve_workflow_node_model` 解析模型(节点 → 工作流默认 → 运行参数 → 自动回退),`call_model_text` 非流式调用本地引擎或远程 API,逐节点推送 `workflow://node-status` 事件。 - `seed_preset_workflows`:启动时首次写入 `default_workflows.json` 中的预制工作流(`settings.preset_workflows_seeded` 标记只执行一次);`restore_preset_workflows` 命令可随时补齐缺失预制体。 - `run_due_scheduled_tasks`:后台调度入口,由 `lib.rs` 启动的 tokio 循环每 30 秒调用一次;先清理重启前中断的「运行中」任务,再取出到点的启用计划逐个标记并异步执行。 - `execute_scheduled_task` / `run_scheduled_task_once`:定时计划单次执行——解析执行智能体(指定智能体已删除时回退「通用助手」)与模型(`resolve_scheduled_model`:智能体默认模型 → 第一个本地模型 → 第一个已启用在线模型),在该智能体作用域内创建/复用空会话,写入用户消息并注入智能体系统提示词,本地模型未运行则自动拉起引擎,最后经 `call_model_messages` 调用模型并把助手回答写回数据库。 - `call_model_messages`:`call_model_text` 的通用版,可携带 system + 多轮消息调用本地引擎或远程 OpenAI 兼容 API(定时计划复用)。 - `auto_load_models`:应用启动时读取设置键 `auto_load_models`(JSON 数组,本地模型 id 按序排列),逐个调用 `start_engine_and_wait` 部署,非最后一个模型加载完即停止,最后一个保持运行。 - `start_engine_and_wait`:本地模型引擎启动的公共实现(构造 `EngineConfig`、推送 `engine://deploy` / `engine://deploy-progress` 事件、轮询加载进度、更新 `engine_base`);`deploy_model` 命令与 `auto_load_models` 共用。 - `autostart_status` / `autostart_set`:查询 / 设置开机启动(`tauri-plugin-autostart` 的 `ManagerExt`)。 - `run_scheduled_task_once`:大模型执行完成后,若任务开启邮件,按内容模式发送——固定模式用填写的主题/正文,LLM 模式用智能体回答作正文(主题留空取回答首行);邮件发送失败时任务标记失败但保留回答内容。 - `send_task_email` / `load_smtp_config` / `split_recipients`:读取设置页「邮件」SMTP 配置、拆分多收件人并调用 `mail.rs` 发送。 - `kb_import_documents`:base64 解码 → `knowledge.rs::extract_text` 提取文本(文本类直接 UTF-8,PDF 走 pdf-extract)→ `kb_db::chunk_text` 切块(按知识库 chunk_size/overlap)→ `insert_document_with_chunks` 事务写入文档与分块,逐文件返回成功/失败结果。 - `kb_search` / `kb_rechunk_document`:检索走 `kb_db::search`(FTS5 trigram + BM25,短查询回退 LIKE);重切按知识库最新分块设置重建该文档分块与索引。 - `kb_add_source` / `kb_scan_sources` / `kb_remove_source`:目录来源注册与后台扫描——`knowledge.rs::collect_files` 按后缀过滤(空=全部)与递归开关收集文件,`classify` 分成文本 / 图片视频 / 音频三类(其他忽略),文本提取切块入库、媒体以文件名为内容登记,`kb_db::document_exists` 按(kb_id + file_path)去重;扫描过程逐文件推送 `kb://scan-progress`(处理数/成功/失败/忽略/分块),多目录重扫最后推送一次汇总 done;删除来源级联删除其导入文档。 **邮件发送模块(`apps/desktop/src/mail.rs`):** - `send_email`:用 lettre 通过 SMTP 发送纯文本邮件;加密方式按设置分支——隐式 SSL 用 `relay`(465)、STARTTLS 用 `starttls_relay`(587)、无加密用 `builder_dangerous`(25),均可自定义端口与超时。 **工作流执行引擎(`apps/desktop/src/workflow.rs`):** - `topo_order`:Kahn 拓扑排序,检测循环 / 未知节点 / 自连。 - `resolve_template`:解析 `{{input}}` 与 `{{节点id}}` 变量。 - `execute_workflow`:按拓扑顺序执行 start / text / llm / end 节点,收集各节点输出并汇总最终结果;通过注入的 `call_model` 闭包调用模型,与具体模型解耦(单元测试用假模型跑通 5 个案例,另有真实模型端到端测试 `real_model_translation_workflow_e2e`)。 **工具协议(技能 / MCP):** - `apps/desktop/src/tools.rs`:`ToolDef`、标记解析(`[[skill:名]]` / `[[mcp:服务:工具:参数]]`)、`MarkerFilter`(流式输出时过滤标记)、`run_tool_round`(执行工具并回填模型,最多 3 轮)、系统提示词构建。 - `apps/desktop/src/mcp_client.rs`:MCP Streamable HTTP 客户端(`initialize` / `tools/list` / `tools/call`,兼容 SSE 响应)。 - 聊天链路:`chat_send` / `regenerate_message` / `edit_message` 解析会话工具并注入系统提示词 → `run_generation_and_stream` 流式输出时过滤标记 → 完成后执行工具循环并保存最终内容。 --- ## 5. 核心库(`crates/core`) ### 5.1 `app.rs` - `CoreApp`:持有 SQLite 连接(`Mutex`)与数据目录。 - `seed_default_settings`:启动时用 `insert_default` 补齐缺失的设置键(不覆盖用户已保存值)。 - `open_db`:执行 `schema.sql` + **增量迁移** `ensure_column`(为旧库补充新列,幂等)。 ### 5.2 `schema.sql`(表结构) | 表 | 关键字段 | 说明 | | --- | --- | --- | | `models` | `kind`(local/remote)、`enabled`、`file_name`、`file_path`、`status`、`base_url`、`api_key`、`api_model`、`meta_json` | 模型注册表;`enabled` 决定在线 API 模型是否出现在聊天页可选列表 | | `settings` | `key`/`value` | 键值设置 | | `conversations` | `title`、`model_id`、`system_prompt`、`agent_id`、`pinned`、`favorite`、`tools_json` | 会话;`agent_id` 为空表示普通对话,否则属于对应智能体 | | `agents` | `kind`(preset/custom)、`name`、`icon`、`description`、`system_prompt`、`model_id`、`enabled` | 智能体(预制 + 自定义) | | `workflows` | `kind`(preset/custom)、`name`、`icon`、`description`、`nodes_json`、`edges_json`、`model_id`、`enabled` | 工作流(节点/连线以 JSON 存储,节点含 type/label/position/data) | | `scheduled_tasks` | `name`、`agent_id`、`prompt`、`interval_minutes`、`enabled`、`next_run_at`、`last_run_at`、`last_status`(idle/running/success/error)、`last_result`、`last_error`、`email_enabled`、`email_to`、`email_mode`(fixed/llm)、`email_subject`、`email_body` | 计划任务;`next_run_at` 由 SQLite `datetime('now', '+N minutes')` 计算(UTC),每次执行完成后推进 | | `messages` | `role`、`model_id`、`content`、`tokens_in/out`、`elapsed_ms`、`first_token_ms`、`images_json` | 消息;`model_id` 记录该回答所用模型(回答下方展示模型名) | | `message_versions` | `content`、`tokens_out`、`seq` | 重新生成前的旧版本 | | `skills` | `name`、`description`、`content`、`enabled` | 技能工具库 | | `mcp_servers` | `name`、`description`、`url`、`auth_token`、`enabled` | MCP 服务配置 | | `knowledge_bases` | `name`、`description`、`chunk_size`、`chunk_overlap` | 知识库及分块设置 | | `kb_documents` | `kb_id`(级联删除)、`name`、`file_type`、`file_size`、`char_count`、`chunk_count`、`content`(提取后的纯文本/媒体文件名)、`file_path`、`source_id` | 知识库文档;目录导入记录文件路径与来源,`file_path` 用于去重;删除/重切分块由 FTS 触发器同步 | | `kb_chunks` | `kb_id`、`document_id`(级联删除)、`seq`、`content` | 文档分块 | | `kb_chunks_fts` | FTS5 虚拟表(contentless-delete + trigram 分词) | 全文检索索引,由 `kb_chunks` 触发器维护 | | `kb_sources` | `kb_id`(级联删除)、`path`、`extensions`、`recursive`;`(kb_id, path)` 唯一 | 目录来源(多个);添加时立即扫描,可重新扫描增量导入 | 迁移清单(`ensure_column`):`models.kind/base_url/api_key/api_model/enabled`、`messages.elapsed_ms/first_token_ms/images_json/model_id`、`conversations.pinned/favorite/tools_json/agent_id`。 新增列迁移:`scheduled_tasks.email_enabled / email_to / email_mode / email_subject / email_body`、`kb_documents.file_path / source_id`(`ensure_column` 幂等补齐)。 ### 5.3 `models.rs` 模型 CRUD、`set_enabled`(启用/停用)、`scan_directory`(扫描 GGUF 目录)、量化猜测 `guess_quant`。 ### 5.4 `sessions.rs` 会话/消息/版本 CRUD;`find_empty_conversation`(新建对话复用空会话);`import_message`(导入对话用,可指定创建时间)。 ### 5.5 `agents.rs` 智能体 CRUD(`list/get/insert/update/delete/set_enabled`)与预制体批量写入 `insert_presets_if_missing`(按 id 忽略已存在,供首次种子与「恢复预制智能体」复用)。 ### 5.6 `settings.rs` `get/set/insert_default/all`。 ### 5.7 `workflows.rs` 工作流 CRUD(`list/get/insert/update/delete/set_enabled`)与预制体批量写入 `insert_presets_if_missing`(按 id 忽略已存在);节点 `WorkflowNode`(type=start/llm/text/end、position、data)与连线 `WorkflowEdge` 以 JSON 列存储,序列化/反序列化在读写时完成。 ### 5.8 `scheduled_tasks.rs` 计划任务 CRUD 与运行状态落库:`list/get/insert/update/delete/set_enabled`(停用时清空 `next_run_at`,启用时重新计算)、`mark_running` / `finish_run`(写执行结果并推进下次执行时间)、`list_due`(到点且未运行中的启用计划)、`reset_stale_running`(应用重启后把中断的「运行中」标记为失败);任务行含邮件配置字段(`email_enabled/email_to/email_mode/email_subject/email_body`)。 ### 5.9 `knowledge_base.rs` 知识库 CRUD(`list/get/insert/update/delete`)、文档 CRUD(`list/get/get_detail`、`count_documents` / `list_documents_page` 分页)、`insert_document_with_chunks`(文档 + 分块同事务写入,FTS 触发器自动建索引)、`delete_document`(级联删除分块并同步索引)、`document_exists`(目录导入按文件路径去重)、`rechunk_document`、`chunk_text`(按字符切块 + 重叠)、`search` / `count_search`(FTS5 trigram BM25 排序 + 总数统计,查询 <3 字或 MATCH 失败回退 LIKE);目录来源 `list/get/upsert/delete_sources` 与 `delete_docs_by_source`。 --- ## 6. 引擎与远程调用(`crates/engine`) ### 6.1 `manager.rs`(`EngineManager`) - `start`:以子进程启动 llama-server(`CREATE_NO_WINDOW`),轮询 `/health` 等待就绪;最多 180s。 - `stop`:先请求 `/shutdown`,超时再 kill。 - `stream_chat` / `chat`:流式 / 非流式聊天(`/v1/chat/completions`)。 - `status`:返回 running / port / model。 ### 6.2 `remote.rs` - `stream_chat_remote` / `chat_remote`:OpenAI 兼容远程 API(Bearer 认证)。 - `normalize_base`:Base URL 自动补 `/v1`。 ### 6.3 `types.rs` - `ChatMessage`:role/content/images,多模态时序列化为 content 数组。 - `ChatRequest`:model / messages / temperature / top_p / max_tokens / stream。 - `ChatStreamEvent`:Text / Reasoning(思考过程)/ Usage。 --- ## 7. 事件通道(Tauri emit → 前端 onEvent) | 事件 | 方向 | 说明 | | --- | --- | --- | | `chat://token` | 后端→前端 | 流式增量文本 | | `chat://reasoning` | 后端→前端 | 思考过程增量 | | `chat://done` | 后端→前端 | 回答完成(含 message_id、model_id、用量) | | `chat://suggestions` | 后端→前端 | 预测建议列表(全局订阅,存入 store) | | `chat://tool-status` | 后端→前端 | 工具调用状态(running/done),界面提示 | | `chat://message-updated` | 后端→前端 | 消息内容更新(恢复版本后) | | `chat://title-updated` | 后端→前端 | 标题更新 | | `chat://error` | 后端→前端 | 生成错误 | | `engine://status` | 后端→前端 | 引擎状态变化 | | `engine://deploy` | 后端→前端 | 部署状态(loading/ready/error) | | `engine://deploy-progress` | 后端→前端 | 部署进度百分比/阶段 | | `models://updated` | 后端→前端 | 模型列表变化 | | `download://started/progress/done/error` | 后端→前端 | 下载任务进度 | | `server://status` | 后端→前端 | 本地 API 服务状态 | | `workflow://node-status` | 后端→前端 | 工作流节点运行状态(running/done/error)与输出文本 | | `scheduled://updated` | 后端→前端 | 定时计划状态变化(创建/编辑/启停/执行完成),前端刷新列表 | | `conversations://updated` | 后端→前端 | 定时计划执行后会话列表变化(供智能体会话页刷新) | | `kb://scan-progress` | 后端→前端 | 知识库目录扫描进度(处理/成功/失败/忽略/分块数;status=scanning/done) | --- ## 8. 设置项(设置键 / 默认值) 定义于 `crates/core/src/app.rs` 的 `seed_default_settings`: | 键 | 默认值 | 用途 | | --- | --- | --- | | `model_dir` | 数据目录/models | 模型目录 | | `engine_bin` | engines/cpu/llama-server.exe | llama-server 路径 | | `backend` | auto | 后端(auto/cpu/cuda/vulkan) | | `hf_endpoint` | https://hf-mirror.com | 模型下载源 | | `api_port` / `api_key` / `api_enabled` | 1234 / 空 / false | 本地 API 服务 | | `upload_max_mb` | 10 | 上传大小上限 | | `auto_title` | true | 自动生成标题 | | `suggest_enabled` | true | 预测用户接下来说的话开关 | | `suggest_count` | 3 | 预测条数(1–5) | | `tavily_api_key` | (内置演示值) | 联网搜索 API Key | | `tool_web_search_enabled` | true | 联网搜索工具开关 | | `auto_load_models` | `[]` | 启动时自动加载的本地模型 id 列表(JSON 数组,顺序即加载顺序) | | `smtp_host` / `smtp_port` / `smtp_tls` | 空 / 465 / wrapper | SMTP 发件服务器、端口、加密方式(wrapper/starttls/none) | | `smtp_user` / `smtp_password` | 空 / 空 | SMTP 用户名(通常为发件邮箱)与授权码/密码 | | `smtp_from` / `smtp_from_name` | 空 / 仙人工作室 | 发件人地址(留空用用户名)与显示名称 | | `recommend_dir` | 数据目录/recommendations | 推荐列表目录 | | `preset_agents_seeded` | 首次启动后为 `1` | 预制智能体是否已写入(内部标记,避免覆盖用户删除) | | `preset_workflows_seeded` | 首次启动后为 `1` | 预制工作流是否已写入(内部标记,避免覆盖用户删除) | --- ## 9. 构建与运行 ```powershell # 开发模式(自动拉起 Vite + Tauri) npm --prefix apps/desktop run dev # 正式版(必须带 custom-protocol 特性,前端资源才会内嵌进 exe) npm run build --prefix ui cargo build --release -p xianren-desktop --features custom-protocol # 或一键打包(tauri build 会自动启用该特性并打 NSIS 安装包) npm --prefix apps/desktop run build ``` > 注意:不带 `custom-protocol` 编译出的 release exe **不会内嵌前端页面**,直接运行会白屏,因此正式发布必须带该特性。 --- ## 10. 文档维护约定 - 功能变化 → 更新 `docs/FEATURES.md` 对应章节,并在「改动记录」追加。 - 结构/流程/数据模型变化 → 更新本文档对应章节。 - 大版本信息(技术栈、目录说明)变化 → 同步更新 `README.md`。