diff --git a/.github/workflows/prcheck.yml b/.github/workflows/prcheck.yml index 6f88f91c86..b77d37ad52 100644 --- a/.github/workflows/prcheck.yml +++ b/.github/workflows/prcheck.yml @@ -74,6 +74,9 @@ jobs: - name: format:check run: pnpm run format:check + - name: Check renderer architecture baseline + run: pnpm run architecture:renderer-baseline:check + - name: Configure pnpm workspace for Linux ${{ matrix.arch }} run: pnpm run install:sharp env: diff --git a/AGENTS.md b/AGENTS.md index 391710c8e6..035031b1ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ ## Project Structure & Module Organization - `src/main/`: Electron main process; presenters in `presenter/` (Window/Tab/Thread/Mcp/Config/LLMProvider), `eventbus.ts` for app events. - `src/preload/`: Secure IPC bridge (contextIsolation on). -- `src/renderer/`: Vue 3 app. App code in `src/renderer/src` (`components/`, `stores`, `views`, `i18n`, `lib`). Secondary renderers live in `src/renderer/browser`, `src/renderer/settings`, `src/renderer/floating`, and `src/renderer/splash`. +- `src/renderer/`: Vue 3 app. Main-window composition lives in `src/renderer/src/apps/chat-main`; shared main renderer code remains in `components/`, `stores`, `views`, `i18n`, and `lib`. Secondary renderers live in `src/renderer/browser-overlay`, `src/renderer/settings`, `src/renderer/floating`, and `src/renderer/splash`. - `src/shared/`: Shared TS types/utilities. - `test/`: Vitest suites (`test/main`, `test/renderer`) with setup files. - `scripts/`: Build/signing/runtime installers, commit checks. diff --git a/CHANGELOG.md b/CHANGELOG.md index 43a9990109..9b0d3e5e54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## v1.1.0-beta.4 (2026-07-19) +- Added browser session import and an agent picture-in-picture view +- Improved Feishu delivery error feedback and test user-data directory handling +- Reworked the Tape runtime into layered architecture with improved session recall reliability +- Restructured the chat main renderer and added rendering performance diagnostics +- 新增浏览器会话导入与 Agent 画中画视图 +- 改进飞书投递错误反馈及测试用户数据目录处理 +- 将 Tape runtime 重构为分层架构,提升会话召回可靠性 +- 重构聊天主渲染器并新增渲染性能诊断 + ## v1.1.0-beta.3 (2026-07-17) - Reworked the overall architecture and improved reliability - 重构整体架构,提升可靠性 diff --git a/docs/FLOWS.md b/docs/FLOWS.md index 7552be6279..7c5de88cfb 100644 --- a/docs/FLOWS.md +++ b/docs/FLOWS.md @@ -81,8 +81,8 @@ Provider、Tool、Skill、Memory 和 Session data 都通过创建时传入的必 不会伪造新的 outer round。 - Memory prompt contribution 必须等待结果、清理内容、限制大小并允许失败;terminal extraction 在后台 执行,并保持 epoch、cursor 和 fence 约束。 -- `TapeRecorder.appendToolFact` 在 message projection 完成后写 terminal tool call/result;写入失败不影响 - 当前回复完成。 +- `TapeToolFactWriter.appendToolFact` 在 message projection 完成后写 terminal tool call/result; + 写入失败不影响当前回复完成。 ## 4. ACP 执行 diff --git a/docs/architecture/baselines/agent-system-layered-runtime-baseline.json b/docs/architecture/baselines/agent-system-layered-runtime-baseline.json index 1baa3fce5b..be21f707cc 100644 --- a/docs/architecture/baselines/agent-system-layered-runtime-baseline.json +++ b/docs/architecture/baselines/agent-system-layered-runtime-baseline.json @@ -1,7 +1,7 @@ { "schemaVersion": 2, "goal": "agent-system-layered-runtime", - "headCommit": "d87cb4f69dca7af499e153d9a1d71015e1bfad60", + "headCommit": "df1cd3ae5b19d78e6c3cab79cdc9e4c5938fb2d4", "relevantWorkingTree": { "dirty": false, "files": [] @@ -127,11 +127,12 @@ "src/main/agent/shared/storage/sessionPaths.ts", "src/main/provider/providers/acpProvider.ts", "src/main/session/assignment.ts", - "src/main/session/data/tape.ts", "src/main/session/data/transcript.ts", "src/main/session/lifecycle.ts", "src/main/session/query.ts", - "src/main/session/turn.ts" + "src/main/session/turn.ts", + "src/main/tape/application/sessionTape.ts", + "src/main/tape/ports/capabilities.ts" ], "expectedFiles": { "src/main/agent/acp/instance/acpAgentInstance.ts": true, @@ -155,11 +156,12 @@ "src/main/agent/shared/appSessionService.ts": true, "src/main/provider/providers/acpProvider.ts": true, "src/main/session/assignment.ts": true, - "src/main/session/data/tape.ts": true, "src/main/session/data/transcript.ts": true, "src/main/session/lifecycle.ts": true, "src/main/session/query.ts": true, - "src/main/session/turn.ts": true + "src/main/session/turn.ts": true, + "src/main/tape/application/sessionTape.ts": true, + "src/main/tape/ports/capabilities.ts": true }, "ownerEvidence": { "agentManager": { @@ -192,8 +194,8 @@ "exists": true, "declarationCount": 1 }, - "tapeRecorder": { - "file": "src/main/agent/deepchat/loop/ports.ts", + "tapeToolFactWriter": { + "file": "src/main/tape/ports/capabilities.ts", "exists": true, "declarationCount": 1 }, @@ -297,11 +299,12 @@ "src/main/agent/deepchat/runtime/process.ts", "src/main/provider/providers/acpProvider.ts", "src/main/session/assignment.ts", - "src/main/session/data/tape.ts", "src/main/session/data/transcript.ts", "src/main/session/lifecycle.ts", "src/main/session/query.ts", - "src/main/session/turn.ts" + "src/main/session/turn.ts", + "src/main/tape/application/sessionTape.ts", + "src/main/tape/ports/capabilities.ts" ] }, "contracts": { @@ -366,7 +369,7 @@ "src/shared/contracts/routes/window.routes.ts", "src/shared/contracts/routes/workspace.routes.ts" ], - "sha256": "406ef501353454e8677f773c556b8938141d931229eebabae6fcb9b0c37abe3c" + "sha256": "e624008521f11befaa0497a325cb65b4bf38f36e575dd4285622ad3705955b9e" }, "storage": { "sqlite": { @@ -376,7 +379,7 @@ "src/main/data/schemaTypes.ts" ], "tableIdentifiers": [], - "sha256": "411d0c6078cf4264f2241e1198315e52dcf085342975d344e5d8967333b8129b" + "sha256": "3465d92dff615489b7037de640077ce95bda7a7abbb0144ce84bb144dcd85a9e" }, "memoryDuckDbSidecar": { "files": [ @@ -396,7 +399,7 @@ "src/main/app/mainProcess.ts", "src/main/appMain.ts" ], - "sha256": "dc13adbe8b76f0c4bb463605c780fc83e4a78696b8875d6765e767a4c2dcf70f" + "sha256": "394cd861f9fe06a29159d06f87f83b7ba1866287f129fae2a42a382e7e2e6c95" }, "dependencyMetrics": { "loopFiles": [ diff --git a/docs/architecture/baselines/renderer-application-boundaries-baseline.json b/docs/architecture/baselines/renderer-application-boundaries-baseline.json new file mode 100644 index 0000000000..3e5cfcd4df --- /dev/null +++ b/docs/architecture/baselines/renderer-application-boundaries-baseline.json @@ -0,0 +1,727 @@ +{ + "schemaVersion": 1, + "apps": [ + { + "id": "chat-main", + "html": "src/renderer/index.html", + "entry": "src/renderer/src/main.ts", + "htmlExists": true, + "entryExists": true + }, + { + "id": "browser-overlay", + "html": "src/renderer/browser-overlay/index.html", + "entry": "src/renderer/browser-overlay/main.ts", + "htmlExists": true, + "entryExists": true + }, + { + "id": "floating", + "html": "src/renderer/floating/index.html", + "entry": "src/renderer/floating/main.ts", + "htmlExists": true, + "entryExists": true + }, + { + "id": "splash", + "html": "src/renderer/splash/index.html", + "entry": "src/renderer/splash/main.ts", + "htmlExists": true, + "entryExists": true + }, + { + "id": "settings", + "html": "src/renderer/settings/index.html", + "entry": "src/renderer/settings/main.ts", + "htmlExists": true, + "entryExists": true + } + ], + "browser": { + "legacyDirectoryExists": false, + "activeOverlayDirectory": "src/renderer/browser-overlay" + }, + "settingsToChatAppImports": [ + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/composables/useDeviceVersion" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/composables/useFontManager" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/lib/iconLoader" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/lib/startupDeferred" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/lib/storeInitializer" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/stores/language" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/stores/modelCheck" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "../src/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/components/settings/ModelCheckDialog.vue" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/ollamaStore" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/providerDeeplinkImport" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/startupWorkloadStore" + }, + { + "file": "src/renderer/settings/App.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/AboutUsSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AboutUsSettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/AboutUsSettings.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/AboutUsSettings.vue", + "specifier": "@/stores/upgrade" + }, + { + "file": "src/renderer/settings/components/AcpDebugDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AcpDebugDialog.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/AcpDependencyDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AcpProfileDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AcpSettings.vue", + "specifier": "@/components/agent/AgentTransferDialog.vue" + }, + { + "file": "src/renderer/settings/components/AcpSettings.vue", + "specifier": "@/components/icons/AcpAgentIcon.vue" + }, + { + "file": "src/renderer/settings/components/AcpSettings.vue", + "specifier": "@/components/mcp-config/AgentMcpSelector.vue" + }, + { + "file": "src/renderer/settings/components/AcpSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AcpTerminalDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/AddCustomModelButton.vue", + "specifier": "@/components/settings/ModelConfigDialog.vue" + }, + { + "file": "src/renderer/settings/components/AddCustomProviderDialog.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/BedrockProviderSettingsDetail.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/BedrockProviderSettingsDetail.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/components/ModelSelect.vue" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/stores/mcp" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/BuiltinKnowledgeSettings.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/common/AutoCompactionSettingsSection.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/common/DefaultModelSettingsSection.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/common/DefaultModelSettingsSection.vue", + "specifier": "@/components/ModelSelect.vue" + }, + { + "file": "src/renderer/settings/components/common/DefaultModelSettingsSection.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/common/DefaultModelSettingsSection.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/common/LoggingSettingsSection.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/common/LoggingSettingsSection.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/common/PrivacySettingsSection.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/common/PrivacySettingsSection.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/common/ProxySettingsSection.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/common/SettingToggleRow.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/CommonSettings.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/CronJobsSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/DataSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/DataSettings.vue", + "specifier": "@/lib/cloudSyncForm" + }, + { + "file": "src/renderer/settings/components/DataSettings.vue", + "specifier": "@/lib/utils" + }, + { + "file": "src/renderer/settings/components/DataSettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/DataSettings.vue", + "specifier": "@/stores/sync" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/components/agent/AgentTransferDialog.vue" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/components/icons/AgentAvatar.vue" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/components/ModelSelect.vue" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/DeepChatAgentsSettings.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/DifyKnowledgeSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/DifyKnowledgeSettings.vue", + "specifier": "@/stores/mcp" + }, + { + "file": "src/renderer/settings/components/display/FontSettingsSection.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/display/FontSettingsSection.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/DisplaySettings.vue", + "specifier": "@/stores/floatingButton" + }, + { + "file": "src/renderer/settings/components/DisplaySettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/DisplaySettings.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/DisplaySettings.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/EnvironmentsSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/EnvironmentsSettings.vue", + "specifier": "@/stores/ui/project" + }, + { + "file": "src/renderer/settings/components/FastGptKnowledgeSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/FastGptKnowledgeSettings.vue", + "specifier": "@/stores/mcp" + }, + { + "file": "src/renderer/settings/components/GeminiSafetyConfig.vue", + "specifier": "@/lib/gemini" + }, + { + "file": "src/renderer/settings/components/GitHubCopilotOAuth.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/GitHubCopilotOAuth.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/GrokOAuth.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/KnowledgeFile.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/KnowledgeFileItem.vue", + "specifier": "@/lib/utils" + }, + { + "file": "src/renderer/settings/components/McpBuiltinMarket.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/components/mcp-config/components/McpServers.vue" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/components/onboarding/GuidedOnboardingOverlay.vue" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/composables/useGuidedOnboardingStep" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/stores/mcp" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/stores/ui/agent" + }, + { + "file": "src/renderer/settings/components/McpSettings.vue", + "specifier": "@/stores/ui/session" + }, + { + "file": "src/renderer/settings/components/MemoryConfigInlinePanel.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/MemoryConfigInlinePanel.vue", + "specifier": "@/components/ModelSelect.vue" + }, + { + "file": "src/renderer/settings/components/MemoryConfigInlinePanel.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/MemoryConfigInlinePanel.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/MemoryDiagnosticsPanel.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/MemoryInboxBar.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/MemoryInlinePanel.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/MemoryListView.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/MemoryPersonaPanel.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/components/onboarding/GuidedOnboardingOverlay.vue" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/composables/useGuidedOnboardingStep" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/stores/startupWorkloadStore" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettings.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/lib/gemini" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/lib/gemini" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/ModelProviderSettingsDetail.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/NotificationsHooksSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/NowledgeMemSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/OllamaProviderSettingsDetail.vue", + "specifier": "@/components/settings/ModelConfigItem.vue" + }, + { + "file": "src/renderer/settings/components/OllamaProviderSettingsDetail.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/OllamaProviderSettingsDetail.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/OllamaProviderSettingsDetail.vue", + "specifier": "@/stores/ollamaStore" + }, + { + "file": "src/renderer/settings/components/OllamaProviderSettingsDetail.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/OpenAICodexOAuth.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/prompt/CustomPromptSettingsSection.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/prompt/CustomPromptSettingsSection.vue", + "specifier": "@/lib/download" + }, + { + "file": "src/renderer/settings/components/prompt/CustomPromptSettingsSection.vue", + "specifier": "@/stores/prompts" + }, + { + "file": "src/renderer/settings/components/prompt/PromptEditorSheet.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/prompt/PromptEditorSheet.vue", + "specifier": "@/lib/utils" + }, + { + "file": "src/renderer/settings/components/prompt/SystemPromptSettingsSection.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/prompt/SystemPromptSettingsSection.vue", + "specifier": "@/stores/systemPromptStore" + }, + { + "file": "src/renderer/settings/components/ProviderApiConfig.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/ProviderApiConfig.vue", + "specifier": "@/stores/modelCheck" + }, + { + "file": "src/renderer/settings/components/ProviderConfigImportDialog.vue", + "specifier": "@/lib/utils" + }, + { + "file": "src/renderer/settings/components/ProviderDeeplinkImportDialog.vue", + "specifier": "@/components/icons/ModelIcon.vue" + }, + { + "file": "src/renderer/settings/components/ProviderDeeplinkImportDialog.vue", + "specifier": "@/stores/theme" + }, + { + "file": "src/renderer/settings/components/ProviderModelList.vue", + "specifier": "@/components/settings/ModelConfigItem.vue" + }, + { + "file": "src/renderer/settings/components/ProviderModelList.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/ProviderModelList.vue", + "specifier": "@/stores/uiSettingsStore" + }, + { + "file": "src/renderer/settings/components/ProviderRateLimitConfig.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/RagflowKnowledgeSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/RagflowKnowledgeSettings.vue", + "specifier": "@/stores/mcp" + }, + { + "file": "src/renderer/settings/components/RemoteSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/SettingsOverview.vue", + "specifier": "@/stores/modelStore" + }, + { + "file": "src/renderer/settings/components/SettingsOverview.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/SettingsOverview.vue", + "specifier": "@/stores/sync" + }, + { + "file": "src/renderer/settings/components/SettingsOverview.vue", + "specifier": "@/stores/ui/agent" + }, + { + "file": "src/renderer/settings/components/ShortcutSettings.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/ShortcutSettings.vue", + "specifier": "@/stores/shortcutKey" + }, + { + "file": "src/renderer/settings/components/skills/InstallFromGitDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/InstallSkillToAgentDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillAgentsTab.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillAgentsTab.vue", + "specifier": "@/stores/skillsStore" + }, + { + "file": "src/renderer/settings/components/skills/SkillDetailDialog.vue", + "specifier": "@/components/markdown/MarkdownRenderer.vue" + }, + { + "file": "src/renderer/settings/components/skills/SkillFolderTree.vue", + "specifier": "@/stores/skillsStore" + }, + { + "file": "src/renderer/settings/components/skills/SkillImportExportTab.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillInstallDialog.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillInstallDialog.vue", + "specifier": "@/stores/skillsStore" + }, + { + "file": "src/renderer/settings/components/skills/SkillsHeader.vue", + "specifier": "@/stores/language" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/components/onboarding/GuidedOnboardingOverlay.vue" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/composables/useGuidedOnboardingStep" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/stores/skillsStore" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/stores/ui/agent" + }, + { + "file": "src/renderer/settings/components/skills/SkillsSettings.vue", + "specifier": "@/stores/ui/session" + }, + { + "file": "src/renderer/settings/components/skills/SkillSyncDialog/ExportWizard.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/skills/SkillSyncDialog/ExportWizard.vue", + "specifier": "@/stores/skillsStore" + }, + { + "file": "src/renderer/settings/components/skills/SkillSyncDialog/ImportWizard.vue", + "specifier": "@/components/use-toast" + }, + { + "file": "src/renderer/settings/components/VertexProviderSettingsDetail.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/components/VoiceAIProviderConfig.vue", + "specifier": "@/stores/providerStore" + }, + { + "file": "src/renderer/settings/lib/guidedOnboardingSettings.ts", + "specifier": "@/lib/onboardingResume" + }, + { + "file": "src/renderer/settings/main.ts", + "specifier": "../src/lib/iconLoader" + }, + { + "file": "src/renderer/settings/main.ts", + "specifier": "@/i18n" + } + ], + "settingsToChatAppImportCount": 170 +} diff --git a/docs/architecture/chat-display-model-boundary/plan.md b/docs/architecture/chat-display-model-boundary/plan.md new file mode 100644 index 0000000000..bce0141698 --- /dev/null +++ b/docs/architecture/chat-display-model-boundary/plan.md @@ -0,0 +1,34 @@ +# 实施计划 + +## 1. 建立 feature model + +在 `src/renderer/src/features/chat-page/model/displayMessage.ts` 原样迁移 +`messageListItems.ts` 的所有 type 和 pure helper: + +- `DisplayMessage` 家族与 `MessageListItem`; +- assistant block 的 internal tool、filter、presence 策略; +- compaction 判定。 + +新模块只保留对 `@shared/types/*` 的 type/value 依赖,因此可以被 feature、component、store 和 +纯 UI helper 使用而不引入运行时分层循环。 + +## 2. 原子切换消费者 + +把 renderer source、renderer tests 和 fixtures 的 import 改为 +`@/features/chat-page/model/displayMessage`。特别保留 component 对 feature model 的单向读取: +组件不会导入 ChatPage、feature composable 或 store。 + +删除旧的 `components/chat/messageListItems.ts`,不建立过渡 re-export;这样新增引用无法继续落在 +错误的 component 目录。 + +## 3. 验证 + +1. 搜索确认旧模块 import 为零。 +2. 执行 formatter;随后执行 i18n、lint 与 renderer type check。 +3. 运行直接覆盖消息 list/window、message block 和 chat feature composable 的 targeted suites;如 + repository runner 支持,再执行完整 renderer test suite。 + +## 兼容性与回滚 + +模块导出名和实现不变,调用方数据格式与运行时行为不变。若出现解析或架构问题,单次提交即可将 +imports 和文件位置恢复,无需迁移数据或 IPC contract。 diff --git a/docs/architecture/chat-display-model-boundary/spec.md b/docs/architecture/chat-display-model-boundary/spec.md new file mode 100644 index 0000000000..91fb983ab0 --- /dev/null +++ b/docs/architecture/chat-display-model-boundary/spec.md @@ -0,0 +1,35 @@ +# Chat 展示模型边界收敛 + +## 背景 + +`DisplayMessage`、其 block/usage 契约,以及 assistant block 的可渲染性策略目前定义在 +`src/renderer/src/components/chat/messageListItems.ts`。但记录到展示消息的转换、流式尾部拼装、 +是否显示空 assistant 消息的决策都由 `features/chat-page` 持有。feature 因而反向依赖 UI 目录以 +取得自己的领域展示模型,模型所有权与实际业务所有权不一致。 + +这些契约同时被 chat list、message block 组件、message store、chat-only composable 与测试使用。 +它们不是可复用通用 UI 的模型,而是 chat-page feature 的输入/输出契约。 + +## 目标 + +1. 将 `DisplayMessage` 家族、`MessageListItem` 与 assistant block 可渲染性策略迁入 + `src/renderer/src/features/chat-page/model/`。 +2. 所有消费者直接引用 feature model,不保留 `components/chat/messageListItems.ts` 作为第二个 + 定义或兼容 re-export。 +3. 保持类型形状、过滤条件与 compaction 判定完全不变;这是纯模块边界调整。 +4. 记录 chat 组件可以依赖该 feature 的**纯 model contract**:model 只依赖 shared types, + 不依赖 Vue、Pinia、IPC、component 或 composable,且不得反向导入消费者。 + +## 非目标 + +- 不调整消息转换、流式缓存、虚拟化或 Markdown 渲染逻辑。 +- 不变更 `MessageList` / `MessageListRow` 的 props、events 或 template。 +- 不迁移通用 renderer foundation,也不改变 IPC/store 数据格式。 +- 不在本切片拆分 `ChatStatusBar` 或继续提取 ChatPage viewport 生命周期。 + +## 验收标准 + +1. `components/chat/messageListItems.ts` 不再存在,且 renderer 与测试中没有对其的 import。 +2. 所有原有导出的 type 和 helper 在 feature model 有同名导出,运行行为保持一致。 +3. feature model 不导入 Vue、Pinia、renderer store、renderer API 或 component。 +4. `pnpm run format`、`pnpm run i18n`、`pnpm run lint` 和相关 renderer type/test 校验通过。 diff --git a/docs/architecture/chat-display-model-boundary/tasks.md b/docs/architecture/chat-display-model-boundary/tasks.md new file mode 100644 index 0000000000..4c91772991 --- /dev/null +++ b/docs/architecture/chat-display-model-boundary/tasks.md @@ -0,0 +1,7 @@ +# 任务清单 + +- [x] 审计展示模型、renderability policy 与全部 source/test 消费者。 +- [x] 在 `features/chat-page/model/` 建立纯展示模型模块。 +- [x] 原子更新 renderer source、tests 与 fixtures 的 import。 +- [x] 删除旧 component-local 模块并确认无残留引用。 +- [x] 执行 format、i18n、lint、typecheck 与 targeted renderer tests。 diff --git a/docs/architecture/chatpage-decomposition/spec.md b/docs/architecture/chatpage-decomposition/spec.md index b4d9f444e1..59fe8759aa 100644 --- a/docs/architecture/chatpage-decomposition/spec.md +++ b/docs/architecture/chatpage-decomposition/spec.md @@ -2,7 +2,8 @@ ## 背景 -`src/renderer/src/pages/ChatPage.vue` 已膨胀到 3050 行,单个 ` diff --git a/src/renderer/settings/components/DataSettings.vue b/src/renderer/settings/components/DataSettings.vue index a1d66730bb..e1d64cc103 100644 --- a/src/renderer/settings/components/DataSettings.vue +++ b/src/renderer/settings/components/DataSettings.vue @@ -937,49 +937,55 @@
-