Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
016f987026 | ||
|
|
2c5300d031 | ||
|
|
a3b41bf2b1 | ||
|
|
0a02a17cb6 | ||
|
|
d2ceff8db5 | ||
|
|
8201c9c27e | ||
|
|
cc451f698d | ||
|
|
9cc5dc1244 | ||
|
|
f7f501a8e3 | ||
|
|
e4f7b8d993 | ||
|
|
b6d24ada87 | ||
|
|
c23dca65e8 | ||
|
|
bf64181c85 | ||
|
|
3be55348a2 | ||
|
|
89fc100d4f | ||
|
|
6edfc0046b | ||
|
|
ab85e72f01 | ||
|
|
80edd15438 | ||
|
|
7fb23d9b6b | ||
|
|
925d410247 | ||
|
|
2d8e58e995 | ||
|
|
6293ef105d | ||
|
|
d30f794184 | ||
|
|
608a9a5fec | ||
|
|
a662b16f5e | ||
|
|
911eed5e67 | ||
|
|
ed47e2c2a5 | ||
|
|
9c88ca20f3 | ||
|
|
d1b92deff3 | ||
|
|
9a9170441e | ||
|
|
3c9229ac7a | ||
|
|
86347af0b1 | ||
|
|
4baf4ec142 | ||
|
|
1603871f7c | ||
|
|
393a07ccdf | ||
|
|
50e8fde64c | ||
|
|
13ff182858 | ||
|
|
594222a2b5 | ||
|
|
1c6264dd87 | ||
|
|
120076a13d | ||
|
|
d8f0ef1301 | ||
|
|
10f3b4f2c1 | ||
|
|
58e6808f1f | ||
|
|
8650907b75 | ||
|
|
c11f204b17 | ||
|
|
be23c1346b | ||
|
|
47ba54f47d | ||
|
|
76e781a0a8 | ||
|
|
0cdf04261a | ||
|
|
66f77b83c2 | ||
|
|
83a3ea261e | ||
|
|
013e72f69e | ||
|
|
61590395ef | ||
|
|
4e5239256d | ||
|
|
65a21390de | ||
|
|
706726bad6 | ||
|
|
5cdffee9ee | ||
|
|
d9e1e42288 | ||
|
|
d47f967781 | ||
|
|
f35198df01 | ||
|
|
8e607366ca | ||
|
|
ee1bf8a187 | ||
|
|
b8b6007b51 | ||
|
|
12594961fe | ||
|
|
5a6ba6c14f | ||
|
|
0f8bf405db | ||
|
|
5ecc19dfe0 | ||
|
|
4a2986ca5d | ||
|
|
2713a81bd9 | ||
|
|
11facf0392 | ||
|
|
0f0b6ac21d | ||
|
|
eb53c827c6 | ||
|
|
8b15399577 | ||
|
|
67dedc2ed2 | ||
|
|
ceb275bdb8 | ||
|
|
44cd944601 | ||
|
|
40c108da1a | ||
|
|
5177b47aeb | ||
|
|
4edf06b685 | ||
|
|
f81f342cde | ||
|
|
1094433a7d | ||
|
|
55efca3ee1 | ||
|
|
5116613615 |
@@ -103,6 +103,13 @@ npm run build
|
||||
|
||||
中间构建输出位于 `out`。该目录为生成内容,应修改源文件后重新构建,不要直接编辑。
|
||||
|
||||
Obsidian 接入的构建钩子将锁定的 npm `@bitbonsai/mcpvault@0.16.0` 及递归运行依赖、
|
||||
许可证和原生辅助资源复制到 `out/main/obsidian-mcpvault`,桌面打包时解包到
|
||||
`app.asar.unpacked`。运行时复用现有工具执行环境的 Node,不执行在线 npm 安装。
|
||||
生产组件自动化、Electron 托管 Node、Windows 设置与聊天 UI,以及受限网络下的
|
||||
Windows x64 解包应用已验证;物理断网、安装器及其他系统验收待完成。
|
||||
验证记录见 [Obsidian 进度](./docs/features/obsidian/progress.md)。
|
||||
|
||||
## 图标生成
|
||||
|
||||
应用图标源文件位于 `icons`。修改源图或图标处理逻辑后运行:
|
||||
@@ -175,6 +182,30 @@ npm run dist:linux:arm64
|
||||
已由 Vite 打包的 `@antv/g6` 归类为构建期依赖,不会再作为独立 Node 模块复制进桌面
|
||||
安装包。
|
||||
|
||||
Desktop packaging includes only `out/main`, `out/preload`, and `out/renderer`;
|
||||
validation builds elsewhere under `out` are not shipped. Renderer-only React,
|
||||
Xterm, Mermaid, Fabric, Quill, i18next, and Markdown/math dependencies are build-time
|
||||
dependencies: Vite ships their browser bundles, while the existing license
|
||||
resources remain included. Install development dependencies before building;
|
||||
do not prune them before bundling and copying license resources.
|
||||
|
||||
The desktop DS Web resource filter excludes JavaScript/TypeScript source maps,
|
||||
`.d.ts` / `.d.mts` / `.d.cts` declarations, and `.pdb` debug symbols. It preserves
|
||||
the installed dependency layout, plugin configuration, browser assets, licenses,
|
||||
native binaries, and non-code `.map` assets. This filter does not change the
|
||||
separately built remote Agent or Runtime payloads.
|
||||
|
||||
Windows x64 development validation on 2026-09-28 compared the existing 0.15.2
|
||||
portable directory (excluding `data`) with a fresh unpacked test build:
|
||||
`app.asar` decreased from 609.4 to 350.5 MiB, and DS Web decreased from 28,701
|
||||
files / 463.4 MiB to 14,984 files / 357.0 MiB. Total measured size decreased from
|
||||
1,758.3 to 1,438.4 MiB despite the test build retaining 45.6 MiB more Electron
|
||||
locales than the portable build. These are unpacked sizes, not installer download
|
||||
sizes. Builder-copy regression tests, production build/type checks, packaged
|
||||
Harness/OpenCode/npm smoke checks, DS Web authentication/page scripts/workspace
|
||||
creation, and packaged App/settings/notes-page loading passed. Full editor/canvas
|
||||
interaction and other platform packages were not revalidated in this check.
|
||||
|
||||
以上 `dist*` 与 `portable` 命令用于普通本地桌面打包。它们会携带
|
||||
`agent-runtime-lock.json`、`remote-runtime-lock.json` 与公开的
|
||||
`agent-release-keys.json`,但所有桌面构建路径(包括本地 `portable`)都不会嵌入
|
||||
|
||||
+188
-37
@@ -52,13 +52,21 @@ records are listed separately and do not introduce another feature status.
|
||||
longer stop at 100 conversations, and consecutive sends no longer truncate
|
||||
saved history beyond 500 messages. Model context limits still apply;
|
||||
previously lost messages cannot be restored.
|
||||
Pinned and unpinned groups order by the latest message creation time,
|
||||
keeping positions stable during streaming text and tool updates.
|
||||
- [x] **Optional desktop task notifications**: A default-on switch under
|
||||
Platform Features / General immediately controls system task reminders.
|
||||
In-app notifications remain available independently; General settings group
|
||||
shortcuts, conversations and notifications, and workspace and downloads.
|
||||
- [x] **On-demand contextual help**: Supplementary page and settings
|
||||
explanations use shared title- or field-adjacent help controls with mouse
|
||||
and keyboard access. Important operation consequences and errors remain visible.
|
||||
- [x] **Compact conversation controls**: Composer options share a compact
|
||||
settings panel while Runtime, mode, sending, and queue controls remain
|
||||
available. Conversation search has an inline clear action that restores the
|
||||
scoped list and returns focus to the input.
|
||||
scoped list and returns focus to the input. New conversation and expandable
|
||||
search share one row. Composer shortcut hints reflect successful registration
|
||||
and saved settings, without being overwritten by late startup responses.
|
||||
- [x] **On-demand conversation history**: Lists load lightweight summaries
|
||||
rather than every conversation's process metadata. Opened and active
|
||||
conversations retain full details; search, copy, export, continued requests,
|
||||
@@ -135,12 +143,13 @@ records are listed separately and do not introduce another feature status.
|
||||
models, approval policy, budgets, and timeouts in a Project, with reusable
|
||||
templates.
|
||||
- [x] **Application center and navigation**:
|
||||
Clicking the bottom App Center opens a lightweight upward anchored popup with enabled apps,
|
||||
The footer shows equal-height Apps and Settings buttons with visible labels and a subtle vertical divider.
|
||||
Clicking Apps, marked with an upward chevron, opens a lightweight upward anchored popup with enabled apps,
|
||||
regardless of pinning or opening history, and no modal backdrop. Clicking an app row closes
|
||||
the popup; Local Inference Monitor opens a separate modal preserving the workspace, while other apps
|
||||
open their main content pages. Manage Apps opens searchable cards with settings details;
|
||||
open their main content pages. Manage Apps uses a LayoutGrid icon and opens Application Center with searchable cards and settings details;
|
||||
layout and interaction rules are defined in the [UI design](./docs/features/application-tool-navigation/ui-design.md).
|
||||
All four application cards support arrow and drag reordering regardless of enablement or pinning.
|
||||
All five application rows support arrow and drag reordering regardless of enablement or pinning.
|
||||
Cards, the launcher, and the filtered sidebar share one persisted order. Knowledge
|
||||
is always enabled and pinned, with Open and reorder controls. Supervisor, Notes,
|
||||
and Local Inference Monitor have enablement and pinning settings. Supervisor uses
|
||||
@@ -162,6 +171,14 @@ records are listed separately and do not introduce another feature status.
|
||||
local-engine checks, and remaining platform/package coverage. Historical
|
||||
failures are not the current full-suite result. See the
|
||||
[validation progress](./docs/features/application-tool-navigation/progress.md).
|
||||
- [x] **Local device-sharing metadata** (implemented in source): Open Device Sharing
|
||||
from Apps or Application Center, save a service URL and device name, register the
|
||||
device, browse returned records, publish capability or knowledge metadata, and
|
||||
revoke this device ID's entries. The default service is `http://127.0.0.1:8787`.
|
||||
This unauthenticated local service uses IDs for identification only. Server source
|
||||
mode does not upload or sync content, and independent knowledge search/read/download
|
||||
flags are declarations, not content access or remote execution. See
|
||||
[scope and validation](./docs/features/device-sharing/README.md).
|
||||
- [ ] **Privately deployable application marketplace** (planned): Extends
|
||||
application management with an organization-owned catalog and application
|
||||
distribution. Current management covers built-in apps only, not marketplace
|
||||
@@ -324,7 +341,7 @@ records are listed separately and do not introduce another feature status.
|
||||
failure, Agent `SIGKILL`/restart, and recovery from a reopened Desktop SQLite
|
||||
database. Successful tool START/END events appear exactly once, with no
|
||||
Prompt, provider, or tool replay observed. The current Agent source lock is
|
||||
`0.13.4`, while the current Desktop release candidate is `0.13.16`; formal
|
||||
`0.15.1`, paired with the current Desktop release candidate `0.15.6`; formal
|
||||
publication status follows the separate Agent and Desktop
|
||||
release channels. Previous macOS validation covered native package installation,
|
||||
detached lifecycle, Attach, real Ask/Execute, and cancellation of tools in
|
||||
@@ -373,7 +390,8 @@ records are listed separately and do not introduce another feature status.
|
||||
compatible connection without requiring a duplicate selection. Settings
|
||||
displays the actual administrator or fallback model source. Ask permits
|
||||
only real Host-registered `read` and `skill` tools plus Main-managed Web
|
||||
Search/Fetch proxies, and rejects plugin impersonation of those names.
|
||||
Search/Fetch and enabled Story Graph proxies, and rejects plugin impersonation
|
||||
of those names.
|
||||
Execute allows all enabled built-in and plugin tools with the current user's
|
||||
permissions. Image input follows the selected model connection's declared
|
||||
capability: text models reject images before Host or model invocation, while
|
||||
@@ -393,6 +411,22 @@ records are listed separately and do not introduce another feature status.
|
||||
user's authorization for all tools, processes, network access, and writable
|
||||
paths available to the current local or SSH account, including paths outside
|
||||
the workspace and native subagent work.
|
||||
- **Local native Runtime clients (preview)**: The composer opens Continue or
|
||||
OpenCode in a workbar terminal, or the official DS Web client in the system
|
||||
browser, using the current local project and model. These are independent
|
||||
sessions, without imported GoodBuddy conversation history. Closing a DS page
|
||||
does not stop its service; use GoodBuddy's stop action. Remote shortcuts are
|
||||
not connected. Continue/OpenCode Ask now map Main-bound read tools through
|
||||
native permissions. Managed standard Node delivery and full cross-platform
|
||||
package acceptance remain incomplete;
|
||||
existing Windows real-model evidence does not establish full capability parity.
|
||||
See the [implementation and remaining work](./docs/features/assistant-workbar/progress.md#2026-09-27-local-native-client-validation).
|
||||
- **Runtime telemetry opt-out**: Local DS Web and remote Runtime/model-bridge
|
||||
launches share the telemetry opt-out environment without blocking model, MCP,
|
||||
or user-requested networking. Continue skips disabled automatic-update checks.
|
||||
Remote changes require a newly started Runtime from the matching Agent;
|
||||
current-source Linux x64 Agent/model validation is recorded in the
|
||||
[0.15.0 preparation record](./docs/development/release-preparation-0.15.0.md).
|
||||
- [x] **Efficient direct-model workspace tools**: Direct models use bundled
|
||||
ripgrep with native arguments for file discovery and content search, read large
|
||||
UTF-8 files by line, and apply multi-file patches in Execute. Ask searches stay
|
||||
@@ -420,6 +454,8 @@ records are listed separately and do not introduce another feature status.
|
||||
waiting for another approval. See the [interaction boundaries](./docs/features/assistant-workbar/runtime-interactions.md).
|
||||
- [x] **Native execution checklists**: OpenCode and Continue update a
|
||||
read-only checklist above the conversation, with progress saved in history.
|
||||
Details expand in an anchored, scrollable floating panel without shifting chat
|
||||
content; outside clicks close it and Escape restores focus to its trigger.
|
||||
Explicit clears and remote replay retain request ownership; cancellation
|
||||
does not mark unfinished items complete. Remote delivery requires the matching
|
||||
Agent package. See the
|
||||
@@ -444,10 +480,19 @@ records are listed separately and do not introduce another feature status.
|
||||
direct models report their own backoff phase. Footer dots are static, and
|
||||
unsupported Runtime retry details are not invented. Conversation-list
|
||||
indicators and send/stop behavior remain unchanged.
|
||||
- [x] **Simplified Runtime selection**: Conversation and project menus no
|
||||
longer enumerate every Runtime/model combination. Configure Runtime models
|
||||
in system settings; saved fixed project selections remain usable and
|
||||
explicitly display their fixed model.
|
||||
Cancellation and failure retain existing replies and use a single status;
|
||||
cancellation is neutral, and Edit again appears only when input can be restored.
|
||||
Model-visible history preserves interrupted partial replies or placeholders
|
||||
so cancelled questions are not merged into later requests. Reused local
|
||||
OpenCode sessions receive a one-time interruption notice.
|
||||
- [x] **Layered Runtime and model selection**: Resolve Runtime and model per
|
||||
field through conversation, project, and global defaults. The two-column
|
||||
composer picker shows sources and supports overrides or restoring project
|
||||
defaults; project and channel settings share the same rules. Main resolves
|
||||
each request again, including queued dispatch. Deleted or incompatible
|
||||
connections fall back, while missing credentials remain explicit errors.
|
||||
Schema 49 migrates stored choices. Purpose-specific models remain planned;
|
||||
see the [selection design](./docs/features/model-connections/runtime-selection-design.md).
|
||||
- [x] **Role-bound model connections**: Each role can inherit the default model
|
||||
or select an independent text-model connection. Invalid connections safely
|
||||
fall back to the default; the synthesis role always inherits the default.
|
||||
@@ -472,7 +517,12 @@ records are listed separately and do not introduce another feature status.
|
||||
fields take precedence, and these ordinary connection settings must not be
|
||||
used to store API keys or other secrets. See
|
||||
[model request customization](./docs/features/model-connections/README.md).
|
||||
- [x] **Context usage and automatic compaction**: Direct models update usage
|
||||
- [x] **Context usage and compaction**: Local direct text-model conversations
|
||||
also support manual compaction below the automatic threshold or with automatic
|
||||
compaction disabled. The selected summary model may incur charges; recent turns
|
||||
and full stored history remain available, and saved summaries are reused.
|
||||
Image connections and remote direct-model entry points are excluded.
|
||||
Direct models update usage
|
||||
from each successful provider call. Images and tool rounds use the same
|
||||
accounting, with estimation only when the provider omits usage. The UI
|
||||
distinguishes This Model Call from Post-Compaction Conversation Estimate,
|
||||
@@ -577,10 +627,22 @@ records are listed separately and do not introduce another feature status.
|
||||
the applicable checks pass.
|
||||
- [x] **On-demand built-in MCP**: Knowledge, Magic Notes, GoodBuddy
|
||||
configuration, and built-in browser MCP can be enabled independently and assigned to direct
|
||||
models, GoodBuddy-managed OpenCode, and Continue. Settings explicitly marks
|
||||
DeepSeek Harness unsupported. Built-in MCP uses short-lived local authority
|
||||
models, GoodBuddy-managed OpenCode, and Continue. DeepSeek Harness remains
|
||||
unsupported for these servers; Story Graph supports it through the Main proxy.
|
||||
Built-in MCP uses short-lived local authority
|
||||
for the current request, and user configuration cannot loosen Ask/Execute
|
||||
read/write boundaries.
|
||||
- **Obsidian integration (implemented in source, acceptance in progress)**:
|
||||
Disabled by default, with all locally registered vaults as the default scope
|
||||
and an optional folder that can be tested before saving or enabling.
|
||||
Bundled MCPVault 0.16.0 provides all upstream abilities through 19 shared tools.
|
||||
Automated production-component checks, Electron managed-Node tests, Windows
|
||||
settings and chat UI checks, and restricted-network Windows x64 unpacked-app
|
||||
checks passed. Physical-offline, installer, and other-platform acceptance
|
||||
remain pending. DeepSeek
|
||||
Harness and remote execution remain unavailable. See the
|
||||
[feature docs and validation record](./docs/features/obsidian/README.md);
|
||||
this is not a release claim.
|
||||
- [x] **MCP Tools**: Explicitly enabled custom MCP can be assigned to direct
|
||||
models, GoodBuddy-managed OpenCode, Continue Agent Execute, and DeepSeek
|
||||
Harness, and loads only in Execute. Agent child processes receive only
|
||||
@@ -601,6 +663,10 @@ records are listed separately and do not introduce another feature status.
|
||||
retrieval parameters are collapsed by default. Documents distinguish ready,
|
||||
processing, and failed states, with source opening, retry, and confirmation
|
||||
before source removal.
|
||||
Sources and indexed documents share one searchable list: single-document
|
||||
sources do not duplicate rows, while directories retain grouped documents and
|
||||
failed sources retain recovery actions. Task history and secondary operations
|
||||
remain reachable from the consolidated controls.
|
||||
- [x] **External knowledge-base connections**: Manage Dify, FastGPT,
|
||||
and RAGFlow instances from the Knowledge page, then discover remote
|
||||
knowledge bases or enter their IDs and verify bindings with provider-specific
|
||||
@@ -650,7 +716,9 @@ records are listed separately and do not introduce another feature status.
|
||||
records without replacing editors. Successful saves establish the editor's
|
||||
normalized baseline; only unsaved changes require confirmation on leaving. Opening
|
||||
a note shows a blank text/canvas composer above the history, and creation resets it
|
||||
for the next record. Explicit editing updates a saved record. The separate To-dos view offers search, status filters,
|
||||
for the next record. Explicit editing updates a saved record and exits after a
|
||||
successful save; automatic comments do not reopen the editor, and failed saves
|
||||
retain drafts. The separate To-dos view offers search, status filters,
|
||||
grouped tasks and direct completion, with instructions, source entries and AI
|
||||
comments in a right detail pane beside a stable task list. Narrow views offer
|
||||
on-demand detail with an explicit return to the list. Wide views support a
|
||||
@@ -663,6 +731,17 @@ records are listed separately and do not introduce another feature status.
|
||||
navigation can show the incomplete-todo count, and create, save, and comment
|
||||
results use application-wide notifications. Agent/MCP note writes automatically
|
||||
refresh the open workbench while preserving selection and unsaved drafts.
|
||||
- **Conversation capture and quick notes** (implemented; real Electron acceptance passed):
|
||||
Preview and edit an assistant response or complete conversation text before
|
||||
appending to an existing note or creating one with its first entry. The compact
|
||||
Notes workbar tab supports title/body search, quick text appends and full-workspace
|
||||
navigation. Saved sources link back to conversations and messages; drafts survive
|
||||
conversation switches. Real App/preload/IPC/SQLite acceptance passed, including
|
||||
complete 502-message history and native keyboard use in a 214px panel, with zero
|
||||
model calls. The [feature validation record](./docs/features/magic-notes/progress.md)
|
||||
separates focused passes, fixture repairs and earlier execution-time failures;
|
||||
the [0.15.0 candidate validation](./docs/development/release-preparation-0.15.0.md)
|
||||
passed the full suite, typecheck and lint.
|
||||
- [x] **Paged canvas notes**: The integrated PeopleLib Fabric + Quill editor
|
||||
combines flowing body text with pen/highlighter, object selection/transforms,
|
||||
floating text, images and paper templates. Editors and read-only viewers support
|
||||
@@ -685,13 +764,13 @@ records are listed separately and do not introduce another feature status.
|
||||
invalidated by layout changes and reanalyzed in after-save-auto mode. MCP
|
||||
rejects plain-text replacement of canvas entries. Implementation is complete;
|
||||
final validation status is tracked in the [feature progress record](./docs/features/magic-notes/progress.md).
|
||||
The first upgrade migrates stored bodies into files and raises the database
|
||||
schema to 39 together with attachment changes. Older clients cannot reopen
|
||||
Historical body migration moved stored bodies into files; schema 48 now adds
|
||||
conversation-source metadata. Older clients cannot reopen
|
||||
that database; rollback requires a pre-upgrade backup.
|
||||
- [ ] **MCP Server Control Plane** (planned): Unified MCP lifecycle, health
|
||||
checks, reconnection, schema cache, isolation, approval, and audit.
|
||||
- [ ] **Traceable note excerpts and AI editing** (planned): Collects sourced
|
||||
excerpts from conversations, knowledge, and the web and provides
|
||||
- [ ] **Knowledge/web excerpts and AI editing** (planned): Extend capture beyond
|
||||
the implemented conversation-text path to knowledge and web excerpts, with
|
||||
confirmation-based summarization, rewriting, and organization.
|
||||
|
||||
### Work management, long-term collaboration, and workflows
|
||||
@@ -707,7 +786,11 @@ records are listed separately and do not introduce another feature status.
|
||||
model and normalizes the different OpenAI-compatible and Anthropic Messages
|
||||
cache-reporting semantics when showing cache hit rate. Project and conversation
|
||||
usage groups show collapsed totals by default and expand to Runtime/model child
|
||||
rows; model grouping remains flat. Activity is grouped
|
||||
rows; model grouping remains flat. A separate System tasks tab groups
|
||||
background usage by source, with manual refresh and updates when usage is
|
||||
recorded. Supervisor reviews, image regeneration, graph extraction, and remote
|
||||
embeddings feed usage records; missing historical/provider data is not reconstructed.
|
||||
Activity is grouped
|
||||
by conversation and collapsed by default so long histories do not fill the
|
||||
page.
|
||||
- [x] **Compact conversation tool records**: Expand individual tool records
|
||||
@@ -739,26 +822,31 @@ records are listed separately and do not introduce another feature status.
|
||||
[Scheduled Task PRD](./docs/features/task-and-job/scheduled-task-prd.md).
|
||||
Status counts and filters identify running tasks and those needing attention;
|
||||
task approvals remain actionable in their task cards.
|
||||
- [x] **Memory and Smart Heartbeat**: Provides periodic review, suggested
|
||||
memories, insights, follow-up tasks, and auditable run history.
|
||||
- [x] **Automatic supervision settings and scope**: Supervisor / Automatic supervision is
|
||||
the sole authoritative plan configuration, automatic report, and suggestion entry. Daily or weekly plans can be
|
||||
created and edited for Global or one or more selected Projects. Legacy
|
||||
single-project settings migrate without loss, and project-level memory and
|
||||
action output must explicitly target a Project in scope. Task Center and
|
||||
Settings no longer duplicate the form. Partition-aware review, candidate
|
||||
generation, and recall triggers remain to be designed. See the
|
||||
[Smart Heartbeat PRD](./docs/features/smart-heartbeat/prd.md).
|
||||
- [x] **Memory and Smart Heartbeat**: Plans trigger shared incremental reviews
|
||||
instead of separate heartbeat reports. Choose memory/graph updates only or
|
||||
evidence-backed suggestions for open items, disagreements, revisions, and
|
||||
candidate conventions. Accepted open items create paused tasks; confirmed
|
||||
conventions become long-term background. Suggestion failures can be retried
|
||||
independently without undoing reviews.
|
||||
- [x] **Smart heartbeat settings and scope**: Supervisor / Smart heartbeat
|
||||
manages daily or weekly Global or selected-Project plans and suggestions.
|
||||
Task Center and Settings do not duplicate this form. Pending suggestions are
|
||||
not repeated; dismissed suggestions can return with changed evidence.
|
||||
Project/global processing progress remain separate and real-time conversation
|
||||
intervention remains planned. See the
|
||||
[implemented rules](./docs/features/conversation-supervision/logic-design.md).
|
||||
- [x] **Supervisor reviews, story graphs, and activity**: Review a selected scope
|
||||
and period, read dated supervision results and history in Work review, inspect saved result graphs and sources, confirm or revise entities,
|
||||
and preview local knowledge entity writes. Sidebar feedback follows or pins a
|
||||
and continue a discussion with source-linked review context. Sidebar feedback follows or pins a
|
||||
Conversation or Task and opens its matching result. It shows target names with
|
||||
compact pin/refresh buttons and preserves long-title readability and keyboard
|
||||
focus in narrow sidebars. Activity combines heartbeat
|
||||
and downstream review stages, including failures and links to older results.
|
||||
Automatic stages process only new, changed, or unprocessed source portions;
|
||||
no-change checks skip model calls. Manual review pages through the selected history
|
||||
and saves batches with their facts and sources. Runs can pause and resume from
|
||||
no-change checks skip model calls. Manual review is also incremental by default;
|
||||
explicit reanalysis rereads the period without changing shared progress.
|
||||
Automatic reviews do not resume user-paused runs. Reviews save batches with
|
||||
their facts and sources. Runs can pause and resume from
|
||||
saved progress, without fixed-duration automatic pauses; settings expose
|
||||
concurrency, per-request timeouts, batch sizes, and response capacity.
|
||||
Activity emphasizes connected stages and saved-batch coverage, with secondary
|
||||
@@ -766,6 +854,15 @@ records are listed separately and do not introduce another feature status.
|
||||
flow with a separate run status and correctly placed empty state.
|
||||
Calls remain read-only without tools and may incur model charges. See the
|
||||
[implementation and evidence](./docs/features/conversation-supervision/progress.md).
|
||||
Manual starts, automatic triggers, and resume share one active review;
|
||||
cancellation from Activity preserves saved batches and holds admission until
|
||||
cleanup finishes. Cancelled reviews cannot resume. Story-graph events, entities,
|
||||
and relations have separate counted tabs synchronized with canvas selection.
|
||||
Continue discussion opens directly from feedback or graph sources, with an
|
||||
editable question and explicit target-conversation navigation. The UI no
|
||||
longer exposes knowledge-entity writeback controls or redundant context
|
||||
explanations. Smart heartbeat shows actionable suggestions rather than report
|
||||
metrics and trends.
|
||||
- [ ] **Further supervision capabilities** (planned): Full event-by-event replay,
|
||||
Experiment targets, chronological manual-edit audits, event
|
||||
triggers, and broader execution observation remain incomplete. Current automatic
|
||||
@@ -775,6 +872,13 @@ records are listed separately and do not introduce another feature status.
|
||||
- [ ] **Batch runs and comparison lab** (planned): Compares model, Prompt,
|
||||
role, and workflow configurations in batches and summarizes quality,
|
||||
duration, tokens, cost, failure rate, and artifact differences.
|
||||
- **Story Graph read tools (Desktop 0.15.2 / Agent 0.15.0)**: Agents can search saved work,
|
||||
read current claims or timelines, and page through source evidence. Supervisor
|
||||
enablement and Runtime assignment control discovery and calls, including old
|
||||
sessions. Model, local Harness, and local/remote OpenCode and Continue share
|
||||
the desktop reader. Queries make no model calls and do not infer replacement
|
||||
from newer reviews. Cross-scope fact reuse and `as_of` remain deferred; see the
|
||||
[design and validation](./docs/features/conversation-supervision/story-graph-mcp-design.md).
|
||||
- [ ] **Temporal memory and fact-conflict detection** (planned): Adds validity
|
||||
periods, current/expired/conflicting fact detection, fact checking, and
|
||||
evidence tracing to memory and the knowledge graph.
|
||||
@@ -855,9 +959,50 @@ records are listed separately and do not introduce another feature status.
|
||||
|
||||
### Open source, builds, and releases
|
||||
|
||||
- The current Desktop candidate is `0.13.16`; Agent `0.13.4` is published, with
|
||||
- The current Desktop candidate is `0.15.6`; published Agent `0.15.1` is unchanged, with
|
||||
OpenCode pinned to `1.18.29` and Continue to `1.5.47`. Publication status follows the independent
|
||||
Desktop and Agent release channels.
|
||||
- Desktop `0.15.6` adds optional, persisted frosted-glass header/checklist surfaces
|
||||
(off by default, without OS desktop transparency), reduces repeated chat renders,
|
||||
and supports direct previews for draft/queued images. Settings are grouped with
|
||||
right-aligned switches, and note headers/editor spacing are tighter.
|
||||
Local OpenCode retries explicit transient MCP transport failures once after
|
||||
cleanup and retires uncertain names; it does not replay prompts or tool calls.
|
||||
Redacted MCP diagnostics support feedback. Schema 52 adds execution-statistics
|
||||
indexes; back up the database and notes before upgrading.
|
||||
See the [preparation record](./docs/development/release-preparation-0.15.6.md).
|
||||
- Desktop `0.15.5` updates Smart heartbeat and incremental review, preserves
|
||||
cancelled-turn history, floats checklist details, and exits note editing after
|
||||
saving. It also adds manual note tags with AND filtering and rename/merge/delete,
|
||||
a persistent two-pane note layout with a full-width overview, sticky workspace
|
||||
file controls, cached OpenCode terminal dependencies, and shorter MCP names.
|
||||
Schema 51 adds tag storage alongside the migration of pending legacy memory
|
||||
proposals into unconfirmed conventions; back up the database and adjacent notes before upgrading.
|
||||
See the [preparation record](./docs/development/release-preparation-0.15.5.md).
|
||||
- Desktop `0.15.4` introduces layered Runtime/model choices and separate
|
||||
system-task usage, and reduces duplicate Runtime instructions and history.
|
||||
Schema 49 migrates project/conversation choices; rollback requires the complete
|
||||
pre-upgrade database and adjacent notes backup. Agent `0.15.1` requires Desktop
|
||||
`0.15.4` and fixes remote Continue history wrapping without changing locked
|
||||
Runtime versions. See the [0.15.4 preparation record](./docs/development/release-preparation-0.15.4.md).
|
||||
- Desktop `0.15.3` restores local direct-model manual compaction, retains tool
|
||||
authorization for the request lifetime, clarifies cancellation and sidebar/note
|
||||
controls, avoids redundant startup/storage work, and trims duplicated package
|
||||
dependencies and development files. It does not claim a proven overall rendering
|
||||
speedup. Office live editing remains a design, not a delivered capability.
|
||||
See the [0.15.3 preparation record](./docs/development/release-preparation-0.15.3.md).
|
||||
- Desktop `0.15.1` carries forward the unpublished `0.15.0` Obsidian integration, conversation capture into Magic
|
||||
Notes, and preview local native clients, plus knowledge, Supervisor, and UI
|
||||
fixes. Schema 48 adds conversation-source metadata; older clients require a
|
||||
complete pre-upgrade backup for rollback. Agent `0.15.0` requires Desktop
|
||||
`0.15.2`, retains Node `24.19.0`, and updates remote telemetry opt-out and
|
||||
disabled Continue update-check behavior without adding remote client shortcuts.
|
||||
- Desktop `0.15.1` completed all six native release targets and GitHub/OSS publication.
|
||||
Desktop `0.15.2` adds read-only Story Graph tools and a fully editable
|
||||
Supervisor follow-up message, simplifies note capture, and improves exit diagnostics.
|
||||
Remote Story Graph requires the paired Agent `0.15.0`; planned Host and cloud
|
||||
management applications remain unimplemented. Current candidate evidence is in the
|
||||
[0.15.2 preparation record](./docs/development/release-preparation-0.15.2.md).
|
||||
- Desktop `0.13.15` carries forward the unpublished `0.13.14` changes to paged Supervisor reviews and resume behavior,
|
||||
native ripgrep searches, to-do layouts, and explicit remote follow-up after an
|
||||
uncertain result. Database schema 47 requires a complete pre-upgrade backup
|
||||
@@ -879,7 +1024,7 @@ records are listed separately and do not introduce another feature status.
|
||||
packaging, and publication verification remain separate acceptance steps.
|
||||
No local production build, packaging, or LoongArch preview is requested.
|
||||
Current validation status is recorded in the
|
||||
[release preparation record](./docs/development/release-preparation-0.13.16.md).
|
||||
[release preparation record](./docs/development/release-preparation-0.15.0.md).
|
||||
- Desktop `0.13.12` and Agent `0.13.3` have completed their native release jobs;
|
||||
this does not replace development-time real-Host scenario coverage.
|
||||
- Validation records remain separate from implementation status. Current-source
|
||||
@@ -960,9 +1105,15 @@ records are listed separately and do not introduce another feature status.
|
||||
offline GoodBuddy transfer release acceptance. Until these gates pass, this
|
||||
path must not be described as published or as having passed formal release
|
||||
acceptance.
|
||||
- [ ] **Multi-cloud remote sandbox Agents** (planned): Manages dedicated Linux
|
||||
sandboxes through cloud-provider APIs and SSH Agents. Credentials remain in
|
||||
Main, and high-risk control-plane operations receive separate confirmation.
|
||||
- [ ] **Host and cloud environment management** (planned): Move host management
|
||||
into App Center with a list/detail workspace. A sibling cloud application
|
||||
reuses host connections and remote execution. The first-version adapter plan
|
||||
covers AWS, Azure, Alibaba Cloud, Tencent Cloud, VMware vCenter / vSphere,
|
||||
and ZStack, delivered in batches with real instance discovery, import, and
|
||||
execution acceptance. Instance creation, start/stop, deletion, and network
|
||||
orchestration follow later. Provider APIs are not implemented; existing cloud
|
||||
servers can already be added manually when SSH requirements are met. See the
|
||||
[product scope](./docs/features/remote-host/prd.md).
|
||||
|
||||
## Roadmap Principles
|
||||
|
||||
|
||||
+34
-15
@@ -22,6 +22,8 @@
|
||||
- [x] **跨项目会话活动**:统一入口汇总各项目正在运行和需要处理的对话,保留仍有活动的较早会话。锚定的“项目 → 会话”菜单支持键盘导航和精确打开对话,不再使用整块活动弹窗;空闲时隐藏摘要,长会话子菜单独立滚动,项目选择器继续显示活动数量。
|
||||
后台会话成功完成后,在本次客户端运行期间保留完成提示,直到对应聊天可见且加载完成;提示不跨重启保留。
|
||||
- [x] **会话置顶与完整历史**:常用会话可置顶,重启后保留。列表和搜索不再限于最近 100 个会话,连续发送不再截断超过 500 条的已保存历史;模型上下文限制仍有效,已丢失的历史无法恢复。
|
||||
置顶与非置顶分组按最近一条消息的创建时间排序,流式文本和工具进度更新不再反复改变位置。
|
||||
- [x] **可选桌面任务通知**:“平台功能 / 通用设置”提供默认开启、保存后立即生效的系统任务提醒开关,应用内提示独立保留;通用设置按快捷键、会话与通知、工作目录与下载分组。
|
||||
- [x] **按需上下文帮助**:页面和设置中的补充说明使用标题或字段旁的共享帮助入口,支持鼠标与键盘;关键操作后果和错误提示保持可见。
|
||||
- [x] **紧凑会话控件**:输入选项集中在紧凑设置面板,Runtime、工作模式、发送和队列操作保持可用;会话搜索提供内嵌清除按钮,清除后恢复当前范围列表并把焦点返回输入框。
|
||||
- [x] **会话历史按需加载**:列表只加载轻量摘要,不再一次读入全部会话的过程元数据;已打开和活动会话保留完整详情,搜索、复制、导出、续聊和远程待答问题保持可用。图片合并不会重新发送未变化消息,已确认保存的空闲详情随现有视图缓存释放。详见[历史读取与保留规则](./docs/features/assistant-workbar/execution-history-storage.md#会话列表读取与前端保留)。
|
||||
@@ -34,7 +36,8 @@
|
||||
- [x] **AI 回复与完整会话复制**:已完成的 AI 回复可从消息底部复制不含推理、工具日志和引用元数据的 Markdown 原文;完整会话复制复用同一条经过 Preload/Main 校验的剪贴板路径。
|
||||
- [x] **助手工作栏、多终端与可调布局**:工作栏开关位于明暗主题按钮旁;右侧工作栏使用持久“+”能力目录和应用 Tab,任务中心与工作区为不可关闭的单实例,浏览器可打开多个独立实例。任务中心可切换当前项目和所有项目,范围随布局保存;无项目任务在所有项目中标注“未绑定项目”。用户可为当前本机或托管 SSH 项目打开多个独立终端,获得有界输出、调整尺寸、结束与显式重连。关闭终端 Tab 会结束 Shell,应用重启只恢复已结束的 Tab 描述,不自动重启 Shell。主侧栏和魔法笔记编辑器的 AI 评论栏支持鼠标与键盘调宽;AI 评论栏记住显示状态及宽度,窄窗口下移至编辑器底部。
|
||||
- [ ] **项目 Agent Space**(规划中):在 Project 中统一角色、知识、Skills/MCP、模型、审批策略、预算和超时,并支持模板复用。
|
||||
- [x] **应用中心与导航**:底部应用中心向上展开轻量锚定菜单,无模态遮罩,只列已启用应用,不按打开历史或常驻筛选。点击应用行关闭菜单,本机推理监控打开保留底层工作区的独立 Modal,其余应用打开主内容区;底部“管理应用”打开可搜索卡片及设置详情,布局与交互见 [UI 设计](./docs/features/application-tool-navigation/ui-design.md)。四张应用卡片均支持上下移动和拖动排序,不受启用或常驻状态限制;卡片、菜单和经过过滤的侧栏共用一份保存顺序。知识库始终启用并常驻,提供“打开”和排序;监督者、魔法笔记和本机推理监控可设置启用与常驻。监督者沿用智能心跳身份,缺失启用设置时默认关闭,已明确保存的选择保留;关闭后保留计划和历史,拒绝新回顾并隐藏侧栏反馈,在途运行可完成。启用应用不会自动创建计划。旧应用顺序补齐默认项并保留已有相对顺序。设置持久化后的事件同步各入口,包括工具配置写入;重开中心刷新期间锁定修改,新快照覆盖迟到的旧读取。`local-inference` Modal 直接显示服务列表,不展示任务历史或外部连接;向量服务显示独立进程 CPU 与工作集内存,ASR/OCR 说明共享进程无法独立统计的原因。ASR 就绪状态未知,不从活动请求推断运行中。受支持的服务操作保留影响确认,失败后刷新列表并要求重新确认;TTS 显示不可用。取消中的推理在 Worker 确认或退出前仍计入活动任务及服务停止影响。实现已接入生产 App;验收记录分别列出完整 App、组件 fixture、真实本地引擎和剩余平台/安装包覆盖,不以历史失败代替当前全量结果,详见[验证进度](./docs/features/application-tool-navigation/progress.md)。
|
||||
- [x] **应用中心与导航**:底部“应用”和“设置”为显示文字的等高按钮,中间使用弱竖分隔线。“应用”带向上箭头,点击后向上展开轻量锚定菜单,无模态遮罩,只列已启用应用,不按打开历史或常驻筛选。点击应用行关闭菜单,本机推理监控打开保留底层工作区的独立 Modal,其余应用打开主内容区;底部“管理应用”使用 `LayoutGrid` 图标,打开标题仍为“应用中心”的可搜索列表及设置详情,布局与交互见 [UI 设计](./docs/features/application-tool-navigation/ui-design.md)。五个应用行均支持上下移动和拖动排序,不受启用或常驻状态限制;列表、菜单和经过过滤的侧栏共用一份保存顺序。知识库始终启用并常驻,提供“打开”和排序;监督者、魔法笔记和本机推理监控可设置启用与常驻。设备共享始终可从应用菜单打开,不提供启用或常驻开关。监督者沿用智能心跳身份,缺失启用设置时默认关闭,已明确保存的选择保留;关闭后保留计划和历史,拒绝新回顾并隐藏侧栏反馈,在途运行可完成。启用应用不会自动创建计划。旧应用顺序补齐默认项并保留已有相对顺序。设置持久化后的事件同步各入口,包括工具配置写入;重开中心刷新期间锁定修改,新快照覆盖迟到的旧读取。`local-inference` Modal 直接显示服务列表,不展示任务历史或外部连接;向量服务显示独立进程 CPU 与工作集内存,ASR/OCR 说明共享进程无法独立统计的原因。ASR 就绪状态未知,不从活动请求推断运行中。受支持的服务操作保留影响确认,失败后刷新列表并要求重新确认;TTS 显示不可用。取消中的推理在 Worker 确认或退出前仍计入活动任务及服务停止影响。实现已接入生产 App;验收记录分别列出完整 App、组件 fixture、真实本地引擎和剩余平台/安装包覆盖,不以历史失败代替当前全量结果,详见[验证进度](./docs/features/application-tool-navigation/progress.md)。
|
||||
- [x] **本地设备共享元数据**(源码已实现):从应用菜单或应用中心进入设备共享,保存服务地址和设备名称、注册本机、浏览服务返回的目录、发布能力或知识元数据并撤销本机 ID 的条目。默认服务为 `http://127.0.0.1:8787`。服务未认证,ID 只用于识别;服务器来源不上传或同步内容,知识搜索/读取/下载标志是独立声明,不提供正文访问或远程执行。详见[范围与验证](./docs/features/device-sharing/README.md)。
|
||||
- [ ] **私有化应用市场**(规划中):在应用管理基础上提供组织自己的目录与应用分发。当前只管理内置应用,尚无市场浏览或安装能力,详见 [FR-15](./docs/features/application-tool-navigation/prd.md#fr-15-私有化市场与-yaml-交换后续)。
|
||||
- [ ] **通用助手工作栏与执行空间后续能力**(规划中):在现有工作栏和多终端基础上继续加入更完整的执行监督、统一 Runtime 监控、受管进程、可固定目标的工作区/浏览器/成果实例、底部停靠与独立窗口。Task Center 保持 Task 的单例索引,附件与知识库继续由会话输入区管理,未来的记忆与历史执行上下文归入关联 Task。详见 [Feature PRD](./docs/features/assistant-workbar/prd.md)。
|
||||
- [ ] **ShareServer Office 协同编辑**(设计中):通过可选 ShareServer 集成 ONLYOFFICE Docs,在助手工作栏中以文件名打开多个文档 Tab,支持 DOCX、XLSX、PPTX 的人工编辑、保存、撤销、源文件冲突保护和后续 AI 选区修改。Office 正文会由所选 ShareServer 和编辑引擎处理;Desktop 不内置或启动 Document Server,未配置服务时不宣称离线编辑。详见[设计文档](./docs/features/office-document-editing/README.md)。
|
||||
@@ -50,25 +53,29 @@
|
||||
- [x] **高效直连模型工作区工具**:直连模型使用随包 ripgrep 的原生参数发现文件和搜索内容,按行分页读取大型 UTF-8 文件,并在 Execute 中应用多文件补丁。Ask 限于工作区只读搜索和读取,Execute 按当前账号权限搜索;用户无需另行安装 ripgrep。搜索保留原生输出与退出码,大结果通过 `output_read` 完整续读,可处理的参数错误允许模型调整后继续。
|
||||
- [x] **长上下文与工具输出分页**:历史消息、长回复和文档解析文本不再采用旧的固定截断限制。直连模型可分页续读已保存的搜索、命令和 Subagent 输出;所选模型的上下文窗口及传输边界仍然有效。
|
||||
- [x] **OpenCode 与 Continue**:使用隔离子进程、环境变量白名单、统一配置、取消、启动与控制请求时限、有界流式输出和活动记录;共享进程回收逻辑保留 Windows 完整进程树终止,并对采用独立进程组的 POSIX 子进程执行组回收。聊天状态检查使用一次性探测 Runtime 并在返回后立即回收,不进入按模型与项目隔离的执行 Runtime 缓存;本机 GoodBuddy 管理的 OpenCode 在该被动检查中只确认所选路径和模型凭据,不启动用后即毁的 Server,设置中的显式连接测试和原生能力清单仍执行完整启动及健康检查,原生能力清单随后与首次实际请求复用同一个执行 Runtime,不再重复冷启动;执行 Runtime 仍按项目复用,但 OpenCode 配置依赖和按内容摘要生成的 Skill 快照在所有本机项目间全局复用,会话数据、工具输出及请求级 MCP 状态继续隔离。本机 GoodBuddy 管理的 OpenCode 只对同一会话内的请求保持顺序,不同会话即使属于同一项目也可并行,不同项目同样可并行;请求级动态 MCP 通过默认通配禁用和当前请求精确放行保持隔离。托管的本机和远端 OpenCode 跳过界面未使用的自动 Git 快照,避免同步差异计算拖住会话,文件工具、子代理与工作区 Git 差异保留;Continue 持续排空不用展示的宿主 stdout,防止控制台输出填满管道。这些调整随新启动的 Runtime 生效,不改写外部 OpenCode Server 配置。OpenCode 与 Continue 不再按固定工具调用数或活动数中止单次运行,已观察到的工具与 Subagent 活动全部保留在本地会话,不再在原生任务继续执行时丢弃后续详情。交互提问只由前台对话回答,定时任务、远程通道和委派等后台执行遇到提问时会立即失败并提示改为前台运行,避免无限等待。本机 OpenCode 启动时直接使用已选择的绝对路径,不预先检查文件或运行 `--version`,路径失效时由实际启动返回错误;托管 Linux ARM Host 激活 Runtime 时复用准备阶段已验证的 registry 和 manifest,不重新哈希或检查完整 OpenCode 二进制。
|
||||
- [x] **托管 SSH OpenCode 与 Continue**:该能力由“设置 > 平台功能”中的独立“远程项目”页签控制并默认关闭;关闭时不影响本地项目、普通桌面功能或桌面发布。支持 Linux x64、Linux arm64 和 macOS arm64 Host,不支持 Intel Mac;通过 SSH 按需启动 detached Agent,不要求开机服务。Ask 在 Runtime 工具边界保持只读,Execute 使用所选 SSH 账号的完整权限。Agent 持有 Prompt、模型和工具轮次、Runtime 进程及语义 transcript,Desktop 断开后重新 Attach 原操作而不重发 Prompt;模型凭据仅在当前操作内存中使用,不写入 Renderer、SSH 参数、环境或磁盘。当前 Agent 可以常驻,更新替换的旧 Agent 排空活动任务后退出。任务完成后回收空闲 Runtime,共享进程仍有任务或待答问题时保留;下一轮重建 Runtime 并恢复对话历史。设置页按平台和架构显示包状态,用户显式下载、更新或导入/导出包含 Agent、固定 Node、OpenCode 和 Continue 的签名 `.gbagent`;三个目标共用一个签名 catalog,继续校验签名和 SHA-256。Continue 需要更新后的联合包与配套 Desktop。首次发布混合 catalog 前需先升级 Desktop,旧版 Linux-only 目录读取器无法解析包含 Darwin 的目录。历史 macOS OpenCode 原生安装、生命周期、Attach、真实 Ask/Execute 和独立进程组工具取消已在真实 Host 验证,不代表 Continue 的同等实机覆盖。Agent `0.13.4` 已发布,当前 Desktop 候选为 `0.13.16`;详细运行边界和 Linux 历史回归证据见[远程主机技术设计](docs/features/remote-host/technical-design.md),正式发布状态以独立发布渠道为准。
|
||||
- [x] **托管 SSH OpenCode 与 Continue**:该能力由“设置 > 平台功能”中的独立“远程项目”页签控制并默认关闭;关闭时不影响本地项目、普通桌面功能或桌面发布。支持 Linux x64、Linux arm64 和 macOS arm64 Host,不支持 Intel Mac;通过 SSH 按需启动 detached Agent,不要求开机服务。Ask 在 Runtime 工具边界保持只读,Execute 使用所选 SSH 账号的完整权限。Agent 持有 Prompt、模型和工具轮次、Runtime 进程及语义 transcript,Desktop 断开后重新 Attach 原操作而不重发 Prompt;模型凭据仅在当前操作内存中使用,不写入 Renderer、SSH 参数、环境或磁盘。当前 Agent 可以常驻,更新替换的旧 Agent 排空活动任务后退出。任务完成后回收空闲 Runtime,共享进程仍有任务或待答问题时保留;下一轮重建 Runtime 并恢复对话历史。设置页按平台和架构显示包状态,用户显式下载、更新或导入/导出包含 Agent、固定 Node、OpenCode 和 Continue 的签名 `.gbagent`;三个目标共用一个签名 catalog,继续校验签名和 SHA-256。Continue 需要更新后的联合包与配套 Desktop。首次发布混合 catalog 前需先升级 Desktop,旧版 Linux-only 目录读取器无法解析包含 Darwin 的目录。历史 macOS OpenCode 原生安装、生命周期、Attach、真实 Ask/Execute 和独立进程组工具取消已在真实 Host 验证,不代表 Continue 的同等实机覆盖。当前 Agent 源码锁为 `0.15.1`,配套 Desktop 候选为 `0.15.6`;详细运行边界和 Linux 历史回归证据见[远程主机技术设计](docs/features/remote-host/technical-design.md),正式发布状态以独立发布渠道为准。
|
||||
- [x] **SSH Host 手动环境准备源码链路**:Host Key、认证和系统探针成功后先保存 Host,并只读探测共享 Agent/Runtime;保存 Host、打开项目都不自动安装。Host 卡片只有一个按版本事实显示“安装远程环境”“更新远程环境”或“重新安装”的主按钮,次级 SegmentedControl 选择默认且不持久化的“自动”、Host 下载或 GoodBuddy 传输;“版本匹配”badge 不等同环境健康。自动模式只在 operation/prepare 前探测并择一,显式选择保持有效,任何 prepare、commit 或 adoption 失败都不跨 acquisition 自动 fallback。两种方式把同一签名 compound `.gbagent` 交付到固定 staging 后,共用 control-plane prepare、commit、Agent activate/health、Runtime activate、finalize 与显式 cleanup。GoodBuddy 路径可在同一次操作下载并验证缺失候选、缓存并取得 lease,再有界流式 SFTP 上传一个归档和其中已验证的 bootstrap Node,不把约 294 MiB 整包读入 Main `Buffer`;Host 在解包时完成一次完整 payload 校验。未完成操作只记录暂存 cleanup 所需的 operation ID;下次更新尽力清理旧暂存后重新 prepare,不保存远端 metadata 副本,也不让 cleanup 失败阻塞新更新或回滚健康环境。已有项目在实际使用 Workspace/Runtime 时按需解析 Host current identity 并执行固定 `attach-or-bootstrap`,注册后的 health、capabilities 和 prompt 启动不扫描完整 payload。详见 [设计说明](./docs/features/remote-host/environment-provisioning-technical-design.md)。
|
||||
- **SSH Host 环境准备验证记录**:当前源码已在隔离 Linux x64 环境通过包安装、Ask/Execute、原生子代理工作区外写入、重连及 stop/bootstrap。现有记录未覆盖 Host 卡片的完整 GitHub、北京镜像、Linux x64/arm64、取消和离线 GoodBuddy 传输矩阵,候选 CI/原生打包与系统休眠唤醒也尚未验证;开发记录不代表版本已经发布。
|
||||
- [x] **远程工作区与长任务更新**:Agent `0.11.23` 新增远程文件/Git 管理和可选模型限额,随包 Runtime 不再施加固定十分钟 Prompt 时限;无限请求时长仍保留独立连接超时。请先升级 Desktop 至 `0.12.11`,再下载并更新 Host 上的 Agent。
|
||||
- [x] **远程原生问答与取消修复**:Agent `0.11.24` 修复远程原生问答转交和取消待答后同一会话续发,需要先升级 Desktop 至 `0.13.0`。
|
||||
- [x] **DeepSeek Harness(预览)**:使用 GoodBuddy 固定 Host 和 OpenAI 兼容模型连接;优先使用管理员提供的连接,否则跟随兼容的默认模型或首个兼容连接,无需单独重复选择,设置页显示实际管理员或回退模型来源。Ask 只允许调用 Host 中真实注册的 `read`、`skill` 以及 Main 管理的 Web Search/Fetch 代理,拒绝插件同名冒充,Execute 放行全部已启用内置及插件工具,并以当前用户权限运行。图像输入跟随所选模型连接的能力声明,文本模型在 Host 或模型调用前拒绝图片,图片模型通过有界内联内容和临时 Attachment Store 接收 JPEG/PNG。Windows Host 启动和 ACP 会话共用规范工作区路径,同目录不同写法可复用正常 Runtime,不再因路径不一致而创建会话失败。
|
||||
- [x] **DeepSeek Harness(预览)**:使用 GoodBuddy 固定 Host 和 OpenAI 兼容模型连接;优先使用管理员提供的连接,否则跟随兼容的默认模型或首个兼容连接,无需单独重复选择,设置页显示实际管理员或回退模型来源。Ask 只允许调用 Host 中真实注册的 `read`、`skill` 以及 Main 管理的 Web Search/Fetch 和已启用的 Story Graph 代理,拒绝插件同名冒充,Execute 放行全部已启用内置及插件工具,并以当前用户权限运行。图像输入跟随所选模型连接的能力声明,文本模型在 Host 或模型调用前拒绝图片,图片模型通过有界内联内容和临时 Attachment Store 接收 JPEG/PNG。Windows Host 启动和 ACP 会话共用规范工作区路径,同目录不同写法可复用正常 Runtime,不再因路径不一致而创建会话失败。
|
||||
- [x] **DSH npm 插件市场**:市场默认关闭,由用户显式开启后搜索公共 npm 的 `dsh-plugin` 包,使用捆绑 npm 执行精确版本安装和普通 lifecycle scripts,并支持启停、JSON 配置、移除、失败启动自动停用和离线管理已安装插件;关闭市场只隐藏目录与管理界面,不改变已有插件的启停状态,第三方代码不受 Ask 初始化隔离。
|
||||
- [x] **Ask 与 Execute 工作模式**:Ask 保持只读;Execute 是用户对当前本机或 SSH 账号可用工具、进程、网络和可写路径的完整授权,包括工作区外路径及原生子代理工作。
|
||||
- **本地 Runtime 原生客户端(预览)**:输入区可按当前本地项目与模型,在工作栏终端打开 Continue/OpenCode,或在系统浏览器打开官方 DS Web。客户端使用独立会话,不导入 GoodBuddy 对话历史;关闭 DS 网页不停止服务,可在 GoodBuddy 中停止。Continue/OpenCode Ask 已通过原生权限映射 Main 绑定的只读工具。远程快捷入口未接通,托管标准 Node 交付和完整跨平台安装包验收仍有缺口;Windows 真实模型证据不代表全部会话能力等价,详见[实现与剩余工作](./docs/features/assistant-workbar/progress.md#2026-09-27-local-native-client-validation)。
|
||||
- **Runtime 遥测关闭配置**:本地 DS Web、远程 Runtime 和模型桥启动共用遥测关闭环境,不限制模型、MCP 或用户主动联网。Continue 在自动更新关闭时跳过检查;远程改动随配套 Agent 新启动的 Runtime 生效,当前源码 Linux x64 Agent/model 验证见 [0.15.0 发布准备](./docs/development/release-preparation-0.15.0.md)。
|
||||
- [x] **Runtime 原生交互转交**:OpenCode 与 Continue 的选择、yes/no、自由文本回答和跳过使用现有问答卡片,本机与托管 SSH OpenCode 同时转交属于当前请求的子会话提问。托管 SSH OpenCode 问答需要 Desktop `0.13.0`、Agent `0.11.24` 和新启动的托管 Runtime,不扩展到任意 ACP 服务。回答或跳过成功后在原位置保留问题与答案,支持多轮记录和本地会话重载;旧版本已丢弃的答案不能恢复。并行问题按顺序等待回答,重复事件保留草稿,提交失败可重试;取消远程待答后可在同一会话继续发送。Execute 权限确认自动处理,不等待第二次审批;具体支持范围见[交互边界](./docs/features/assistant-workbar/runtime-interactions.md)。
|
||||
- [x] **原生执行清单**:OpenCode 和 Continue 在对话顶部更新只读执行清单,进度随会话保存。显式清空和远程重放保留请求归属,取消不把未完成条目标成完成;远程交付需要配套 Agent,详见[清单契约](./docs/features/assistant-workbar/runtime-checklist-technical-design.md)。
|
||||
- [x] **原生执行清单**:OpenCode 和 Continue 在对话顶部更新只读执行清单,进度随会话保存。详情在可滚动的锚定浮层中展开,不挤动聊天内容;点击外部关闭,Escape 关闭后焦点返回入口。显式清空和远程重放保留请求归属,取消不把未完成条目标成完成;远程交付需要配套 Agent,详见[清单契约](./docs/features/assistant-workbar/runtime-checklist-technical-design.md)。
|
||||
- **取消后的历史**:模型可见历史保留已中断的部分回复或占位标记,避免旧问题合入下一轮;本地 OpenCode 复用会话时附带一次中断说明。
|
||||
- [x] **专家与 Subagent**:支持显式专家、团队分析和最多三个专家并行分析。专家继承父请求 Ask/Execute 模式,可使用已启用的本机直连模型工具,Ask 仍只读;这些工具不是远程 OpenCode 子会话。聊天先展示可逐项展开的专家完整输出,再在其下展示总 Agent 的综合结果,并随会话保存。
|
||||
- [x] **OpenCode 子代理过程与最终结果**:子代理卡片按顺序显示文字、推理和工具过程,最终结果独立展示。远程实时过程需要 Agent `0.11.20`,旧包仍显示最终结果但不补造缺失过程。
|
||||
- [x] **OpenCode 事件连接回收**:聊天与原生上下文压缩在结束事件迭代前关闭各自订阅,覆盖完成、失败、取消和消费方提前结束,不取消其他并行会话。
|
||||
- [x] **准确的消息底部状态**:区分请求准备、等待重试、开始重试、工具活动、待回答和终态;本机 OpenCode 使用原生重试次数和计划时间,直连模型显示自身退避阶段。消息底部状态点保持静态,未接入的 Runtime 重试不编造提示,会话列表闪点及发送、停止行为不变。
|
||||
- [x] **直连模型命令工作目录**:Execute 命令可通过绝对路径、相对路径或符号链接使用工作区外目录;工作区仍为默认目录和相对路径基准,Ask 保持只读。
|
||||
- [x] **简化 Runtime 选择**:会话与项目菜单不再枚举每个 Runtime 与模型的组合,Runtime 模型在系统设置中配置;已保存的项目固定模型仍可使用,并明确显示其固定模型。
|
||||
- [x] **Runtime 与模型分层选择**:按会话、项目、全局逐字段解析 Runtime 和模型。会话双栏选择器显示来源,可覆盖或恢复项目默认;项目与通道设置共用规则,Main 在每次请求及排队派发时重新解析。已删除或不兼容的连接会回退,缺少凭据仍明确报错。schema 49 迁移已保存选择,用途模型仍为规划,详见[选择设计](./docs/features/model-connections/runtime-selection-design.md)。
|
||||
- [x] **角色绑定模型连接**:每个角色可继承默认模型或选择独立文本模型连接,失效连接安全回退默认模型,综合角色始终继承默认模型。
|
||||
- [x] **多协议模型配置**:支持 Anthropic Messages、OpenAI Responses、OpenAI Chat Completions、OpenAI Images 和无认证本机模型;新用户默认连接为本机 Ollama 兼容地址,不预置第三方云模型服务。升级时只替换从未配置凭据且仍完全等于旧内置值的历史默认连接,用户显式保存或加密凭据的连接保持不变;已有部署仅使用兼容环境变量提供凭据时继续沿用对应的历史连接参数,通用模型环境变量仍优先。“保存并测试模型”会发送有界的真实文本或图片生成请求并校验生成结果,而不是只检查 HTTP 连通性,因此可能产生少量服务商用量费用。
|
||||
- [x] **模型请求定制**:每个 LLM 连接可填写有界 JSON 自定义请求头和顶层请求体。直连与 Continue 支持两者;本地 OpenCode 和 DeepSeek Harness 只使用各自原生支持的请求头,受管 SSH OpenCode 模型网关支持两者。Runtime、协议和认证字段始终优先,这些普通连接设置不能用于保存 API Key 或其他密钥。详见[模型连接请求定制](./docs/features/model-connections/README.md)。
|
||||
- [x] **本地直连手动压缩**:文本模型会话可在自动压缩关闭或未到阈值时手动生成摘要,保留最近轮次和完整历史,保存的摘要用于后续对话;图像连接和远程直连入口不适用。摘要模型调用可能产生费用。
|
||||
- [x] **上下文用量与自动压缩**:直连模型按每次成功调用更新供应商用量,图片与工具轮次使用同一口径,供应商缺失 usage 时才回退估算;界面明确区分“本次模型调用”和“压缩后对话估算”,压缩线始终根据当前设置与所选模型窗口即时计算,不在每个对话中保存旧配置;压缩标识的前后值使用同一估算口径,运行记录仍保留各次模型调用的供应商 usage。对话与多轮工具 Agent 可在已完成调用越过阈值后自动重复压缩,规划时先为固定提示、工具定义和摘要预留预算;同一回复会分别保留 Agent 工具上下文与对话历史的压缩标识,并在应用重启或较早消息滚出本地历史窗口后继续复用摘要。
|
||||
- [x] **持久凭据保护**:API Key 由 Main 使用系统安全存储加密且不暴露给 Renderer。托管 SSH accepted Prompt 只把当前 profile 与密钥放入 Agent 内存,不写入 SSH 参数、远端环境或磁盘;其他路径仍在 Main 内使用。密钥随对应模型连接保存,修改服务地址或临时切换为无需认证不会要求重新输入;只有用户显式清除凭据或删除连接时才移除。
|
||||
- [x] **有界故障诊断**:Desktop 在用户数据目录中轮转保存启动、Runtime 和远程连接的固定阶段失败,最多 4 个 256 KiB 文件;GoodBuddy Agent 在各 installation 的私有 state 目录中轮转保存 daemon、连接、恢复和 Runtime 生命周期,最多 3 个 64 KiB 文件,并可通过固定 `diagnostics --installation-id` 命令读取。两端都只记录白名单阶段、稳定错误码/类型和固定短消息,不保存 Prompt、凭据、文件内容、路径、环境、SSH 参数或 Provider 原始响应;诊断写入失败不改变正常运行。
|
||||
@@ -83,10 +90,12 @@
|
||||
- [x] **Skills 按需接入**:可分配给直连模型、OpenCode、Continue 和 DeepSeek Harness,并使用有界资源和受控 Runtime 边界。
|
||||
- [x] **本机工具执行环境源码链路**:在“能力与工具 > 工具执行环境”中为本机 Skills 与 stdio MCP 选择 GoodBuddy 托管 Node.js、按需安装的托管 Python,或经过真实验证的自定义解释器;提供独立的原生地址/OSS 镜像选择、诊断、安装进度、取消和删除。新的本机 Runtime 与 stdio MCP 获得不可变 PATH 快照,不修改普通终端、系统环境或远程 Host。Windows x64 托管 Node 与原生地址 Python 已通过真实安装验证;托管 Python 归档按目标文件系统验证,Linux 保留大小写不同的合法路径,所有目标仍拒绝完全重复路径和不安全条目。
|
||||
- **本机工具执行环境验证记录**:六个平台/架构的 OSS 镜像对象已完成字节、大小和 SHA-256 公开回读验证。托管 Python 保持按需下载,不向 Desktop 发行包额外带入许可证文件。每个标准打包任务使用目标架构原生 Runner,并在打包前真实安装托管 Python,验证 SSL、pip 与 venv。不可变的 `v0.12.0` 尝试在发布前通过 Windows 与 macOS,但暴露了 Linux TAR 大小写处理问题;`v0.12.1` 在同步 Agent 发布时于原生打包前取消。已发布的 `v0.12.2` 随后通过全部六个原生打包任务及其托管 Python 安装探针。现有记录未覆盖真实 Skill/MCP、自定义解释器和运行中进程协调。
|
||||
- [x] **内置 MCP 按需接入**:知识库、魔法笔记、GoodBuddy 配置与内置浏览器 MCP 可分别启停,并可分配给直连模型、GoodBuddy 管理的 OpenCode 和 Continue;DeepSeek Harness 在设置中明确显示为暂不支持。内置 MCP 仅通过当前请求的短期本机权限提供,Ask / Execute 读写边界不受用户配置放宽。
|
||||
- [x] **内置 MCP 按需接入**:知识库、魔法笔记、GoodBuddy 配置与内置浏览器 MCP 可分别启停,并可分配给直连模型、GoodBuddy 管理的 OpenCode 和 Continue;这些 Server 在 DeepSeek Harness 中仍不支持。Story Graph 另通过 Main 代理支持 Harness。内置 MCP 仅通过当前请求的短期本机权限提供,Ask / Execute 读写边界不受用户配置放宽。
|
||||
- **Obsidian 接入(源码已实现,验收中)**:默认关闭,默认发现全部本机注册仓库,也可指定文件夹并在保存或启用前测试。随包提供 MCPVault 0.16.0,19 个共享工具保留全部上游能力;生产组件自动化、Electron 托管 Node、Windows 设置与聊天 UI,以及受限网络下的 Windows x64 解包应用已验证。物理断网、安装器及其他系统验收待完成。DeepSeek Harness 与远程执行保持不可用,详见[功能文档与验证记录](./docs/features/obsidian/README.md);此项不表示已发布。
|
||||
- [x] **MCP Tools**:显式启用的自定义 MCP 可按 Runtime 分配给直连模型、GoodBuddy 管理的 OpenCode、Continue Agent Execute 和 DeepSeek Harness,并仅在 Execute 加载;Agent 子进程只获得按请求签发的本机回环权限,MCP 地址、命令和凭据保留在 Main,动态工具仍经过发现、执行记录与权限边界。直连模型与 Harness 的健康调用复用当前请求已发现的工具清单,不在每次调用前重复发现。
|
||||
- [x] **MCP Prompts 与 Resources 元数据**:MCP 测试仅在 Server 声明对应能力时发现有界的 Prompt、参数与 Resource 元数据,不读取 Resource 内容;Runtime 支持的 Prompt 可填入聊天草稿后继续编辑。OpenCode 可报告实验性 Resource 清单,Continue 当前版本明确不支持 Resources。
|
||||
- [x] **本地知识库**:支持文件、目录和网页导入、SQLite FTS5 检索及来源追溯。知识范围按对话保存,新对话默认不选择知识库;创建与检索高级参数默认折叠。文档区分可用、处理中和失败,支持打开来源、失败重试及移除来源前确认。
|
||||
内容来源与文档索引共用可搜索列表,单文档来源不重复占行,目录保留分组文档,失败来源保留恢复操作;任务历史和次级操作从统一入口访问。
|
||||
- [x] **外部知识库接入**:在知识库页面管理 Dify、FastGPT 和 RAGFlow 实例,通过目录或手工 ID 验证并绑定远端知识库,保留 Provider 专属检索配置和引用;对话支持按需检索及每次回答前检索。外部系统只负责知识检索,不接入其 App、Chat、Workflow 或 Agent,也不批量同步、本地索引或修改远端内容。被回答引用的有界检索片段随会话保存在本机。详见[外部知识库接入 PRD](./docs/features/knowledge-base/external-knowledge-prd.md)。
|
||||
- **外部知识库验证记录**:三家 Provider 已通过真实服务、本机 HTTP MCP 和生产 IPC 短答案检查,Dify 另通过完整 App 输入区到回答及引用的链路。现有记录未覆盖 FastGPT/RAGFlow 桌面专属参数、复杂多库问答和远程回答前检索,详见[验证记录](./docs/features/knowledge-base/progress.md)。
|
||||
- [x] **知识图谱**:支持规则、模型和混合抽取,以及实体、关系、别名和证据维护。
|
||||
@@ -98,28 +107,32 @@
|
||||
- [x] **受控知识本体**:每个知识库可定义实体、关系、别名和端点约束,保留证据偏移、置信度和抽取来源,并显式提示图谱重建。
|
||||
- [x] **强制检索与引用上下文**:对话可按需或每次先检索,显示零结果、降级、失败与取消状态,并可查看引用上下文或安全打开来源。
|
||||
- [x] **魔法笔记 / Magic Notes**:提供本地优先的笔记与待办工作台、范围管理、编辑、筛选和受控 AI 评论。笔记从自适应卡片总览打开;独立待办页提供搜索、状态筛选、分组列表和直接勾选,宽屏列表稳定在左侧,任务说明、来源记录及 AI 评论在右侧同一区域显示,窄屏按需显示详情并提供返回列表。紧凑页签放在页头新建按钮左侧,筛选放在搜索右侧。打开原笔记再返回可恢复任务上下文;切换任务不会混入上一项的来源内容,读取失败使用应用通知并提供就地重试,来源缺失有明确提示。左侧入口可按设置显示未完成待办数量,创建、保存和评论结果使用统一应用通知。Agent / MCP 写入后,已打开的工作台自动更新,并保留当前选择与未保存草稿。
|
||||
- **会话采集与快速笔记**(已实现,真实 Electron 验收通过):单条助手回答或完整会话正文可先预览、编辑,再追加到已有笔记或连同首条记录创建新笔记。右侧笔记 Tab 支持标题与正文搜索、快速追加及打开完整工作区,记录来源可返回会话和消息;切换会话保留草稿。真实 App/preload/IPC/SQLite 验收覆盖完整 502 条历史及 214px 面板原生键盘操作,模型调用为 0。[功能验证进度](./docs/features/magic-notes/progress.md)保留聚焦通过、fixture 修复与当时的测试和类型检查失败;[0.15.0 候选验证](./docs/development/release-preparation-0.15.0.md)已通过全量测试、类型检查和 lint。
|
||||
- 待办宽屏列表与详情之间可拖动分隔条并记住宽度;来源笔记分组可独立折叠,不清除当前选中任务的详情。
|
||||
- [x] **连续记录工作区**:笔记详情连续展示全部记录,左侧索引默认 168px,可拖动右边界或用键盘在 140–320px 内调宽,并记住偏好;索引与右侧 AI 评论独立收起。每条画布记录显示真实首页缩略图、页数和时间,文字记录显示摘要;点击索引只滚动定位,保留当前编辑器和草稿。打开笔记就在标题下方显示空白输入区,保留文字/画布选择和保存操作;新增保存后清空,供下一条记录使用,旧记录通过编辑入口修改。空白输入区和保存后未再修改的记录返回时不提示;保存失败和真实修改仍受保护。窄屏索引使用固定宽度折叠抽屉,不显示调宽分隔条,AI 评论移至底部。
|
||||
- [x] **分页画布笔记**:已集成 PeopleLib Fabric + Quill 编辑器,支持跨页正文、笔迹、高亮、对象选择及变换、浮动文字、图片和纸张模板。PDF 可作为分页底版导入并提取原生文字;正文和批注可导出为栅格 PDF,导出文件不保留可搜索文字层。用户手动保存后,记录正文与二进制资源存入本地笔记文件,SQLite 保留元数据、索引、修订、待办和评论。备份须协调保存 SQLite 与笔记目录,产品无一键备份入口。撤销/重做限当前批注页或 Quill 模式,不提供全局文档撤销、无限画布或 PNG 下载按钮。草稿、已保存记录和来源为画布的待办按默认模型图像输入能力使用页面图像加文字,或明确标注仅文字降级;“发送画布页数”可选 1~8,默认 1,按当前顺序发送前 N 页,文字和图片范围一致,保存与导出仍支持 50 页。纯视觉记录/草稿需要支持图像输入的模型。即时评论模式提供手动画布分析,保存后自动分析失败不阻断或回滚保存。提取文字不变时保留文字评论;布局变化使视觉评论失效,并在保存后自动评论模式下重新分析。MCP 禁止以纯文字覆写画布记录。实现已完成,最终验证状态见[功能进展](./docs/features/magic-notes/progress.md)。
|
||||
编辑与只读画布均支持 25%–300% 视图缩放、100% 还原及随视口调整的“适应宽度”,不改变保存内容或导出尺寸。
|
||||
首次升级将历史正文迁移到文件,并随附件变更把数据库升级至 schema 39;旧客户端不能再打开,回退需使用升级前备份。
|
||||
历史正文迁移已改用文件存储,当前 schema 48 新增会话来源元数据;旧客户端不能再打开,回退需使用升级前备份。
|
||||
- [ ] **MCP Server Control Plane**(规划中):统一 MCP 生命周期、健康检查、重连、Schema 缓存、隔离、审批和审计。
|
||||
- [ ] **可追溯笔记摘录与 AI 编辑**(规划中):从对话、知识和网页收集带来源的摘录,并提供需确认的总结、改写和整理操作。
|
||||
- [ ] **知识/网页摘录与 AI 编辑**(规划中):在已实现的会话正文采集之外,扩展知识和网页摘录,并提供需确认的总结、改写和整理操作。
|
||||
|
||||
### 工作管理、长期协作与工作流
|
||||
|
||||
- [x] **任务、活动与成果**:集中管理任务状态、审计活动和独立成果文件;普通聊天回复只保留在会话中,不再自动复制到成果栏,已有重复聊天 Markdown 从成果列表隐藏但不物理删除。运行记录改由 Main SQLite 保存,不再受旧 Renderer 的 500 条、单详情 4,000 字符或约 2 MB 上限影响,页面按批继续显示;不再常驻旧缓存截断警告,但不会恢复此前已丢失的历史。Token 用量按 Runtime 与模型归类,并针对 OpenAI 兼容与 Anthropic Messages 的不同上报口径归一化展示缓存命中率;用量按项目或会话分组时默认收起并显示汇总,展开后显示 Runtime / 模型子行,按模型分组时保持平铺;活动按会话分组并默认收起,避免长历史占满页面。
|
||||
- [x] **任务、活动与成果**:集中管理任务状态、审计活动和独立成果文件;普通聊天回复只保留在会话中,不再自动复制到成果栏,已有重复聊天 Markdown 从成果列表隐藏但不物理删除。运行记录改由 Main SQLite 保存,不再受旧 Renderer 的 500 条、单详情 4,000 字符或约 2 MB 上限影响,页面按批继续显示;不再常驻旧缓存截断警告,但不会恢复此前已丢失的历史。Token 用量按 Runtime 与模型归类,并针对 OpenAI 兼容与 Anthropic Messages 的不同上报口径归一化展示缓存命中率;用量按项目或会话分组时默认收起并显示汇总,展开后显示 Runtime / 模型子行,按模型分组时保持平铺。独立“系统任务”页签按来源汇总后台用量,支持手动刷新和记录更新后刷新;监督回顾、图片重新生成、图谱提取和远程嵌入补充用量记录,不补算缺失的历史或供应商数据。活动按会话分组并默认收起,避免长历史占满页面。
|
||||
- [x] **紧凑会话工具记录**:逐项展开工具记录即可查看和复制结果、错误及输入参数;会话与子任务进度使用简洁行,减少重复 Runtime 摘要。OpenCode、Continue、DeepSeek Harness 和直连模型可显示已有文件路径、命令或搜索摘要,并在工具完成和会话重载后保留。
|
||||
- [x] **Task 与定制任务体验**:每个产品级 Task 只关联一条 Conversation,一条 Conversation 可承载多个 Task;左侧会话列表通过行首展开按钮显示带共享状态点的 Task 子项,父会话行不重复任务标签,UI 只展示到 Task,不暴露 Job/Run 层级。新建定制任务可关联当前或新 Conversation,默认 Execute 并沿用 Runtime、工具和审批边界;重复触发复用同一 Task,文本结果回写 Conversation,独立文件和图片保留为成果。普通消息与到期 Scheduled Task 共用 Conversation 级持久发送队列,同一会话一次只执行一项;当前回复期间仍可继续发送,队列按顺序续跑,并允许删除或“立即中断并插入”。Task Center 继续作为完整索引,不建设独立 Automation Center。当前计划触发支持单次、每日和每周;高级时区、Cron、事件触发与重试治理仍按 PRD 逐步实现。详见 [Task Center PRD](./docs/features/task-and-job/task-center-prd.md) 和 [Scheduled Task PRD](./docs/features/task-and-job/scheduled-task-prd.md)。
|
||||
- [x] **记忆与智能心跳**:当前提供周期回顾、建议记忆、洞察、后续任务和可审计运行轨迹。
|
||||
- [x] **记忆与智能心跳**:计划触发共享增量回顾,不再单独生成心跳报告;可只更新记忆图谱,或从未决事项、分歧、修订和候选约定生成有依据的建议。接受未决事项创建暂停任务,确认约定写入长期背景;建议失败可单独重试,不撤销已完成回顾。
|
||||
- [x] **定时消息沿用会话**:定时消息使用会话当前历史、Runtime、工作模式和已保存的知识检索设置;任务详情显示实际运行模式,当前 occurrence 未结束时禁止重复“立即运行”。
|
||||
任务中心通过状态数量和筛选定位运行中及待处理任务,审批操作保留在对应任务卡片中。
|
||||
- [x] **自动监督设置与范围**:“监督者 > 自动监督”统一管理计划、自动监督报告和建议,支持创建和编辑 Global 或指定一个、多个 Project 的每日、每周计划;工作回顾阅读带日期的统一监督结果及历史。旧单项目配置无损迁移,项目级记忆与行动输出必须显式指定范围内的 Project。Task Center 和设置中心不再复制心跳表单;按分区回顾、候选生成和唤起条件仍待设计。详见 [智能心跳 PRD](./docs/features/smart-heartbeat/prd.md)。
|
||||
- [x] **监督者回顾、故事线图谱与活动**:按范围和时间回顾工作,查看保存结果的图谱及来源,确认或修订实体,预览写入本地知识库实体。侧栏可跟随或固定 Conversation、Task,并打开匹配结果。活动合并心跳报告与下游监督的阶段状态,保留失败和旧结果入口。自动阶段只处理新增、修改及未处理的来源片段,无变化时跳过模型;手动回顾重新整理有界历史。回顾只读且禁止工具,模型调用可能产生费用,详见[实施与验证记录](./docs/features/conversation-supervision/progress.md)。
|
||||
- [x] **智能心跳设置与范围**:“监督者 > 智能心跳”统一管理 Global 或指定 Project 的每日、每周计划及建议,Task Center 和设置中心不复制表单。待处理建议不重复,忽略后有新依据才再次提出;项目与全局仍分别维护进度,会话级实时主动介入仍为规划。详见[实现规则](./docs/features/conversation-supervision/logic-design.md)。
|
||||
- [x] **监督者回顾、故事线图谱与活动**:按范围和时间回顾工作,查看保存结果的图谱及来源,确认或修订实体,并带入相关回顾上下文继续讨论。侧栏可跟随或固定 Conversation、Task,并打开匹配结果。活动合并心跳触发与下游监督的阶段状态,保留失败和旧结果入口。自动与默认手动回顾只处理新增、修改及未处理来源,无变化时跳过模型;显式“重新整理”重读区间,但不推进或重置共享进度,自动回顾不续跑用户暂停的运行。回顾只读且禁止工具,模型调用可能产生费用,详见[实施与验证记录](./docs/features/conversation-supervision/progress.md)。
|
||||
手动开始、自动触发和继续共用一个活动回顾;活动记录可取消并保留已保存批次,清理结束前不接纳新回顾,已取消回顾不可继续。故事线事件、实体和关系按独立页签展示数量,并与画布选择同步。
|
||||
可从监督反馈或图谱来源直接继续讨论,编辑问题并明确打开目标会话;界面不再提供知识实体写回控件或重复上下文说明,智能心跳用可处理的监督建议代替报告指标和趋势。
|
||||
- 手动回顾分页处理所选历史,并按批保存事实与来源;不再按固定时长自动暂停,仍支持主动暂停和从保存进度继续。设置提供并发、单次请求超时、批次大小和响应容量;活动记录突出相连阶段、已保存批次与剩余来源,次要统计可展开查看。工作回顾采用全宽纵向布局,运行状态单独显示,空态不再挤在控件旁。
|
||||
- [ ] **监督后续能力**(规划中):逐事件完整回放、Experiment 目标、人工修改时间序列审计、事件触发及更完整的执行观察仍未完成。当前自动回顾受输入预算和滚动窗口限制,删除报告不会重置处理进度或重建图谱。详见 [会话监督 PRD](./docs/features/conversation-supervision/prd.md)。
|
||||
- [ ] **批量运行与对比实验室**(规划中):对模型、Prompt、角色和工作流配置执行批量对比,汇总质量、耗时、Token、费用、失败率和成果差异。
|
||||
- [ ] **时态记忆与事实冲突检测**(规划中):为记忆和知识图谱增加有效期、当前事实、过期与矛盾检测、事实核验及证据回溯。
|
||||
- **Story Graph 只读工具(Desktop 0.15.2 / Agent 0.15.0)**:Agent 可搜索已保存的工作,读取当前主张或时间线,并分页核对来源。监督者应用开关及 Runtime 分配同时控制发现和调用,旧会话也受限制。Model、本地 Harness、本地与远程 OpenCode/Continue 共用桌面读取入口;查询不调用模型,不以较新回顾推断替代关系。跨 scope 事实复用及 `as_of` 仍待实现,详见[设计与验证](./docs/features/conversation-supervision/story-graph-mcp-design.md)。
|
||||
- [ ] **可视化受控工作流**(规划中):提供版本化 DAG、条件分支、审批、取消和恢复,执行节点继续经过 Main Runtime 边界。
|
||||
- [ ] **统一 Run Graph 与回放**(规划中):关联任务、Subagent、模型、知识、工具审批、用量和成果,支持失败定位、重试和脱敏导出。
|
||||
|
||||
@@ -143,12 +156,18 @@
|
||||
|
||||
### 开源、构建与发布
|
||||
|
||||
- 当前 Desktop 候选为 `0.13.16`,Agent `0.13.4` 已发布,OpenCode 固定为 `1.18.29`、Continue 为 `1.5.47`;正式发布状态以独立发布渠道为准。
|
||||
- Desktop `0.15.3` 修复本地直连手动压缩和请求有效期间的工具授权,区分取消与失败并去除重复提示,优化侧栏搜索、注册成功后的快捷键提示及笔记操作布局,减少启动和存储中的重复处理,并精简重复依赖及开发文件。不宣称整体渲染性能已显著提升;Office 实时编辑仍为设计。证据见[0.15.3 发布准备](./docs/development/release-preparation-0.15.3.md)。
|
||||
- 当前 Desktop 候选为 `0.15.6`,已发布 Agent 保持 `0.15.1`,OpenCode 固定为 `1.18.29`、Continue 为 `1.5.47`;正式发布状态以独立发布渠道为准。
|
||||
- Desktop `0.15.6` 增加默认关闭、可保存的顶栏与清单磨砂外观,不透出系统桌面;减少聊天重复渲染,草稿与队列图片支持直接预览,设置分组及开关右对齐,笔记标题和编辑间距更紧凑。本地 OpenCode 在清理后对明确暂时性 MCP 传输错误最多重试一次,作废结果不确定的名称,不重放 Prompt 或工具调用;反馈包含脱敏连接诊断。schema 52 增加执行统计索引,升级前备份数据库和笔记。详见[发布准备](./docs/development/release-preparation-0.15.6.md)。
|
||||
- Desktop `0.15.5` 更新智能心跳与增量回顾,保留中断轮次历史,执行清单改为浮层,笔记保存成功后退出编辑;自动评论不重新打开编辑器,失败保留草稿。新增手动笔记标签、AND 筛选及重命名/合并/删除,双栏笔记与全宽概览,固定工作区文件操作栏,缓存 OpenCode 终端依赖并缩短 MCP 名称。schema 51 增加标签存储,同时迁移旧待确认记忆为待处理约定;升级前备份数据库与相邻笔记。证据见[发布准备](./docs/development/release-preparation-0.15.5.md)。
|
||||
- Desktop `0.15.4` 增加 Runtime/模型分层选择及独立系统任务用量,减少 Runtime 指令和历史重复。schema 49 迁移项目与会话选择,回退须恢复完整升级前数据库和相邻笔记备份。Agent `0.15.1` 要求 Desktop `0.15.4`,修复远程 Continue 历史重复封装,Runtime 锁版本不变。证据见[0.15.4 发布准备](./docs/development/release-preparation-0.15.4.md)。
|
||||
- Desktop `0.15.1` 已完成六平台原生打包及 GitHub/OSS 发布。Desktop `0.15.2` 新增 Story Graph 只读工具和完整可编辑的监督讨论消息,简化笔记采集并补充退出诊断;远程图谱读取需配套 Agent `0.15.0`。主机与云环境管理应用仍为待实现规划,当前候选证据见[0.15.2 发布准备](./docs/development/release-preparation-0.15.2.md)。
|
||||
- Desktop `0.15.1` 承接未发布的 `0.15.0` Obsidian 接入、会话采集到魔法笔记和预览中的本地原生客户端,并修复知识库、监督者与界面操作。schema 48 新增会话来源元数据,回退旧客户端需使用升级前完整备份。Agent `0.15.0` 要求 Desktop `0.15.2`,保留 Node `24.19.0`,补齐远程遥测关闭配置及 Continue 跳过已关闭的更新检查,不新增远程客户端快捷入口。
|
||||
- Desktop `0.13.15` 承接未发布的 `0.13.14`,改善监督者分页回顾与续跑、ripgrep 原生搜索、待办布局和远程结果未知后的显式续聊。数据库升级至 schema 47,回退旧客户端需使用升级前完整备份。
|
||||
- Desktop `0.13.16` 分离结构升级与旧历史回收,移除回顾固定时长自动暂停,并改善监督者布局。相较 `0.13.15` 不新增 schema 变更,也不要求更新 Agent。
|
||||
- Agent `0.13.3` 回收空闲 Runtime,并使被替换的 Agent 等已有工作结束后退出;复合包要求 Desktop `0.13.12`,请先升级 Desktop,再更新 Host 环境。Node 保持 `24.19.0`。
|
||||
- Agent `0.13.4` 在完成前等待模型交付确认,空闲 Runtime 回收失败不改变已完成结果,并在环境更新后清理已确认停用的旧程序及所属孤儿进程;保留历史、活动及状态不明的安装。独立包要求 Desktop `0.13.14` 或更新版本;因 `0.13.14` 未发布,请先升级至 Desktop `0.13.15`,再更新 Host。
|
||||
- 发布准备要求全量测试、发布说明校验、类型检查及 lint;候选主分支 CI、生产构建、原生打包及公开发布核验为独立验收步骤。本轮不做本地生产构建、打包或龙芯预览,当前验证状态见[发布准备记录](./docs/development/release-preparation-0.13.16.md)。
|
||||
- 发布准备要求全量测试、发布说明校验、类型检查及 lint;候选主分支 CI、生产构建、原生打包及公开发布核验为独立验收步骤。本轮不做本地生产构建、打包或龙芯预览,当前验证状态见[发布准备记录](./docs/development/release-preparation-0.15.0.md)。
|
||||
- Desktop `0.13.12` 和 Agent `0.13.3` 已完成原生发布流程,但不替代开发期真实 Host 场景覆盖。
|
||||
- 验证记录与功能状态分开。存储已有本地及 Linux x64 Host 真实工具任务、多项目多会话、取消和无损迁移验证;进程复用有 Windows 完整 App 与 Linux x64 Host 证据,PPTX OCR 与空闲内存释放有 Windows 真实文件证据。图片工具已有真实服务商生成/编辑及 Host 传输证据,这些记录未覆盖完整界面自然语言调用和本地/远程切换。候选仍需主分支 CI 及原生发布打包,详见[Runtime 验证记录](./docs/features/assistant-workbar/progress.md)与[图片工具验证记录](./docs/features/conversation-media-generation/progress.md)。
|
||||
- 发布准备前,`9836a4c` 已通过本地 4,858 项测试(67 项跳过)、完整类型检查和 lint;真实服务商画布分析仍未验证。该提交的三个原生 Agent CI 构建通过;桌面 CI `35485936807` 为 4,875 项通过、8 项 Electron 测试失败,均因 Linux 沙箱辅助程序未配置,在页面断言前退出。候选配置该程序并在 Xvfb 下运行测试,不关闭沙箱;候选本地验证、主分支 CI 与原生标签打包分别记录,不在发布准备中运行本地生产构建或打包。
|
||||
@@ -166,7 +185,7 @@
|
||||
- [ ] **Headless Runtime API**(规划中):提供本机优先的任务、事件、状态和成果 API,以及有范围、有效期、限流和撤销能力的令牌。
|
||||
- [ ] **GoodBuddy Team Hub**(规划中):以可选服务提供组织、RBAC、项目共享、远程 Agent、策略下发和租户审计。
|
||||
- **SSH 主机与远程执行空间验证记录**:主机 CRUD、Host Key、加密凭据、Project UI、Workspace、OpenCode ACP v5、Agent-owned Prompt/gateway/transcript、Ask 只读、Execute 完整账号权限、取消、detached Agent 精确重连和 release-only 双架构资源校验已经接线。Linux x64 当前源码已用真实模型与工具通过 detach、进程结束、relay 丢失、并发、取消、Provider 异常、Agent 重启和 Desktop SQLite 恢复矩阵;当前源码测试签名 Agent `0.11.17` 又通过两个并发 Ask 读取、一次 Execute 写入并读回,以及 6 次带自定义 Header 和 Body 的真实受管网关模型请求,未发现 Provider 请求重放,隔离 Agent state 中也没有 API Key 或自定义请求值。公开 signing key registry 已供应。控制面直连源码不等待新 installer-bearing 包;现有记录未覆盖当前 Linux x64/arm64 正式签名工件的完整公开核对及 GitHub/北京镜像、双架构和离线 GoodBuddy 传输矩阵,发布结果另行记录。
|
||||
- [ ] **多云远程沙盒 Agent**(规划中):通过云厂商 API 和 SSH Agent 管理专用 Linux 沙盒;凭据留在 Main 进程,高风险控制面操作单独确认。
|
||||
- [ ] **主机管理与云环境管理**(规划中):主机管理迁入应用中心,提供列表与详情工作页面;云环境管理作为同级应用,复用主机连接和执行能力。首版适配计划覆盖 AWS、Azure、阿里云、腾讯云、VMware vCenter / vSphere、ZStack,分批完成已有实例发现、接入及真实执行验收;实例创建、启停、销毁和网络编排后续交付。平台 API 尚未实现,现有云主机可按 SSH 条件手工接入。详见[产品范围](./docs/features/remote-host/prd.md)。
|
||||
|
||||
## 规划原则
|
||||
|
||||
|
||||
+61
-25
@@ -43,6 +43,10 @@
|
||||
|
||||
两种主题必须保持相同的信息层级,但不要求机械地反转明暗。浅色主题以白色主内容画布、冰蓝灰侧栏和轻微着色的顶栏建立空间关系;深色主题使用深海军蓝与蓝灰表面逐层提亮,避免纯黑。蓝色承担主要选择和交互,青绿色主要承担成功与可用状态,二者不得混用语义。
|
||||
|
||||
外观设置提供“透明磨砂特效”开关,当前默认关闭,文字在左、共享 Switch 在右。选择保存在应用设置中,保存成功后立即生效,重启后恢复。开启时,右侧内容框架顶栏的背景不透明度在浅色主题为 65%、深色主题为 70%,保留 18px 背景模糊与淡分隔线。聊天滚动视口向上延伸 58px,消息上滚时实际经过顶栏背后;不使用人工渐变充当背景。初始留白放在滚动内容中,包含顶栏高度和当前任务/待办条的实测高度,首条消息仍从这些控件下方开始。任务/待办条固定在顶栏下方并保持实色;展开的 Runtime 待办卡片使用两主题各自的 75% 不透明背景、18px 背景模糊和清晰的文字颜色。
|
||||
|
||||
已保存的开关状态同步到文档根节点,卸载时清理,使 body/top layer 中的待办卡片也能应用样式;其他菜单保持原有表面。输入区、右侧工作栏和非聊天页面保持原有位置,聊天加载态及无活动消息面板时不扩展视口。窗口拖拽和控制按钮保持原有行为;该效果不透出操作系统桌面。关闭后恢复顶栏下方的聊天布局,顶栏与待办卡片均恢复实色。`tests/frosted-glass.electron.test.ts` 使用真实 `ChatHistoryPane` 检查消息与顶栏的可见矩形交叠、初始留白、关闭恢复、浅深主题、跳底、历史加载锚点和会话切换。
|
||||
|
||||
## 3. 设计令牌
|
||||
|
||||
令牌以 CSS 自定义属性实现。`:root` 提供浅色值,`[data-theme="dark"]` 覆盖深色值。组件样式不得新增只服务于单个页面的颜色、阴影、圆角或间距常量。
|
||||
@@ -68,7 +72,7 @@
|
||||
| `--success`、`--success-subtle` | 成功状态 |
|
||||
| `--warning` | 警告状态 |
|
||||
| `--danger`、`--danger-strong` | 危险文本和状态 |
|
||||
| `--danger-solid` | 最终确认按钮等需要反白文字的危险背景 |
|
||||
| `--danger-solid`、`--danger-solid-hover` | 最终确认按钮等需要反白文字的危险背景及悬停背景 |
|
||||
| `--danger-border`、`--danger-subtle` | 危险入口和失败状态背景 |
|
||||
|
||||
浅色与深色具体值只在 `styles.css` 的主题根节点维护。状态组件必须同时显示文字或图标,不能仅靠颜色区分。
|
||||
@@ -116,6 +120,7 @@
|
||||
|
||||
- 业务组件通过 `--font-family-ui` 与字体尺寸令牌继承字体,不创建页面专属字体栈。
|
||||
- 表单按钮、输入框、选择框和文本域必须继承界面字体,避免回退为原生控件字体。
|
||||
- 文本表单复用 `.field` 下的共享输入规则;不适合增加字段包装层的独立输入或文本域使用 `.field-control`。文本输入规则排除 Checkbox 和 Radio,保留全局 `:focus-visible` 轮廓,不清除 Switch 焦点环。
|
||||
- 连续阅读内容使用 `14px`,持久辅助信息不得小于 `11px`。
|
||||
- 本地兜底字体资源必须随生产包交付,并同时包含 Inter 与 Noto Sans SC 的 OFL 许可证。
|
||||
- 页面内不得通过同时放大字号、加粗和使用强调色制造多个同级主标题。
|
||||
@@ -269,6 +274,11 @@
|
||||
- `danger-solid`:确认对话框中的最终危险操作。
|
||||
- `danger-zone`:设置页中集中展示的高影响操作区域。
|
||||
|
||||
`danger-solid` 必须是全局共享类,不依赖页面祖先;通过 Portal 挂到 `body` 后仍须生效。
|
||||
尺寸、圆角、字体、间距和禁用状态与 `primary-button`、`secondary-button` 共用规则,
|
||||
键盘焦点沿用全局 `button:focus-visible`。背景及可用态悬停使用危险实心色令牌,文字使用
|
||||
`--text-on-accent`;禁用时不触发悬停变色。
|
||||
|
||||
普通页面不得用实心红色按钮与主操作并列。危险入口必须使用具体动词和对象,例如“删除知识条目”,避免只写“确定”。
|
||||
|
||||
### 6.7 数据表格与活动列表
|
||||
@@ -287,9 +297,15 @@
|
||||
- 浅色侧栏使用冰蓝灰表面,与白色主内容画布形成明确边界;深色侧栏使用比主画布略亮的蓝灰表面。
|
||||
- 一级导航与最近会话之间、最近会话与底部账户区之间必须有可见结构分隔线。浅色主题使用 `--border-default`,深色主题可在可辨前提下使用 `--border-subtle`。
|
||||
- 当前导航项和当前会话使用一致的淡蓝选中背景、强调色文字和中等字重,不额外描边或添加侧边标记;导航图标随选中状态使用强调色,悬停时保留选中状态。浅深主题遵循相同规则,强制颜色模式保留系统选中边框。
|
||||
- 固定导航行高至少 `36px`、行间距 `4px`,图标统一为 `16px`;导航与最近会话分隔线上下各留 `16px`。普通待办和待处理建议数量使用中性色徽标,不使用危险红色;徽标高度不得改变导航行高。搜索框获得内部焦点时显示完整焦点环。
|
||||
- 固定导航行高至少 `36px`、行间距 `4px`,图标统一为 `16px`;导航与会话区域之间、会话区域与底部入口之间的分隔线上下均各留 `8px`(`--space-2`)。普通待办和待处理建议数量使用中性色徽标,不使用危险红色;徽标高度不得改变导航行高。搜索框获得内部焦点时显示完整焦点环。
|
||||
- 未选中项保持平整,不为每一行添加卡片边框或阴影。悬停反馈不得强于选中状态。
|
||||
- 最近会话列表在精细指针设备上使用细原生滚动条,滑块使用 `--border-control`、轨道透明;强制颜色与粗指针设备保留系统默认。
|
||||
- 会话区域使用 `--surface-raised` 与主导航区分,浅色为白底,深色为相邻的深蓝灰底。不显示“最近会话”标题,保留区域的无障碍名称,列表独立滚动。搜索与新对话共用主导航上方的一行,不在会话区域另设搜索头部;展开、关闭和键盘规则见[会话搜索](./docs/features/application-tool-navigation/ui-design.md#会话搜索)。搜索框使用透明背景、`--border-control` 边框与完整焦点环。
|
||||
- 窗口高度不超过 `600px` 时,侧栏允许整体纵向滚动,会话区域至少保留 `200px` 高度,避免搜索框、列表与底部入口相互覆盖。
|
||||
- 最近会话的顺序不随流式输出增量反复变化;置顶与新消息排序遵守
|
||||
[会话列表排序规则](./docs/features/application-tool-navigation/ui-design.md#会话置顶与操作菜单)。
|
||||
- 项目选择器顶行保留项目切换与新建按钮;项目设置统一从下拉列表对应行的管理按钮进入,关闭后焦点返回项目选择器。
|
||||
- 项目选择器与下方默认的新建对话按钮等宽,两行右侧图标按钮均宽 `36px`,与左侧控件间距均为 `8px`;搜索展开时项目选择器宽度保持不变。
|
||||
- 项目下拉列表通过 `FloatingPortal` 浮在侧栏与会话区上方,默认宽度 `380px`,不受侧栏裁剪;距窗口边缘至少 `16px`,窄窗口自动收窄,长列表内部滚动。浮层锚定项目选择按钮,窗口、滚动和尺寸变化后重新定位。
|
||||
- 项目选择器下方仅在有运行中、待处理或已完成未查看会话时显示跨项目活动汇总,无活动时隐藏;项目计数与项目、会话级联菜单遵守
|
||||
[项目活动汇总 UI 规则](./docs/features/application-tool-navigation/ui-design.md#10-项目活动汇总)。
|
||||
@@ -320,10 +336,10 @@
|
||||
接受用户本机选择的 PNG、JPEG 或 WebP 内联数据,宽高不超过 `4096 × 4096`、总像素不
|
||||
超过 1600 万且大小不超过 `512 KB`;不得读取远程 Logo URL。名称或副标题溢出品牌区时
|
||||
单行截断,不能撑宽或挤压侧栏。
|
||||
- 侧栏底部提供应用中心入口,设置按钮独立靠右。点击应用中心向上展开轻量锚定菜单,无模态遮罩,只列已启用应用,不按打开历史或常驻状态筛选;点击行关闭菜单,知识库、智能心跳和魔法笔记在主内容区打开页面。本机推理监控从菜单、常驻入口或管理 Modal 打开时均使用独立 Modal,保留底层工作区。菜单底部“管理应用”打开既有整窗管理 Modal,共同应用设置沿用设置 Modal。
|
||||
四个内置应用的管理列表、菜单和侧栏共用保存顺序,菜单按启用过滤,侧栏按启用且常驻过滤。知识库、智能心跳始终启用并常驻,可调整位置;管理 Modal 提供“打开”和排序,不提供启用、常驻开关或通用空设置,标签为“始终显示”(英文 `Always shown`)。原工作区配置及心跳单条计划 enabled 保持不变。只有魔法笔记、本机推理监控可修改启用和常驻,取消常驻不关闭功能。当前对话、运行记录和设置保持固定系统位置,不参与应用排序。
|
||||
- 侧栏底部提供“应用 / Apps”和“设置 / Settings”两个横向等高 `nav-item` 按钮,均显示图标和文字,中间使用弱竖分隔线。“应用”带向下箭头,点击后向上展开轻量锚定菜单,无模态遮罩,只列已启用应用,不按打开历史或常驻状态筛选;点击行关闭菜单,知识库、智能心跳和魔法笔记在主内容区打开页面。本机推理监控从菜单、常驻入口或管理 Modal 打开时均使用独立 Modal,保留底层工作区。菜单底部“管理应用”使用 `LayoutGrid` 图标,打开既有整窗管理 Modal,标题仍为“应用中心 / Application Center”,共同应用设置沿用设置 Modal。
|
||||
五个内置应用的管理列表、菜单和侧栏共用保存顺序,菜单按启用过滤,侧栏按启用且常驻过滤。知识库始终启用并常驻,可调整位置;管理 Modal 提供“打开”和排序,不提供启用、常驻开关或通用空设置,标签为“始终显示”(英文 `Always shown`)。监督者沿用智能心跳身份,可修改启用和常驻,执行边界见[监督者逻辑](./docs/features/conversation-supervision/logic-design.md#应用启停与执行)。魔法笔记、本机推理监控同样可修改启用和常驻。设备共享始终可从应用菜单及管理 Modal 打开,标签为“内置”,提供排序,不提供启用或常驻开关;在主内容区打开元数据页面,规则见[设备共享 UI](./docs/features/device-sharing/ui-design.md#当前首期页面)。当前对话、运行记录和设置保持固定系统位置,不参与应用排序。
|
||||
设置持久化后的事件同步各入口及工具配置写入;重开中心刷新期间锁定修改,新快照不被旧读取覆盖。文件、终端、浏览器和资源监控只通过右侧工作栏访问,不在左侧复制入口。
|
||||
管理 Modal 始终使用紧凑单列横向列表,纵向对应保存顺序;左侧为图标、名称及简短用途,右侧为打开、可用的设置及上下移动操作,行间使用弱分隔线,不加卡片外框。窄窗口操作换行且不溢出,保留共享键盘焦点环。可选应用关闭时禁用“打开”。启用、常驻位于紧凑设置详情;四行均提供上下移动及拖动排序,不受启用或常驻影响,箭头按完整顺序判断边界。搜索时禁用拖动,箭头仍按完整顺序移动,不丢失未命中项。尺寸、返回与滚动重置规则见[应用中心 UI 设计](./docs/features/application-tool-navigation/ui-design.md)。已有稳定设置入口时,不在顶栏重复提供同一入口。
|
||||
管理 Modal 始终使用紧凑单列横向列表,纵向对应保存顺序;左侧为图标、名称及简短用途,右侧为打开、可用的设置及上下移动操作,行间使用弱分隔线,不加卡片外框。窄窗口操作换行且不溢出,保留共享键盘焦点环。可选应用关闭时禁用“打开”。启用、常驻位于紧凑设置详情;五行均提供上下移动及拖动排序,不受启用或常驻影响,箭头按完整顺序判断边界。搜索时禁用拖动,箭头仍按完整顺序移动,不丢失未命中项。尺寸、返回与滚动重置规则见[应用中心 UI 设计](./docs/features/application-tool-navigation/ui-design.md)。已有稳定设置入口时,不在顶栏重复提供同一入口。
|
||||
- 本机推理监控 Modal 复用整窗 Portal、背景隔离和焦点循环;停止、重启及释放使用其上方的紧凑影响确认。Escape 只关闭最上层,操作提交期间禁止关闭及重复提交;焦点恢复与尺寸见[本机推理监控 UI 规则](./docs/features/application-tool-navigation/ui-design.md#91-本机推理管理)。
|
||||
|
||||
### 6.9 助手工作栏
|
||||
@@ -348,13 +364,14 @@
|
||||
“当前项目”和“所有项目”;无项目任务在“所有项目”中标注“未绑定项目”。范围变化不得创建第二个 Task Center。每个 Task 只
|
||||
关联一条 Conversation,一条 Conversation 可以关联多个 Task;列表不得复制会话内容,也
|
||||
不得把 Job/Run 提升为可导航 UI 对象。
|
||||
- 各栏目读取当前会话或项目的对应内容;当前内容不可用时仍保留栏目入口并说明原因。
|
||||
- 能力、连接和内容可以动态变化,栏目入口不能随之自动隐藏。不可用状态必须说明原因、影响和可执行入口。
|
||||
- 各栏目按声明的范围读取内容;笔记使用应用级数据,选择和草稿不跟随项目或会话变化。当前内容不可用时仍保留栏目入口并说明原因。
|
||||
- 能力、连接和内容可以动态变化,栏目入口不能随之自动隐藏。不可用状态必须说明原因、影响和可执行入口。笔记遵循应用中心的业务启用设置,禁用前处理草稿,禁用后隐藏目录入口并移除笔记 Tab。
|
||||
- 用户可以主动排序栏目,并可关闭可关闭实例或恢复默认布局;任务中心和工作区不能隐藏或
|
||||
关闭。应用不能用用户偏好机制实现自动能力裁剪。
|
||||
- 已打开实例保留 `tablist`、`tab`、`tabpanel`、方向键、Home、End 和焦点恢复语义。
|
||||
实例过多时 Tab 区单行横向滚动,“+”保持可见,不换行或改成下拉框。不可关闭实例不渲染
|
||||
关闭按钮,也不响应关闭快捷命令。
|
||||
“+”位于滚动容器外并占用固定宽度;滚动箭头限定在剩余的页签区域内,不能覆盖添加入口。
|
||||
- 当前工作栏 Tab 必须同时使用连续内容表面、可见边框、顶部指示、图标或较高字重中的至少
|
||||
两种信号;悬停反馈不得强于当前选中态。Tab 关闭按钮保留固定布局空间,默认仅在对应 Tab 悬停或
|
||||
`focus-within` 时显示;无悬停或粗指针设备始终显示,键盘与辅助技术始终可访问。
|
||||
@@ -366,7 +383,7 @@
|
||||
记忆功能实现前不展示占位内容,未来的记忆与历史执行上下文归入关联 Task 的任务中心详情。
|
||||
- 徽标可以提示未解决意见、等待审批、失败或连接状态,但不能成为唯一状态信号,也不能无条件抢占当前栏目。
|
||||
- 浏览器 Tab 的内容顶部固定使用一条紧凑工具栏,按“返回、刷新/停止加载、地址输入、
|
||||
前往、交互、关闭浏览器”排列。“刷新”在当前页面加载时原位切换为“停止加载”;
|
||||
前往、交互、关闭浏览器”排列。“前往”使用纯右箭头图标按钮,保留悬停提示和可访问名称。“刷新”在当前页面加载时原位切换为“停止加载”;
|
||||
“关闭浏览器”必须使用明确文字和与页面导航控件清楚区分的危险操作视觉,不能继续标为
|
||||
含义模糊的“停止浏览器”。地址输入显示浏览器权威提交 URL,但用户编辑期间保留本地草稿,
|
||||
不被画面或状态刷新覆盖;提交裸域名时自动添加 `http://`,提交、失焦后的同步规则不得让
|
||||
@@ -411,13 +428,13 @@
|
||||
绘制,避免被 Modal 或滚动容器遮挡。菜单和帮助挂在触发按钮所属 Modal 内,通知跟随当前活动
|
||||
Modal,无 Modal 时挂在 `body`;不能只提高 `z-index` 或解除背景的 `inert`。
|
||||
- 原生浏览器 `WebContentsView` 不受网页 `z-index` 控制。应用级 Modal 打开时统一释放
|
||||
浏览器 viewport;非模态对话框、菜单、局部确认或应用通知与浏览器区域相交时也释放。
|
||||
浏览器 viewport;非模态对话框、菜单、同行帮助 tooltip、局部确认或应用通知与浏览器区域相交时也释放。
|
||||
浮层关闭后只恢复当前活动实例的 viewport,不关闭、重建或刷新网页。接线与测试见
|
||||
[浏览器多实例技术设计](./docs/features/assistant-workbar/browser-tabs-technical-design.md#4-renderer-与-viewport)。
|
||||
- 遮罩必须 `inset: 0` 铺满整窗,并由 `styles.css` 中统一的遮罩选择器声明
|
||||
`-webkit-app-region: no-drag`,否则 `.brand` 与 `.topbar` 的原生拖动区域会截获指针,
|
||||
使遮罩上的控件无法悬停和点击。新增整窗遮罩时扩展该共享选择器,不要在各自规则里复制
|
||||
`no-drag`,也不要用 `inset: 38px 0 0` 之类的偏移绕开标题栏。
|
||||
`no-drag`,也不要用 `inset: 38px 0 0` 之类的偏移绕开标题栏。遮罩回归按 fixed/inset 声明发现,不能只按 `backdrop` 或 `modal` 类名后缀筛选;知识引用的 `-dialog` 同样适用。
|
||||
- 当前会话存在 Task 时,Task 上下文栏位于标题栏下方并承载任务摘要与详情;没有 Task 时
|
||||
整行隐藏。折叠状态保持为 `46px` 单行表面,与右侧工作栏标签栏等高,左右分隔线必须水平
|
||||
对齐。该栏不重复放置新建入口。
|
||||
@@ -475,6 +492,7 @@ Switch 用于在两个持久状态之间立即切换,例如启用能力、开
|
||||
- Checkbox 保留原生 Checkbox 语义和方形勾选视觉,不得添加 `role="switch"`。多项分配、列表选择、确认声明和“保存时清除密钥”等一次性选择均属于 Checkbox。
|
||||
- 不创建页面专属 Switch 样式。需要紧凑布局时仍复用同一轨道、滑块、焦点环、禁用状态和动效,只调整共享组件支持的布局变体。
|
||||
- Switch 支持 Tab 聚焦和 Space 切换,键盘焦点至少显示 `2px` 高对比焦点环。可见标签应描述被控制的能力,不能只显示“开 / 关”。
|
||||
- 共享开关行统一为标签在左、Switch 靠右,说明放在标签下方;不因 JSX 中输入控件与文字的先后顺序改变视觉位置。窄窗口允许文字换行,开关保持固定尺寸。Checkbox 和 Radio 保留各自的选择布局。
|
||||
- 异步切换期间禁用重复操作并保留原状态。失败时恢复或保留最后确认状态,通过应用通知或就地可恢复错误说明原因。
|
||||
- 涉及联网、上传、电脑控制或其他外部影响的 Switch,附近必须持续说明数据去向、权限范围或风险,不能只靠设置名称表达影响。
|
||||
- 自动化测试应按 `switch` 角色查询二元开关,按 `checkbox` 角色查询多选或确认项,防止视觉迁移后语义回退。
|
||||
@@ -500,6 +518,7 @@ Switch 用于在两个持久状态之间立即切换,例如启用能力、开
|
||||
- `footer` 使用共享操作区,按钮整体右对齐,次要取消在前、主要保存在后。放弃修改确认沿用同一操作区,继续编辑在前、危险操作在后。
|
||||
- header、滚动 body、footer 是 surface 的三个直接子区域。沿用共享 Grid 的 `auto minmax(0, 1fr) auto`,只有 body 滚动,短窗口仍可见标题、关闭和提交操作;窄窗口沿用共享外边距、内边距和主题令牌。
|
||||
- X、取消、Escape 和遮罩关闭共用业务关闭检查,不绕过未保存确认或提交锁定。确认中的 Escape 或 X 返回编辑;继续复用 `activateModalFocus`、`trapTabFocus`,保留背景隔离、初始焦点和关闭后的焦点恢复。保存失败保留草稿及可恢复错误。
|
||||
- 从已有 Modal 打开的子 Modal 同样复用 `--z-dialog` 和 `activateModalFocus`,以较后挂载的 body Portal 绘制在父层上方,并隔离父层;不能只手动聚焦或使用旧的页面层级常量。子层关闭后恢复父层的隔离状态与触发按钮焦点,Escape 不继续关闭父层。
|
||||
|
||||
## 7. 交互状态
|
||||
|
||||
@@ -516,6 +535,8 @@ Switch 用于在两个持久状态之间立即切换,例如启用能力、开
|
||||
|
||||
异步提交成功后更新内容并通过统一应用通知提供明确反馈。失败时保留用户输入和筛选上下文。
|
||||
|
||||
共享控件的状态规则须在容器组合中生效:菜单通用按钮样式不能覆盖危险按钮,普通图标悬停不能覆盖危险图标或作用于禁用按钮,页签悬停保留当前选中态。深色主题通过令牌提供控件颜色,避免用页面祖先下的通用输入规则替换控件边框。验证时读取最终 computed style;共享令牌对比度与源码规则存在性检查不能代替容器内、body Portal 和伪状态回归。修复与验证记录见[共享控件审查](docs/quality/shared-controls-review-2026-09-27.md)。
|
||||
|
||||
## 8. 范围与数据语义
|
||||
|
||||
### 8.1 页面范围
|
||||
@@ -654,6 +675,7 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
全屏预览遵循统一 Modal 的背景隔离、初始焦点、Tab 循环、Escape 关闭和焦点恢复规则,
|
||||
并沿用同一套清理与 Sandbox/CSP 边界。关闭平台功能后必须显示 HTML 源码,不能隐藏内容
|
||||
或保留旧预览。
|
||||
Tab 和 Shift+Tab 必须能进入及离开 iframe;焦点在预览内部时 Escape 仍关闭当前全屏层并返回入口。空 sandbox 与禁脚本 CSP 保持不变,跨文档键盘接线见[HTML 渲染技术设计](docs/features/conversation-html-rendering/technical-design.md#ui-与无障碍)。
|
||||
- Mermaid 大图支持缩放和拖动;图形超过画布时,四个边缘都必须能通过滚动到达,不能因居中而裁掉顶部或左侧。
|
||||
弹窗工具栏提供“导出 PNG”,保存完整图形,不受当前缩放和滚动位置影响;背景使用当前主题的画布底色。
|
||||
导出按原图四周留出 `16px`,以 2 倍分辨率绘制,任一边最多 `4096px`。导出期间禁用重复点击,失败在按钮旁提示重试。
|
||||
@@ -682,7 +704,7 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
- 已选择的工作模式在触发按钮中只显示 `Ask` 或 `Execute`;完整中文含义和说明保留在菜单选项、可访问名称及输入区下方的模式说明中。
|
||||
- 宽度大于 `700px` 时,主工具栏的添加内容、Runtime、模式、会话选项与发送保持同一行。窄输入区按容器宽度换行,保留发送及停止入口;选项浮层不得超出输入区宽度,不再常驻独立的 Runtime 专属功能行。
|
||||
- 输入框原生支持 `Ctrl+V`:文本直接进入草稿,系统截图和从文件管理器复制的一个或多个支持文件加入本次消息附件。文件粘贴与上传按钮共用读取、解析进度和数量限制;读取期间阻止重复导入及发送,错误就地关联输入框和附件按钮。具体类型、大小及批次失败规则见[聊天附件要求](./docs/features/document-processing/prd.md#321-聊天附件入口)。默认工具栏不提供独立“读取剪贴板”“截取当前屏幕”和“选择应用窗口”入口。
|
||||
- “Enter 发送 · Shift+Enter 换行 · Ctrl+V 粘贴文件、图片或文本”等输入操作提示放在空输入框内部,作为主占位文案的次级行;不得在输入框下方单独占用第二行。输入框下方只保留一行当前模式、安全边界或全局快捷键说明。
|
||||
- 空输入框使用三行原生占位文案:第一行为消息提示(生图模式保留图片描述提示),第二行为“Enter 发送 · Shift+Enter 换行 · Ctrl+V 粘贴”,第三行为“Ctrl+N 新建对话 · 实际已注册快捷键 快捷唤起”。新建与粘贴快捷键按平台显示,macOS 使用 Command;全局快捷键不可用时省略该项。输入文字后占位提示自然隐藏,输入框下方不再重复全局快捷键,保留模式、安全边界和其他元信息。
|
||||
- 输入操作提示不能替代表单的可访问名称,输入框始终保留持久的程序化标签。
|
||||
- 草稿与消息中的附件操作使用紧凑图标按钮,并提供悬停和键盘焦点提示;文件名、解析状态与操作行的布局遵循[附件操作规则](./docs/features/document-processing/ui-design.md#12-附件操作菜单)。
|
||||
- 空对话展示可执行的起始建议,发送失败保留输入并提供重试。
|
||||
@@ -714,14 +736,14 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
### 13.4 智能心跳
|
||||
|
||||
- 监督者入口使用 `supervisor` 壳层;智能心跳设置位于同一壳层内。
|
||||
- 顶层页签为“工作回顾 / 故事线图谱 / 自动监督 / 活动记录 / 设置”,使用一套共享 PageTabs,窄窗口单行横向滚动。页签下不重复同名标题,也不保留空标题容器;所选回顾使用“监督结果”标题,历史结果不得标为最新。
|
||||
- 工作回顾只展示统一监督结果、历史选择和紧凑的新回顾控件;结果保留自身范围、覆盖区间和生成时间,图谱读取同一结果 ID。自动监督集中展示当前计划、运行概览、指标、趋势、自动监督报告、记忆与行动建议及心跳运行审计;活动记录只展示统一执行活动、进度和详情。每页保留所属数据的一处刷新入口,范围与时间选择仅作用于新回顾请求。详细布局与阅读规则见[监督者 UI 设计](docs/features/conversation-supervision/ui-design.md#应用入口)。
|
||||
- 顶层页签为“工作回顾 / 故事线图谱 / 智能心跳 / 活动记录 / 设置”,使用一套共享 PageTabs,窄窗口单行横向滚动。页签下不重复同名标题,也不保留空标题容器;所选回顾使用“监督结果”标题,历史结果不得标为最新。
|
||||
- 工作回顾只展示统一监督结果、历史选择和紧凑的新回顾控件;结果保留自身范围、覆盖区间和生成时间,图谱读取同一结果 ID。智能心跳集中展示心跳计划、监督建议和只读的历史心跳报告;活动记录只展示统一执行活动、进度和详情。每页保留所属数据的一处刷新入口,范围与时间选择仅作用于新回顾请求。详细布局与阅读规则见[监督者 UI 设计](docs/features/conversation-supervision/ui-design.md#应用入口)。
|
||||
- 监督者保留统一页面壳层;工作回顾与活动子面板铺满壳层可用内容宽度,与页签左右对齐。工具栏、历史导航、状态和结果共享宽度,不再增加子面板宽度上限。工作回顾按纵向排列,空态独占工具栏下方整行并水平居中。活动筛选按内容紧邻排列,阶段使用编号圆点和连接线,次要统计收进详情;具体布局见[监督者 UI 设计](docs/features/conversation-supervision/ui-design.md)。
|
||||
- 范围明确区分 Global 与指定的一个或多个 Project;Global 与指定项目互斥,多项目选择使用
|
||||
Checkbox,不能依靠进入页面时的当前项目推断。
|
||||
- 状态卡片使用统一状态令牌,不只依赖颜色。
|
||||
- 活动记录先显示运行状态、时间、范围及实际阶段,恢复操作紧邻进度。原始错误默认折叠,展开后在有界面板内滚动并可选择复制;配置归入次要详情。任务层级只展示可查询的记录,缺失阶段明确标注,不能用剩余来源为零推断发布成功。具体阶段与分页规则见[监督者活动设计](docs/features/conversation-supervision/ui-design.md#活动)。
|
||||
- 自动监督的当前状态下显示计划列表,仅保留列表的一个创建按钮;无计划时使用列表的未配置说明,不叠加第二个空态或创建入口。创建与编辑复用同一份表单及共享 Modal 焦点、背景隔离和遮罩样式;未保存关闭须确认,保存失败保留草稿,编辑暂停计划不恢复运行。“执行记录”进入按该计划 ID 筛选的活动页,活动页不重复显示心跳审计列表。
|
||||
- 智能心跳的“心跳计划”卡片内直接排列状态说明、创建按钮和计划列表,不再嵌套第二层边框;仅保留一个创建按钮,说明文字按无计划、全部暂停、正常三种状态只显示一条。创建与编辑复用同一份表单及共享 Modal 焦点、背景隔离和遮罩样式;未保存关闭须确认,保存失败保留草稿,编辑暂停计划不恢复运行。“执行记录”进入按该计划 ID 筛选的活动页,活动页不重复显示心跳审计列表。
|
||||
- 设置只展示模型超时与并发、分页、分批和单次响应容量,不含计划、报告、审计或嵌套页签,不显示整页全局徽标或独立刷新行。
|
||||
- 监督者的设置、帮助、空态及错误文案不得向终端用户展示内部路线图、交付进度或设计与实现缺项;只说明当前行为、适用范围和可执行的下一步。不得因此夸大为提供商全局限流或完整语义识别;真实的运行失败、超时、暂停、来源失效及恢复操作必须保留。
|
||||
- 智能心跳菜单入口是完整配置的权威位置;任务中心和设置中心不得复制同一 CRUD 表单。
|
||||
@@ -759,7 +781,9 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
|
||||
### 13.7 魔法笔记
|
||||
|
||||
- 笔记总览与待办使用一个普通按钮切换,放在页头“新建笔记”按钮左边。按钮显示目标“切换到待办”或“切换到笔记”及对应图标,按内容宽度显示,不拉伸;窄窗口操作组可换行到标题下方,保留控件高度。
|
||||
会话联动已接入:右侧提供可关闭的单实例笔记 Tab,通过工作栏“+ → 笔记”打开;左下角和聊天页头不再提供重复的“快速笔记”入口。助手消息和会话标题菜单可打开文字采集预览;保存记录在面板和完整工作区显示独立来源条。草稿由 App 保留,关闭、替换及禁用前确认。具体交互由[魔法笔记会话联动界面设计](./docs/features/magic-notes/ui-design.md)维护。真实 Electron 验收已通过,全仓验证未全绿,见[验证进度](./docs/features/magic-notes/progress.md)。下列规则描述独立工作区。
|
||||
|
||||
- 未打开笔记详情时,笔记列表与待办使用页头普通按钮切换。按钮显示目标“切换到待办”或“切换到笔记”及对应图标,按内容宽度显示,不拉伸;笔记的新建入口位于左侧列表标题行,待办页的新建入口位于页头。窄窗口操作组可换行到标题下方,保留控件高度。
|
||||
- 切换按钮不使用页签语义,切换后焦点回到同一个按钮;内容 section 持续提供当前列表的 `aria-label`。切换沿用草稿保护入口,待办状态仍使用独立的 `SegmentedControl`。
|
||||
- 文字记录编辑器保留 Quill 原生列表快捷输入:输入 `-`、`*`、`1.`、`[ ]` 或 `[x]` 后按空格,分别转换为项目符号、编号或待办清单。快捷输入只生成现有 Delta 富文本,不引入 Markdown 源码模式、第二套文字记录持久化格式或第三方 Markdown 插件;新建文字记录的操作提示收进类型选择旁的 `InlineHelp`。
|
||||
- 新记录可选择“文字 / 画布”;已保存画布提供分页阅读和“展开编辑画布”。画布使用 PeopleLib 的 Fabric 分页批注与 Quill 跨页正文,支持纸张模板、增删页、笔迹、高亮、整对象橡皮、选择及移动缩放旋转、浮动文字、图片和 PDF 底版。画布有固定页面边界;已保存记录、待办来源和编辑态默认容纳完整当前页及工具栏,高度随当前页实际显示尺寸变化,纵向由外层笔记流滚动。多页仍属于一条记录,通过页码翻页;窄窗口工具栏换行,纸张仅在自身视口内横向滚动,不撑宽外层页面。
|
||||
@@ -770,26 +794,34 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
- 魔法笔记设置提供“发送画布页数”单选框,复用设置表单 `.field` 控件样式,范围 1~8,默认 1。标题同行的问号使用 `InlineHelp`,下拉框通过稳定的帮助 ID 关联展开的说明,交互遵循 6.14。说明包含当前页序前 N 页、不足时发送全部页、数量指单个画布页数而非记录数,以及完整保存与导出不受影响。修改后沿用设置保存反馈,下次分析生效。
|
||||
- 草稿、已保存画布记录及来源为画布的待办,按默认模型的 `supportsImageInput` 使用所选前 N 页图像与文字,或只发送同一范围文字并标注“仅文字分析(未使用画布图像)”。所选页只有视觉内容的记录/草稿遇到文字模型时提示切换支持图像输入的默认模型,不声称已理解笔迹或布局。待办分析同时保留任务标题、说明和所选来源画布页的上下文。
|
||||
- 画布文字评论在提取的 `plainText` 不变时保留;图像评论随画布内容或布局变化失效,在保存后自动评论模式下重新分析。草稿内容变化清除旧草稿分析,评论区显示实际使用的输入模式。存储和判定细节见[画布技术设计](./docs/features/magic-notes/technical-design.md#canvas-analysis-and-comments)。
|
||||
- 默认进入笔记总览,不自动打开第一篇笔记。笔记以自适应卡片网格平铺,卡片显示标题、最多两行内容预览、记录数和本地化更新时间。点击笔记进入详情,详情不保留内部左列表;“返回总览”恢复搜索、滚动位置和入口焦点。新建入口在笔记总览与待办页可见,创建成功后进入笔记详情。
|
||||
- 总览是全宽的“全部笔记”页,以自适应卡片网格(最小 `260px`)显示全部笔记,不显示右侧空白详情,也不自动打开第一篇;卡片显示标题、短日期、两行预览和记录数。打开笔记后切为左侧紧凑列表与右侧详情,页头右上角显示带文字的“返回总览”,点击回到全部笔记页并恢复搜索、滚动位置与卡片焦点;“切换到待办”只在总览显示。列表按紧凑两行行项显示:第一行为标题与短日期(今天显示时间,其余显示月/日,完整时间在工具提示中),第二行为单行预览;记录数只提供给读屏。行项无边框、透明底色,悬停为次级底色,选中为淡蓝底色加左侧 `3px` 强调标记;“更多”按钮悬停或聚焦时覆盖在日期位置。保留搜索、置顶菜单和当前选中状态。打开笔记只更新右侧详情;列表独立滚动,切换保留搜索和列表位置,并在工作区挂载期间记住各篇笔记的阅读位置。明确定位某条记录时优先跳到该记录。
|
||||
- 笔记列表默认展开、宽 `280px`,支持拖动分隔线在 `240–420px` 内调宽,方向键每次调整 `16px`,Home/End 跳到边界;桌面端详情页提供列表显隐开关,记住宽度和展开偏好。工作区宽度不超过 `900px` 时切换显示列表与详情,返回恢复列表位置和入口焦点,不覆盖桌面偏好。新建成功后打开新笔记;切换、新建和删除当前笔记都保护未保存的正文与标题。
|
||||
- 待办页是独立任务视图:搜索任务标题、说明或来源笔记,搜索框右侧同一工具栏放置“全部 / 未完成 / 已完成”筛选,显示匹配数与总数;任务按来源笔记分组。列表独立滚动,页头、搜索和筛选保持可见,窄屏工具栏空间不足时换行。直接勾选完成或恢复未完成,不自动选择任务;状态变化后按当前筛选更新列表。
|
||||
- 待办内容容器宽于 `700px` 时,任务列表稳定在左侧,右侧显示当前任务说明、来源记录和 AI 评论;未选择时右侧提示选择任务。点击任务只更新右侧,不改变列表宽度、行位置或滚动位置,再次点击取消选择。AI 不增加第三栏。容器不超过 `700px` 时,按需详情替换同一内容区域,并提供“返回待办列表”;列表保持挂载,返回恢复滚动和任务行焦点,不将列表与详情上下堆叠。任务按钮提供 `aria-expanded` 和 `aria-controls`。
|
||||
- 待办左右栏分割线支持拖拽,并记住列表宽度;键盘左右方向键每次调整 `16px`,Home/End 调整至边界。列表默认 `320px`、最小 `240px`,详情至少保留 `300px`;窄屏隐藏分割线,临时缩窄窗口不覆盖已保存宽度。每个来源笔记标题可独立收起或展开待办列表,保留标题与数量,通过 `aria-expanded` 和 `aria-controls` 表明状态;收起不清除右侧当前详情。
|
||||
- 待办 AI 评论保留方向选择、流式输出、重新分析和已有结果;来源加载失败通过应用通知提示,并提供就地重试。从待办打开原笔记后,“返回待办”恢复任务选择、搜索、筛选和列表滚动;宽屏焦点返回任务行,窄屏返回待办详情中的返回按钮。
|
||||
- 笔记详情主区按新到旧连续展示全部记录。打开笔记即在标题下、历史记录上显示空白输入区,保留文字/画布类型选择和保存操作,标题栏与索引均不提供“新增记录”按钮。新增保存成功后重建空白输入区,保留所选类型;自动分析结束也不转入旧记录编辑。旧记录通过显式编辑入口修改,保存使用同一 ID 和返回的修订号。点击索引或当前笔记内的 AI 来源只按 entry ID 滚动定位,不卸载编辑器、不清草稿、不询问离开。空白输入区离开不提示,返回总览、打开其他笔记或改为编辑另一条记录时仍保护未保存修改。
|
||||
- 详情页的一级标题显示当前笔记已保存的标题,不显示模块说明;全局范围、返回导航和索引开关保持可见。原标题输入框使用正文大小,保留原有编辑、失焦保存与键盘操作,不形成第二个醒目标题。新建文字记录的输入区初始约四行,随内容自然增高,保留原有调整大小与滚动方式;此高度不作用于旧记录编辑器或画布。笔记内部列表、记录流、AI 区域和文字编辑区在精细指针设备上使用细原生滚动条,轨道透明;强制颜色与粗指针设备保留系统默认。说明、摘要和输入提示使用 `--font-body` 与 `--text-secondary`,时间和短标签保留 `--font-caption`。
|
||||
- 左侧记录索引默认 `168px`,可拖动右边界在 `140–320px` 内调整栏宽,缩略图随列宽等比适配。开关独立位于详情标题左侧,提供 `aria-controls`、展开状态和动作提示;收起后完全移除索引列、分隔条、间隙、边框及轨道,不占宽度,隐藏内容不可聚焦。右侧 AI 评论独立显示、滚动和收起,不与索引共享页签。每条记录一个导航项:画布显示真实首页缩略图及总页数,文字显示摘要,两者均显示类型和时间。两侧分别记住桌面展开状态和宽度,共用原有布局偏好;宽布局分隔条共用样式及 `separator` 语义,方向键每次调整 `16px`,Home、End 跳到当前上下限。两侧宽度按可用空间协调限制,为主区保留至少 `300px`,窗口缩小时不覆盖保存的偏好。内容容器不超过 `800px` 时索引默认隐藏,由同一标题栏按钮开闭标题栏下方固定 `168px` 的抽屉,不显示调宽分隔条;标题栏自身保留控件高度,不保留轨道。选择记录或按 Escape 后关闭,Escape 将焦点返回开关。AI 移至底部,高度不超过可用布局的 40% 且最多 `280px`,不显示分隔条。
|
||||
AI 评论的唯一显隐入口位于页面右上角,使用紧凑面板图标按钮;展开时应用共享选中样式,图标随显示或隐藏动作切换,并提供对应的工具提示、可访问名称、`aria-expanded` 和 `aria-controls`。评论面板内部不再显示重复的“AI 评论”标题或隐藏按钮行,保留区域的可访问名称、评论方向选择及各记录的分析操作。
|
||||
- 打开笔记后页面一级标题仍为“魔法笔记”;笔记标题只在记录流顶部出现一次,使用 `22px` 的可编辑大标题,悬停显示下划线,聚焦显示强调色下划线,保留失焦保存、Enter 与 Escape。标题上方为吸顶的细工具栏,依次放置收起笔记列表、记录索引、条数与更新时间、AI 评论开关,均为带工具提示和可访问名称的图标按钮。记录流左右留白 `24px`(窄于 `600px` 时 `12px`),正文最大宽度 `880px` 并居中;吸顶工具栏不受此限制,始终铺满记录流宽度,AI 开关贴在右边缘,底部分隔线横贯整栏。
|
||||
- 桌面笔记详情的列表标题行、正文工具栏与 AI 评论方向标签行顶部对齐,首行统一使用 `40px` 控件高度并垂直居中;AI 区域不叠加面板和表单的顶部留白。
|
||||
- 文字记录的新建与编辑区域铺满卡片内沿,格式工具栏紧接头部,输入区域紧接工具栏;编辑器外层不再增加内边距或圆角。正文保留编辑器内部的文字留白,底部操作栏独立保留内边距与顶部分隔线;画布仍保留 `12px` 内容间距。
|
||||
- 新建记录输入区空闲时收成一行虚线提示框,隐藏类型切换、格式工具栏和保存栏;聚焦、已有草稿、选择画布或出现校验错误时展开,初始约四行并随内容增高。保存成功或切换笔记后恢复为一行。此规则不作用于旧记录编辑器。
|
||||
- 已保存记录的 AI 分析、编辑、删除为 `28px` 图标按钮,精细指针设备上悬停或键盘聚焦记录时才显示;删除悬停时使用危险色,确认条保持原样。粗指针设备始终显示。笔记内部列表、记录流、AI 区域和文字编辑区在精细指针设备上使用细原生滚动条,轨道透明;强制颜色与粗指针设备保留系统默认。说明、摘要和输入提示使用 `--font-body` 与 `--text-secondary`,时间和短标签保留 `--font-caption`。
|
||||
- 左侧记录索引默认收起,只在用户展开后记住展开状态;展开宽度默认 `168px`,可拖动右边界在 `140–320px` 内调整栏宽,缩略图随列宽等比适配。开关位于笔记工具栏,提供 `aria-controls`、展开状态和动作提示;收起后完全移除索引列、分隔条、间隙、边框及轨道,不占宽度,隐藏内容不可聚焦。右侧 AI 评论独立显示、滚动和收起,不与索引共享页签。每条记录一个导航项:画布显示真实首页缩略图及总页数,文字显示摘要,两者均显示类型和时间。两侧分别记住桌面展开状态和宽度,共用原有布局偏好;宽布局分隔条共用样式及 `separator` 语义,方向键每次调整 `16px`,Home、End 跳到当前上下限。两侧宽度按可用空间协调限制,为主区保留至少 `300px`,窗口缩小时不覆盖保存的偏好。内容容器不超过 `800px` 时索引默认隐藏,由同一标题栏按钮开闭标题栏下方固定 `168px` 的抽屉,不显示调宽分隔条;标题栏自身保留控件高度,不保留轨道。选择记录或按 Escape 后关闭,Escape 将焦点返回开关。AI 移至底部,高度不超过可用布局的 40% 且最多 `280px`,不显示分隔条。
|
||||
AI 评论默认不占列:当前笔记已有评论、正在分析或存在草稿评论时自动展开;用户对该笔记手动收起后保持收起,直到发起新的分析。无评论时手动展开即视为固定,固定状态跨笔记和重启保留,再次收起即取消固定。AI 评论的唯一显隐入口位于笔记工具栏右端,使用紧凑面板图标按钮;展开时应用共享选中样式,图标随显示或隐藏动作切换,并提供对应的工具提示、可访问名称、`aria-expanded` 和 `aria-controls`。评论面板内部不再显示重复的“AI 评论”标题或隐藏按钮行,保留区域的可访问名称、评论方向选择及各记录的分析操作。
|
||||
- 笔记详情的内部记录索引使用透明底色,与主内容表面连续,仅保留细调宽分隔线。每条索引记录保留 `1px` 的 `--border-subtle` 淡边框,不加卡片底色或阴影,悬停使用轻微次级底色;选中记录使用淡蓝背景和左侧 `3px` 蓝色内侧标记,悬停时保留选中态。缩略图保留纸张边界,键盘焦点环与强制颜色模式选中边框保持可见。窄屏抽屉使用不透明的主内容表面,避免下层正文透出;深色主题沿用语义令牌。
|
||||
- 笔记详情的标题、正文和记录流不再包裹额外的大外框,记录流容器不加内边距;缩略图列表顶部与正文区顶部对齐,左边界与索引栏左边界对齐,仅在右侧和底部保留 `8px` 留白,键盘焦点环向内绘制以避免滚动容器裁切。每条已保存记录使用一层 `1px` 的 `--border-subtle` 淡边框和 `--radius-control` 圆角,保留透明底色与记录间留白,不加阴影或头部下划线。记录编辑时保留输入区边框、页面安全边距及 AI 区域分隔。此规则仅作用于笔记详情,不改变卡片总览与待办独立布局。
|
||||
- 笔记详情的标题、正文和记录流不再包裹额外的大外框,记录流容器只保留上述左右留白;缩略图列表顶部与正文区顶部对齐,左边界与索引栏左边界对齐,仅在右侧和底部保留 `8px` 留白,键盘焦点环向内绘制以避免滚动容器裁切。每条已保存记录使用一层 `1px` 的 `--border-subtle` 淡边框和 `--radius-control` 圆角,保留透明底色与记录间留白,不加阴影或头部下划线。记录编辑时保留输入区边框、页面安全边距及 AI 区域分隔。此规则仅作用于笔记详情,笔记列表与待办保持独立布局。
|
||||
- 画布新建、编辑和只读态统一保留 `12px` 内容间距;详情中已保存画布去掉预览外框和工具栏底色、下划线,保留灰色画布衬底与白色纸张,编辑态保留编辑器边框。记录头部操作按内容宽度排列,空间不足时自然换行。文字新建的保存区与编辑器属于同一卡片,空白编辑区使用最小高度,不随容器百分比高度拉长。文字工具栏图标、菜单和原生滚动条须跟随主题。
|
||||
- 整篇笔记的置顶、取消置顶和删除放在卡片的“更多”菜单,标题编辑区不重复提供入口。按钮在悬停、键盘聚焦或菜单展开时显示,触屏设备常显;菜单沿用会话列表样式,通过 Portal 避免滚动区域裁切,支持方向键、Home、End 和 Escape。删除在菜单内二次确认并说明笔记标题及全部记录;打开菜单不进入详情。
|
||||
- 标签使用中性胶囊样式(`--surface-subtle` 底色、`--border-subtle` 边框、`--font-caption`),不使用颜色区分。总览搜索框下方是标签筛选行:“全部”加各标签和对应篇数,均为 `aria-pressed` 切换按钮;可以多选,多选时只显示同时带有全部所选标签的笔记。选中时使用 `--accent-subtle` 底色和强调色边框。卡片最多显示 3 个标签,其余合并为“+N”。打开笔记后,左侧列表不显示筛选行,只显示“已筛选:A · B”提示条和清除按钮。
|
||||
- 笔记标题下方是标签编辑行:已有标签后带 × 移除按钮,末尾是虚线“+ 标签”按钮。点击后展开组合框,按输入内容过滤已有标签,也可以新建。方向键切换选项,Enter、逗号或中文逗号确认,Escape 关闭并把焦点还给“+ 标签”。达到 10 个时,“+ 标签”禁用并说明上限。
|
||||
- 列表标题行右侧只放“管理标签”,不再放 `+` 新建按钮。“新建笔记”统一放在页头右上角,是主按钮,始终位于“切换到待办 / 切换到笔记”或“返回总览”的右侧。打开笔记时点击,桌面端展开左侧列表并显示标题输入,窄屏先回到列表。“管理标签”在总览显示图标加文字,打开笔记后只显示图标。点击后打开共享 `custom-task-dialog` 对话框,按使用篇数列出标签,每行提供重命名和删除图标按钮。重命名在行内编辑;新名称与已有标签相同时,提示保存后会合并。删除在行内二次确认,并说明涉及的篇数。Escape 依次退出行内编辑或确认,最后关闭对话框。
|
||||
- 整篇笔记的置顶、取消置顶和删除放在列表行的“更多”菜单,打开详情时仍可操作,标题编辑区不重复提供入口。按钮在悬停、键盘聚焦或菜单展开时显示,触屏设备常显;菜单沿用会话列表样式,通过 Portal 避免滚动区域裁切,支持方向键、Home、End 和 Escape。删除在菜单内二次确认并说明笔记标题及全部记录;删除当前笔记还须处理未保存草稿,删除其他笔记保留当前内容与草稿。打开菜单不切换笔记。
|
||||
- 左侧“魔法笔记”入口可显示未完成待办数量。数量为 0 时隐藏徽标,超过 99 时显示 `99+`,可访问名称仍说明精确数量;勾选、取消勾选以及 Agent / MCP 对笔记清单的写入都必须刷新数量。
|
||||
- 未完成待办徽标的高度不得超过主导航图标;数量从 0 变为可见或再次隐藏时,主导航项行高和相邻菜单位置必须保持不变。
|
||||
- 在待办面板勾选或取消勾选后,当前缓存中的源笔记正文必须立即同步对应清单状态,不得依赖离开工作区后重新加载。
|
||||
- Agent / MCP 或其他入口成功写入笔记后,已打开的工作台自动更新笔记列表、当前详情、待办及来源记录,不增加刷新按钮。保留仍存在的笔记与待办选择、搜索和筛选,以及未保存的标题、输入区和记录编辑草稿;普通后台刷新不重建编辑器。
|
||||
- 外部删除当前笔记时,无草稿则返回总览;有草稿则保留编辑区并提示先复制草稿。外部删除正在编辑的记录时,同样保留该编辑器并明确提示记录已删除;保存失败不得清空草稿。
|
||||
- 当前记录草稿非空或标题尚未保存时,返回总览必须先就地确认;编辑另一条记录等会丢弃正文草稿的操作沿用同一保护。继续编辑时保留草稿并恢复编辑焦点,只有明确选择放弃后才切换。
|
||||
- 保存成功后,以该修订的编辑器初始化并完成 flush 后的内容作为修改比较基线;没有新编辑时返回不再提示。编辑器归一化不算用户修改,后续输入、画布变更和保存失败仍保留离开保护;同修订的后台刷新不替换已建立的基线。
|
||||
- 文字和画布记录保存修改成功后退出编辑状态,显示已保存正文;后续自动评论成功或失败均不重新打开编辑器。再次修改须点击编辑入口,以该修订的编辑器初始化内容作为修改比较基线。编辑器归一化不算用户修改,后续输入、画布变更和保存失败仍保留离开保护;同修订的后台刷新不替换已建立的基线。
|
||||
- 创建、保存、更新、删除和 AI 评论完成等短期结果进入应用级通知,不在编辑区或列表上方堆放页内通知。
|
||||
- 标题或正文校验、删除确认、同步进度和可就地恢复的错误仍靠近对应编辑器或操作呈现。
|
||||
|
||||
@@ -798,21 +830,25 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
- 设置中心以整窗遮罩上的大 Modal 打开,保留底层工作区、会话草稿和助手工作栏,不切换一级页面。固定标题区和右上角关闭按钮,左侧分类与右侧内容各自滚动。关闭后返回原工作区并恢复入口焦点。
|
||||
- 新建项目与项目设置弹窗固定标题、关闭按钮和底部操作区,仅表单内容滚动;滚动条不进入标题区,关闭按钮保留至少 40 × 40px 的点击区域。
|
||||
- 项目弹窗通过 Portal 挂载到 `document.body`,避免侧栏内的弹窗与主窗口标题栏拖动区域重叠时,Electron 截获关闭按钮的鼠标输入。
|
||||
- Modal 最大尺寸为 `1200px × 900px`,常规外边距为 `24px`;窗口宽度不超过 `1020px` 或高度不超过 `720px` 时接近全屏,保留 `16px` 外边距。左侧分类宽度依次为 `220px`、`180px`(宽度不超过 `1020px`)、`120px`(不超过 `720px`);极窄窗口隐藏分类辅助说明,仍保留左右布局。内容区在可用空间内伸缩,最大宽度为 `960px`。
|
||||
- Modal 最大尺寸为 `1200px × 900px`,常规外边距为 `24px`;窗口宽度不超过 `1020px` 或高度不超过 `720px` 时接近全屏,保留 `16px` 外边距。左侧分类宽度依次为 `220px`、`180px`(宽度不超过 `1020px`)、`120px`(不超过 `720px`);窄窗口仍保留左右布局,长分类名称可换行。内容区在可用空间内伸缩,最大宽度为 `960px`。
|
||||
- 设置 Modal 通过 Portal 挂载到 `document.body`,复用共享背景隔离与焦点恢复机制。打开后聚焦关闭按钮,Tab 在弹窗内循环;Escape 先交由嵌套弹窗处理,设置自身的 Escape 与关闭按钮共用未保存确认,确认出现后再按 Escape 返回编辑。点击遮罩不关闭;保存、测试和清理数据期间禁止关闭。每次打开重新挂载设置,模型和消息通道等直达入口使用本次指定分类,普通入口默认打开 Agent Runtime。
|
||||
- 设置中心不显示全局操作页脚,避免重复关闭入口和没有功能意义的整宽分隔线。
|
||||
- 所有分类使用共享的 `SettingsCategoryHeader` 呈现分类标题、说明、错误与操作,不得在内容卡片内复制分类标题或创建页面专属操作栏。左侧分类名称与说明来自同一份分类定义,新增分类时不得分别维护导航和内容标题。
|
||||
- 所有分类使用共享的 `SettingsCategoryHeader` 呈现分类标题、说明、错误与操作,不得在内容卡片内复制分类标题或创建页面专属操作栏。左侧分类名称与右侧标题来自同一份分类定义,新增分类时不得分别维护导航和内容标题。
|
||||
- 左侧按“常规 / 模型与执行 / 功能与扩展 / 系统”分组,顺序与键盘导航一致。分类按钮最小高度 `40px`,只显示名称;分类说明集中在右侧页头,外层标题不再重复功能简介。组名使用辅助字号,普通项使用正文和中等字重,选中项使用强调底色与加粗文字。
|
||||
- 设置区块使用共享圆角、间距和表面令牌;标题为 `--font-section-title`,持久说明至少为 `--font-caption`。嵌套设置区块以顶部细分隔线和留白组织,不叠加卡片背景与四周边框。“能力与工具”的上级页签使用默认 `PageTabs` 外观,与 MCP 内部的分段页签区分。
|
||||
- 当前分类存在“保存”或“测试”等未提交配置操作时,统一放在分类页头右侧;主保存操作在最右侧,测试等次操作排列在其左侧。
|
||||
- 自动生效、仅执行即时命令或自行管理编辑流程的分类不显示全局保存操作。窄窗口下操作区可以换行,但保存入口必须保持清晰可见。
|
||||
- 智能心跳的单条配置不在设置中心重复管理。设置中心如需呈现平台级说明,只提供
|
||||
“打开智能心跳”导航,不复制创建、暂停、恢复或删除表单。
|
||||
- 保存或测试成功统一进入应用通知视口,并按全局规则自动消失,不在分类页头或内容卡片中保留持久成功文案。加载、保存和测试错误显示在分类页头下方,并保留可处理的上下文。
|
||||
- “模型连接”的认证字段按“认证方式 → API Key → 凭据状态”排列;只有选择 API Key 时显示输入框。已保存的 API Key 属于该连接,修改模型服务地址或临时选择“无需认证”不得自动清除,也不得要求重新输入;仅由明确的“清除凭据”或“删除连接”操作移除。
|
||||
- 设置中的连接列表与详情共用 `.model-connection-manager`,按容器可用宽度响应:不超过 `640px` 时上下排列,列表内部滚动高度最多 `180px`;更宽时恢复左右排列。LLM、向量连接和角色编辑复用此规则,不以整窗宽度代替表单宽度。接口协议的中英文当前值须完整可读。回归范围见[窄容器布局修复记录](docs/quality/responsive-controls-review-2026-09-27.md)。
|
||||
- “保存并测试模型”必须在保存后发送一次有界的真实模型请求。文本连接校验本次随机测试文本,图像连接校验实际返回的内联图片;仅收到成功 HTTP 状态、模型列表或健康检查响应不算测试成功。界面持续说明该操作可能产生少量服务商用量费用,成功反馈明确写为“真实生成测试通过”。
|
||||
- 所有显式保存的设置草稿都参与离开保护:关闭、切换分类、主侧栏或工作区导航及托盘导航不得静默丢弃,统一通过设置中心的就地确认提供继续编辑与明确放弃入口,保存失败后保留输入。“平台功能 / 通用设置”承载全局快捷唤起的共享 Switch、可访问 accelerator 录制输入、恢复默认、保存及注册、停用或冲突状态,不新增分类或页签;注册或持久化失败时保留上一组可用快捷键和当前草稿,保存或停用成功后同步更新输入区的快捷键提示。
|
||||
- “平台功能 / 通用设置”同时提供默认开启的“在会话中渲染 HTML”持久 Switch。说明必须
|
||||
明确该能力只生成禁用脚本、联网、表单提交和窗口操作的静态预览;保存成功后当前会话立即
|
||||
更新,保存失败时保留最后确认状态。
|
||||
- 通用设置按快捷唤起、会话与通知、工作目录与下载分组,复用现有卡片。“桌面通知”为默认开启的持久 Switch,保存后立即控制窗口未聚焦时的任务完成、失败和取消系统通知,关闭不影响应用内通知。旧配置缺少该字段时默认开启,明确关闭后重启仍保持关闭;保存失败保留最后确认状态并显示应用内错误通知。
|
||||
- “平台功能”使用共享 `PageTabs` 区分“通用设置”和“远程项目”,默认进入通用设置。“远程项目”页将持久 Switch 与用户数据目录中的 Linux x64、Linux arm64、macOS arm64 Agent 包清单分成独立卡片;每张卡片与下载进度按平台和架构区分,不能把两个 arm64 目标合并。清单延迟到首次打开该页签时由 Main 完整校验,并读取所选更新源的小型签名目录,显示本地版本、在线最新兼容版本以及“有更新”“已是最新”“未下载”“校验失败”。打开页签或刷新不得自动下载 `.gbagent`;只有用户点击带目标版本的下载/更新按钮后才传输包。签名目录不可用时继续显示并允许导出已验证本地包,提供就地重试错误;清单不混入 Host 已安装状态、缓存路径或敏感签名细节。下载和导入期间保留上下文进度,成功进入全局通知视口。全局模型下载源使用 `fieldset`、持久 `legend` 与整行可点击的原生 Radio 卡片;选中状态同时依靠 Radio、边框和背景表达,读取失败时不得用默认值伪装为已保存选择。
|
||||
- “关于与更新”的更新源位于“启动时检查新版本”开关下方,常规宽度下将标签、同行帮助和原生单选下拉框放在同一行,用途说明收进 `InlineHelp`,并复用设置表单的统一控件样式;关闭启动检查后仍可选择更新源,手动检查继续使用当前选择。选项显示“GitHub(默认)”和中性的“镜像节点”。该选择同时控制手动检查、启动时检查、下载页和 Agent 包在线下载,不显示底层服务商名称。
|
||||
- “关于与更新”在版本信息之后提供应用内反馈卡片。反馈对话框使用原生字段、明确隐私说明和一张可选截图;另提供默认关闭的原生 Checkbox,让用户主动附加最近桌面诊断摘要。Checkbox 附近必须持续说明摘要只含时间、组件、阶段、稳定错误码、错误类型和固定短消息,不含对话、Prompt、凭据、文件内容、路径、Provider 原始响应或远端 Agent 日志。勾选时为诊断摘要预留描述字符预算,超长草稿必须保留并显示字段错误,不得静默截断。失败时保留草稿、勾选状态和请求编号并提供就地重试,成功时在对话框内保留可复制编号而不重复发送全局通知;对话框遵循统一 Modal 的背景隔离、初始焦点、Tab 循环、Escape、焦点恢复和窄窗口布局。
|
||||
@@ -896,7 +932,7 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证
|
||||
- [ ] 将输入快捷键与附件提示置于空输入框内部,输入区下方保持单行说明。
|
||||
- [ ] 最近对话迁移到 `standard`,统一搜索、范围、时间和删除行为。
|
||||
- [ ] 知识库迁移到 `master-detail`,清除内联浅色样式并补齐窄窗口单面板流程。
|
||||
- [x] 监督者使用 `supervisor`,工作回顾读取统一监督结果;自动监督包含 Global / 多 Project 计划、概览、自动监督报告、建议与审计;活动记录显示统一执行,设置只保留算法参数。
|
||||
- [x] 监督者使用 `supervisor`,工作回顾读取统一监督结果;智能心跳包含 Global / 多 Project 心跳计划、监督建议与历史心跳报告;活动记录显示统一执行,设置只保留算法参数。
|
||||
- [x] 在现有工作栏中完善任务中心,统一范围、状态、最近进展和筛选,不新建平行任务平台。
|
||||
- [ ] 活动记录迁移到 `dashboard`,统一导航、筛选和表格行为。
|
||||
- [ ] 设置中心使用共享分类定义与 `SettingsCategoryHeader`,将保存与测试操作统一放到分类页头右侧,并把成功反馈接入应用通知。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"agentVersion": "0.13.4",
|
||||
"agentVersion": "0.15.1",
|
||||
"protocol": {
|
||||
"major": 2,
|
||||
"minor": 0
|
||||
|
||||
@@ -159,7 +159,10 @@ function portableRequiredPaths(directory) {
|
||||
}
|
||||
|
||||
function assertPortableOutput(directory) {
|
||||
const requiredPaths = portableRequiredPaths(directory)
|
||||
const requiredPaths = [
|
||||
...portableRequiredPaths(directory),
|
||||
join(directory, 'resources', 'runtimes', 'dsh', 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js')
|
||||
]
|
||||
const missing = requiredPaths.filter(
|
||||
(filePath) => !statSync(filePath, { throwIfNoEntry: false })?.isFile()
|
||||
)
|
||||
|
||||
@@ -184,7 +184,7 @@ async function run() {
|
||||
model: 'qwen-plus',
|
||||
supportsImageInput: false,
|
||||
requestHeaders: {},
|
||||
harnessVersion: '0.1.2-rc.1',
|
||||
harnessVersion: '0.1.7-rc.2',
|
||||
credentialRefs: ['GOODBUDDY_HARNESS_MODEL_API_KEY'],
|
||||
skillPackages: [],
|
||||
extensionPackages: [],
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
const { cp, mkdir, readFile, rm } = require('node:fs/promises');
|
||||
const { existsSync } = require('node:fs');
|
||||
const { dirname, join, relative } = require('node:path');
|
||||
const tar = require('tar');
|
||||
|
||||
// Preserve npm's installed layout (including nested versions) and every package
|
||||
// asset. The official loader discovers plugins and browser assets at runtime.
|
||||
async function prepareNativeDshResources(projectDir, platform, architecture, downloadPackage, lockedIntegrity) {
|
||||
const target = join(projectDir, '.runtime-resources', `dsh-${architecture}`);
|
||||
await rm(target, { recursive: true, force: true });
|
||||
await mkdir(target, { recursive: true });
|
||||
const visited = new Set();
|
||||
function locate(name, from) {
|
||||
for (let directory = from; ; directory = dirname(directory)) {
|
||||
const candidate = join(directory, 'node_modules', name);
|
||||
if (existsSync(join(candidate, 'package.json'))) return candidate;
|
||||
if (dirname(directory) === directory) return undefined;
|
||||
}
|
||||
}
|
||||
async function copyPackage(directory) {
|
||||
if (visited.has(directory)) return;
|
||||
visited.add(directory);
|
||||
const manifest = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8'));
|
||||
await cp(directory, join(target, relative(projectDir, directory)), { recursive: true, verbatimSymlinks: true });
|
||||
const optional = manifest.optionalDependencies ?? {};
|
||||
for (const name of Object.keys({ ...manifest.dependencies, ...manifest.peerDependencies, ...optional })) {
|
||||
const dependency = locate(name, directory);
|
||||
if (dependency) await copyPackage(dependency);
|
||||
else if (!(name in optional) && !manifest.peerDependenciesMeta?.[name]?.optional) {
|
||||
throw new Error(`DS Web bundle is missing ${name} required by ${manifest.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
await copyPackage(join(projectDir, 'node_modules', '@deepseek-ai', 'dsh'));
|
||||
// Cross-architecture packaging cannot rely on the build host's npm optional
|
||||
// selection. Fetch the exact target Sharp packages from the existing lock.
|
||||
const sharp = JSON.parse(await readFile(join(projectDir, 'node_modules', 'sharp', 'package.json'), 'utf8'));
|
||||
const lock = JSON.parse(await readFile(join(projectDir, 'package-lock.json'), 'utf8'));
|
||||
const nativePackages = [`@img/sharp-${platform}-${architecture}`];
|
||||
if (platform !== 'win32') nativePackages.push(`@img/sharp-libvips-${platform}-${architecture}`);
|
||||
for (const name of nativePackages) {
|
||||
const version = sharp.optionalDependencies[name];
|
||||
if (!version) throw new Error(`DS Web Sharp does not support ${platform}/${architecture}`);
|
||||
const destination = join(target, 'node_modules', 'sharp', 'node_modules', name);
|
||||
if (existsSync(join(destination, 'package.json'))) continue;
|
||||
const locked = lock.packages[`node_modules/sharp/node_modules/${name}`] ?? lock.packages[`node_modules/${name}`];
|
||||
if (locked?.version !== version || !locked.integrity) throw new Error(`Missing locked ${name}@${version}`);
|
||||
const integrity = locked.integrity;
|
||||
const archive = await downloadPackage(projectDir, name, version, integrity);
|
||||
await mkdir(destination, { recursive: true });
|
||||
await tar.x({ file: archive, cwd: destination, strip: 1 });
|
||||
}
|
||||
const koffi = JSON.parse(await readFile(join(projectDir, 'node_modules', 'koffi', 'package.json'), 'utf8'));
|
||||
const koffiName = `@koromix/koffi-${platform}-${architecture}`;
|
||||
const koffiDestination = join(target, 'node_modules', koffiName);
|
||||
if (!existsSync(join(koffiDestination, 'package.json'))) {
|
||||
const integrity = await lockedIntegrity(projectDir, koffiName, koffi.version);
|
||||
const archive = await downloadPackage(projectDir, koffiName, koffi.version, integrity);
|
||||
await mkdir(koffiDestination, { recursive: true });
|
||||
await tar.x({ file: archive, cwd: koffiDestination, strip: 1 });
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = { prepareNativeDshResources };
|
||||
@@ -88,7 +88,7 @@ async function main() {
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: '@deepseek-ai/dsh-llm',
|
||||
version: '0.1.2-rc.1',
|
||||
version: '0.1.7-rc.2',
|
||||
private: true,
|
||||
type: 'module'
|
||||
},
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
const { dirname, join, resolve } = require('node:path')
|
||||
const { copyFileSync, mkdtempSync, mkdirSync, rmSync } = require('node:fs')
|
||||
const { tmpdir } = require('node:os')
|
||||
const { pathToFileURL } = require('node:url')
|
||||
const assert = require('node:assert/strict')
|
||||
|
||||
if (!process.versions.electron || process.env.ELECTRON_RUN_AS_NODE === '1') {
|
||||
const { spawnSync } = require('node:child_process')
|
||||
const root = mkdtempSync(join(tmpdir(), 'goodbuddy-obsidian-ui-'))
|
||||
const env = { ...process.env, GOODBUDDY_OBSIDIAN_ACCEPTANCE_ROOT: root }
|
||||
if (process.argv.includes('--live') || process.argv.includes('--chat')) {
|
||||
env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_LIVE = process.argv.includes('--live') ? '1' : '0'
|
||||
env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_CHAT = process.argv.includes('--chat') ? '1' : '0'
|
||||
env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_CONTINUE_ONLY = process.argv.includes('--continue-only') ? '1' : '0'
|
||||
require('esbuild').buildSync({ entryPoints: ['tests/obsidian-runtime-acceptance.ts'],
|
||||
outfile: join(root, 'runtime.cjs'), bundle: true, external: ['electron', 'ssh2', 'node-pty', 'koffi'], platform: 'node', format: 'cjs',
|
||||
banner: { js: `require = require('node:module').createRequire(${JSON.stringify(resolve('package.json'))});` } })
|
||||
}
|
||||
delete env.ELECTRON_RUN_AS_NODE
|
||||
try {
|
||||
const result = spawnSync(require('electron'), [__filename], {
|
||||
env, stdio: 'inherit', timeout: 300_000
|
||||
})
|
||||
if (result.error) throw result.error
|
||||
process.exitCode = result.status ?? 1
|
||||
} finally {
|
||||
rmSync(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 })
|
||||
}
|
||||
} else {
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const root = process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_ROOT
|
||||
assert(root)
|
||||
const profile = join(root, 'profile')
|
||||
mkdirSync(profile)
|
||||
if (process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_LIVE === '1' || process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_CHAT === '1') {
|
||||
const settings = process.env.GOODBUDDY_ACCEPTANCE_SETTINGS ?? join(app.getPath('appData'), 'goodbuddy', 'runtime-settings.json')
|
||||
copyFileSync(join(dirname(settings), 'Local State'), join(profile, 'Local State'))
|
||||
}
|
||||
mkdirSync(join(root, 'Temporary Vault'))
|
||||
app.setPath('userData', profile)
|
||||
app.setAppPath(resolve('.'))
|
||||
const timer = setTimeout(() => { console.error('Acceptance timed out'); app.exit(1) }, 280_000)
|
||||
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms))
|
||||
;(async () => {
|
||||
const chat = process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_CHAT === '1'
|
||||
? await require(join(root, 'runtime.cjs')).prepareChat(root, profile) : undefined
|
||||
await import(pathToFileURL(resolve('out/main/index.js')).href)
|
||||
let window
|
||||
for (let attempt = 0; attempt < 120; attempt++) {
|
||||
window = BrowserWindow.getAllWindows().find(item => item.webContents.getURL().includes('index.html'))
|
||||
if (window && await window.webContents.executeJavaScript('Boolean(document.querySelector("button"))')) break
|
||||
await wait(250)
|
||||
}
|
||||
assert(window, 'Production main must open its BrowserWindow')
|
||||
assert.equal(app.getPath('userData'), profile)
|
||||
const preferences = window.webContents.getLastWebPreferences()
|
||||
assert.equal(preferences.contextIsolation, true)
|
||||
assert.equal(preferences.nodeIntegration, false)
|
||||
const js = code => window.webContents.executeJavaScript(code).catch(error => { throw new Error(`${code}: ${error.message}`) })
|
||||
const click = async expression => {
|
||||
window.focus()
|
||||
for (let i=0;i<100;i++) { if (await js(`Boolean(${expression})`)) break; await wait(100) }
|
||||
const point = await js(`(() => { const element = ${expression}; if (!element) throw new Error('Missing control'); element.scrollIntoView({block:'center'}); const r=element.getBoundingClientRect(); return {x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)} })()`)
|
||||
window.webContents.sendInputEvent({ type: 'mouseDown', button: 'left', clickCount: 1, ...point })
|
||||
window.webContents.sendInputEvent({ type: 'mouseUp', button: 'left', clickCount: 1, ...point })
|
||||
await wait(500)
|
||||
}
|
||||
if (chat) {
|
||||
await js(`(async()=>{const p=(await window.goodbuddy.projects.list())[0];await window.goodbuddy.projects.update(p.id,{name:p.name,description:p.description,rootPath:${JSON.stringify(join(root,'chat-workspace'))},defaultWorkMode:'execute',runtimeSelection:{provider:'opencode'}})})()`)
|
||||
window.webContents.reload()
|
||||
await wait(1000)
|
||||
}
|
||||
await click(`document.querySelector('button[aria-label="\u8bbe\u7f6e"]')`)
|
||||
await click(`Array.from(document.querySelectorAll('button')).find(b=>b.innerText.startsWith('\u80fd\u529b\u4e0e\u5de5\u5177'))`)
|
||||
await click(`Array.from(document.querySelectorAll('[role="tab"]')).find(b=>b.innerText==='MCP' && b.getClientRects().length)`)
|
||||
const card = `Array.from(document.querySelectorAll('.capability-card')).find(c=>c.querySelector('strong')?.textContent==='Obsidian')`
|
||||
const poll = async (expression, attempts=100) => {
|
||||
for (let i=0;i<attempts;i++) { if (await js(expression)) return; await wait(200) }
|
||||
console.error('VISIBLE_TABS',await js(`JSON.stringify(Array.from(document.querySelectorAll('[role="tab"]')).map(e=>({text:e.innerText,selected:e.getAttribute('aria-selected')})))`))
|
||||
throw new Error(`Timed out: ${expression}`)
|
||||
}
|
||||
await poll(`Boolean(${card})`)
|
||||
assert.equal(await js(`(${card}).querySelector('[role="switch"]').checked`), false)
|
||||
await click(`(${card}).querySelector('select')`)
|
||||
window.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'End' })
|
||||
window.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Return' })
|
||||
window.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'Return' })
|
||||
await poll(`Boolean((${card}).querySelector('input:not([type="checkbox"])'))`)
|
||||
const input = `(${card}).querySelector('input:not([type="checkbox"])')`
|
||||
const vault = join(root, 'Temporary Vault')
|
||||
await click(input)
|
||||
await window.webContents.insertText(vault)
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[1]`)
|
||||
await poll(`Boolean((${card}).querySelector('[role="status"]'))`)
|
||||
assert.match(await js(`(${card}).querySelector('[role="status"]').textContent`), /18/)
|
||||
assert.equal((await js('window.goodbuddy.capabilities.getSnapshot()')).obsidian.vaultPath, '')
|
||||
assert.equal(await js(`(${card}).querySelector('[role="switch"]').checked`), false)
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[2]`)
|
||||
await poll(`!(${card}).querySelector('.primary-button').disabled`)
|
||||
assert.equal((await js('window.goodbuddy.capabilities.getSnapshot()')).obsidian.vaultPath, vault)
|
||||
await click(input)
|
||||
window.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'A', modifiers: ['control'] })
|
||||
window.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'A', modifiers: ['control'] })
|
||||
await window.webContents.insertText(join(root, 'missing-vault'))
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[1]`)
|
||||
await poll(`Boolean((${card}).querySelector('[role="alert"]'))`)
|
||||
assert.equal(await js(`(${input}).value`), join(root, 'missing-vault'))
|
||||
assert.equal((await js('window.goodbuddy.capabilities.getSnapshot()')).obsidian.vaultPath, vault)
|
||||
console.log('PASS: native UI draft test (18 tools), no implicit save/enable, save through IPC, missing-folder error preserves draft')
|
||||
if (process.platform === 'win32') {
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[0]`)
|
||||
const user32 = require('koffi').load('user32.dll')
|
||||
const getWindow = user32.func('uintptr_t __stdcall GetWindow(uintptr_t hwnd, uint32_t command)')
|
||||
const getPid = user32.func('uint32_t __stdcall GetWindowThreadProcessId(uintptr_t hwnd, _Out_ uint32_t *pid)')
|
||||
const postMessage = user32.func('bool __stdcall PostMessageW(uintptr_t hwnd, uint32_t message, uintptr_t wparam, intptr_t lparam)')
|
||||
const handle = Number(window.getNativeWindowHandle().readBigUInt64LE())
|
||||
const popup = getWindow(handle, 6)
|
||||
assert(popup && Number(popup) !== handle, 'Native folder dialog must open')
|
||||
const pid = [0]
|
||||
getPid(popup, pid)
|
||||
assert.equal(pid[0], process.pid, 'Only close this acceptance process dialog')
|
||||
assert(postMessage(popup, 0x10, 0, 0))
|
||||
await poll(`!(${card}).querySelector('.primary-button').disabled`)
|
||||
assert.equal(await js(`(${input}).value`), join(root, 'missing-vault'))
|
||||
console.log('PASS: real Windows folder dialog opened and cancelled without changing draft')
|
||||
}
|
||||
window.setMinimumSize(640, 480)
|
||||
window.setSize(760, 720)
|
||||
await wait(500)
|
||||
const geometry = await js(`(() => {const c=${card};const r=c.getBoundingClientRect();return {width:innerWidth,left:r.left,right:r.right,scroll:c.scrollWidth,client:c.clientWidth}})()`)
|
||||
assert(geometry.scroll <= geometry.client + 1 && geometry.right <= geometry.width && geometry.left >= 0, JSON.stringify(geometry))
|
||||
console.log('PASS: narrow card has no horizontal overflow', JSON.stringify(geometry))
|
||||
await click(input)
|
||||
window.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'A', modifiers: ['control'] })
|
||||
window.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'A', modifiers: ['control'] })
|
||||
await window.webContents.insertText(vault)
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[1]`)
|
||||
await poll(`Boolean((${card}).querySelector('[role="status"]'))`)
|
||||
await js(`(${card}).querySelector('[role="switch"]').focus()`)
|
||||
window.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Space' })
|
||||
window.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'Space' })
|
||||
await poll(`(${card}).querySelector('[role="switch"]').checked && !(${card}).querySelector('[role="switch"]').disabled`)
|
||||
await click(`(${card}).querySelector('button[aria-expanded]')`)
|
||||
await poll(`(${card}).querySelectorAll('.mcp-server-tools li').length === 19`)
|
||||
console.log('PASS: keyboard switch enables Obsidian; expanded production UI lists 19 tools')
|
||||
for (const theme of ['light', 'dark']) {
|
||||
await js(`document.documentElement.dataset.theme=${JSON.stringify(theme)}`)
|
||||
const bounds = await js(`(()=>{const c=${card};const r=c.getBoundingClientRect();return {right:r.right,width:innerWidth,scroll:c.scrollWidth,client:c.clientWidth,background:getComputedStyle(c).backgroundColor}})()`)
|
||||
assert(bounds.right <= bounds.width && bounds.scroll <= bounds.client + 1)
|
||||
console.log(`PASS: ${theme} narrow Obsidian bounds`, JSON.stringify(bounds))
|
||||
}
|
||||
if (process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_LIVE === '1') {
|
||||
await require(join(root, 'runtime.cjs')).run(root, await js('window.goodbuddy.capabilities.getSnapshot()'))
|
||||
}
|
||||
if (chat) {
|
||||
await click(`document.querySelector('.settings-panel__header button')`)
|
||||
window.setSize(1280, 850)
|
||||
try {
|
||||
const providers = process.env.GOODBUDDY_OBSIDIAN_ACCEPTANCE_CONTINUE_ONLY === '1' ? ['Continue'] : ['OpenCode', 'Continue']
|
||||
for (const provider of providers) {
|
||||
if (provider === 'Continue') {
|
||||
await poll(`!document.querySelector('button[title^="Runtime \u548c\u6a21\u578b"]').disabled`)
|
||||
await js(`document.querySelector('button[title^="Runtime \u548c\u6a21\u578b"]').click()`)
|
||||
await click(`Array.from(document.querySelectorAll('.runtime-picker__menu strong')).find(b=>b.innerText==='Continue Runtime')?.nextElementSibling`)
|
||||
}
|
||||
await poll(`!document.querySelector('button[title^="Runtime \u548c\u6a21\u578b"]').disabled`)
|
||||
const mode = `document.querySelector('button[aria-label^="\u5de5\u4f5c\u6a21\u5f0f"]')`
|
||||
if (!(await js(`(${mode}).innerText.includes('Execute')`))) {
|
||||
await click(mode)
|
||||
await click(`Array.from(document.querySelectorAll('[role="menuitemradio"]')).find(b=>b.innerText.startsWith('Execute'))`)
|
||||
}
|
||||
const marker = `CHAT_${provider}_${require('node:crypto').randomUUID()}`
|
||||
const before = chat.observations.length
|
||||
await click(`document.querySelector('textarea')`)
|
||||
await window.webContents.insertText(`Use only Obsidian tools. Write ${provider}-chat.md containing ${marker} using obsidian_write_note, then read it using obsidian_read_note. Reply with the content read. Do not use other tools.`)
|
||||
await click(`document.querySelector('button[aria-label="\u53d1\u9001"]')`)
|
||||
await poll(`Array.from(document.querySelectorAll('.message--assistant')).some(e=>e.innerText.includes(${JSON.stringify(marker)}))`,450)
|
||||
await poll(`!document.querySelector('button[title^="Runtime \u548c\u6a21\u578b"]').disabled`,450)
|
||||
assert((require('node:fs').readFileSync(join(vault,`${provider}-chat.md`),'utf8')).includes(marker))
|
||||
console.log(JSON.stringify({ provider, fullChatUi: 'passed', realModelHttpRequests: chat.observations.length-before }))
|
||||
}
|
||||
} finally {
|
||||
console.log(JSON.stringify({ chatModelHttpRequests: chat.observations.length }))
|
||||
await chat.close()
|
||||
}
|
||||
}
|
||||
await wait(1000)
|
||||
clearTimeout(timer)
|
||||
app.exit(0)
|
||||
})().catch(error => { console.error(error); clearTimeout(timer); app.exit(1) })
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
const assert = require('node:assert/strict')
|
||||
const { spawn } = require('node:child_process')
|
||||
const { mkdtemp, mkdir, readFile, readdir, writeFile, rm, stat } = require('node:fs/promises')
|
||||
const { tmpdir } = require('node:os')
|
||||
const { join, resolve } = require('node:path')
|
||||
|
||||
async function main() {
|
||||
const executable = resolve(process.argv[2])
|
||||
await stat(executable)
|
||||
const root = await mkdtemp(join(tmpdir(), 'goodbuddy-obsidian-packaged-'))
|
||||
const profile = join(root, 'profile')
|
||||
const vault = join(root, 'Packaged Vault')
|
||||
await mkdir(profile)
|
||||
await mkdir(vault)
|
||||
const audit = join(root, 'node-audit.jsonl')
|
||||
const guard = join(root, 'offline.cjs')
|
||||
await writeFile(guard, `
|
||||
const fs = require('node:fs');
|
||||
const net = require('node:net');
|
||||
const original = net.Socket.prototype.connect;
|
||||
net.Socket.prototype.connect = function(...args) {
|
||||
const options = net._normalizeArgs(args)[0];
|
||||
const host = options.host || 'localhost';
|
||||
if (!options.path && !['localhost','127.0.0.1','::1'].includes(host)) throw new Error('Offline acceptance blocked network');
|
||||
return original.apply(this,args);
|
||||
};
|
||||
globalThis.fetch = async () => { throw new Error('Offline acceptance blocked fetch'); };
|
||||
require('node:module').syncBuiltinESMExports();
|
||||
fs.appendFileSync(${JSON.stringify(audit)}, JSON.stringify({entry:process.argv[1],exe:process.execPath,electron:process.versions.electron})+'\\n');
|
||||
`)
|
||||
const env = { ...process.env, NODE_OPTIONS: `--require ${JSON.stringify(guard)}`,
|
||||
PATH: join(process.env.SystemRoot, 'System32') }
|
||||
delete env.Path
|
||||
delete env.ELECTRON_RUN_AS_NODE
|
||||
const child = spawn(executable, [`--user-data-dir=${profile}`, '--remote-debugging-port=0', '--inspect=0',
|
||||
'--proxy-server=http://127.0.0.1:9', '--proxy-bypass-list=<-loopback>'], { env, stdio: ['ignore', 'ignore', 'pipe'] })
|
||||
let diagnostic = ''
|
||||
child.stderr.on('data', chunk => { diagnostic += chunk.toString() })
|
||||
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||
let socket
|
||||
let mainSocket
|
||||
try {
|
||||
let port
|
||||
for (let i=0;i<100;i++) {
|
||||
try { port = (await readFile(join(profile, 'DevToolsActivePort'), 'utf8')).split('\n')[0]; break } catch { await wait(200) }
|
||||
}
|
||||
assert(port, 'Packaged app must expose debugging only in the isolated profile')
|
||||
const mainEndpoint = diagnostic.match(/ws:\/\/127\.0\.0\.1:\d+\/[-a-f0-9]+/u)?.[0]
|
||||
assert(mainEndpoint, 'The isolated Main inspector must be available')
|
||||
mainSocket = new WebSocket(mainEndpoint)
|
||||
await new Promise((resolve, reject) => { mainSocket.onopen=resolve;mainSocket.onerror=reject })
|
||||
// Packaged Electron strips NODE_OPTIONS at startup. Restore it only for this
|
||||
// disposable Main so its real MCPVault child receives the offline guard.
|
||||
await new Promise((resolve,reject) => {
|
||||
const timer=setTimeout(()=>reject(new Error('Main inspector timed out')),10_000)
|
||||
mainSocket.onmessage=message=>{const value=JSON.parse(message.data);if(value.id===1){clearTimeout(timer);if(value.error || value.result?.exceptionDetails)reject(new Error('Unable to set child network guard'));else resolve()}}
|
||||
mainSocket.send(JSON.stringify({id:1,method:'Runtime.evaluate',params:{expression:`process.env.NODE_OPTIONS=${JSON.stringify(env.NODE_OPTIONS)}`}}))
|
||||
})
|
||||
mainSocket.close()
|
||||
let target
|
||||
for (let i=0;i<100;i++) {
|
||||
target = (await (await fetch(`http://127.0.0.1:${port}/json/list`)).json()).find(item => item.type === 'page' && item.url.includes('index.html'))
|
||||
if (target) break
|
||||
await wait(200)
|
||||
}
|
||||
assert(target, 'Packaged production renderer must load')
|
||||
socket = new WebSocket(target.webSocketDebuggerUrl)
|
||||
await new Promise((resolve, reject) => { socket.onopen = resolve; socket.onerror = reject })
|
||||
let id = 0
|
||||
const pending = new Map()
|
||||
socket.onmessage = message => { const value = JSON.parse(message.data); if (pending.has(value.id)) { const {resolve,reject}=pending.get(value.id); pending.delete(value.id); if (value.error) reject(new Error(value.error.message)); else resolve(value.result) } }
|
||||
const send = (method, params={}) => new Promise((resolve,reject) => {
|
||||
const key=++id
|
||||
const timer=setTimeout(()=>{pending.delete(key);reject(new Error(`CDP timed out: ${method}`))},10_000)
|
||||
pending.set(key,{
|
||||
resolve: value=>{clearTimeout(timer);resolve(value)},
|
||||
reject: error=>{clearTimeout(timer);reject(error)}
|
||||
})
|
||||
socket.send(JSON.stringify({id:key,method,params}))
|
||||
})
|
||||
const js = async expression => { const result=await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true});assert(!result.exceptionDetails,JSON.stringify(result.exceptionDetails));return result.result.value }
|
||||
const poll = async expression => { for(let i=0;i<100;i++){ if(await js(expression))return;await wait(200) } throw new Error(`Timeout: ${expression}`) }
|
||||
const click = async expression => {
|
||||
await js(`(()=>{const e=${expression};if(!e)throw new Error('Missing control');e.scrollIntoView({block:'center'});e.focus();e.click()})()`)
|
||||
await wait(500)
|
||||
}
|
||||
await poll('Boolean(window.goodbuddy && document.querySelector("button"))')
|
||||
await stat(join(profile,'assistant.sqlite'))
|
||||
assert.equal(await js('typeof require'), 'undefined')
|
||||
await click(`document.querySelector('button[aria-label="\u8bbe\u7f6e"]')`)
|
||||
await poll(`Array.from(document.querySelectorAll('button')).some(b=>b.innerText.startsWith('\u80fd\u529b\u4e0e\u5de5\u5177'))`)
|
||||
await click(`Array.from(document.querySelectorAll('button')).find(b=>b.innerText.startsWith('\u80fd\u529b\u4e0e\u5de5\u5177'))`)
|
||||
await click(`Array.from(document.querySelectorAll('[role="tab"]')).find(b=>b.innerText==='MCP' && b.getClientRects().length)`)
|
||||
const card=`Array.from(document.querySelectorAll('.capability-card')).find(c=>c.querySelector('strong')?.textContent==='Obsidian')`
|
||||
await poll(`Boolean(${card})`)
|
||||
await js(`{const e=(${card}).querySelector('select');e.value='folder';e.dispatchEvent(new Event('change',{bubbles:true}));}`)
|
||||
await poll(`Boolean((${card}).querySelector('input:not([type="checkbox"])'))`)
|
||||
await click(`(${card}).querySelector('input:not([type="checkbox"])')`)
|
||||
await send('Input.insertText',{text:vault})
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[1]`)
|
||||
await poll(`Boolean((${card}).querySelector('[role="status"]'))`)
|
||||
assert.match(await js(`(${card}).querySelector('[role="status"]').textContent`),/18/)
|
||||
await click(`(${card}).querySelectorAll('.capability-card__actions button')[2]`)
|
||||
await poll(`!(${card}).querySelector('.primary-button').disabled`)
|
||||
assert.equal((await js('window.goodbuddy.capabilities.getSnapshot()')).obsidian.vaultPath,vault)
|
||||
const bin=join(profile,'tool-environment','bin')
|
||||
const shims=(await readdir(bin,{recursive:true})).filter(name=>name.endsWith('node.cmd'))
|
||||
assert(shims.length>0)
|
||||
assert((await readFile(join(bin,shims[0]),'utf8')).includes(executable))
|
||||
console.log('PASS: packaged app.asar UI -> real IPC -> packaged MCPVault (18 tools), save, managed packaged Electron shim, PATH=System32, Chromium dead proxy')
|
||||
const records=(await readFile(audit,'utf8')).trim().split('\n').map(line=>JSON.parse(line))
|
||||
assert(records.some(item=>item.entry?.includes('app.asar.unpacked') && item.entry.endsWith('server.js') && item.exe===executable && item.electron))
|
||||
console.log('PASS: packaged MCPVault child loaded Node network guards; audited packaged executable and unpacked server entry')
|
||||
console.log('Boundary: MCPVault Node API guards + Chromium proxy; no OS firewall, physical disconnection, or installer execution')
|
||||
} finally {
|
||||
socket?.close()
|
||||
mainSocket?.close()
|
||||
if (child.exitCode === null) {
|
||||
const killer=spawn('taskkill',['/PID',String(child.pid),'/T','/F'],{stdio:'ignore'})
|
||||
await new Promise(resolve=>killer.once('exit',resolve))
|
||||
}
|
||||
await rm(root,{recursive:true,force:true,maxRetries:10,retryDelay:200})
|
||||
}
|
||||
}
|
||||
main().catch(error=>{console.error(error);process.exitCode=1})
|
||||
@@ -18,6 +18,7 @@ const {
|
||||
prepareBundledOpenCodeConfig,
|
||||
} = require("./opencode-config.cjs");
|
||||
const { npmInvocation } = require("./npm-invocation.cjs");
|
||||
const { prepareNativeDshResources } = require("./native-dsh-resources.cjs");
|
||||
|
||||
const architectureNames = {
|
||||
1: "x64",
|
||||
@@ -184,6 +185,7 @@ module.exports = async function prepareBundledRuntimes(context) {
|
||||
architecture === "x64" ? `${architecture}-baseline` : architecture;
|
||||
const packageName = `opencode-${packagePlatform}-${suffix}`;
|
||||
const projectDir = context.packager.projectDir;
|
||||
await prepareNativeDshResources(projectDir, platform, architecture, downloadPackage, lockedIntegrity);
|
||||
await prepareBundledOpenCodeConfig(projectDir);
|
||||
const projectPackage = JSON.parse(
|
||||
await readFile(join(projectDir, "package.json"), "utf8"),
|
||||
|
||||
@@ -225,6 +225,10 @@
|
||||
|
||||
### 7.1 布局
|
||||
|
||||
通用设置按快捷唤起、会话与通知、工作目录与下载分成三张卡片。模型下载源位于
|
||||
“工作目录与下载”卡片内的工作目录输入之后;以下仅展示下载源控件,完整分组及通知
|
||||
开关行为见 [UI 设计规范](../../UI-DESIGN.md#138-设置中心)。
|
||||
|
||||
```text
|
||||
平台功能
|
||||
管理通用平台行为与可选工作区能力
|
||||
@@ -244,7 +248,7 @@
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
页面只保留一个视觉上最突出的任务。模型下载源保存属于即时设置,不增加与来源选项竞争的
|
||||
模型下载源保存属于即时设置,不增加与来源选项竞争的
|
||||
大型“保存全部”按钮。
|
||||
|
||||
### 7.2 控件
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
# Desktop 0.15.1 与 Agent 0.15.0 发布准备及恢复
|
||||
|
||||
日期:2026-09-27 至 2026-09-28。原 Desktop 0.15.0 标签构建失败,
|
||||
用户已选择 Desktop 0.15.1 与 Agent 0.15.0 恢复发布;验证通过不代表已发布。
|
||||
|
||||
## 范围与批准
|
||||
|
||||
- 用户要求 Desktop 与 GoodBuddy Agent 同步升级至 `0.15.0`,明确不构建 LoongArch。
|
||||
- 源码基线:`0f8bf405db7ca21a85cc70009ad083eb837e1e03`。
|
||||
- Desktop 差异基线为已发布的 `v0.13.16`,Agent 为 `agent-v0.13.4`。
|
||||
- `v0.15.0` 已创建并推送,保持不可变;恢复使用 `v0.15.1`,
|
||||
`agent-v0.15.0` 尚未创建或推送。
|
||||
- 用户已批准两份完整双语说明,正式正文仅维护在
|
||||
[Desktop 发布资源](../../resources/release-notes.json) 的 `0.15.1` 条目与
|
||||
[Agent 发布资源](../../resources/agent-release-notes/0.15.0.md)。
|
||||
已逐条核对写入文本与批准草案一致,本记录不再复制正文。
|
||||
- `FEATURES.md` 与 `FEATURES.zh-CN.md` 已核对本轮能力、限制和候选版本。
|
||||
- 用户要求两张未跟踪宣传截图保留原位、不提交,打标签前另行处理;
|
||||
不移动、删除、暂存或更改忽略规则。
|
||||
- 2026-09-28 用户更新授权:当前工作区的宣传文档与素材可以一起提交、推送,
|
||||
后续候选由代理自行审核确认,不再逐次等待用户批准,继续完成双产品正式发布。
|
||||
三张新增候选图已读取检查,保留原始草稿属性,不冒充正式发布截图或对外媒体发文。
|
||||
发布说明正文保持不变,`releasedAt` 更新为实际准备发布日期 2026-09-28。
|
||||
|
||||
## 本地验证
|
||||
|
||||
- `npm run typecheck`:通过。
|
||||
- `npm run lint`:通过。
|
||||
- `npm run release:notes:verify`:通过。
|
||||
- 发布说明相关三个文件定向测试:16 项通过。
|
||||
- 首轮 `npm test`:5,313 通过、79 跳过、4 失败,耗时 697.61 秒。
|
||||
三项失败来自当时尚未批准写入的 0.15.0 Desktop/Agent 发布说明;
|
||||
另一项为 `magic-notes-layout.electron.test.ts` 的布尔断言。
|
||||
该布局用例单独复验 1 项通过,未修改源码或放宽断言。
|
||||
单独通过不替代全量结果。
|
||||
- 正式说明写入后的最终 `npm test`:**5,317 通过、79 跳过、0 失败**,
|
||||
453 个测试文件通过、11 个跳过,耗时 645.49 秒。随后再次执行完整
|
||||
`npm run typecheck` 与 `npm run lint`,均通过。
|
||||
- 最终验证期间出现并行宣传文档编辑及新增 `storygraph.png`,均不属于本次
|
||||
发布准备改动,不暂存或覆盖。打标签前仍须处理工作区洁净条件。
|
||||
- 修改文档的相对文件链接、版本一致性和 `git diff --check` 通过。
|
||||
- 不运行本地生产构建、打包或安装包启动。准确候选提交须经用户批准,
|
||||
然后双远端推送、主分支 CI、生产构建、原生发布与公开核验分别进行。
|
||||
|
||||
## Agent 当前源码实机验证
|
||||
|
||||
共享 Linux x64 Host 的 LAN/VPN SSH 端口均可达,实际通过 LAN 与既有固定
|
||||
Host Key、加密凭据连接。重新捆绑当前源码的 Agent CLI、daemon、model bridge
|
||||
与 Desktop 适配器,仅上传独立 `/root/tmp/gb-lifecycle-*` 测试目录,复用已安装且
|
||||
版本锁未变的 Node/OpenCode/Continue,不替换原安装,不构建正式包。
|
||||
|
||||
最终 OpenCode、Continue 各通过一次 Ask 和一次 Execute,无工具请求,
|
||||
验证回答、后续历史、空闲 Runtime 回收及测试停止后所属进程为 0。
|
||||
模型请求时读取所属进程的固定遥测字段,确认 `DO_NOT_TRACK=1`、
|
||||
`OTEL_SDK_DISABLED=true` 及三个 exporter 均为 `none`,不输出整个环境。
|
||||
这些结果补齐 `eb53c82` 的 Agent/model bridge 真实链路验证,
|
||||
但不证明后台没有其他网络流量,也不替代三目标正式包验收。
|
||||
|
||||
首轮 Continue 探针沿用了 OpenCode 原生历史持久化假设,未像 Desktop 一样传入
|
||||
`request.history`,第二轮历史断言失败;当前 Continue 冷启动源码明确要求传入
|
||||
保存历史。修正测试输入及会话 ID 断言后通过,未修改产品实现。
|
||||
|
||||
有完整计数的实机运行共 **8 次**真实模型 HTTP 请求:首次 OpenCode 2 次、
|
||||
首次 Continue 2 次、最终 Continue 2 次、最终 OpenCode 2 次。
|
||||
此前一次直接启动 Electron 的探针未捕获子进程输出,不能确认是否实际发出请求,
|
||||
该次上限 2 次,不纳入通过证据;因此不能把 8 次写成本轮精确总数,总量为 8–10 次。
|
||||
后续均使用等待退出并记录脱敏输出的启动器;本轮探针 Electron 进程已退出。
|
||||
本地诊断证据在临时 `opencode/release-015-host/`,不提交脚本、日志或凭据。
|
||||
|
||||
## 首次候选 CI 与测试修正
|
||||
|
||||
用户批准的首次候选 `5a6ba6c14f5c58f3da5e9afe281b18e0cbdb1ae8`
|
||||
已推送至 `origin/main` 和 `github/main`,未创建两个发布标签。
|
||||
|
||||
- [Agent CI 36329271991](https://github.com/mesalogo/goodbuddy/actions/runs/36329271991)
|
||||
源码验证及 Linux x64、Linux arm64、Darwin arm64 原生构建全部通过。
|
||||
- [Desktop CI 36329271967](https://github.com/mesalogo/goodbuddy/actions/runs/36329271967)
|
||||
为 5,342 通过、51 跳过、3 失败。两个 App 长历史场景超过默认 5 秒单用例时限;
|
||||
会话采集 Electron 场景等待 Escape 返回笔记列表超时。生产构建未运行。
|
||||
- 测试修正仅让原生键盘辅助函数显示窗口、获取焦点并等待 `document.hasFocus()`,
|
||||
然后发送真实输入;两个长历史场景采用仓库既有的 15 秒单用例时限。
|
||||
不修改产品实现、不跳过 Linux、不关闭沙箱、不删除或放宽数据和键盘断言。
|
||||
- Windows 聚焦复验三个失败场景通过,其中真实 Electron 覆盖完整 502 条历史、
|
||||
214px 窄栏键盘操作、浅深主题确认按钮、真实 IPC/SQLite 和重开保留。
|
||||
修正后首次全量复验被中断,不计为通过;随后完整重跑为 **5,317 通过、
|
||||
79 跳过、0 失败**,453 个文件通过、11 个跳过,耗时 646.48 秒。
|
||||
类型检查、lint 和发布说明校验均通过,新候选 Linux CI 仍需独立通过。
|
||||
- 本次只改测试和验证文档,不改变 Agent、远程 Runtime 或模型桥;
|
||||
沿用上方当前源码 Host 验证,不新增真实模型请求。
|
||||
- 新提交必须重新取得准确 SHA 批准,原发布说明正文保持不变。
|
||||
|
||||
## Linux 实机复现与最终同步修正
|
||||
|
||||
2026-09-28:第二次批准候选 `12594961fe1e814e89f55de1fbfe245310505115`
|
||||
的 [Desktop CI 36331853137](https://github.com/mesalogo/goodbuddy/actions/runs/36331853137)
|
||||
为 5,343 通过、51 跳过、2 失败。两个 App 长历史场景已通过;
|
||||
Escape 返回列表仍失败,活动历史迁移这次超过默认 5 秒时限,生产构建仍未执行。
|
||||
|
||||
按用户要求直接在共享 Linux x64 Host 测试准确候选源码。使用独立磁盘测试目录、
|
||||
锁定 Node 24.19.0 和 `npm ci`,补齐 Xvfb 与匹配的 X server 系统依赖;
|
||||
没有创建新账号,使用既有非 root 账号运行测试,保留 Electron 沙箱及其标准 helper 权限。
|
||||
不替换既有 Agent,不修改其安装或工作区,不执行生产构建或打包。
|
||||
|
||||
原测试在 Host 上稳定复现:缩窄窗口会按产品既有行为收起工作栏,隐藏面板仍有非零宽度。
|
||||
诊断显示 Escape 实际发给 `aria-expanded=false` 的工作栏开关,而不是笔记输入框。
|
||||
因此仅获取窗口焦点不够;测试改为等待窄视口及响应式渲染完成,按真实按钮打开工作栏,
|
||||
确认展开状态和目标输入框焦点后再发送键盘输入。临时诊断代码已移除。
|
||||
|
||||
迁移测试在 Host 上以原默认时限通过,保留 10,000 条记录、完整迁移、WAL 字节比、
|
||||
扫描次数与无变化写入断言;仅为这一个大数据场景采用已有的 15 秒单用例时限,
|
||||
不改数据库实现或全局时限。
|
||||
|
||||
- 最终 Linux Host 完整 `npm test`:**5,345 通过、51 跳过、0 失败**,
|
||||
449 个文件通过、15 个跳过,耗时 751.09 秒。
|
||||
- Windows 聚焦回归:3 项通过,包含真实 Electron 和迁移。
|
||||
- Windows 完整类型检查、lint、发布说明校验:全部通过。
|
||||
- Linux Electron 实测覆盖 502 条历史、218px 窄栏、Escape/Tab/Enter、
|
||||
浅深主题确认按钮、真实 IPC/SQLite 与重开保留;Windows 对应窄栏为约 214px。
|
||||
- 本阶段不新增真实模型请求,不改变产品代码或双语说明。
|
||||
新候选仍须重新批准 SHA 并通过自己的主分支 CI/生产构建,两个标签仍未创建。
|
||||
|
||||
## 后续 CI 焦点前提与确定性取消验证
|
||||
|
||||
`b8b6007` 的 [CI 36335076841](https://github.com/mesalogo/goodbuddy/actions/runs/36335076841)
|
||||
两次执行均为 5,344 通过、51 跳过、1 失败,失败点改为 `new title focus`,
|
||||
生产构建没有运行。该次失败未在 Host 的 10 次带诊断复验中重现,其中 5 次限制单 CPU;
|
||||
移除临时诊断后再测也通过。这些独立结果不替代 CI。
|
||||
|
||||
测试原先直到键盘阶段才显示窗口,前面的自动聚焦检查仍在隐藏窗口执行。
|
||||
现让测试窗口从开始即显示并确认焦点,保留标题自动聚焦原断言;
|
||||
超时增加实际焦点、标题禁用/可见/隔离状态和保存状态,避免只报告阶段名称。
|
||||
可见窗口版本在 Host 连续五次聚焦复验通过。
|
||||
|
||||
随后 Host 全量出现一个独立的 Continue 取消测试竞争:
|
||||
`setTimeout(0)` 没有保证取消发生在子进程启动前,空 mock 已被调用。
|
||||
用例改在既有启动环境回调处精确取消,仍验证回调执行、子进程未启动和临时配置删除,
|
||||
不更改 Continue 产品实现或取消机制。
|
||||
|
||||
- 最终 Host 完整测试:**5,345 通过、51 跳过、0 失败**,449 个文件通过、
|
||||
15 个跳过,耗时 743.34 秒。
|
||||
- Windows 可见窗口 Electron 回归及确定性取消回归通过。
|
||||
- 完整类型检查、lint 通过;双语说明正文不变,日期调整后另行验证发布资源。
|
||||
- 上述均为测试或验证文档调整,不新增真实模型调用,不改变 Agent 发布输入。
|
||||
正式发布仍要求当前候选自己的 CI/生产构建通过。
|
||||
|
||||
## 完整分支快照重新核对
|
||||
|
||||
`d9e1e42` 的 [Desktop CI 36340682594](https://github.com/mesalogo/goodbuddy/actions/runs/36340682594)
|
||||
已通过原生会话采集焦点测试,但为 5,367 通过、51 跳过、4 失败。
|
||||
核对祖先后确认准备期间另有四个并行提交进入分支:
|
||||
`ee1bf8a` 输入区控件样式、`8e60736` 流式会话稳定排序、
|
||||
`f35198d` 桌面通知开关、`d47f967` 监督结果继续讨论。
|
||||
它们已随用户授权的当前分支推送;前述 Host 的 5,345 项通过使用较早源码快照,
|
||||
不能作为包含这四项的新候选验证结果。
|
||||
|
||||
本轮已重新核对四个提交的实现和文档,补充两份功能矩阵与双语发布说明:
|
||||
通知开关默认开启且不影响应用内提示;流式更新不改变排序;
|
||||
监督结果可直接编辑问题并继续讨论,界面不再提供知识实体写回控件。
|
||||
Agent 产品源码及 Runtime 锁未因这四项改变,Agent
|
||||
[CI 36340682607](https://github.com/mesalogo/goodbuddy/actions/runs/36340682607)
|
||||
源码校验和三个原生构建全部通过。
|
||||
|
||||
补齐通知默认值的契约 fixture;Obsidian 多次真实子进程调用使用单用例 15 秒时限,
|
||||
避免前项超时后的在途调用污染下一项取消断言;笔记来源用例按面板查询控件,
|
||||
并等前次来源操作释放禁用状态后再发起下一次。
|
||||
这些修正不改变产品实现。Windows 聚焦回归 19 项通过,类型、lint 和说明校验通过。
|
||||
从 Git tree `1758ff58a6ff33fcf7ddaa3d35dd2fcc57cd1265` 导出完整快照,
|
||||
覆盖 Host 测试源码,而非只同步早期快照中的少数文件。
|
||||
该完整快照 `npm test` 为 **5,371 通过、51 跳过、0 失败**,
|
||||
451 个文件通过、15 个跳过,耗时 751.42 秒,包含全部四个并行提交。
|
||||
最终提交前再次核对源码、测试、依赖和发布资源与该已验证 tree 一致,
|
||||
仅追加本段验证结果;完整候选仍需自己的主分支 CI 与生产构建通过。
|
||||
|
||||
### 完整候选后的焦点同步修正
|
||||
|
||||
`5cdffee` 的 Agent [CI 36343184917](https://github.com/mesalogo/goodbuddy/actions/runs/36343184917)
|
||||
三个原生构建和源码校验通过;桌面
|
||||
[CI 36343184916](https://github.com/mesalogo/goodbuddy/actions/runs/36343184916)
|
||||
为 5,369 通过、51 跳过、2 失败,生产构建未执行。
|
||||
会话采集的焦点等待可被 `body` 后代文字误满足,菜单随后被真正的消息聚焦关闭;
|
||||
另一个原生 Runtime 控件用例在启动完成前打开失焦关闭的菜单。
|
||||
本轮收紧消息焦点的元素断言,并等待项目能力请求及启动渲染后再打开 Runtime 选项。
|
||||
不重试菜单、不跳过场景、不改产品实现。
|
||||
|
||||
完整冻结 tree `2ddc0da69b6bcb42d8272c44dd11e3e6904d0438` 在 Host 全量
|
||||
**5,371 通过、51 跳过、0 失败**,耗时 748.21 秒。
|
||||
Windows 原生 Runtime 聚焦用例、类型检查和 lint 通过。
|
||||
提交仅追加本段记录;仍须等待修正候选的主分支 CI 和生产构建。
|
||||
|
||||
`706726b` 的桌面 [CI 36345672365](https://github.com/mesalogo/goodbuddy/actions/runs/36345672365)
|
||||
已通过上述采集与 Runtime 用例,但另一个外部知识库测试失败:
|
||||
5,370 通过、51 跳过、1 失败,生产构建未执行。
|
||||
该 fixture 只在查询新库 ID 时返回包含已创建库的快照,普通轮询会返回创建前数据;
|
||||
同时错误地要求最后一次请求必须属于新库,忽略后台轮询。
|
||||
改为模拟已持久化的库列表,等待新库请求发生,保留原库与新增库选中、被排除库未选中的
|
||||
全部界面断言,不修改产品代码。Windows 完整 App 300 项通过,类型、lint 和说明校验通过。
|
||||
冻结 tree `42a92450ad7d9ebc50167c7946bff53cff2889e6` 的 Linux 全量为
|
||||
**5,371 通过、51 跳过、0 失败**,耗时 748.67 秒。
|
||||
|
||||
## Desktop 0.15.1 恢复
|
||||
|
||||
`65a21390debe0dd04871417a363a9d87a29339e6` 的主分支
|
||||
[CI 36347785076](https://github.com/mesalogo/goodbuddy/actions/runs/36347785076)
|
||||
验证与生产构建全部通过后,两个远端创建了不可变 `v0.15.0`。
|
||||
其正式 [CI 36348938269](https://github.com/mesalogo/goodbuddy/actions/runs/36348938269)
|
||||
两个 macOS 目标在 `codesign --verify --deep --strict` 失败,
|
||||
报 `invalid destination for symbolic link in bundle`;GitHub Release 未发布。
|
||||
|
||||
Host 隔离 fixture 经实际 DS 资源准备和 electron-builder 文件复制,
|
||||
复现相对 npm CLI 链接变成原构建目录的绝对链接。不是签名凭据或测试超时问题。
|
||||
用户明确选择 **Desktop 0.15.1 + Agent 0.15.0** 恢复,不移动或复用旧标签。
|
||||
修正仅让复制保留相对链接;新增回归移除原安装与暂存目录后验证最终链接仍可读。
|
||||
该路径不用于 Agent,远程 Runtime 与 Agent 源码未改,不增加真实模型调用。
|
||||
未发布 Desktop 0.15.0 的双语条目迁移到 0.15.1,保留全部功能说明;
|
||||
Agent 版本不变,其包元数据从新版 Desktop manifest 派生最低版本 0.15.1,
|
||||
两份说明和功能矩阵同步这个升级顺序。
|
||||
|
||||
原标签最终 Windows/Linux 四个目标成功,两个 macOS 失败,发布任务跳过,
|
||||
公开 Latest 仍为 `v0.13.16`。
|
||||
Windows 打包相关测试 45 通过、1 个 POSIX 链接用例跳过,类型、lint、
|
||||
发布说明校验通过。冻结 tree `99d3271174a68922fbf0a1a4cfbadbb85a6067c8`
|
||||
在 Linux Host 全量 **5,372 通过、51 跳过、0 失败**,耗时 745.88 秒;
|
||||
新增符号链接回归实际执行通过。提交仅追加验证记录,恢复候选 CI 与 macOS 签名待验证。
|
||||
|
||||
## 数据、兼容与验收边界
|
||||
|
||||
Desktop schema 48 新增魔法笔记会话来源元数据。升级前应备份完整用户数据,
|
||||
包括数据库及相邻 `notes/` 目录;旧客户端不能打开升级后的数据库。
|
||||
本次发布准备不修改数据库迁移实现,也不直接改写用户数据库。
|
||||
|
||||
Agent 发布工作流以候选 `package.json` 设置最低 Desktop 版本,因此
|
||||
Agent 0.15.0 包要求 Desktop 0.15.1;Node、OpenCode、Continue 锁不变。
|
||||
Agent 与 Desktop 独立发布,Agent 不替代 Desktop Latest。
|
||||
|
||||
原生客户端的远程 coordinator、托管标准 Node 交付整合、Continue/OpenCode
|
||||
Ask 内置 MCP 映射及完整跨平台安装包验收仍有缺口,见
|
||||
[原生客户端进度](../features/assistant-workbar/progress.md#2026-09-27-local-native-client-validation)。
|
||||
本次说明明确标为本地预览,不将这些未完成部分宣称为已提供能力。
|
||||
@@ -0,0 +1,48 @@
|
||||
# Desktop 0.15.2 与 Agent 0.15.0 发布准备
|
||||
|
||||
日期:2026-09-28。用户要求包含当前本地工作、推送双远端,等待候选 CI 和生产构建通过后打标签;
|
||||
确认同时发布 Agent 0.15.0,不构建 LoongArch。沿用此前自行审核候选和双语说明的授权。
|
||||
|
||||
## 发布范围
|
||||
|
||||
- Desktop 基线为已发布的 `v0.15.1`(`4e5239256d42c856bb1420d87c4a338f17867b80`)。
|
||||
[发布 CI 36368878429](https://github.com/mesalogo/goodbuddy/actions/runs/36368878429)
|
||||
六个原生目标和 GitHub/OSS 发布全部成功,0.15.1 的历史说明保留。
|
||||
- 新源码截止 `66f77b83c2b6ebe0018a6c5c2bc72e1b4c1e43b1`:
|
||||
renderer 退出诊断、笔记采集界面、双语网站及 Story Graph 只读工具与完整讨论草稿。
|
||||
- Agent 0.15.0 尚未发布,基线仍为 `agent-v0.13.4`。
|
||||
既有遥测和 Continue 更新检查修复保留,补充远程 Story Graph 工具;
|
||||
最低 Desktop 版本由当前 manifest 派生为 0.15.2。三个原生目标和 Runtime 锁不变。
|
||||
- 当前未提交的功能矩阵、主机/云环境设计和宣传文稿一并审核纳入。
|
||||
云平台适配与主机入口迁移明确为待实现规划,不进入发布功能说明。
|
||||
宣传稿保持草稿和原核查截止点,不代表已对外发布。
|
||||
- 正式双语正文仅维护在 `resources/release-notes.json` 的 0.15.2 条目和
|
||||
`resources/agent-release-notes/0.15.0.md`。两份 FEATURES 已对照实现与规划核对。
|
||||
|
||||
## 验证边界
|
||||
|
||||
Story Graph 已有开发期证据见
|
||||
[监督者验证进度](../features/conversation-supervision/progress.md#2026-09-28-story-graph-只读工具):
|
||||
真实 Linux Host 上的 OpenCode/Continue Ask、Execute 调用与禁用检查通过;
|
||||
推理为本机确定性响应,10 次请求含 2 次标题生成,外部付费请求 0 次。
|
||||
不将这些证据称为真实模型建议质量验证,也不宣称历史重建、跨范围事实合并或大库性能已验收。
|
||||
|
||||
本轮类型、lint、双语说明及网站静态校验通过。按当前源码重建隔离 Agent 探针,
|
||||
在共享 Linux x64 Host 经固定身份完成 OpenCode/Continue Ask、Execute、空闲进程回收、
|
||||
冷启动历史恢复和遥测关闭环境检查;每个 Runtime 2 次真实模型请求,共 **4 次**,
|
||||
没有重试或假模型调用,结束时归属进程均为 0。该补充检查不等于真实模型图谱建议质量验收。
|
||||
|
||||
准备期间另有 `0cdf042` 宣传稿提交,已核对只有三份文档变化,产品源码仍截止 `66f77b8`,
|
||||
一并纳入完整候选。用户随后中断本地全量步骤,明确要求直接推送等待 CI;
|
||||
本地全量不记为通过,由精确候选的主分支 CI 执行完整测试和生产构建,通过后才打标签。
|
||||
不运行本地生产构建、安装包打包或安装包启动;使用既有隔离 Host 目录,不更改生产 Agent。
|
||||
schema 保持 48;从旧版升级应备份完整数据库和相邻 `notes/`,不能用旧客户端打开升级后的库。
|
||||
|
||||
## 首次候选 CI
|
||||
|
||||
`76e781a` 已同步双远端。Agent [CI 36379713606](https://github.com/mesalogo/goodbuddy/actions/runs/36379713606)
|
||||
通过;Desktop [CI 36379713607](https://github.com/mesalogo/goodbuddy/actions/runs/36379713607)
|
||||
5,389 通过、51 跳过、1 失败,生产构建未执行,未打标签。
|
||||
失败的设置测试用固定五个服务器名称过滤按钮,却用新增 Story Graph 后的六项目录断言数量。
|
||||
同步把旧模拟列表与按钮身份断言改为复用正式目录,保留数量和原交互断言,并逐项验证目录按钮存在。
|
||||
最终完整 SettingsPanel 文件、类型、lint 和发布说明检查通过;全量继续交由新提交 CI。
|
||||
@@ -0,0 +1,36 @@
|
||||
# Desktop 0.15.3 发布准备
|
||||
|
||||
日期:2026-09-28。用户确认沿用双远端推送、精确提交 CI 和生产构建通过后自动打标签的流程;
|
||||
本次仅发布 Desktop 0.15.3,已发布 Agent 0.15.0 保持不变,不构建 LoongArch。
|
||||
|
||||
## 范围
|
||||
|
||||
- 已发布基线:`v0.15.2`,提交 `47ba54f47db4f22f69375310925eedab020b3cf0`。
|
||||
- 本轮已核对 15 个提交,截止 `86347af0b1cc8726c1166b3f9fa3d7f12a0cc5e3`。
|
||||
包含手动压缩、请求级工具授权、取消/失败状态、聊天/笔记重复工作、
|
||||
侧栏与工作栏布局、打包依赖精简。起始工作区干净。
|
||||
- Office 同会话实时编辑仅更新需求与验收设计,不计入交付能力。
|
||||
- `package.json`、lockfile 两处 Desktop 版本统一为 0.15.3。
|
||||
已发布 0.15.2 与 Agent 0.15.0 的正文保持不变;新双语说明单独追加。
|
||||
- 两份 FEATURES 对照实现更新手动压缩、状态反馈、搜索、箭头方向及发布状态。
|
||||
不用局部 Markdown 基准宣称整体渲染性能提升,不提前承诺跨平台安装包缩小比例。
|
||||
|
||||
## Agent 与验证边界
|
||||
|
||||
`src/agent-daemon`、`src/main/remote-agent`、Agent 和 Runtime 锁在本轮未变。
|
||||
授权修复属于 Desktop 的 `KnowledgeMcpGateway`:请求有效期间不再按固定十分钟撤销,
|
||||
取消和清理继续撤销;不修改远程工具通道或部署包,不需要重发 Agent 0.15.0。
|
||||
手动直连压缩仅用于本地文本会话,UI 与 IPC 均排除 SSH/远程直连入口。
|
||||
|
||||
开发期证据分别见[直连模型进度](../features/direct-model-agent/progress.md)、
|
||||
[导航进度](../features/application-tool-navigation/progress.md)和
|
||||
[性能基准](../roadmap/product-performance-experience-improvement-plan.md)。
|
||||
开发期全量曾报告侧栏和笔记 Electron 用例失败,不把这些历史结果计为本候选通过。
|
||||
本轮 `npm run typecheck`、`npm run lint`、`npm run release:notes:verify` 通过。
|
||||
网关、Obsidian 授权、桌面资源与 DS 打包、手动压缩真实 Electron 生产链路共 6 文件:
|
||||
**85 通过、1 跳过**。跳过的是 Windows 不适用的 POSIX 符号链接用例。
|
||||
压缩测试使用本机 HTTP fixture,不冒充外部模型调用;本轮没有新增付费模型请求。
|
||||
沿用用户确认的直接推送等待 CI 流程,完整测试及生产构建以精确候选 CI 为发布门槛。
|
||||
不进行本地生产构建、打包或安装包启动。
|
||||
|
||||
schema 保持 48;从更早版本升级前备份完整数据库及相邻 `notes/` 目录。
|
||||
@@ -0,0 +1,55 @@
|
||||
# Desktop 0.15.4 与 Agent 0.15.1 发布准备
|
||||
|
||||
日期:2026-09-29。用户确认两个补丁版本,提交并推送两个远端;
|
||||
候选 CI 和生产构建成功后自动打标签发布,不构建 LoongArch。
|
||||
|
||||
## 范围与说明
|
||||
|
||||
- Desktop 已发布基线为 `v0.15.3`(`3c9229ac7a57071fc955adb1095c499ffdfd006a`)。
|
||||
本轮源码截止 `9c88ca20f3c62ca29b9aca179dc191b460db37d8`,开始时工作区干净。
|
||||
- 三个提交包含系统任务 Token 统计、Runtime/模型分层和宣传稿归档。
|
||||
正式功能说明以实现为准;用途模型和旧全局 provider 移除仍为规划。
|
||||
- Agent 基线为已发布 `agent-v0.15.0`。本轮 Continue helper 识别首次历史封装、
|
||||
去除保存消息中的工作模式前缀,因此发布新 Agent 0.15.1,不覆盖旧产物。
|
||||
Node 24.19.0、OpenCode 1.18.29、Continue 1.5.47 和协议锁保持不变。
|
||||
- 正文仅维护在 Desktop 0.15.4 JSON 条目及 Agent 0.15.1 Markdown;
|
||||
已发布版本正文保留。FEATURES 中修正旧的简化选择描述,并同步用量、版本和限制。
|
||||
|
||||
## 数据与兼容
|
||||
|
||||
schema 49 在既有 SQLite 事务中迁移项目与会话选择,不引入额外恢复系统。
|
||||
已读迁移指南并核对合成 schema 48 数据迁移回归;本轮不改写用户原库。
|
||||
关闭应用后备份完整数据库及相邻 `notes/`,旧客户端不能打开升级后的库,
|
||||
降级需要恢复完整升级前备份。远程先升级 Desktop 0.15.4,再更新 Agent 0.15.1。
|
||||
统计无法补算历史未记录的调用或缺失的供应商 usage。
|
||||
|
||||
## 验证
|
||||
|
||||
- `npm run typecheck`、`npm run lint`、`npm run release:notes:verify` 通过。
|
||||
- 10 个聚焦文件、221 项通过:包含数据库迁移/用量分类、选择解析、选择器、
|
||||
Activity UI、后台用量记录和 Continue helper。
|
||||
- 当前源码隔离 Agent 在共享 Linux x64 Host 验证 OpenCode 与 Continue Ask、Execute、
|
||||
空闲进程回收及冷启动历史恢复。成功场景每个 Runtime 两次真实模型请求。
|
||||
OpenCode 原模型连接前三次尝试未完成,第三次脱敏诊断明确为上游 `ECONNRESET`;
|
||||
随后测试显式使用 Continue 已配置且成功的模型连接,未修改用户设置或产品回退规则。
|
||||
本轮共 7 次上游请求分发尝试,4 次成功、3 次未完成;不推断失败尝试的计费情况。
|
||||
所有探针结束时归属进程为 0,用户设置只在临时加密副本中读取,测试副本已清理。
|
||||
- 既有开发记录缺少完整 UI 目测及全仓通过结果,保留边界,不将局部通过冒充全量。
|
||||
完整测试与生产构建交由精确提交 CI;不执行本地生产构建、打包或安装包启动。
|
||||
|
||||
## 首轮候选 CI
|
||||
|
||||
`ed47e2c` 已同步两个远端。Agent `36580699297` 三平台验证通过。
|
||||
Desktop `36580699255` 为 5,472 通过、52 跳过、1 失败,生产构建未执行,
|
||||
尚未创建任何本轮发布标签。问答测试在 Runtime 就绪前点击仍禁用的发送按钮,
|
||||
没有产生首个请求;按现有异步同步机制等待按钮可用,保留全部问答与重载断言。
|
||||
该修正仅影响测试和发布记录,运行时源码、锁文件及双语发布说明不变。
|
||||
修正后完整 `App.test.tsx` 314 项通过,类型检查与 lint 再次通过。
|
||||
|
||||
## 发布前界面修正
|
||||
|
||||
用户要求移除会话 Runtime 按钮图标与名称间的圆点,并确认继续提交、推送和发布。
|
||||
删除专用覆盖标记 class 及其伪元素样式,保留菜单内来源提示和恢复默认操作,
|
||||
同步双语说明及选择设计。完整 App 与样式回归共 351 项通过,类型检查和 lint 通过。
|
||||
该改动仅在 Renderer,不影响 Agent 或桌面至 Agent 协议,无需新增真实模型请求。
|
||||
此前中断的测试不计为通过;本条结果来自重新执行。最终新提交仍须等待独立 CI。
|
||||
@@ -0,0 +1,74 @@
|
||||
# Desktop 0.15.5 发布准备
|
||||
|
||||
日期:2026-09-30。用户授权按新增改动确定版本、提交推送两个远端,
|
||||
CI 与生产构建通过后自动打标签发布;本轮不构建 LoongArch。
|
||||
|
||||
## 范围
|
||||
|
||||
已发布基线 `v0.15.4`:`a662b16f5e076f67788457653d29c0d2fbacdab0`。
|
||||
初始工作区干净,产品源码截止 `2d8e58e995c4ac2e3d885b028e588d49d06f05cf`。
|
||||
四个提交分别为取消轮次历史、执行清单浮层、智能心跳增量回顾与监督建议、
|
||||
笔记保存后退出编辑。双语正文维护在 `resources/release-notes.json`;
|
||||
已发布正文保留,两个 FEATURES 同步当前能力和剩余边界。
|
||||
|
||||
Agent 保持 0.15.1,不发布新标签或修改其历史说明。Agent daemon、协议实现和
|
||||
Runtime 锁没有变化;共享合同新增的是桌面监督配置/API,历史构建在 Renderer/Main
|
||||
进行,远程继续通过现有 history 字段传输。因桌面至 Agent 历史输入改变,
|
||||
仍对当前源码完成真实 Host 取消后续聊验证。
|
||||
|
||||
## 数据与行为边界
|
||||
|
||||
schema 50 在既有事务中增加心跳介入方式、建议状态和建议表;旧报告中仍 proposed
|
||||
的记忆迁为 pending 约定,不确认或删除原记录。已读迁移指南并核对 49→50 回归;
|
||||
没有读取或升级用户原库,也不声明大规模真实旧库性能已验证。
|
||||
升级前关闭应用,备份完整数据库及相邻 `notes/`;降级需恢复完整升级前备份。
|
||||
|
||||
手动回顾默认增量,显式重新整理不推进或重置共享进度。建议以本次结果中的依据为准,
|
||||
有候选才进行额外模型调用;项目与全局分别维护进度,会话级实时介入仍未实现。
|
||||
本地 OpenCode 的取消会话标记不等同于 Agent 实现;远程使用共享桌面历史输入与
|
||||
原有取消/会话恢复路径,不声称复用了本地 OpenCode 类。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- 类型检查和 lint 通过。
|
||||
- 首轮定向 34 文件:1092 通过、1 跳过、1 失败。会话合并用例只等待 Runtime
|
||||
mock 调用便触发新会话,单独复跑通过;补充等待已发送消息可见,保留两次同批
|
||||
新建请求和最终会话数量断言。最终 34 文件全部通过,1093 项通过、1 项既有条件跳过;
|
||||
类型检查、lint、双语发布说明及差异检查再次通过。
|
||||
- 当前源码在共享 Linux x64 Host:OpenCode、Continue 各在 Ask 输出后主动取消,
|
||||
用生产 `buildRuntimeHistory` 生成中断历史,再以 Execute 发送无工具的新问题。
|
||||
两条路径均只回答新问题,未续写原列表;归属进程最终为 0。
|
||||
本轮恰好 4 次真实上游请求,全部 HTTP 200,无重试或假模型;用户设置只读取
|
||||
临时加密副本,未修改正式 Agent 安装和工作目录。
|
||||
- 智能心跳开发记录中的 4 次 DeepSeek 请求是该功能开发证据,不计入本轮新增调用。
|
||||
参见[实施记录](../features/conversation-supervision/progress.md)。
|
||||
- 不执行本地生产构建、打包或安装包启动。全仓验证和生产构建以最终提交的 CI
|
||||
为准,标签只能在该门槛通过后创建。
|
||||
|
||||
## 中断后扩展候选
|
||||
|
||||
用户新增四个提交并授权再次推送继续发布;源码范围扩至
|
||||
`6edfc0046b83150f2027167352000f161fb0dd0a`,恢复时工作区干净。
|
||||
新增 OpenCode 终端依赖缓存、短 MCP 名称与并行占用、工作区固定工具栏、
|
||||
笔记双栏布局及手动标签。说明和功能矩阵已同步,目标 schema 改为 51。
|
||||
标签支持多选 AND 筛选、重命名/合并/删除及桌面笔记工具字段,非自动分类;
|
||||
Agent daemon 和协议不变,Agent 仍为 0.15.1。
|
||||
|
||||
上一候选 `925d410` 的 Agent CI 通过,Desktop `36664224641` 为 5481 通过、
|
||||
55 跳过、3 失败,生产构建未执行,未创建标签。两个笔记分析用例的旧编辑按钮
|
||||
假设已由新提交修正;新源码真实 Electron 复验已通过。监督布局仍查找旧记忆建议
|
||||
标题及已移除的心跳运行审计,修正为监督建议区域和两条建议断言、审计不重复展示,
|
||||
保留页签、宽度、历史报告和导航检查。
|
||||
|
||||
扩展候选复验:15 文件、502 项通过,包含上述三个失败场景、笔记标签与布局、
|
||||
工作区滚动布局、schema 51 数据库、MCP 网关/名称及原生终端缓存测试;
|
||||
类型检查、lint、双语说明校验和差异检查通过。该轮测试使用隔离 fixture,
|
||||
没有新增付费模型调用;先前 4 次真实 Host 请求仅对应取消后续聊范围,
|
||||
不作为新增标签工具的完整远程 UI 实测声明。
|
||||
|
||||
`89fc100` 的 Agent CI 通过;Desktop `36707706849` 为 5507 通过、55 跳过、
|
||||
2 失败,前述三个失败场景均已通过。笔记滚动在请求完成回调中早于 DOM 提交,
|
||||
以立即执行动画帧的回归稳定复现后,改在布局 Effect 中定位已挂载记录。
|
||||
手动压缩独立复跑通过,夹具同步当前分层选择格式并等待目标会话历史显示;
|
||||
尚不将独立通过视为 Linux 全仓通过。修正后完整 App/笔记组件及真实 Electron
|
||||
导航/压缩共 450 项通过,类型检查和 lint 通过,无新增外部模型调用。
|
||||
@@ -0,0 +1,70 @@
|
||||
# Desktop 0.15.6 发布准备
|
||||
|
||||
日期:2026-10-01。用户授权提交当前未提交改动并继续双远端推送与发布,
|
||||
如 Agent 实际受影响可升补丁版本;另明确本轮仅标准六平台,不含 LoongArch。
|
||||
|
||||
## 候选范围
|
||||
|
||||
基线 `v0.15.5` 为 `3be55348a215f4343326b1950a69529247cbae6a`,
|
||||
六个新增提交截止 `9cc5dc124464a67ed93014c53cbc93f96764caa2`。
|
||||
初始未提交改动仅 `application-center.css` 一行选择器:
|
||||
侧栏底部仅对第二个直接子元素文字 span 禁止伸缩,避免影响其他 span。
|
||||
已核对并纳入本轮,未包含凭据、日志或临时产物。
|
||||
|
||||
新增内容包括磨砂外观、输入/缓存会话切换渲染优化、直接图片预览、设置与笔记布局、
|
||||
本地 MCP 恢复及不确定名称退役、诊断和执行统计索引。
|
||||
双语说明和功能矩阵按实现更新,不将已有开发记录中的全量失败记为成功。
|
||||
|
||||
Agent 保持 0.15.1:相对其发布标签,daemon 与锁文件无变化。
|
||||
本地 OpenCode 的 HTTP 注册恢复属于 `OpenCodeRuntime`,远端使用
|
||||
`RuntimeAcpBackend`/`AgentImageToolMcp`,不经过这条 HTTP 注册路径。
|
||||
没有据此声称远程恢复得到同样改进,也没有新发布 Agent 包。
|
||||
|
||||
## 数据与验证
|
||||
|
||||
已读数据库迁移指南。schema 52 在事务内增加任务事件部分索引,不转换消息正文,
|
||||
不执行 VACUUM;建立索引的耗时受历史规模影响,本轮未测真实大库升级。
|
||||
升级前关闭应用并备份数据库和相邻 `notes/`,降级需要完整升级前备份。
|
||||
|
||||
- 当前源码 17 个定向文件、886 项通过,包含真实 OpenCode + HTTP 网关合成服务的
|
||||
MCP 故障恢复和晚到初始化回归,数据库/统计、诊断、设置、App、图片附件和真实
|
||||
Electron 磨砂、笔记布局、工作栏设置布局。
|
||||
- `npm run typecheck`、`npm run lint` 通过;本轮新增付费模型调用 0 次。
|
||||
- 完整测试和生产构建等待精确候选 CI,不运行本地生产构建、打包或安装包探针。
|
||||
|
||||
## 首轮 CI
|
||||
|
||||
候选 `cc451f6` 已含用户未提交样式修正并同步两个远端。Agent `36743915140`
|
||||
通过,Desktop `36743915207` 为 5573 通过、57 跳过、1 失败,生产构建未执行。
|
||||
磨砂测试切换主题后立即读取样式,窗口按钮 color 正在过渡,导致深色关闭态与
|
||||
先前基线不同。测试改为等待当前 CSS Transition 完成,保留完整样式、几何、
|
||||
拖拽、对比度及原生交互断言,不修改产品外观或全局超时。
|
||||
修正后完整磨砂 Electron 回归、类型检查及 lint 通过;双语说明与产品源码不变。
|
||||
|
||||
`8201c9c` 的 CI `36746918608` 中磨砂回归通过,唯一失败为 161 条历史的多次
|
||||
热切换 App 用例超过默认 5 秒(5573 通过、57 跳过)。只将该用例预算设为 15 秒,
|
||||
保留消息数量、DOM 复用、零额外渲染、草稿、附件、展开状态和滚动位置的全部断言;
|
||||
不修改全局超时或将运行时性能要求替换为等待通过。
|
||||
调整后完整 App 319 项、类型检查及 lint 通过。
|
||||
|
||||
## 再次扩展候选
|
||||
|
||||
用户要求将当前未提交改动一起提交。新增 `0a02a17`(新建笔记入口)和
|
||||
`a3b41bf`(设备共享元数据),并纳入五份应用导航文档修改。
|
||||
设备共享需另行运行 ShareServer,首期面向本地未认证服务,仅注册设备及管理元数据;
|
||||
不执行远程能力,不传输或检索知识正文,设备 ID 不构成所有权认证。
|
||||
Agent 实现和锁不变,仍不升版。
|
||||
|
||||
扩展源码类型检查和 lint 已通过。用户随后明确要求停止本地测试、直接推送等 CI,
|
||||
进行中的定向测试已中断,不计为通过,也不沿用旧候选的全量结果。
|
||||
最终发布取决于包含新增提交和文档的精确候选 CI 与生产构建。
|
||||
|
||||
## 扩展候选焦点回归
|
||||
|
||||
`2c5300d` 的 Desktop CI `36753498640`:5580 通过、58 跳过、1 失败,
|
||||
生产构建未执行;Agent CI `36753498643` 通过。
|
||||
笔记导航用例在打开并取消带 `autoFocus` 标题输入框的新建表单后,
|
||||
才断言此前打开详情时的返回按钮焦点,混合了两个不同交互阶段。
|
||||
将原焦点断言移至打开新建表单之前,并断言新建标题输入框取得焦点;
|
||||
保留返回列表、滚动位置、搜索内容和原卡片焦点断言,不改产品代码或延长超时。
|
||||
按用户要求不运行本地测试,由新候选 CI 验证。
|
||||
@@ -21,8 +21,10 @@ diagnosis of their cause.
|
||||
- Native crashes and main-frame load failures use the existing bounded desktop
|
||||
diagnostics store (`desktop.renderer.gone`, `desktop.renderer.load-failed`,
|
||||
stage `renderer`). Persistent records retain fixed summaries rather than raw
|
||||
errors. Crash reason/exit code and React errors/component stacks go to their
|
||||
respective process consoles. There is no new diagnostic IPC.
|
||||
errors. Renderer exit records also retain Electron's enumerated `reason` and
|
||||
numeric `exitCode` when written, read back and exported; older records without
|
||||
these fields remain readable. The exit details still go to the Main console.
|
||||
React errors/component stacks remain console-only. There is no new diagnostic IPC.
|
||||
|
||||
The boundary does not catch module evaluation/startup failures before React
|
||||
mounts, event-handler exceptions, asynchronous rejections, a hung renderer, or
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
# 应用导航与系统工具入口
|
||||
|
||||
本功能整理 GoodBuddy 主侧栏的入口层级:系统入口保持固定,四个内置应用共用可调整的保存顺序,知识库始终启用并常驻;
|
||||
智能心跳、魔法笔记和本机推理监控可通过应用管理控制启用和常驻。底部应用中心向上展开轻量锚定菜单,列出已启用应用;底部“管理应用”打开既有管理 Modal。系统工具由右侧工作栏 Tab 承载。应用商店是后续功能,首期不提供
|
||||
本功能整理 GoodBuddy 主侧栏的入口层级:系统入口保持固定,五个内置应用共用可调整的保存顺序,知识库始终启用并常驻;
|
||||
智能心跳、魔法笔记和本机推理监控可通过应用管理控制启用和常驻。底部“应用”向上展开轻量锚定菜单,列出已启用应用;底部“管理应用”打开既有“应用中心”管理 Modal。系统工具由右侧工作栏 Tab 承载。应用商店是后续功能,首期不提供
|
||||
商店入口、推荐位或安装流程。
|
||||
|
||||
设备共享作为第五项追加到原有应用顺序,始终可从菜单和管理 Modal 打开,不提供启用、常驻
|
||||
开关;服务地址与设备名称在其页面保存。首期仅支持本地服务的设备注册与元数据目录,详见
|
||||
[设备共享](../device-sharing/README.md)。
|
||||
|
||||
当前分期见 [PRD 第 8 节](./prd.md#8-分期),实施步骤见[技术设计第 11 节](./technical-design.md#11-实施顺序)。
|
||||
本轮 A–D 已接入生产源码:应用菜单、应用管理 Modal、共享应用设置、持久化偏好及本机推理监控。菜单不按打开历史或常驻状态筛选,无模态遮罩;点击应用行关闭菜单,知识库、智能心跳和魔法笔记打开主内容区页面。本机推理监控从菜单、常驻入口或管理 Modal 打开时均使用独立 Modal,保留底层工作区。管理列表、菜单和侧栏按同一保存顺序排列,侧栏按启用和常驻过滤。知识库在管理 Modal 中提供“打开”和排序,不提供启用、常驻开关或通用空设置;原工作区配置及心跳单条计划 enabled 保持原义。验证范围及集成缺口见[实施进度](./progress.md)。
|
||||
|
||||
@@ -23,6 +27,10 @@
|
||||
|
||||
## 文档导航
|
||||
|
||||
待实现的应用扩展见 [FR-17](./prd.md#fr-17-主机管理与云环境管理待实现):
|
||||
主机管理从设置中心迁入独立工作页面,云环境管理作为同级应用;业务定义由
|
||||
[远程主机功能文档](../remote-host/README.md)维护。该计划不包含已接入的设备共享元数据页面。
|
||||
|
||||
现有 `heartbeat` 入口承载监督者工作回顾与故事线图谱,可管理启用、常驻和排序。应用默认关闭;完整执行边界见[应用启停与执行](../conversation-supervision/logic-design.md#应用启停与执行)。未来市场复用同一应用身份,不增加平级重复入口,目标定义见[监督者产品设计](../conversation-supervision/supervisor-prd.md)。
|
||||
|
||||
| 文档 | 权威职责 |
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
2. 运行记录不进入工具注册表、应用显隐设置或插件市场。
|
||||
3. 文件浏览器、终端、浏览器和资源监控始终是系统工具,不能卸载或被插件替换。
|
||||
4. 左下角提供应用中心和独立固定设置入口;文件、终端、浏览器、资源监控只通过右侧工作栏 Tab 和“+”访问,不进入应用中心。
|
||||
5. 四个内置应用共享保存顺序。知识库始终启用并常驻,位置可调整;智能心跳、魔法笔记、本机推理监控可独立设置启用和常驻。取消常驻不关闭功能,关闭不删除数据或导航偏好。
|
||||
5. 五个内置应用共享保存顺序。知识库始终启用并常驻,位置可调整;智能心跳、魔法笔记、本机推理监控可独立设置启用和常驻。设备共享始终可从应用菜单打开,不常驻侧栏,也不提供启停开关。取消常驻不关闭功能,关闭不删除数据或导航偏好。
|
||||
6. 入口不能扩大执行空间、文件、PTY、网络或浏览器权限。
|
||||
7. 应用中心始终可达,点击向上展开无模态遮罩的锚定菜单,只列已启用应用,不使用打开历史或常驻过滤。菜单底部“管理应用”打开既有 Modal,关闭的可选应用在其中仍可搜索、配置和重新开启。
|
||||
8. 所有入口和新请求的功能判断读取同一份保存成功的权威设置;保存中的目标值不提前生效。
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
```ts
|
||||
type NavigationContribution =
|
||||
| { type: 'application'; id: 'device-sharing'; source: 'builtin'; enabled: true; pinned: false }
|
||||
| {
|
||||
type: 'system-entry'
|
||||
id: 'chat' | 'activity' | 'application-center' | 'settings'
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
- 用户从侧栏底部进入应用中心,查找、打开和配置内置应用。
|
||||
- 主导航承载应用入口,本机推理监控打开 Modal,其余内置应用打开完整页面;辅助工具由工作栏承载。
|
||||
- 运行记录始终可发现,不受应用显示设置和插件状态影响。
|
||||
- 四个内置应用均支持排序;智能心跳、魔法笔记和本机推理监控可独立设置启用与常驻,知识库始终显示,未常驻的已启用应用仍可从应用菜单打开。
|
||||
- 五个内置应用均支持排序;智能心跳、魔法笔记和本机推理监控可独立设置启用与常驻,知识库始终显示,设备共享始终可从应用菜单打开且不常驻侧栏。未常驻的已启用应用仍可从应用菜单打开。
|
||||
- 为插件应用和插件工具保留明确的入口契约,不提前建设插件安装能力。
|
||||
|
||||
## 4. 非目标
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
### FR-3 内置应用区
|
||||
|
||||
主导航在当前对话之后按共享保存顺序显示应用,知识库始终显示,可选应用仅显示已启用且常驻项;运行记录位于应用区之后。四个应用均可排序。本机推理监控入口打开独立 Modal,其余应用打开对应一级页面,保留
|
||||
主导航在当前对话之后按共享保存顺序显示应用,知识库始终显示,可选应用仅显示已启用且常驻项;运行记录位于应用区之后。五个应用均可排序。本机推理监控入口打开独立 Modal,其余应用打开对应一级页面,保留
|
||||
现有徽标、范围和页面状态。管理 Modal 列出全部内置应用,知识库只提供“打开”和排序。
|
||||
|
||||
### FR-4 隐藏应用
|
||||
@@ -86,7 +86,7 @@
|
||||
|
||||
### FR-5 应用中心入口
|
||||
|
||||
侧栏底部提供应用中心和独立设置入口。点击应用中心向上展开锚定按钮的轻量菜单,无模态遮罩。菜单列出已启用应用,不按是否打开过、历史记录或常驻状态筛选;点击应用行关闭菜单,本机推理监控打开 Modal,其余应用在主内容区打开页面。
|
||||
侧栏底部提供“应用”(英文 `Apps`)和独立“设置”入口,两个按钮均显示文字。点击“应用”向上展开锚定按钮的轻量菜单,无模态遮罩。菜单列出已启用应用,不按是否打开过、历史记录或常驻状态筛选;点击应用行关闭菜单,本机推理监控打开 Modal,其余应用在主内容区打开页面。
|
||||
菜单底部“管理应用”关闭菜单并打开既有管理 Modal,在其中浏览、搜索全部内置应用,为已关闭的可选应用提供设置与重新开启入口。无搜索结果时显示空状态并可清除搜索。
|
||||
首期不展示商店、安装、推荐或系统工具清单。入口具有可访问名称,Escape 关闭后恢复触发位置的焦点。
|
||||
|
||||
@@ -127,13 +127,13 @@ Renderer 内存中最多保留最近 5 分钟。任一条件不满足时停止
|
||||
|
||||
### FR-11 应用导航设置
|
||||
|
||||
管理 Modal 的四个应用行均提供上下移动和拖动排序,不受启用或常驻状态限制;管理列表、菜单和侧栏共用一份顺序。箭头边界按完整顺序计算,搜索过滤不丢失隐藏项。智能心跳、魔法笔记和本机推理监控另提供应用设置、常驻管理;知识库提供“打开”和排序,不添加通用空设置页或开关。原工作区配置入口及心跳单条计划 enabled 保持不变。设置中“启用应用”与“常驻左侧菜单”分别保存,
|
||||
管理 Modal 的五个应用行均提供上下移动和拖动排序,不受启用或常驻状态限制;管理列表、菜单和侧栏共用一份顺序。箭头边界按完整顺序计算,搜索过滤不丢失隐藏项。智能心跳、魔法笔记和本机推理监控另提供应用设置、常驻管理;知识库与设备共享提供“打开”和排序,不添加通用空设置页或开关。原工作区配置入口及心跳单条计划 enabled 保持不变。设置中“启用应用”与“常驻左侧菜单”分别保存,
|
||||
修改即时提交;请求期间串行处理并禁用会修改同一配置的控件,失败就地反馈。
|
||||
魔法笔记设置统一从应用中心对应行进入,笔记页与全局设置不再提供重复入口。持久化成功后的设置变更同步覆盖工具配置写入;每次重开中心先刷新并锁定修改,较新的确认快照优先于迟到的读取结果。
|
||||
|
||||
### FR-12 偏好持久化
|
||||
|
||||
四个应用的顺序及可选应用启用、常驻按设备持久化,重启后恢复。默认顺序为知识库、智能心跳、魔法笔记、本机推理监控。心跳应用默认关闭,其余应用默认启用;心跳和魔法笔记默认常驻,本机推理监控默认不常驻;
|
||||
五个应用的顺序及可选应用启用、常驻按设备持久化,重启后恢复。默认顺序为知识库、智能心跳、魔法笔记、本机推理监控、设备共享。心跳应用默认关闭,其余应用默认启用;心跳和魔法笔记默认常驻,本机推理监控默认不常驻,设备共享不提供常驻开关;
|
||||
魔法笔记待办数量默认显示,评论方式与形式沿用现有默认值。迁移保留已保存的启用、常驻和排序选择,
|
||||
旧魔法笔记入口开关绑定业务启用值,迁为“启用应用”并保留原值;常驻使用独立配置,
|
||||
只有已发布的独立显隐偏好才映射到常驻,不能由常驻推导业务启停。旧可选应用顺序补入知识库、智能心跳默认位置并保留已有相对顺序,具体补齐规则见[技术设计](./technical-design.md#43-持久化与-ipc)。`heartbeatEnabled` 的缺失值与保存值按[应用启停与执行](../conversation-supervision/logic-design.md#应用启停与执行)处理;不读取未发布草案中的 `knowledgeEnabled`。
|
||||
@@ -173,7 +173,7 @@ Renderer 内存中最多保留最近 5 分钟。任一条件不满足时停止
|
||||
- 主导航能明确区分固定系统入口和可配置内置应用。
|
||||
- 运行记录在所有应用显隐组合下保持可见并可打开。
|
||||
- 左下角不再用“本地工作区”与系统架构占据主要空间。
|
||||
- 应用菜单只列已启用应用,点击行关闭菜单;本机推理监控打开保留底层工作区的 Modal,其余应用进入主内容区。“管理应用”打开可搜索的既有 Modal。四个应用均可排序,知识库始终可用,三个可选应用可管理启用与常驻,首期无商店入口。
|
||||
- 应用菜单只列已启用应用,点击行关闭菜单;本机推理监控打开保留底层工作区的 Modal,其余应用进入主内容区。“管理应用”打开可搜索的既有 Modal。五个应用均可排序,知识库与设备共享始终可用,三个可选应用可管理启用与常驻,首期无商店入口。
|
||||
- 系统工具仅从右侧 Tab 与“+”访问;选择 Tab 不创建或改绑实例,“+”可显式创建额外浏览器或终端。
|
||||
- 资源监控以 2 秒间隔更新,保留不超过 150 个样本;面板不活动、工作栏收起或窗口隐藏、
|
||||
最小化后停止请求新样本。
|
||||
@@ -188,7 +188,7 @@ Renderer 内存中最多保留最近 5 分钟。任一条件不满足时停止
|
||||
|
||||
- 侧栏最底部应用中心打开向上锚定的轻量菜单,无模态遮罩;底部“管理应用”进入与设置相同的整窗 Modal 和可搜索应用列表,设置按钮保持独立。
|
||||
- 应用中心提供魔法笔记、知识库、智能心跳及本轮追加的本机推理监控入口,不要求安装。本机推理监控 Modal 与服务单独实现和验证。
|
||||
- 四个应用共享排序;支持智能心跳、魔法笔记、本机推理监控常驻主导航及取消常驻,知识库始终显示。已启用未常驻应用仍可从菜单打开,取消常驻不删除数据或停止后台任务。
|
||||
- 五个应用共享排序;支持智能心跳、魔法笔记、本机推理监控常驻主导航及取消常驻,知识库始终显示。设备共享仅从应用菜单和管理 Modal 进入,业务定义见[设备共享](../device-sharing/README.md)。已启用未常驻应用仍可从菜单打开,取消常驻不删除数据或停止后台任务。
|
||||
- 通用应用设置统一从应用中心对应行进入;应用页面保留实际业务配置,本机推理监控保留“模型与连接设置”。
|
||||
魔法笔记优先接入待办数量、AI 评论方式和评论形式,入口显示与常驻控制统一,避免重复开关。
|
||||
- 文件、终端、浏览器保留在右侧工作栏 Tab,不在左下角复制入口,也不纳入应用中心。
|
||||
@@ -264,3 +264,14 @@ Modal 只有服务列表,显示名称、简短状态、引擎、模型、资
|
||||
资源监控仍是只读系统工具,本机推理监控聚焦本地服务状态。该项独立于商店接入生产源码,支持 OCR 空闲加载与释放、内置向量进程启动/停止/重启;TTS 显示不可用。后端保留请求登记及原有取消能力,供执行路径和服务影响校验使用。各引擎边界见
|
||||
[技术清单](./technical-design.md#111-本机推理任务与执行服务),验证范围见[实施进度](./progress.md)。
|
||||
原首期资源监控的 GoodBuddy 桌面进程统计范围不因此扩大。
|
||||
|
||||
### FR-17 主机管理与云环境管理(待实现)
|
||||
|
||||
2026-09-28 确认新增两个同级应用:“主机管理”和“云环境管理”。主机管理从设置中心迁入,
|
||||
两个应用均从应用菜单、管理应用和常驻入口打开主内容区独立页面,不嵌入管理 Modal。
|
||||
应用中心负责通用应用配置,业务操作在各自页面完成。
|
||||
|
||||
导航扩展须保留已有应用排序、常驻偏好和远程能力启用值;取消主机常驻不影响云环境使用
|
||||
主机能力。两个应用的能力依赖、迁移范围及产品验收由
|
||||
[主机与云环境 PRD](../remote-host/prd.md)和[功能逻辑](../remote-host/logic-design.md)定义,
|
||||
业务页面布局见[界面设计](../remote-host/ui-design.md)。该项尚未实现,不改变上文五应用的当前状态描述。
|
||||
|
||||
@@ -1,5 +1,87 @@
|
||||
# 应用导航实施进度
|
||||
|
||||
## 2026-10-01:设备共享入口
|
||||
|
||||
新增 `device-sharing`,应用菜单及管理 Modal 均进入主内容区页面;管理行可排序,不提供启用
|
||||
或常驻开关。旧顺序通过现有存储归一化追加新项,保留原设置;权威写入要求五项完整顺序。
|
||||
ApplicationCenter、ApplicationMenu、设置迁移以及 App 入口/排序回归已通过,真实 Electron
|
||||
从应用中心进入页面并完成后端流程。精确命令、完整范围及全仓测试记录见
|
||||
[设备共享实施进度](../device-sharing/progress.md)。下方历史四应用记录保留原验证时的范围。
|
||||
|
||||
## 2026-09-28: Composer shortcut initialization follow-up
|
||||
|
||||
The composer now retains successful shortcut-settings snapshots independently of
|
||||
the startup app-info request. A failed or pending app-info read no longer drops a
|
||||
successful shortcut save, and a late startup response cannot restore a disabled
|
||||
hint. Registration remains authoritative; no default shortcut is advertised when
|
||||
registration is unavailable. This preserves the existing [composer rule](../../../UI-DESIGN.md#131-聊天).
|
||||
|
||||
The failed/pending read regressions reproduced the missing hint before the fix.
|
||||
The reported screenshot's actual registration status and IPC result were not
|
||||
captured, so its specific runtime cause remains unconfirmed.
|
||||
|
||||
Validation: App, sidebar layout, main IPC, and shortcut-service suites passed
|
||||
(500 tests, one skipped); `npm run typecheck`, ESLint on the four changed source
|
||||
and test files, and `git diff --check` passed. The first broader run hit the
|
||||
60-second command limit; the rerun completed in 95 seconds. No full-repository
|
||||
suite, native Electron screenshot reproduction, packaging, or OS registration
|
||||
probe was run for this follow-up.
|
||||
|
||||
## 2026-09-28:新建对话与搜索共用一行
|
||||
|
||||
已按[会话搜索](./ui-design.md#会话搜索)接入收起与展开状态,移除列表上方的常驻搜索头部。
|
||||
沿用会话创建、延迟搜索和项目过滤接口。后续按用户反馈恢复默认按钮的聊天加号图标、原有
|
||||
字号字重和整体左对齐;搜索展开后保留居中的同一图标。快捷键说明移至聊天输入框原生占位文案,
|
||||
具体规则见[聊天 UI 规范](../../../UI-DESIGN.md#131-聊天)。
|
||||
|
||||
本次调整验证:`App.test.tsx` 与 `AppSidebarLayout.test.ts` 合计 316 项通过;最终长标签换行
|
||||
调整后,布局 5 项与 `magic-notes-capture.electron.test.ts` 1 项复验通过。Windows Electron
|
||||
在上述 6 种侧栏组合检查原字号字重、左对齐、图标居中、文字无溢出及搜索交互,并验证
|
||||
原生输入后占位提示隐藏、清空后恢复。App 回归覆盖中英文、生图提示、macOS 快捷键格式、
|
||||
全局快捷键缺省以及设置保存后的更新和停用。类型检查、修改文件 ESLint 与差异空白检查通过。
|
||||
未运行全仓测试、打包或 macOS/Linux 原生窗口验证。模型调用 0 次。
|
||||
|
||||
此前搜索展开改动的验证记录:
|
||||
|
||||
```text
|
||||
npm test -- src/renderer/src/App.test.tsx src/renderer/src/AppSidebarLayout.test.ts tests/magic-notes-capture.electron.test.ts
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
三文件合计 311 项通过。最终动画边界与文字宽度调整后,布局及 Electron 共 5 项、App 搜索
|
||||
交互 1 项复跑通过,typecheck 通过。Electron 复用现有 App、生产 Preload、IPC 和临时 SQLite
|
||||
测试环境,以英文界面检查浅深主题下 220px、420px 侧栏和短窗口抽屉,共 6 种组合;检查
|
||||
展开过程及结束后的右边缘、列表位置、完整按钮文字、原生鼠标与 Escape、自动聚焦、关闭
|
||||
焦点恢复、点击列表保留关键词及减少动态效果。中文 App 回归同时覆盖标题、正文、项目
|
||||
过滤和加号创建。模型调用 0 次。
|
||||
|
||||
修改文件的 ESLint 与 `git diff --check` 通过。全仓 ESLint 有 10 个错误,均来自本任务未修改
|
||||
的未跟踪 `sidebar-final-probe.ts` 和 `sidebar-final-run.mjs`。未跑全仓测试、打包程序或
|
||||
macOS/Linux 窗口验证。中文新增规则经 deai-writing 扫描无阻断项,并已人工核对。
|
||||
|
||||
## 2026-09-28:并行会话输出时保持列表顺序
|
||||
|
||||
修复多个会话交替输出时,左侧列表随每个增量反复换位的问题。展示顺序统一使用消息创建
|
||||
时间,摘要查询补充只读 `latestMessageAt`。交互规则见[会话置顶与操作菜单](./ui-design.md#会话置顶与操作菜单),
|
||||
时间字段与合并边界见[会话列表读取与前端保留](../assistant-workbar/execution-history-storage.md#会话列表读取与前端保留)。
|
||||
本地及远程事件的更新时间写入、快照合并判定和增量保存保持原实现。
|
||||
|
||||
聚焦验证命令:
|
||||
|
||||
```text
|
||||
npx vitest run src/renderer/src/chat-conversation.test.ts src/renderer/src/App.test.tsx src/main/assistant/assistant-database.test.ts -t "conversation display order|parallel streaming conversations|summary and detail order|sorts pinned conversations|merges persisted pin metadata|lists lightweight history|persists only the changed conversation|preserves live .* across snapshot|loads only the opened history"
|
||||
```
|
||||
|
||||
结果:3 个文件、13 项通过。覆盖并行文字增量与完成后顺序、保存时间继续推进、本地和消息
|
||||
通道的摘要/详情刷新、新消息前移、置顶合并、同时间固定顺序、空会话回退、摘要附带实时
|
||||
消息及真实 SQLite 摘要时间。历史加载回归继续验证刷新不重复保存未变化的消息。
|
||||
修改过的 7 个 TypeScript 文件定向 ESLint 通过。中文文档按 deai-writing 自查清单复核。
|
||||
|
||||
本轮验证为 App 组件事件回归与真实 SQLite 测试,未进行 Electron 窗口或真实模型调用。
|
||||
改动仅涉及桌面展示及桌面 Main 的只读摘要,未改变 Agent 协议或桌面到 Agent 的执行路径,
|
||||
无需部署 Host。全仓 typecheck、ESLint 和 `git diff --check` 通过;全量测试运行十分钟后
|
||||
超时,期间报告配置摘要和 Agent 离线安装测试失败,未取得全仓测试通过结果。
|
||||
|
||||
2026-09-23 文档校正:当前 `heartbeat` 已作为可选应用管理,默认值与执行边界见[应用启停与执行](../conversation-supervision/logic-design.md#应用启停与执行),设置与导航契约见[技术设计](./technical-design.md#4-应用导航偏好)。下方日期记录保留当时实现与验证结果;其中“心跳始终显示”“无应用级开关”和旧字段删除说明不再代表当前行为。本次仅核对源码并更新文档,未重新执行功能测试。
|
||||
|
||||
## 2026-09-18:窄幅单列应用列表
|
||||
|
||||
@@ -22,6 +22,7 @@ type WorkspaceView =
|
||||
| 'knowledge'
|
||||
| 'heartbeat'
|
||||
| 'local-inference'
|
||||
| 'device-sharing'
|
||||
| 'activity'
|
||||
| 'settings'
|
||||
```
|
||||
@@ -31,7 +32,7 @@ type WorkspaceView =
|
||||
实现以[浏览器多实例技术设计](../assistant-workbar/browser-tabs-technical-design.md)为准。代码中尚无资源指标采集和资源监控
|
||||
面板。侧栏底部已替换为应用中心与独立设置按钮。
|
||||
|
||||
应用中心、四应用共享排序、可选应用常驻及启用联动、共同设置页和本机推理监控已接入生产源码;本机资源监控的
|
||||
应用中心、五应用共享排序、可选应用常驻及启用联动、共同设置页和本机推理监控已接入生产源码;本机资源监控的
|
||||
Main/Preload/Renderer 实现仍待交付。系统工具只使用右侧工作栏已有 Tab 和“+”链路。
|
||||
行为由[功能逻辑](./logic-design.md)定义,验证范围见[实施进度](./progress.md)。
|
||||
|
||||
@@ -61,7 +62,7 @@ Main/Preload/Renderer 实现仍待交付。系统工具只使用右侧工作栏
|
||||
### 3.1 内置应用清单
|
||||
|
||||
```ts
|
||||
type BuiltInApplicationId = 'magic-notes' | 'knowledge' | 'heartbeat' | 'local-inference'
|
||||
type BuiltInApplicationId = 'magic-notes' | 'knowledge' | 'heartbeat' | 'local-inference' | 'device-sharing'
|
||||
|
||||
type BuiltInApplicationDefinition = {
|
||||
id: BuiltInApplicationId
|
||||
@@ -81,7 +82,7 @@ type BuiltInApplicationDefinition = {
|
||||
|
||||
应用中心调用既有 `navigateFromSidebar` 或同一页面导航函数,沿用未保存离开检查和焦点
|
||||
策略。打开前检查确认的启用值;未常驻但已启用的应用不附带常驻写入。本机推理监控从常驻入口、菜单及管理 Modal 均经 `setView('local-inference')` 打开独立 Modal,保留底层工作区与设置草稿;其他应用继续页面导航。
|
||||
`ApplicationMenu` 按四个应用共用的持久化顺序派生清单,仅按启用过滤,不读取常驻或打开历史。应用行先关闭菜单再导航;底部“管理应用”关闭菜单、恢复锚点焦点并打开既有 `ApplicationCenter` Modal。
|
||||
`ApplicationMenu` 按五个应用共用的持久化顺序派生清单,仅按启用过滤,不读取常驻或打开历史。应用行先关闭菜单再导航;底部“管理应用”关闭菜单、恢复锚点焦点并打开既有 `ApplicationCenter` Modal。设备共享始终启用,进入主内容区页面,无常驻字段;业务边界见[设备共享技术设计](../device-sharing/technical-design.md#当前首期实现)。
|
||||
应用中心对应行的设置操作仅接受 `EditableApplicationId`;应用页和全局设置不提供重复入口。知识库的管理行提供“打开”和排序,原工作区实际配置保留,不添加通用空设置页。
|
||||
共同页复用设置 Modal 容器、配置读取及更新方法,不建立独立配置存储或重复表单。
|
||||
|
||||
@@ -124,9 +125,9 @@ type ApplicationNavigationSettings = {
|
||||
}
|
||||
```
|
||||
|
||||
`applicationNavigation` 保存四个应用的完整顺序和三个可选应用的常驻布尔值。默认顺序为
|
||||
`knowledge`、`heartbeat`、`magic-notes`、`local-inference`;心跳和魔法笔记常驻默认 `true`,本机推理监控默认 `false`。
|
||||
权威返回 schema 和更新 schema 均要求四个 ID 各出现一次,拒绝重复、未知和缺失 ID;`pinned` 包含三个可选应用,缺失 `heartbeat` 时补 `true`,显式布尔值保留。Renderer 直接读取该顺序,再按各入口的可见性过滤。知识库始终启用、常驻,无可写开关键。
|
||||
`applicationNavigation` 保存五个应用的完整顺序和三个可选应用的常驻布尔值。默认顺序为
|
||||
`knowledge`、`heartbeat`、`magic-notes`、`local-inference`、`device-sharing`;心跳和魔法笔记常驻默认 `true`,本机推理监控默认 `false`,设备共享无常驻开关。
|
||||
权威返回 schema 和更新 schema 均要求五个 ID 各出现一次,拒绝重复、未知和缺失 ID;`pinned` 包含三个可选应用,缺失 `heartbeat` 时补 `true`,显式布尔值保留。Renderer 直接读取该顺序,再按各入口的可见性过滤。知识库始终启用、常驻,无可写开关键。
|
||||
按[排序规则](./logic-design.md#3-主导航组合规则)提交完整顺序;不持久化可推导的可见 ID 列表。
|
||||
首期不预建插件字段,也不为未发布的旧隐藏 ID 草案增加迁移读取器。
|
||||
|
||||
@@ -166,7 +167,7 @@ Main 继续校验可信 sender、Zod 输入,复用 `ApplicationSettingsStore`
|
||||
`true`、`false`、单选值和无关设置,不迁移或清理笔记、知识及会话业务数据。
|
||||
新安装和升级时缺失整个 `applicationNavigation` 均使用共享默认值,本机推理监控启用但不常驻;本次不增加存储版本。已保存的常驻值均保留,无法区分旧默认 `true` 与用户主动固定,不强制改为 `false`。
|
||||
|
||||
仅存储读取允许补齐旧数据:缺失的 `knowledge`、`heartbeat` 按此顺序前置,再保留已有 ID 的相对顺序,最后按默认顺序追加缺失的可选应用。旧 `[local-inference, magic-notes]` 因此变为 `[knowledge, heartbeat, local-inference, magic-notes]`;完整四项顺序原样保留。缺失或空顺序采用默认顺序,部分 `pinned` 映射仅补缺失键,显式 `false` 保留。重复或未知 ID 仍按现有损坏文件处理规则处理,不静默去重或丢弃。版本 11 迁移时写入归一化结果;版本 12 读取时归一化,下一次设置保存时写入完整结果。IPC 和配置工具写入不接受这些部分数据。
|
||||
仅存储读取允许补齐旧数据:缺失的 `knowledge`、`heartbeat` 按此顺序前置,再保留已有 ID 的相对顺序,最后按默认顺序追加缺失项。旧 `[local-inference, magic-notes]` 因此变为 `[knowledge, heartbeat, local-inference, magic-notes, device-sharing]`;旧完整四项顺序保留并在末尾追加 `device-sharing`。缺失或空顺序采用默认顺序,部分 `pinned` 映射仅补缺失键,显式 `false` 保留。重复或未知 ID 仍按现有损坏文件处理规则处理,不静默去重或丢弃。版本 11 迁移时写入归一化结果;版本 12 读取时归一化,下一次设置保存时写入完整结果。IPC 和配置工具写入不接受这些部分数据。
|
||||
|
||||
版本 12 属于未发布的分支格式,原草案 `knowledgeEnabled` 已移除,不增加兼容读取器。`heartbeatEnabled` 是当前应用启用字段,由 Store 归一化缺失值并保留显式保存值。
|
||||
|
||||
@@ -175,17 +176,21 @@ Main 继续校验可信 sender、Zod 输入,复用 `ApplicationSettingsStore`
|
||||
原 `user-card` 整行设置按钮已替换为容器和相邻独立按钮:
|
||||
|
||||
```tsx
|
||||
<div className="sidebar-footer">
|
||||
<button onClick={toggleApplicationMenu} aria-haspopup="menu" aria-expanded={applicationMenuOpen} ...>
|
||||
{t('navigation.applicationCenter')}
|
||||
<div className="sidebar-footer sidebar-footer--applications">
|
||||
<button className="nav-item" onClick={toggleApplicationMenu} aria-haspopup="menu" aria-expanded={applicationMenuOpen} ...>
|
||||
<Grid2X2 aria-hidden="true" />
|
||||
<span>{t('applications.menuLabel')}</span>
|
||||
<ChevronUp aria-hidden="true" />
|
||||
</button>
|
||||
<button aria-label={t('navigation.settings')} ...>
|
||||
<div className="sidebar-footer__divider" aria-hidden="true" />
|
||||
<button className="nav-item" aria-label={t('navigation.settings')} ...>
|
||||
<Settings aria-hidden="true" />
|
||||
<span>{t('navigation.settings')}</span>
|
||||
</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
应用中心和设置为相邻独立按钮。设置按钮继续调用 `navigateFromSidebar('settings', trigger)`,
|
||||
“应用”(`applications.menuLabel`:中文“应用”、英文 `Apps`)和设置为横向等高独立按钮,使用 `nav-item` 样式和弱竖分隔线;“管理应用”菜单项使用 `LayoutGrid` 图标,管理 Modal 标题保持“应用中心” / `Application Center`。设置按钮继续调用 `navigateFromSidebar('settings', trigger)`,
|
||||
保留设置预加载、焦点恢复和未保存离开确认。该调用只打开设置 Modal,不更新当前工作区或
|
||||
KeepAlive 缓存;`settingsOpen` 独立管理打开状态。关闭后卸载设置内容,下次按入口指定的分类
|
||||
和消息通道重新挂载,避免缓存上次分类覆盖本次直达目标。底层工作区继续挂载,普通关闭不跳回聊天。
|
||||
@@ -348,7 +353,7 @@ resourceMonitor.getLocalSnapshot(input: {
|
||||
|
||||
### 10.2 Main 与契约测试
|
||||
|
||||
- 顺序包含四个应用 ID 各一次;公开写入拒绝重复、缺失、未知 ID 及无效常驻字段;旧存储顺序按迁移规则补齐,不为未发布的 `knowledgeEnabled` 添加迁移。
|
||||
- 顺序包含五个应用 ID 各一次;公开写入拒绝重复、缺失、未知 ID 及无效常驻字段;旧存储顺序按迁移规则补齐,不为未发布的 `knowledgeEnabled` 添加迁移。
|
||||
- 未配置的心跳应用默认关闭,其余应用启用及笔记布尔项默认开启,本机推理监控默认不常驻;已保存的启用、常驻值和评论单选值经迁移及重启保留。
|
||||
- 更新常驻或顺序不修改启用、计划或业务数据;笔记既有配置键保持语义。
|
||||
- 串行 patch 在 Main 最新快照上合并,原子写入失败不发布目标状态;响应丢失后重读实际结果。
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
品牌
|
||||
项目选择
|
||||
项目活动汇总(仅有活动时显示)
|
||||
新对话
|
||||
搜索
|
||||
[新对话] [搜索图标]
|
||||
|
||||
当前对话
|
||||
应用(按保存顺序;知识库始终显示,可选应用仅显示启用且常驻项)
|
||||
@@ -32,24 +31,37 @@
|
||||
...
|
||||
|
||||
────────────────────────
|
||||
[应用中心] [设置]
|
||||
[应用 v] | [设置]
|
||||
```
|
||||
|
||||
“当前对话”和“运行记录”属于固定系统入口,常驻应用位于二者之间。首期应用清单为魔法笔记、
|
||||
知识库、智能心跳及本轮追加的本机推理监控,应用中心与设置始终可见。侧栏底部不再显示“本地工作区”和 `platform · arch`;
|
||||
排障信息移至关于或诊断页面。左侧不再提供文件、终端、浏览器、资源监控的重复入口。
|
||||
|
||||
### 会话搜索
|
||||
|
||||
新建对话与搜索共用原新建对话位置的一行。默认显示 `MessageSquarePlus` 图标与完整“新建对话”文字,整体左对齐,沿用原有 13px、600 字重和 12px 左内边距,右侧为搜索图标;
|
||||
点击搜索后,输入框从右向左展开,新建对话只显示居中的同一图标,保留“新建对话”可访问名称与悬停提示。
|
||||
最窄侧栏中的长标签允许在固定行高内换行,保留字号和图标。搜索右边缘和整行高度保持不变,列表不因展开或关闭而上下移动。宽度动画使用
|
||||
`--motion-normal`,减少动态效果时立即切换;沿用桌面侧栏调宽和窄窗口抽屉尺寸。
|
||||
通道项目继续不提供新对话按钮,搜索展开后使用整行宽度。
|
||||
控件行与新建对话按钮高 `44px`;搜索框本体高 `36px`,上下各留 `4px`,垂直居中。保留 `2px` 焦点外框与 `2px` 外间距,聚焦后外沿与新建对话按钮上下对齐。
|
||||
|
||||
展开时聚焦输入框。X 始终可用,X 或控件行内的 Escape 清空关键词并收起输入框,
|
||||
焦点返回搜索图标。失焦、点击会话列表保持搜索状态和关键词;新建对话图标继续调用原新对话操作。
|
||||
无结果区域的“清除搜索”只清空关键词,保留展开状态。项目活动跳转仍沿用既有清空搜索规则。
|
||||
|
||||
## 2. 底部应用中心入口
|
||||
|
||||
底部使用连续平整表面和顶部分隔线,应用中心在前,固定设置靠右,二者为独立按钮:
|
||||
底部使用连续平整表面和顶部分隔线,“应用”在前,“设置”靠右,二者为横向排列的等宽、等高 `nav-item` 独立按钮,内容各自居中,竖分隔线位于底部入口区域的正中间:
|
||||
|
||||
| 位置 | 图标 | 可见工具提示 | 点击结果 |
|
||||
| 位置 | 图标 | 可见文字 | 点击结果 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | `Grid2X2` | 应用中心 | 向上展开已启用应用菜单,底部“管理应用”进入管理 Modal |
|
||||
| 末位 | `Settings` | 设置 | 在当前工作区上打开设置 Modal |
|
||||
| 1 | `Grid2X2` + `ChevronUp` | 应用 / Apps | 向上展开已启用应用菜单,底部“管理应用”进入管理 Modal |
|
||||
| 末位 | `Settings` | 设置 / Settings | 在当前工作区上打开设置 Modal |
|
||||
|
||||
图标使用项目现有 Lucide 库。应用中心保留文字,设置图标采用统一的 `34px × 34px` 点击区域。
|
||||
底部使用共享间距和焦点样式,设置通过弹性空白靠右;不得把整个容器做成设置按钮。
|
||||
图标使用项目现有 Lucide 库。两个按钮均保留可见文字,沿用主导航的高度、间距和焦点样式;
|
||||
“应用”文字后显示向上箭头,与菜单展开方向一致。竖分隔线宽 1px、高 `--space-6`,使用 `--border-default`,与上方横分隔线颜色一致。不得把整个容器做成设置按钮。
|
||||
|
||||
### 2.1 状态
|
||||
|
||||
@@ -73,18 +85,21 @@
|
||||
```
|
||||
|
||||
取消常驻或关闭可选应用后不留下空白。知识库始终启用并显示;心跳按启用和常驻显示,位置遵守共享应用顺序。运行记录始终位于应用区之后。
|
||||
四个应用均在管理行上通过拖动及“上移”“下移”按钮排序;首尾无目标时禁用对应按钮。两种方式提交完整应用顺序,保存成功后更新,重启保留。当前对话、运行记录和底部系统入口不参与排序。
|
||||
五个应用均在管理行上通过拖动及“上移”“下移”按钮排序;首尾无目标时禁用对应按钮。两种方式提交完整应用顺序,保存成功后更新,重启保留。当前对话、运行记录和底部系统入口不参与排序。
|
||||
|
||||
取消常驻不关闭当前页面或本机推理监控 Modal。重新常驻按已保存顺序恢复,关闭应用保留常驻与顺序偏好。
|
||||
主侧栏始终读取最后确认配置,不展示尚未保存成功的排序或开关目标值。
|
||||
|
||||
## 4. 应用中心与共同设置
|
||||
|
||||
设备共享追加到默认顺序末尾。管理行显示“内置”、打开与排序按钮,不提供通用启用或常驻
|
||||
开关;应用菜单始终保留该项,点击后在主内容区打开[设备共享页面](../device-sharing/ui-design.md#当前首期页面)。
|
||||
|
||||
底部点击打开轻量菜单,锚定按钮向上展开,无模态遮罩、背景隔离或焦点循环。菜单按共享保存顺序列出已启用应用,不按打开历史或常驻状态过滤。点击应用行关闭菜单,本机推理监控打开独立 Modal,知识库、智能心跳和魔法笔记在主内容区打开页面。分隔线下的“管理应用”关闭菜单并打开既有管理 Modal。
|
||||
|
||||
菜单通过共享 `AnchoredMenu` 挂载到 body,宽度最多 `280px`,距窗口边缘至少 `16px`,与按钮上缘间隔 `8px`;短窗口限制高度并内部滚动,滚动、窗口和内容尺寸变化时重算位置。原生浏览器相交遮挡复用共享机制。
|
||||
|
||||
管理 Modal 沿用设置 Modal 的表面、遮罩和焦点规则,提供全部内置应用的名称及用途搜索、打开,以及可选应用的常驻和设置:
|
||||
“管理应用”菜单项使用 `LayoutGrid` 图标。管理 Modal 标题仍为“应用中心”(英文 `Application Center`),沿用设置 Modal 的表面、遮罩和焦点规则,提供全部内置应用的名称及用途搜索、打开,以及可选应用的常驻和设置:
|
||||
|
||||
应用管理始终采用紧凑单列横向列表,从上到下对应保存顺序;行间使用 `--border-subtle` 弱分隔线,不加卡片外框。概览与设置详情共用 `640px` 最大宽度,窄窗口保留两侧各 `16px` 外边距,高度随内容增长并受窗口限制。
|
||||
每行左侧显示图标、名称、状态和简短用途,右侧对齐打开、可用的设置及上下移动操作;空间不足时操作组换到下一行并保持右对齐,组内也可换行,上下箭头保持成组。名称旁区分
|
||||
@@ -189,7 +204,8 @@ CPU 4% · 内存 620 MB · 桌面进程 7
|
||||
|
||||
| 对象 | 文案 |
|
||||
| --- | --- |
|
||||
| 底部入口 | 应用中心 |
|
||||
| 底部入口 | 应用 / Apps |
|
||||
| 管理 Modal 标题 | 应用中心 / Application Center |
|
||||
| 菜单底部管理入口 | 管理应用 |
|
||||
| 应用设置开关 | 启用应用 |
|
||||
| 文件系统工具 | 文件 |
|
||||
@@ -231,7 +247,10 @@ CPU 4% · 内存 620 MB · 桌面进程 7
|
||||
|
||||
会话行的“更多会话操作”提供“置顶会话/取消置顶”,本地与消息通道会话均可使用。
|
||||
置顶会话显示带“已置顶”可访问名称的图标;当前项目和搜索过滤仍生效,过滤后的列表先显示
|
||||
置顶会话,两组内各按更新时间倒序。取消置顶恢复时间排序,不改变会话更新时间。
|
||||
置顶会话,两组内各按最新消息的创建时间倒序;时间相同按会话 ID 固定顺序,无消息时使用
|
||||
会话更新时间。新增消息可以前移会话,同一消息的文字、推理、工具进度和完成状态更新不
|
||||
改变排序。有消息的会话重命名或修改设置也不前移。摘要刷新、打开详情和重新启动沿用同一
|
||||
规则,行右侧仍显示实际更新时间。取消置顶恢复消息时间排序,不改变会话更新时间。
|
||||
置顶状态重启后保留;保存成功后更新图标和顺序,失败保留原状态并显示应用错误通知。
|
||||
存储尚未就绪或置顶请求进行中时禁用置顶操作。
|
||||
|
||||
|
||||
@@ -42,12 +42,12 @@
|
||||
|
||||
- Given 任意主页面和任意侧栏宽度
|
||||
- When 用户查看侧栏底部
|
||||
- Then 设置与应用中心为始终可见的独立按钮,点击区域不重叠
|
||||
- Then “设置”与“应用”为始终显示文字的独立按钮,点击区域不重叠
|
||||
- And 点击后继续遵守未保存内容的离开确认
|
||||
|
||||
## 3. Epic B:管理应用入口
|
||||
|
||||
本节的启用、常驻和共同设置适用于智能心跳、魔法笔记、本机推理监控;四个应用均可排序,知识库始终启用并常驻。心跳的默认关闭及执行边界按[应用启停与执行](../conversation-supervision/logic-design.md#应用启停与执行)验收,保留既有故事 ID。
|
||||
本节的启用、常驻和共同设置适用于智能心跳、魔法笔记、本机推理监控;五个应用均可排序,知识库始终启用并常驻。设备共享始终可从应用菜单和管理 Modal 打开,不提供启用或常驻开关;业务验收见[设备共享首期需求](../device-sharing/prd.md#当前首期本地元数据)。心跳的默认关闭及执行边界按[应用启停与执行](../conversation-supervision/logic-design.md#应用启停与执行)验收,保留既有故事 ID。
|
||||
|
||||
### US-B1 识别完整应用
|
||||
|
||||
@@ -139,14 +139,14 @@
|
||||
验收:
|
||||
|
||||
- Given 首次使用且未配置导航偏好
|
||||
- Then 默认顺序为知识库、智能心跳、魔法笔记、本机推理监控;心跳默认关闭且保留默认常驻偏好,魔法笔记默认常驻,本机推理监控默认启用但不常驻,仍可从应用菜单打开;侧栏只按启用与常驻过滤可选项
|
||||
- Then 默认顺序为知识库、智能心跳、魔法笔记、本机推理监控、设备共享;心跳默认关闭且保留默认常驻偏好,魔法笔记默认常驻,本机推理监控默认启用但不常驻,仍可从应用菜单打开;设备共享只在应用菜单和管理 Modal 提供入口;侧栏只按启用与常驻过滤可选项
|
||||
- When 用户修改常驻,或通过拖动、键盘可操作的上移和下移按钮排序并保存成功
|
||||
- Then 管理列表从上到下、菜单和侧栏按同一保存顺序显示,知识库和智能心跳可移动;当前对话、运行记录及底部系统入口位置不变,重启后恢复保存结果
|
||||
- And 每行均提供上下移动,以完整保存顺序中的相邻应用为目标;未常驻及关闭应用仍可排序,设置详情不提供排序控件
|
||||
- And 搜索时箭头仍按完整顺序移动,保留未命中应用,拖动禁用;清除搜索后显示完整保存结果
|
||||
- Given 旧设置仅保存本机推理监控、魔法笔记的顺序
|
||||
- When 升级后读取设置
|
||||
- Then 知识库、智能心跳补在前面,两个可选应用保留原有相对顺序和常驻值
|
||||
- Then 知识库、智能心跳补在前面,两个可选应用保留原有相对顺序和常驻值,设备共享追加到末尾
|
||||
- Given 应用已关闭或取消常驻
|
||||
- When 用户重新开启或常驻
|
||||
- Then 按保存顺序恢复入口;关闭或取消常驻不删除顺序,已关闭应用仍可管理常驻偏好
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# 助手工作栏
|
||||
|
||||
助手工作栏统一承载本机与远程执行空间、Task、成果、文件、浏览器和终端等持续工作界面。
|
||||
助手工作栏统一承载本机与远程执行空间、Task、成果、文件、浏览器、终端和笔记等持续工作界面。
|
||||
|
||||
“笔记”为应用级、可关闭的单实例 Tab,新布局默认不打开。它提供搜索、浏览和快速追加文字,
|
||||
与主页面魔法笔记共用存储;会话采集、来源跳转与草稿规则由
|
||||
[魔法笔记文档](../magic-notes/README.md)维护。该应用已接入并通过真实 Electron 验收;
|
||||
全仓验证未全绿,聚焦复跑与执行时失败见[笔记验证进度](../magic-notes/progress.md)。
|
||||
|
||||
## 文档导航
|
||||
|
||||
@@ -13,6 +18,7 @@
|
||||
| [执行记录存储与升级回收](./execution-history-storage.md) | 子任务差量存储、远程去重、旧库转换、会话置顶、摘要与完整历史按需读取、内存引用释放 |
|
||||
| [Runtime 交互边界](./runtime-interactions.md) | 原生权限、结构化问答、后台拒绝、终端交互、并行与输出、消息请求状态及资源生命周期规则 |
|
||||
| [Runtime 进程复用技术设计](./runtime-process-reuse-technical-design.md) | 跨 Runtime 资源调研、锁定协议证据、进程与会话拆分、远端模型桥、实施顺序和性能验收 |
|
||||
| [Runtime 原生客户端启动方案](./runtime-native-client-proposal.md) | Local terminal/DS Web shortcut requirements, startup rules, current integration, validation boundaries and remaining remote/resource work |
|
||||
| [Runtime 执行清单技术设计](./runtime-checklist-technical-design.md) | OC/CN 原生清单提取、远程 Agent 传递复用、消息恢复与真实部署验收;尚未实现 |
|
||||
|
||||
当前尚未拆出独立 User Stories、功能逻辑和 UI 设计文档;产品场景与验收保留在现有 PRD,
|
||||
|
||||
@@ -81,12 +81,14 @@ Record<ConversationId, Record<BrowserTabId, BrowserLiveState>>
|
||||
|
||||
`BrowserViewport` 统一观察 body Portal 的插入、移除和可见属性变化,以及浮层尺寸、
|
||||
窗口尺寸、滚动和过渡结束。`browser-viewport-occlusion.ts` 按共享语义识别
|
||||
`aria-modal="true"`、dialog、alertdialog、menu 和应用通知:可见应用级 Modal 始终释放
|
||||
`aria-modal="true"`、dialog、alertdialog、menu、tooltip 和应用通知:可见应用级 Modal 始终释放
|
||||
viewport,其余浮层只在与浏览器区域相交时释放。隐藏节点和隐藏祖先不阻塞浏览器。
|
||||
最后一个遮挡消失后,只有当前活动实例恢复同一 viewport 租约;网页、历史和页面状态不变。
|
||||
终端关闭确认复用此机制,不再维护单独的隐藏条件。页面无需逐个登记弹窗,也不能靠提高
|
||||
CSS `z-index` 覆盖原生子视图。此逻辑仅涉及 Desktop Renderer 的显示租约,不改变
|
||||
Runtime、MCP 或远端 Agent 的请求、导航与生命周期。
|
||||
同行帮助仍使用 `role="tooltip"`;相交判定使用其内容矩形,不使用铺满窗口的
|
||||
`FloatingPortal` 宿主。真实 App 的相交与非相交验证见[浮层审查修复记录](../../quality/overlay-review-2026-09-27.md)。
|
||||
|
||||
浏览器应用声明 `visibleAcrossContextSwitches: true`,打开的 Tab 跨项目、会话切换继续显示。
|
||||
切换活动 Conversation 不改变当前选中的浏览器或其 `targetRef.conversationId`;用户在会话 B
|
||||
|
||||
@@ -52,11 +52,11 @@ WAL 增长与 SQL 全历史扫描次数的定向验证见 [BUILD.md](../../../BU
|
||||
本次读取优化不修改 schema、迁移或用户数据:
|
||||
|
||||
- Renderer 启动及焦点、会话、队列刷新使用 `conversations.listSummaries(detailIds)`。
|
||||
普通未打开会话只返回标题、项目、置顶状态、上下文设置和消息数量/首条角色,不解析或跨 IPC
|
||||
普通未打开会话只返回标题、项目、置顶状态、上下文设置和消息数量/首条角色/最新消息创建时间,不解析或跨 IPC
|
||||
传输正文、工具、子任务及图片操作元数据。
|
||||
- 当前会话、现有 KeepAlive 视图,以及 Main 仍持有请求、数据库中仍有活动 Task 或
|
||||
streaming 消息的会话返回完整消息。列表包含全部 active 会话,不限制数量,
|
||||
按置顶优先、组内更新时间倒序返回;仅置顶不会加载完整历史。
|
||||
Main 按置顶优先、组内更新时间倒序返回;Renderer 使用下述展示排序。仅置顶不会加载完整历史。
|
||||
- 打开历史通过 `conversations.get(id)` 读取全部消息,不使用会截断历史的分页上限。
|
||||
加载时明确显示进度;失败保留会话与输入,提供原地重试。发送、队列派发和压缩上下文
|
||||
必须先确认完整历史,发送时不按消息条数截断;复制与导出临时读取完整内容,不把未打开会话留入视图缓存。
|
||||
@@ -71,6 +71,11 @@ WAL 增长与 SQL 全历史扫描次数的定向验证见 [BUILD.md](../../../BU
|
||||
接口保留供其他调用方使用。
|
||||
- 图片状态通过同一合并函数处理。本地更新与 Main 图片操作按原有时间优先级合并,
|
||||
未变化消息返回原对象,避免每次列表刷新后把无变化的整个历史当作脏消息再次保存。
|
||||
- 展示顺序由 Renderer 的 `sortConversationsForDisplay` 统一派生,规则见
|
||||
[会话列表排序](../application-tool-navigation/ui-design.md#会话置顶与操作菜单)。完整消息取
|
||||
`createdAt` 最大值;摘要的 `latestMessageAt` 在已有聚合查询中取 `MAX(created_at)`,
|
||||
与摘要上附带的实时消息取最大值。该字段仅用于桌面只读投影,不增加数据库列或持久化副本。
|
||||
`updatedAt`/`updated_at` 继续随流式事件更新,原有快照合并、终态优先与逐消息保存规则不变。
|
||||
- 本机和托管 SSH 的 Renderer/Main 读取、持久化与恢复投影共用以上实现。Agent 的
|
||||
transcript、原生 Session、权限及模型桥协议未改变;完整列表、摘要和详情都附带
|
||||
Main 当前恢复请求的问题投影。
|
||||
|
||||
@@ -86,6 +86,7 @@ Runtime
|
||||
资源监控
|
||||
成果
|
||||
文档
|
||||
笔记
|
||||
```
|
||||
|
||||
- 应用不得根据当前项目、会话、Runtime、主机或探测结果无提示地增删能力目录项。
|
||||
@@ -96,6 +97,7 @@ Runtime
|
||||
Conversation、Job、Run 或心跳事项。
|
||||
- 当前能力、连接、数据和空状态可以动态变化。
|
||||
- 能力不可用时,目录项或已打开面板显示原因、影响和可执行的配置或切换入口,不能只通过隐藏表示。
|
||||
- 笔记遵循魔法笔记的业务启用设置,启用时提供应用级单实例 Tab,禁用前处理草稿,禁用后移除入口和实例;取消主侧栏常驻不影响工作栏可用性。采集与来源规则见[魔法笔记逻辑设计](../magic-notes/logic-design.md)。
|
||||
- 用户可以在设置中调整目录顺序;恢复默认布局恢复标准目录与默认打开面板,不强制打开全部能力。
|
||||
- 浏览器、终端及其他声明为多实例的能力可以创建多个实例,每个实例拥有独立身份和范围绑定。
|
||||
|
||||
@@ -232,7 +234,7 @@ Runtime
|
||||
从当前聊天右栏迁移时,Task Center 和工作区作为默认打开、单实例且不可关闭的基础应用保留;
|
||||
浏览器保留一个默认打开实例,但注册为可关闭的多实例应用;成果保持默认打开、单实例且可
|
||||
关闭;终端不默认打开,由用户通过“+”创建,并从首期开始支持多实例。Tab 必须单行横向滚动,
|
||||
不能自动隐藏或缩写到不可辨认,“+”紧随最后一个 Tab 并随标签滚动,溢出时两端提供固定滚动箭头。Task Center 继续作为 Task 的现有
|
||||
不能自动隐藏或缩写到不可辨认。“+”固定在滚动区外的行末,溢出时页签区两端提供固定滚动箭头,箭头不覆盖“+”。Task Center 继续作为 Task 的现有
|
||||
入口;审批定位到所属 Task 或 Runtime。智能心跳不作为工作栏页签,其报告、建议、历史和
|
||||
完整配置统一归属“智能心跳”菜单入口。当前阶段不新增独立自动化中心。
|
||||
|
||||
@@ -391,7 +393,7 @@ Renderer 不接收任意系统 PID 控制能力。控制动作引用 Main 签发
|
||||
|
||||
当前项目目录的文件浏览与 Git 交互遵循以下规则:
|
||||
|
||||
- FR-W1:顶部同一行放置“文件 / Git 工作区”视图切换和右侧刷新;非 Git 目录仍保留刷新。
|
||||
- FR-W1:顶部同一行放置“文件 / Git 工作区”视图切换和右侧刷新;非 Git 目录仍显示选中的“文件”入口和刷新,仅隐藏“Git 工作区”。
|
||||
下一行只提供当前视图的工具:文件视图提供新建文件、新建目录,Git 视图提供分支、Fetch 和更改显示方式,
|
||||
不在 Git 视图重复目录导航或新建文件操作。操作使用带名称和提示的紧凑图标按钮。
|
||||
文件视图在根目录不显示孤立的文件夹图标或空路径行;进入子目录后提供“项目目录名 / 子目录”
|
||||
@@ -399,6 +401,7 @@ Renderer 不接收任意系统 PID 控制能力。控制动作引用 Main 签发
|
||||
长目录名单行省略,完整路径通过提示查看;多级路径在导航内部横向滚动,不撑宽工作栏。
|
||||
选中目录时在该目录创建,选中文件时在其父目录创建,未选择时在当前浏览目录创建。
|
||||
无可用目录时隐藏无关操作。
|
||||
文件列表独立纵向滚动;顶部视图切换、刷新、新建操作和子目录路径导航保持可见,不随列表滚走。
|
||||
- 使用共享 `SegmentedControl` 切换“文件”和“Git 工作区”,默认显示文件;
|
||||
选择只在当前面板挂载期间保存在内存中,不持久化。未提交更改包含当前项目的全部
|
||||
Git 更改,不按 AI、用户或其他工具的修改来源筛选。
|
||||
@@ -445,6 +448,7 @@ Renderer 不接收任意系统 PID 控制能力。控制动作引用 Main 签发
|
||||
- 文件预览提供复制项目相对路径、刷新,以及仅本机项目可用的“使用默认应用打开”。
|
||||
刷新失败保留此前内容并显示错误;Markdown 默认渲染预览,可切换源码。
|
||||
- Diff 提供刷新、复制项目相对路径和“查看当前文件”;删除项不显示查看当前文件入口。
|
||||
文件路径与操作按钮位于分隔线上方,空间不足时换行;只有未暂存差异时省略“工作树更改”标题,同时存在已暂存差异时保留分区标题。
|
||||
- 手动刷新或任务结束更新 Git 状态时,同步重读根目录、当前浏览目录和已展开目录并去重,保留目录展开状态,
|
||||
刷新失败保留已有目录列表;重新展开目录时重读。目录读取错误在对应目录旁显示,
|
||||
可就地重试。正在查看的单文件 Diff 同时重读,旧请求不得覆盖新结果。
|
||||
@@ -662,6 +666,10 @@ SSH/远程项目操作;已有 Host、项目和凭据保持不变。若当前
|
||||
|
||||
启用后,设置中心显示“主机与远程执行”分类,管理:
|
||||
|
||||
> 上述入口为当前实现。2026-09-28 已确认后续迁入应用中心的“主机管理”,并新增同级
|
||||
> “云环境管理”;范围、能力依赖及验收见[主机与云环境 PRD](../remote-host/prd.md)。
|
||||
> 本节保留现有行为,入口迁移尚未实现。
|
||||
|
||||
- 主机名称、地址、端口和用户名。
|
||||
- 认证方式和凭据配置状态。
|
||||
- Host Key 算法与 SHA-256 指纹。
|
||||
@@ -974,12 +982,14 @@ todo/plan,本次不为其增加工具。也不增加 plan 工作模式、计
|
||||
布局遵循 [UI-DESIGN](../../../UI-DESIGN.md#610-应用顶栏与全局操作)。
|
||||
|
||||
默认折叠为一行“执行清单 · 已完成 m/n”,有进行中条目时附简短摘要;展开后按原生顺序
|
||||
显示内容、状态及原生提供的优先级。行内状态使用图标和“待处理 / 进行中 / 已完成 / 已取消”文字,
|
||||
在摘要按钮旁的浮层显示内容、状态及原生提供的优先级,不推移或压缩下方消息流。
|
||||
行内状态使用图标和“待处理 / 进行中 / 已完成 / 已取消”文字,
|
||||
不用可勾选 Checkbox,也不根据位置推测优先级或进行中状态。请求结束后的摘要附真实
|
||||
请求结果,例如“已取消”,不改变条目状态。后台更新不强制展开、不抢焦点。
|
||||
|
||||
展开按钮提供 `aria-expanded` 和 `aria-controls`,支持 Enter/Space,折叠后焦点留在
|
||||
按钮;实时区域只播报摘要变化。复用全局颜色、间距和字体令牌,浅深主题均可读。窄窗口
|
||||
展开按钮提供 `aria-expanded` 和 `aria-controls`,支持 Enter/Space,展开后焦点进入清单。
|
||||
Escape 收起并返回按钮;点击外部或焦点移出也收起。实时区域只播报摘要变化。
|
||||
复用全局颜色、间距和字体令牌,浅深主题均可读。窄窗口
|
||||
摘要截短、展开内容换行并有界滚动,保留完成计数、请求结果与输入区;200% 缩放时仍可
|
||||
操作。没有清单或收到有效空清单时整行隐藏,历史内容仍按消息归属查看。
|
||||
|
||||
|
||||
@@ -1,5 +1,270 @@
|
||||
# 工作栏实现与验证进度
|
||||
|
||||
## 2026-10-01:本地 MCP 晚到初始化覆盖新连接
|
||||
|
||||
根因修复见[本地 MCP 初始化失败恢复](./runtime-process-reuse-technical-design.md#41-本地-mcp-初始化失败恢复)。
|
||||
已核对随包 OpenCode 1.18.29:`MCP.add` 的初始化不随客户端取消而中止,完成后写入同名状态,
|
||||
并关闭该名称下已有的连接;`disconnect` 只处理当时已登记的客户端。旧实现在 `mcp.add`
|
||||
超时或取消后仍复用同一名称,前一轮的晚到初始化(授权已撤销,结果为 `failed`)会覆盖下一轮
|
||||
刚建立的连接。现在响应不确定的名称作废,后续改用唯一替代名称。
|
||||
|
||||
验证:新增真实 OpenCode+实际网关用例,通过本地代理挂起第一次 MCP `initialize`,
|
||||
使第一轮在 3 秒控制超时后结束,第二轮建立连接后再放行挂起的初始化。修复前该用例
|
||||
复现为第二轮连接状态从 `connected` 变为 `failed`;修复后第二轮连接保持 `connected`
|
||||
且请求完成。`opencode-runtime`、`opencode-runtime-lifecycle`、`knowledge-mcp-gateway`
|
||||
三个测试文件 180 项通过;`npm run typecheck` 通过;相关文件 ESLint 通过。模型为本地合成
|
||||
服务,外部模型调用 0 次。9 月 30 日那次失败的原始时序没有底层日志,未确认就是这一竞态;
|
||||
本次修复的是已复现的同类失败路径。尚未发布或替换已安装应用。
|
||||
|
||||
|
||||
## 2026-09-30:本地 MCP 连接诊断与恢复
|
||||
|
||||
已实现[本地 MCP 初始化失败恢复](./runtime-process-reuse-technical-design.md#41-本地-mcp-初始化失败恢复)。
|
||||
常驻 HTTP 网关和请求级授权保留;内置及自定义 MCP 对明确的暂时性传输故障最多重试一次,
|
||||
必须先成功清理失败连接。SDK 返回错误和抛出错误均有覆盖,未知失败、HTTP/API 拒绝和
|
||||
鉴权错误不重试。界面保留脱敏错误详情,两端失败诊断通过令牌摘要关联。
|
||||
网关初始化异常也会回收未完成会话。
|
||||
|
||||
最终定向验证:`npx vitest run` 指定 `opencode-runtime`、`opencode-runtime-lifecycle`、
|
||||
`opencode-runtime-permissions`、`knowledge-mcp-gateway`、`knowledge-mcp-gateway.obsidian`、
|
||||
`create-runtime`、`desktop-diagnostics`、`feedback-service` 八个测试文件,222 项全部通过。
|
||||
`npm run typecheck` 和 `npm run lint` 通过。真实 OpenCode 与实际网关的恢复用例在连接成功后
|
||||
注入响应丢失,验证断开先于重连、授权不变、请求完成和网关继续监听;该用例每轮产生一次
|
||||
本地合成模型请求,外部模型调用为 0。另有真实 HTTP 初始化连续失败后的会话回收测试。
|
||||
|
||||
全量 `npm test` 在 600 秒后超时,未取得汇总;超时前报告 `SettingsPanel.test.tsx` 中
|
||||
中英文磨砂玻璃开关两个用例失败。这些文件存在并行修改,未判定失败归因,全量验证不记为通过。
|
||||
本次未发布或替换已安装应用。远程 Agent 的 ACP 和 Agent MCP 连接路径未修改,
|
||||
不将本地测试结果作为远程恢复验证。
|
||||
|
||||
## 2026-09-30:OpenCode 终端启动准备
|
||||
|
||||
原先每次“在终端中打开” OpenCode 都会把随包插件依赖目录(约 3,600 个文件、52 MB)
|
||||
复制到临时目录,Windows 本机每次约 2.2–2.4 秒。现在该目录只复制一次到用户数据下的
|
||||
`terminal/opencode-config`,按 `.goodbuddy-ready.json` 判断是否需要刷新;Skills、Ask
|
||||
插件和模型配置仍按每次启动单独生成,关闭时清理。
|
||||
|
||||
Windows 本机实测启动准备:首次 2.9 秒,之后 19–44 ms。OpenCode 自身 TUI 从进程启动
|
||||
到显示输入框约 2.9–3.3 秒,由 OpenCode 程序决定,本次未改变。验证:原生终端单元测试
|
||||
5 项通过;已安装 OpenCode 的 Ask/Execute 真实 PTY 测试 2 项通过(合成模型,真实模型
|
||||
调用 0 次)。远程 Agent 使用独立的 OpenCode 启动路径,不受本次修改影响。
|
||||
|
||||
## 2026-09-28:消息取消与失败展示
|
||||
|
||||
消息终态按[Runtime 交互边界](./runtime-interactions.md)保存和展示。取消使用结构化
|
||||
`terminalStatus`,保持已有回答;终止提示不再补入正文。“重新编辑”只回填并聚焦输入框,
|
||||
没有可回填文字时隐藏入口。旧快照只对精确重复的形态隐藏状态副本,保留原正文。
|
||||
深色主题已移除覆盖失败提示颜色的通用规则;检索和压缩记录不再屏蔽终态的无障碍角色。
|
||||
|
||||
Windows 本地验证:
|
||||
|
||||
- 本次修复完成时 `npm run typecheck`、`npm run lint`、`git diff --check` 通过。
|
||||
后续并行的应用入口修改新增 `App.test.tsx:14430` 的 `getByRole(..., { exact: true })`,
|
||||
最后一次类型检查报 TS2769;该选项不属于 `ByRoleOptions`。未修改这处他人新增代码,
|
||||
当前组合工作区不能记为类型检查通过。最后一次 lint 和 diff 检查通过。
|
||||
- `npm test`:5,367 通过、84 跳过、1 失败。失败项为
|
||||
`tests/magic-notes-layout.electron.test.ts` 的原生拖拽测试,90 秒超时;单独复跑仍超时。
|
||||
该文件未修改,本次检查不记为全量通过。
|
||||
- 相关五文件复跑为 447 通过、14 失败;14 项均在并行入口改名期间查找“应用”按钮失败。
|
||||
入口源码更新后,单独复跑 `src/renderer/src/App.test.tsx` 的 304 项全部通过。
|
||||
其余四文件(数据库、时间线、清单和终态 Electron 探针)的 157 项在上述复跑中通过。
|
||||
- `tests/terminal-status-probe.electron.test.ts` 通过真实 App、Preload、生产 IPC、
|
||||
直连 Runtime 和 SQLite 验证空回答取消、部分回答取消、HTTP 400 失败;检查提示唯一性、
|
||||
浅深主题 computed style、重新编辑回填与焦点,以及数据库重开和页面恢复。
|
||||
每轮使用 3 次本地确定性 HTTP 请求,外部模型调用 0 次。探针在结束时关闭 Runtime、
|
||||
HTTP 服务和窗口,并删除本轮独立临时目录。
|
||||
- 数据库回归覆盖恢复事件事务回滚、失败与取消重放、空正文和已有回答保留、重开后元数据。
|
||||
App 和时间线回归覆盖新事件结构化判定、旧消息精确去重、正常正文保留、无效按钮隐藏、
|
||||
活动及工具终态。
|
||||
|
||||
本次未连接远程主机,未创建远程资源。远端事件仍通过既有公共事件进入桌面的
|
||||
`reduceRecoveredAgentEvent`,本次仅修改其消息投影与元数据保存,不改变 Agent、SSH
|
||||
传输、取消执行、ACK 或重连控制;本地 SQLite 恢复测试覆盖该修改。未验证 Linux/macOS
|
||||
原生界面,不把本地探针记为远端取消生命周期验收。
|
||||
|
||||
## 2026-09-28:DS Web 资源符号链接与 macOS 发布恢复
|
||||
|
||||
Desktop `v0.15.0` 原生构建中,两个 macOS 目标均因包外符号链接未通过签名校验。
|
||||
Linux Host 隔离 fixture 调用实际 DS 资源准备及 electron-builder 文件复制后,
|
||||
确认相对 CLI 链接变成构建目录的绝对路径。复制现使用 `verbatimSymlinks`,
|
||||
保留 npm 相对链接;回归移除原始安装和暂存目录后,仍须能读取最终包内链接目标。
|
||||
Windows 打包聚焦回归 45 项通过,1 项 POSIX 符号链接测试不适用于 Windows;
|
||||
类型、lint 和 0.15.1 双语说明校验通过。完整冻结快照在 Linux Host 全量
|
||||
5,372 通过、51 跳过,新增符号链接用例实际执行通过;macOS 原生签名仍待发布 CI。
|
||||
这只改变 Desktop 的本地 DS Web 资源准备,不改变 Agent 的独立 Runtime 包装、
|
||||
模型桥或启动控制,模型调用 0 次。恢复版本及最终证据见
|
||||
[发布恢复记录](../../development/release-preparation-0.15.0.md)。
|
||||
|
||||
## 2026-09-27:窄栏添加入口
|
||||
|
||||
“+”已移出页签滚动容器;左右箭头和溢出测量使用扣除添加按钮宽度后的页签区域。
|
||||
Windows Electron 回归覆盖 `300px` 工作栏、默认四页签和 16 个含长标题的页签,验证
|
||||
原生鼠标打开应用目录、创建浏览器实例、Escape 返回、箭头滚动及 Home/End 激活。
|
||||
窄栏扩到 `900px` 后,默认页签的溢出箭头消失,缩回后恢复。
|
||||
中英文、浅深主题均通过,模型调用 0 次。范围与命令见
|
||||
[窄容器布局修复记录](../../quality/responsive-controls-review-2026-09-27.md)。
|
||||
|
||||
## 2026-09-27 Continue Update Status
|
||||
|
||||
The shared Continue adapter now skips the update service before it emits the
|
||||
checking state; behavior is specified in the [native client design](./runtime-native-client-proposal.md#62-continue-与-opencode).
|
||||
The regression executes the patched method and verifies idle-only state when
|
||||
disabled, while retaining the original path when the flag is absent.
|
||||
|
||||
- Windows production coordinator/PTY and real DS browser validation completed:
|
||||
Continue made 2 supplier requests, OpenCode 1, and DS Web 2; all five returned
|
||||
HTTP 200 and the clients displayed the expected answers. Captured terminal
|
||||
output contained no `Checking for updates`. Original settings stayed byte-identical.
|
||||
- Current adapter source was bundled and uploaded through pinned-identity SSH to
|
||||
the shared Linux x64 Host, under a dedicated `/root/tmp/gb-update-check-*`
|
||||
directory. Continue 1.5.47 reached its initialized Ask TUI and displayed
|
||||
`Continue CLI`; 15 seconds of PTY capture contained no update-check text.
|
||||
This startup check made zero model calls and did not run the Agent protocol or
|
||||
remote model bridge. Agent helper imports this same adapter, but complete
|
||||
remote shortcut and real-model acceptance remain unfinished.
|
||||
- Adapter tests: 30 passed. Repository typecheck and lint passed. Full `npm test`
|
||||
reached the tool's 600-second limit without a final summary; it is not recorded
|
||||
as a passing full run.
|
||||
|
||||
Evidence is in the local temporary `opencode/dsh-017-verify` directory:
|
||||
`update-check-evidence.json`, `update-check-main-result.json`, and
|
||||
`remote-pty-run.cjs`. The local action/IPC harness uses jsdom and simulated
|
||||
Electron transport with real child clients. It does not reproduce or rule out
|
||||
full desktop-window freezing. The inherited TLS verification override and lack
|
||||
of a complete background-network capture also limit the evidence.
|
||||
|
||||
### Full production App follow-up
|
||||
|
||||
A fresh `npm run build` passed. The resulting production Main, Preload and
|
||||
Renderer were launched in an isolated Windows Electron profile. Native mouse
|
||||
input selected Continue and opened its terminal; native text input and Enter
|
||||
submitted a minimal request. The actual Continue output contained the expected
|
||||
joined answer and no `Checking for updates`. Main HTTP dispatch instrumentation
|
||||
recorded two additional provider requests, both HTTP 200: this fix's validation
|
||||
now totals seven external model requests. A subsequent no-submit probe copied
|
||||
initialized TUI content and typed input from the active xterm buffer.
|
||||
|
||||
Early driver attempts targeted a restored inactive terminal, giving an empty
|
||||
clipboard; selecting the newly opened terminal resolved this without product
|
||||
changes. Another attempt sent Enter before focus/input settled and dispatched
|
||||
zero requests. These harness failures are not product freeze fixes. The full App
|
||||
remained callable and accepted terminal input in the successful runs; the user's
|
||||
original freeze has not been reproduced or uniquely diagnosed. Captured PNGs
|
||||
have not been visually reviewed. The production TLS policy still enabled the
|
||||
verification override, despite the launcher's strict environment setting.
|
||||
|
||||
Local evidence: `full-app-model-events.json`, `full-app-calls.json`,
|
||||
`full-app-buffer.txt` and the `full-app*.cjs` drivers in the same temporary folder.
|
||||
The isolated profile was removed after checking that no probe-owned Electron or
|
||||
Node processes remained; the separate diagnostic evidence was retained.
|
||||
The full-suite rerun completed in 734 seconds: 5,298 passed,
|
||||
86 skipped and 3 failed tests, plus one failed suite setup. Failures were the
|
||||
OpenCode isolation fixture (`spawnSync npm.cmd EINVAL`), Magic Notes layout's
|
||||
90-second timeout, and two HeartbeatCenter tablist assertions. These files were
|
||||
not changed here; this is not an all-green suite. Original runtime settings were
|
||||
byte-identical after the full-App probes, and no probe-owned processes remained.
|
||||
Remote shortcut integration and full Agent/model acceptance remain outstanding.
|
||||
|
||||
### Failure triage follow-up
|
||||
|
||||
The OpenCode isolation and native Magic Notes layout files passed together through
|
||||
`npm test` (8 tests). The earlier full-suite supervisor invoked Vitest directly,
|
||||
without npm's launcher environment; its OpenCode setup error did not recur through
|
||||
the npm entry point. The layout timeout also did not recur. These focused results
|
||||
do not replace the failed full-suite result.
|
||||
|
||||
Both HeartbeatCenter language cases failed independently at that point. Source inspection
|
||||
shows the graph contains a separate, named PageTabs for events/entities/relations
|
||||
inside the page-level tabs; the older test assumes there can only be one tablist
|
||||
anywhere on the page. Neither that feature nor its test was changed for this
|
||||
Continue fix. No unrelated UI change or assertion relaxation was made.
|
||||
|
||||
A separate 2026-09-27 follow-up corrected the navigation scope assertions after
|
||||
checking the graph design. HeartbeatCenter, SupervisorWorkspace and shared tab
|
||||
tests passed together (96 tests); the full suite was not rerun. See the
|
||||
[validation record](../../quality/responsive-controls-review-2026-09-27.md#heartbeatcenter-断言修复).
|
||||
|
||||
The retained full-App log contains no matching unresponsive, crash, timeout or
|
||||
maximum-update-depth errors. This does not establish the cause of the reported
|
||||
freeze. This follow-up made zero external model requests (the fix-validation total
|
||||
remains seven); the OpenCode regression uses loopback model fixtures.
|
||||
|
||||
## 2026-09-27 Local Native Client Validation
|
||||
|
||||
Scope: [native client proposal](./runtime-native-client-proposal.md), FR-2/3/5/6/7/8,
|
||||
US-2/4/5/6/8, local portions of P1/P2/P3/P5. Source baseline:
|
||||
`55efca3ee1d8a491c4d9709888e302188cd988bd` plus the concurrent working tree.
|
||||
|
||||
- Fixed the coordinator's browser-open failure path: a ready DS service and its
|
||||
gateway remain available for owner-scoped reopen/stop. Startup failures still
|
||||
release their gateway. Focused regressions cover current credentials, work mode,
|
||||
Node selection, concurrent open, owner isolation and retry.
|
||||
The DS service also includes the coordinator configuration key in its own match
|
||||
hash; updated skill digests or launch settings cannot reuse an older instance.
|
||||
- DS Ask now maps built-in gateway read grants to the official MCP tool names.
|
||||
Custom MCP remains Execute-only, following existing Runtime behavior. The real
|
||||
DS process test loads an assigned directory containing `SKILL.md`, rather than
|
||||
only a synthetic loose Markdown skill file.
|
||||
- Custom standard Node uses the current local tool environment selection without
|
||||
a separate npm install. The managed Node fallback still has a bespoke pinned npm
|
||||
install and remains a delivery gap; it was not exercised by this real-model run.
|
||||
- The opt-in IPC integration test uses the production action component, preload
|
||||
methods, registered handlers, saved project/model stores, coordinator, official
|
||||
DS Web process, and real Continue/OpenCode PTYs. Electron transport is simulated
|
||||
by the existing IPC test harness and the action component runs in jsdom; this is
|
||||
not a full desktop-window or packaged-app acceptance result. DS Web itself was
|
||||
driven in real headless Edge. The hook retains credentials only in process
|
||||
memory; the temporary settings file stores opaque test-cipher identifiers.
|
||||
|
||||
| Client | Configured Model | Supplier HTTP Dispatches | Result |
|
||||
| --- | --- | ---: | --- |
|
||||
| DS Web 0.1.7-rc.2 | `deepseek-flash` | 2 | Workspace/model selected automatically; Web displayed `NATIVE_WEB_OK` |
|
||||
| Continue 1.5.47 | `gpt-6-astra` | 4 | Two prompts and two title requests; second transcript confirms the assistant response, with underscores consumed by Markdown rendering |
|
||||
| OpenCode 1.18.29 | `gpt-6-astra` | 1 | Native TUI displayed `NATIVE_OPENCODE_OK`; supplier response also contains it |
|
||||
| Total | | 7 | All HTTP 200; no further dispatches needed |
|
||||
|
||||
The first terminal assertion matched echoed prompt text and was rejected as
|
||||
evidence. The second prompt did not contain the expected joined answer. The
|
||||
OpenCode probe waits for the rendered TUI and uses bracketed paste before Enter.
|
||||
The initial six-dispatch bound was increased to eight to cover the remaining
|
||||
OpenCode path; seven were used in total. The host environment supplied
|
||||
`NODE_TLS_REJECT_UNAUTHORIZED=0`, so this run does not verify strict TLS.
|
||||
|
||||
Evidence under the approved temporary `opencode/dsh-017-verify` directory:
|
||||
`native-live-evidence.json`, `native-main-result.json`, `native-web.png`, and
|
||||
`native-{continue,opencode}-terminal.txt`. `native-live-run.cjs` composes the existing
|
||||
encrypted settings snapshot/safeStorage bootstrap with the production IPC test.
|
||||
Original `runtime-settings.json` remained byte-identical. The final test verifies
|
||||
DS stop/reopen/owner isolation and failed fetch after stop, closes both terminal
|
||||
sessions, and removes its temporary workspace/configuration. Owned live client
|
||||
processes were absent after completion.
|
||||
|
||||
Checks: official DS/coordinator focused tests passed (12) under standard Node 24.19.0;
|
||||
the opt-in UI/preload/IPC test passed both without provider calls and with the live
|
||||
hooks. Four installed Continue/OpenCode Ask/Execute tests passed with real clients
|
||||
and deterministic supplier responses; these made zero external supplier calls.
|
||||
Repository lint and Agent/Renderer TypeScript checks passed. Main typecheck is
|
||||
currently blocked by concurrent SSH
|
||||
test doubles missing `forwardLoopback`; no local native-client type errors remain.
|
||||
The full `npm test` run finished with 5,285 passed, 79 skipped and one failure:
|
||||
the desktop runtime-hook fixture lacked the new DS Web package tree. The fixture
|
||||
was corrected and all 44 build-release tests then passed in a focused rerun. The
|
||||
full run began before the final configuration-key regression and fixture updates;
|
||||
the final DS/coordinator and UI/preload/IPC paths were rerun separately and passed.
|
||||
This is not a claim of a subsequent all-green full-suite run. Full output is in
|
||||
`native-full-tests.log` beside the live evidence.
|
||||
|
||||
Remaining at this checkpoint: remote coordinator wiring and real Host acceptance belong to the
|
||||
concurrent remote implementation; Continue/OpenCode Ask built-in MCP mappings,
|
||||
managed standard Node distribution, full Electron/packaged UI acceptance and other
|
||||
platforms are not verified here. `ipc.ts` was not edited in this work.
|
||||
|
||||
2026-09-28 update: native Continue/OpenCode Ask now pass Main-bound read-tool
|
||||
names to native permission flags and execution hooks. The Story Graph work also
|
||||
adds Supervisor enablement to native-client reuse keys and gateway checks.
|
||||
The OpenCode generated plugin is executed by a focused test; packaged native UI
|
||||
acceptance remains separate. See [Story Graph validation](../conversation-supervision/progress.md#2026-09-28-story-graph-只读工具).
|
||||
|
||||
## 2026-09-26 结构升级与历史回收分离(未发布)
|
||||
|
||||
- schema 45/46 的回归先复现普通结构升级执行 `VACUUM`,修复后不转换历史、
|
||||
|
||||
@@ -110,7 +110,9 @@ No SQLite schema migration or separate checklist store is needed.
|
||||
|
||||
`ConversationTaskStrip` 与 `RuntimeChecklistStrip` 共用顶部容器,任务在上、清单在下,
|
||||
各自展开和折叠。没有 Task 时清单仍可显示;远程会话也保留清单入口。总高度不超过
|
||||
45vh,各自展开内容不超过 20vh 并内部滚动,标题不收缩。清单内容区可用键盘聚焦和滚动。
|
||||
45vh,Task 展开内容不超过 20vh 并内部滚动,标题不收缩。清单详情复用 `AnchoredMenu`
|
||||
的 `group` 语义和 `FloatingPortal`,宽度跟随摘要按钮并受视口约束,高度按可用空间限制,
|
||||
内部可用键盘滚动。展开不改变顶部容器或消息流的高度;点击外部、焦点移出或 Escape 收起。
|
||||
|
||||
状态文字与条目首行按文字基线对齐,状态图标单独居中。CN 不推断进行中或优先级。
|
||||
新轮先选择本轮消息,再读取清单,不回溯寻找旧轮非空清单。后台更新保持展开状态和焦点。
|
||||
|
||||
@@ -100,6 +100,16 @@ DeepSeek Harness 按调用 ID 保留名称、输入和摘要,结束事件省
|
||||
为静态,不凭请求尚未结束暗示仍有进展;会话列表闪点和发送、停止按钮保持原有行为。
|
||||
持久化快照中的同一条消息仍为生成中时,也不能覆盖本地已收到的终态,即使快照的
|
||||
会话更新时间更晚;否则连续发送或刷新会让已结束的请求重新显示停止按钮。
|
||||
- 失败和取消的终止提示只进入消息状态,不补写正文或文本块,已有回答、推理与工具输出
|
||||
保留。取消使用中性色和礼貌级 `status`,真实失败使用危险色和 `alert`;运行记录的
|
||||
取消结果标题为“任务已取消”。工具详情已表达同一失败时,不再复制到消息底部。
|
||||
- 最新失败或取消消息只有在上一条用户消息含可回填文字时显示“重新编辑”。点击只回填
|
||||
输入框并聚焦,由用户修改后自行发送;附件单独发送且无文字时不显示此按钮。
|
||||
- 实时事件和 Main 历史恢复均将事件的 `failed / cancelled` 写入消息元数据
|
||||
`terminalStatus`;既有 `state: error` 继续表示未成功终态,不改 SQLite 枚举。
|
||||
新事件不按提示文案识别取消。旧快照无此字段时,仅兼容已发布的精确取消标签。
|
||||
旧记录若正文与状态完全相同,且无文本块或唯一文本块位于末尾并等于该状态,展示时
|
||||
保留正文、隐藏重复状态;不修改持久数据,不删除正文中的同名句子或部分匹配内容。
|
||||
- Continue、DeepSeek Harness 和远端 ACP 保留其已接入的处理与工具事件,不伪造未接入
|
||||
的原生重试状态。直连模型的重试等待与请求开始文案见
|
||||
[直连模型 UI 设计](../direct-model-agent/ui-design.md#6-错误与通知);本次不改变任何
|
||||
|
||||
@@ -0,0 +1,401 @@
|
||||
# Runtime 原生客户端启动方案
|
||||
|
||||
日期:2026-09-26
|
||||
Status: Local shortcut/coordinator paths and configured-model responses verified on Windows; remote integration and packaged Node delivery remain open.
|
||||
范围:Continue、OpenCode 的交互终端,以及 DeepSeek Harness(DS)的官方 Web 客户端。
|
||||
|
||||
本文集中维护该新增入口的需求、场景、行为规则、接入设计和验收计划。既有终端行为由
|
||||
[多终端页签 PRD](./terminal-tabs-prd.md)维护,既有 Runtime 权限和资源边界由
|
||||
[Runtime 交互边界](./runtime-interactions.md)维护;本文描述新增客户端路径,不宣称它已经具备后台 Runtime 的全部能力。
|
||||
|
||||
## 1. 方案选择
|
||||
|
||||
在聊天输入区“压缩上下文”左侧增加原生客户端入口。Continue 和 OpenCode 打开 GoodBuddy
|
||||
工作栏中的交互终端;DS 启动官方 Web 服务并在系统默认浏览器中打开。使用当前项目目录和
|
||||
当前模型,默认建立独立客户端会话,不自动复制 GoodBuddy 聊天历史。
|
||||
|
||||
| 当前 Runtime | 按钮文字 | 打开目标 | 本轮计划范围 |
|
||||
| --- | --- | --- | --- |
|
||||
| Continue | 在终端中打开 | 工作栏新终端页签,启动原生 CLI | 本地和托管 SSH 项目 |
|
||||
| OpenCode | 在终端中打开 | 工作栏新终端页签,启动原生 TUI | 本地和托管 SSH 项目 |
|
||||
| DeepSeek Harness | 在浏览器中打开 | 系统默认浏览器,访问官方 Web 应用 | 本地项目 |
|
||||
| 内置模型 | 不显示此快捷入口 | 无 | 保持现状 |
|
||||
|
||||
DS 采用官方 `@deepseek-ai/dsh` Web 应用,不开发新的 DS 终端前端,也不在首轮嵌入
|
||||
GoodBuddy 浏览器工作栏。远程 DS 不在本轮范围:当前共享远程启动契约只接受
|
||||
`opencode` 和 `continue`,不能通过快捷按钮绕过该范围。
|
||||
|
||||
## 2. 调研依据与证据范围
|
||||
|
||||
下表保留早期测试报告,作为技术选型线索。2026-09-26 新增的 DS 0.1.7-rc.2
|
||||
实测单列在表后;Continue、OpenCode 和远程交互终端本轮未复测。
|
||||
|
||||
| 历史报告项目 | 报告结果 | 尚需验证 |
|
||||
| --- | --- | --- |
|
||||
| Continue 1.5.47 | 标准 Node 与真实 PTY 可显示交互输入、配置和模型名称;直接用 Electron 启动失败 | 启动路径错误、当前模型注入、真实请求和权限 |
|
||||
| OpenCode 1.18.29 | 随包二进制可显示 TUI,响应终端尺寸变化 | 排除已有用户配置干扰,验证指定模型实际生效 |
|
||||
| DS Web 0.1.5-rc.3 | Node 24.19.0 启动;Edge 可访问页面及模型设置 | 项目自动选中、模型桥、真实对话、工作模式 |
|
||||
| DS Windows 依赖 | 首次缺少 Sharp 原生包,补装后可启动 | 正式资源中预先带齐各目标平台依赖 |
|
||||
| DS 工作目录 | 指定 cwd 后仍要求选择工作区 | 工作区创建及页面选中的完整路径 |
|
||||
| 终端相关回归 | 报告为 5 个文件、29 项通过 | 新入口尚无回归或端到端验收 |
|
||||
| 远程 Host | 两条网络路线 SSH 端口可达 | 登录后的当前源码、Runtime、模型桥真实验证 |
|
||||
|
||||
早期文档整理和依赖升级报告的真实模型调用为 0 次。本轮核查另发现临时目录
|
||||
`dsh-017-live` 的 7 次历史 dispatch 记录;本轮在独立 `dsh-017-verify` 目录新增
|
||||
9 次,两个计数分别保留。测试过程和结果以 [DS 实现进度](../deepseek-harness/progress.md#2026-09-26-真实模型与官方-web-验证)为准。
|
||||
|
||||
本轮直接检查了以下仓库材料:
|
||||
|
||||
- `src/main/terminal/terminal-session-manager.ts`:已有本地与 SSH 会话创建、窗口归属、事件转发和关闭管理,当前创建路径启动普通终端。
|
||||
- `src/shared/remote-runtime-launch-contracts.ts`:远程 Runtime 枚举包含 Continue 和 OpenCode。
|
||||
- `UI-DESIGN.md`:规定 Composer 元信息区、工作栏、通知、键盘及响应式规则。其聊天章节仍写远程只支持 OpenCode,与当前共享契约不一致;实施时需沿 UI 到执行路径核实并同步修正,不能单凭枚举认定远程交互已可用。
|
||||
|
||||
上游参考:[官方仓库](https://github.com/deepseek-ai/deepseek-harness)、
|
||||
[CLI 文档](https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md)、
|
||||
[使用指南](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/guide/index.md)。
|
||||
这些链接随上游变化;实施时须为选定包版本补充对应源码 revision、启动参数和接口依据。
|
||||
历史测试版本是候选版本,不作为未经复测的最终发布版本。
|
||||
|
||||
2026-09-26 仓库内后台 DS Runtime 已升级至 `0.1.7-rc.2`,Cordis 升级至
|
||||
`4.0.4`,验证记录见 [DS 实现进度](../deepseek-harness/progress.md)。此版本来自
|
||||
npm `next` 标签;查询时 `latest` 仍为较旧的 `0.1.0-rc.6`。本轮另用官方
|
||||
`@deepseek-ai/dsh@0.1.7-rc.2` 验证 Web。Prepared Web resources and backend validation are recorded in section 9.1.
|
||||
|
||||
### 2.1 DS 0.1.7-rc.2 实测结论
|
||||
|
||||
Windows x64、标准 Node 24.19.0、Edge 154.0.4258.37 下,官方 Web 可承接当前
|
||||
工作区和已配置模型,完成页面真实对话。Main 使用 safeStorage 解密隔离副本中的模型
|
||||
配置,经现有 managed model bridge、AgentModelGateway 和 loopback proxy 转发。
|
||||
浏览器与 DS 只取得本地桥接信息,原始 `runtime-settings.json` 测前测后逐字节一致。
|
||||
|
||||
| 实测路径 | 结果 | 供应商 HTTP dispatch |
|
||||
| --- | --- | ---: |
|
||||
| 后台 Ask → `read` | 返回文件中未写入 prompt 的随机校验码,收到工具完成及用量事件 | 2 |
|
||||
| 同一后台会话切 Execute → `write` | 创建测试文件,内容校验通过 | 2 |
|
||||
| Execute → `pwsh` | PowerShell 读回该文件,结果正确 | 2 |
|
||||
| 官方 Web → 当前模型 → 文件读取 → 回答 | 页面返回另一随机校验码,刷新后保留结果 | 3 |
|
||||
| 合计 | 请求中的模型均为 `deepseek-flash`,HTTP 均为 200 | 9 |
|
||||
|
||||
`0.1.7-rc.2` 是 Harness/Web 包版本;`deepseek-flash` 是实际配置和请求中的模型 ID。
|
||||
Web 的 3 次请求包含 1 次未携带工具的请求,计数没有只按用户提交次数计算。
|
||||
后台使用当前源码的真实 ACP、Host、控制面和供应商流式响应,但 Host 在测试进程内组合;
|
||||
该结果不等于重新验收 GoodBuddy 完整 UI 或 Utility Process。Web 使用真实 CLI 子进程和
|
||||
浏览器自动化,未通过尚未实现的快捷按钮。测试继承了环境中的
|
||||
`NODE_TLS_REJECT_UNAUTHORIZED=0`,因此没有验证严格 TLS 证书校验。
|
||||
|
||||
工作区和模型自动准备已验证;官方 Web 到 GoodBuddy Ask/Execute 的工具执行适配、
|
||||
Skills/MCP 承接、取消和产品生命周期仍待实现与验证。此次可行性验证不要求完成按钮。
|
||||
|
||||
## 3. 产品需求
|
||||
|
||||
| ID | 要求 | 用户可见的验收结果 |
|
||||
| --- | --- | --- |
|
||||
| FR-1 | 在压缩按钮左侧提供 Runtime 对应入口 | 无历史、无压缩能力时仍能打开客户端 |
|
||||
| FR-2 | 按项目执行空间启动 | 本地使用本地目录,SSH 使用绑定 Host 与远端目录;目录失效时说明原因 |
|
||||
| FR-3 | 注入点击时选定模型 | 客户端首轮直接使用该模型,无需重复输入供应商密钥 |
|
||||
| FR-4 | 创建独立客户端会话 | 不修改原聊天历史,不把打开操作伪装成当前聊天的续接 |
|
||||
| FR-5 | 保持所选工作模式的执行边界 | Ask 的 AI 工具路径只读;Execute 使用相应账号已有权限 |
|
||||
| FR-6 | 管理启动、重开和关闭 | 不因收起工作栏或切换项目中断;关闭对应客户端资源时释放其桥接 |
|
||||
| FR-7 | 保留可处理的失败信息 | 启动、模型和远程错误可区分,允许修正后重试,不清空聊天草稿 |
|
||||
| FR-8 | 明确原生能力与 GoodBuddy 能力差异 | 已分配的 Skills、MCP 等逐项接入并验证;未接入项有明确说明 |
|
||||
| FR-9 | 交付可直接运行的客户端资源 | 用户无需自行运行 npx、补装 Sharp 或查找 Node |
|
||||
|
||||
聊天附件、知识范围、专家提示及历史不自动移入独立客户端。首轮不提供聊天双向同步、
|
||||
Task 关联恢复或客户端历史导入。原生客户端产生的历史由对应客户端保存,不能在 GoodBuddy
|
||||
活动记录中显示为已经同步的聊天内容。
|
||||
|
||||
FR-8 的实施清单须区分原生工具、GoodBuddy 分配的 Skills、自定义 MCP、内置 MCP、知识工具
|
||||
以及需要 GoodBuddy 原生确认的配置工具。支持情况以真实调用为准;现有 DS 宿主插件能力不能
|
||||
直接算作 DS Web 能力。发现现有分配无法承接时,在实施评审中明确差异和处理方式,不能默默忽略。
|
||||
|
||||
## 4. 场景与状态规则
|
||||
|
||||
### 4.1 用户场景
|
||||
|
||||
| ID | 前提与动作 | 预期结果 | 需求 |
|
||||
| --- | --- | --- | --- |
|
||||
| US-1 | 本地项目选中 Continue 或 OpenCode,点击入口 | 展开工作栏,新建带 Runtime 与项目名称的终端,进入可输入的原生界面 | FR-1~4 |
|
||||
| US-2 | 本地项目选中 DS,首次点击入口 | 服务就绪后打开浏览器,当前项目已选中、模型可直接使用 | FR-2~4、9 |
|
||||
| US-3 | 在支持的 SSH 项目点击终端入口 | 使用已保存 Host 连接,在远端项目目录启动对应 Runtime | FR-2、3 |
|
||||
| US-4 | 启动期间连续点击 | 同一启动只创建一次;按钮显示启动中 | FR-6 |
|
||||
| US-5 | 已打开客户端后切换项目或模式 | 旧客户端保持原项目和启动模式;新操作使用新选择 | FR-5、6 |
|
||||
| US-6 | 启动失败或模型请求失败 | 保留原因与可操作的重试方式;聊天内容和草稿不变 | FR-7 |
|
||||
| US-7 | Ask 下从原生界面请求写文件、执行写命令或使用写入 MCP | AI 执行边界拒绝写入,不能通过客户端模式开关绕过 | FR-5、8 |
|
||||
| US-8 | 关闭终端、停止 DS 服务或退出 GoodBuddy | 对应进程和桥接释放,其他会话不受影响;原生历史保留 | FR-4、6 |
|
||||
|
||||
### 4.2 行为决策
|
||||
|
||||
启动参数按点击时的项目、执行空间、Runtime、模型和工作模式确定。界面后续切换不修改已运行
|
||||
客户端。这里只需保留进程运行所需的内存记录,不增加持久启动快照、恢复日志或数据库迁移。
|
||||
|
||||
Continue 和 OpenCode 启动成功后,每次新的点击创建独立终端。启动中的重复点击合并到同一
|
||||
进行中操作。终端会话数量沿用现有管理器规则,不新增一套数量控制。
|
||||
|
||||
DS 按项目、模型配置及工作模式匹配运行服务。配置相同且服务可用时重新打开原服务;配置变更后
|
||||
新建匹配实例,保留原实例直到用户停止或应用退出,避免在已有页面中静默改变模型和权限。
|
||||
同一匹配项并发启动只执行一次。服务已退出则清除内存记录,下一次点击重新启动。
|
||||
|
||||
| 事件 | 处理 | 关联场景 |
|
||||
| --- | --- | --- |
|
||||
| 启动中切换项目 | 操作仍属于原项目;完成时不抢占新项目的工作栏焦点 | US-4、5 |
|
||||
| 收起工作栏、切换页面 | 保留终端与其模型桥 | US-5 |
|
||||
| 关闭终端页签 | 停止该 PTY/远端进程,释放相应配置和桥接 | US-8 |
|
||||
| 关闭 DS 浏览器标签 | 不推断服务已停止;再次点击可重开 | US-2、8 |
|
||||
| 用户停止 DS 服务 | 停止该服务和桥接;浏览器页面失去连接;保留原生历史 | US-8 |
|
||||
| GoodBuddy 退出 | 清理自己创建的进程与桥接,不停止用户其他进程 | US-8 |
|
||||
| SSH 断开 | 显示断开;收束对应请求,重试时重建连接,不宣称原会话已恢复 | US-3、6 |
|
||||
| 系统浏览器打开失败 | 保留可重开的就绪服务,通知用户重试;不复制含令牌地址到普通日志 | US-6 |
|
||||
| 服务启动失败 | 清理本次创建的临时资源,再允许重试;不删除用户原生历史 | US-6 |
|
||||
|
||||
Ask 沿用现有 Runtime 按工具命令名判断的只读规则,不改变用户手动终端的已有权限。
|
||||
DS 后台的 `read` 和原生 `skill` 可在 Ask 执行;`write`、`edit`、`pwsh`/`bash`
|
||||
在 Ask 拒绝,在 Execute 放行,代理工具沿用现有分类。工具出现在模型请求目录中不等于
|
||||
获准执行,判断仍在 `tools/execute` 路径。Web 接入复用这些规则,不增加 Shell 文本分析、
|
||||
目录围栏、逐工具二次确认或新的权限等级。Execute 使用当前账号已有的文件、进程和网络权限。
|
||||
|
||||
官方 `dsh-plan-mode@0.1.7-rc.2` 的 Plan 只改变规划提示和状态,工具目录不随之变化;
|
||||
权限预设由另外的 sandbox/approval 组件处理。因此不能把 Plan 名称当成 Ask 实现,
|
||||
也不能把官方默认“工作区内修改”当成 GoodBuddy Execute。接入时将启动模式接到现有
|
||||
工具名规则,原生页面的模式选择保持同一语义。
|
||||
|
||||
这些规则覆盖普通启动、使用、关闭和已知失败。尚需技术验证的项目见第 7 节;它们不构成新增
|
||||
授权层级或通用恢复框架的理由。
|
||||
|
||||
## 5. 界面设计
|
||||
|
||||
输入区下方从左到右排列“在终端中打开/在浏览器中打开”“压缩上下文”和现有用量信息。
|
||||
两个按钮独立判断可用性。采用同一轻量操作组,避免两组绝对定位相互覆盖;窄输入区允许
|
||||
操作组换行,保留模式说明、用量信息和对称边距。稳定预留元信息高度的实现应与
|
||||
[统一 UI 规范](../../../UI-DESIGN.md)一起更新并验证。
|
||||
|
||||
按钮使用原生 `button`、共享主题令牌和焦点环,支持 Tab、Enter 与 Space。打开终端后焦点
|
||||
进入新终端;外部浏览器由系统处理焦点。启动期间保留按钮宽度并显示“正在打开…”,完成后
|
||||
恢复原文案。缺少项目目录时在相关位置提供选择目录的操作;其他异步失败进入全局通知视口。
|
||||
|
||||
DS 服务运行后,在入口旁提供轻量菜单“重新打开”“停止此服务”;操作指向当前匹配服务。
|
||||
若正在生成,停止前说明会中断该服务中的请求。输入区不常驻显示独立会话和服务生命周期说明。不在每次启动时增加确认弹窗。
|
||||
|
||||
按钮快捷入口根据所选 Runtime 显示,不改变工作栏“+”中的普通终端和浏览器入口。已有服务
|
||||
的停止入口应在切换回来后仍可找到。
|
||||
|
||||
## 6. 技术接入
|
||||
|
||||
### 6.1 进程职责
|
||||
|
||||
Renderer 仅提交当前会话或项目标识及选择标识。Main 重新解析项目、模型配置、工作模式与
|
||||
程序路径,通过共享 Zod 契约和显式 preload 方法完成调用。保留已有可信发送方校验,供应商
|
||||
密钥留在 Main 加密设置和模型请求路径中。
|
||||
|
||||
建议新增小型原生客户端启动服务,负责配置准备、启动去重和资源释放。终端会话仍由
|
||||
`TerminalSessionManager` 管理;DS 服务只需内存中的子进程、地址和桥接引用。不要新建平行
|
||||
终端管理器或通用进程恢复引擎。
|
||||
|
||||
共享接口应返回可供界面使用的启动状态、终端标识或 DS 服务标识。外部 URL 由 Main 打开,
|
||||
不允许 Renderer 提交任意程序、命令行、凭据或任意服务地址。错误保留组件、阶段和脱敏原因。
|
||||
|
||||
DS Web 随包依赖通过 `build/native-dsh-resources.cjs` 保留 npm 的嵌套布局。
|
||||
复制时原样保留相对符号链接,不能将 CLI 链接改写成构建机的绝对路径;
|
||||
经过 electron-builder 资源复制后,即使移除原始安装和暂存目录,链接仍须能解析到包内文件。
|
||||
这一交付约束覆盖 FR-9;不改变 Agent 的独立 Runtime 打包路径。
|
||||
|
||||
### 6.2 Continue 与 OpenCode
|
||||
|
||||
Continue 使用已解析的标准 Node 启动固定版本 CLI,不能直接假定 Electron 的
|
||||
`process.execPath` 等于 Node。OpenCode 使用已有平台对应可执行资源,启动交互 TUI。
|
||||
两者均复用现有配置生成机制,但单独验证原生交互模式可接受的参数、模型 ID、环境变量及
|
||||
Skills/MCP 配置,避免继承测试机器的全局默认模型。
|
||||
|
||||
本地 PTY 创建需接受 Main 生成的可执行路径、参数、环境和 cwd,不能先打开普通 Shell 再
|
||||
模拟键入一段含凭据的启动命令。退出 CLI 后是否保留终端输出沿用既有终端体验;其桥接应
|
||||
随 CLI 生命周期收束,不等到整个聊天结束。
|
||||
|
||||
Continue 的共享宿主适配器在 `GOODBUDDY_DISABLE_CONTINUE_UPDATES=1` 时,直接让更新服务保持 idle,并显示 `Continue CLI`,不进入 checking 状态。仅跳过底层版本查询仍会短暂显示 `Checking for updates`,因此服务入口和版本查询两处都需跳过。本地原生终端与 Agent Continue helper 使用同一适配器;已有缓存按补丁内容哈希重新生成。实测范围见[更新提示验证记录](./progress.md#2026-09-27-continue-update-status)。
|
||||
|
||||
模型桥作为客户端会话资源保持有效。复用前检查当前桥接是否依赖单轮请求、单一消息 ID
|
||||
或短时授权;必要时只提取所需的会话级资源接口。真实供应商密钥不写入 CLI 配置,客户端
|
||||
仅获得桥接所需的局部连接信息。
|
||||
|
||||
### 6.3 DS Web
|
||||
|
||||
使用固定版本的官方 Web 包,通过标准 Node 在回环地址启动。以下命令已在
|
||||
`@deepseek-ai/dsh@0.1.7-rc.2`、Windows x64、Node 24.19.0 下启动成功:
|
||||
|
||||
```text
|
||||
<managed-node> <resolved-dsh-cli> web --no-open --host 127.0.0.1 --port 0
|
||||
```
|
||||
|
||||
生产环境直接使用已准备的资源,不在用户点击时执行不固定版本的 `npx`。Web 资源与当前
|
||||
DeepSeek Harness 后台 Host 依赖分开管理,避免为了 Web UI 升级而隐式替换后台 Agent 库。
|
||||
沿用既有受管工具环境和资源分发机制,不新增下载体系。若需在线分发,按该功能文档规范
|
||||
明确下载源设置范围、固定版本、大小和 SHA-256;镜像与原地址使用相同字节内容。
|
||||
|
||||
使用 GoodBuddy 管理的独立 `DSH_HOME`,与用户已有 DS 安装隔离。原生历史和用户设置属于
|
||||
持久数据,服务退出只删除可重建启动配置。多个运行实例不得共享不支持并发访问的数据库;
|
||||
在验证官方存储行为后确定按项目及配置分目录的最小方案。
|
||||
|
||||
启动后经官方支持的配置/API 创建或查找项目工作区,初始化模型连接,再打开已选中目标
|
||||
工作区的页面。仅设置 cwd 或成功创建后台工作区都不足以完成该步骤。不得直接修改未经
|
||||
确认的 DS 私有数据库结构。
|
||||
|
||||
本轮验证使用 `$DSH_HOME/cordis.patch.yml` 配置 `llm-pi-ai` 的 `goodbuddy` provider,
|
||||
设置 `api: openai-completions`、本地桥 `baseURL`、`apiKeyEnv` 和模型列表;
|
||||
`agent-default-model` 指向同一 provider/model。环境变量中只放本地桥接标识。
|
||||
官方 CLI 的 `profile-boot` 代码将该 patch 作为用户配置层加载。
|
||||
|
||||
取得官方启动地址并建立认证 cookie 后,调用 `POST /api/workspace/create`,请求形态为:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "client-request",
|
||||
"rpcId": "<uuid>",
|
||||
"method": "workspace/create",
|
||||
"payload": { "args": { "request": { "path": "<project-directory>" } } }
|
||||
}
|
||||
```
|
||||
|
||||
该接口在首次运行返回 `created: true`,重开同一测试目录时返回 `created: false`。
|
||||
随后访问根页面,两次均自动选中 `workspace` 和 `deepseek-flash`,没有手动选择模型或
|
||||
再次输入供应商密钥。此证据覆盖单项目、独立 `DSH_HOME`;多项目共享服务的选中规则未测。
|
||||
首次页面保留官方“内测声明”的“继续”操作;测试通过原生按钮继续,没有伪造接受记录。
|
||||
官方默认权限显示“工作区内修改”,本轮只验证读取;权限适配按第 4.2 节另行接入。
|
||||
|
||||
Main 检查服务就绪后,使用 Electron `shell.openExternal` 打开官方规定的访问地址。
|
||||
如地址带认证令牌,沿用官方认证方式,不写入普通日志。浏览器只访问本机服务;模型请求
|
||||
通过 Main 中的桥接到达供应商。HTTP、流式响应、取消和错误映射都需实测。
|
||||
|
||||
### 6.4 远程 Continue / OpenCode
|
||||
|
||||
沿用 SSH Host 身份、凭据存储和 SSH PTY,并通过既有 GoodBuddy Agent 部署资源定位远端
|
||||
Runtime。远端配置与模型桥需要客户端生命周期,不能直接复用一次聊天请求结束即释放的
|
||||
桥接实例。远端使用已有模型桥协议及传输路径,是否需要补充生命周期接口由源码验证决定。
|
||||
|
||||
开发时必须在共享 Linux x64 Host 上运行当前改动,按
|
||||
[远程主机技术设计](../remote-host/technical-design.md)执行真实启动、模型请求、取消、
|
||||
断开和清理。端口可达不等于验证通过;若 Host 不可达,应记录阻塞,不能宣布远程功能完成。
|
||||
|
||||
远程 DS 将来若扩展,可评估远端 Web 加 SSH 本地端口转发;本轮不修改 DS 远程能力声明。
|
||||
|
||||
## 7. 实施顺序与技术验证
|
||||
|
||||
| 阶段 | 工作与应提交证据 | 通过条件 |
|
||||
| --- | --- | --- |
|
||||
| P1 原生配置验证 | 固定三个客户端版本;保存脱敏命令、环境与程序路径;隔离已有全局配置 | Continue/OpenCode 使用指定模型;DS 自动选中目标项目 |
|
||||
| P2 模型与模式 | 每个客户端发送最小真实请求;验证流式、取消、Ask 写入拒绝及 Execute 专用目录写入 | 请求确实经过 GoodBuddy 模型桥;客户端模式切换不能破坏 Ask 边界 |
|
||||
| P3 生命周期接入 | 配置、PTY、DS 进程和模型桥接入现有管理路径 | 重开、失败重试、关闭及退出能释放对应资源,原生历史保留 |
|
||||
| P4 远程验证 | 在共享 Host 部署当前代码,验证 Continue/OpenCode 的 SSH PTY 与模型桥 | 启动、请求、取消、断开和重试均有真实 Host 证据 |
|
||||
| P5 UI 与交付资源 | 接入按钮、通知、停止 DS 服务;完善平台资源与文档 | 从真实按钮到客户端完成对话,无手动补依赖步骤 |
|
||||
|
||||
P1、P2 是实施前段的实验任务,完成后继续交付完整入口,不将实验程序或不可用按钮作为最终功能。
|
||||
|
||||
DS 单项目工作区选中和当前模型桥协议已通过本轮验证。后续优先接入三个客户端的既有
|
||||
Ask/Execute 工具规则、Skills/MCP 配置及客户端生命周期,再完成快捷入口和交付资源。
|
||||
官方 DS 首次预览声明保留原生“继续”流程,模型配置提前准备。
|
||||
|
||||
## 8. 验收计划
|
||||
|
||||
| 验收面 | 检查内容 | 需求与场景 |
|
||||
| --- | --- | --- |
|
||||
| 实际使用 | 每个本地客户端从 GoodBuddy 按钮进入当前项目,使用当前模型完成一轮真实对话 | FR-1~4、US-1、2 |
|
||||
| 配置隔离 | 预置另一套全局模型后,仍使用当前选择;两个项目不串目录或配置 | FR-2、3、US-5 |
|
||||
| 工作模式 | Ask 尝试文件写入、Shell 写入和 MCP 写入均不执行;Execute 在专用测试目录成功写入 | FR-5、8、US-7 |
|
||||
| 能力复用 | 为声明支持的 Skills、MCP 各验证实际加载及最小调用;列出未承接能力 | FR-8 |
|
||||
| 生命周期 | 连点启动、切项目、隐藏工作栏、关闭页签、重开 DS、停止服务及退出 | FR-6、US-4、5、8 |
|
||||
| 已知失败 | Node/原生依赖缺失、失效目录、模型错误、浏览器打开失败、SSH 中断 | FR-7、9、US-6 |
|
||||
| 远程 | 当前源码在共享 Linux x64 Host 上完成 Continue/OpenCode 的 Ask/Execute、模型和断开场景 | FR-2、3、5、US-3 |
|
||||
| UI | 浅深色、键盘操作、窄输入区、无压缩按钮、空对话、200% 文字缩放 | FR-1、US-1、2 |
|
||||
| 平台资源 | 对实际交付的 Windows、macOS、Linux 架构逐项验证 Node、PTY、CLI 和 DS 原生依赖 | FR-9 |
|
||||
|
||||
完成源码后执行 `npm test`、`npm run typecheck`、`npm run lint`。修改生产构建资源时再按
|
||||
仓库开发规则执行构建验证。单元测试覆盖行为和回归,不能代替真实按钮、模型和远程 Host 路径。
|
||||
每份实测报告记录日期、源码 commit、包版本、平台、结果、脱敏证据位置及实际模型调用次数。
|
||||
|
||||
## 9. 文档交付状态
|
||||
|
||||
本轮完成 DS 后台真实模型与官方 Web 主流程验证,更新方案和
|
||||
[DS 进度证据](../deepseek-harness/progress.md#2026-09-26-真实模型与官方-web-验证)。
|
||||
P1 中 DS 单项目启动、模型预配置和工作区选中,以及 P2 中 DS 模型桥请求已实测。
|
||||
The DS Web backend implementation and its focused validation are recorded below. Current local shortcut evidence is recorded in [workbar progress](./progress.md#2026-09-27-local-native-client-validation); full Electron UI acceptance remains separate.
|
||||
后续入口交付事实写入工作栏 [progress.md](./progress.md),按 FR、US 和阶段编号关联本方案。
|
||||
|
||||
实施时同步更新工作栏产品范围、终端规范、Runtime 交互边界及根 UI 规范;DS Web 的版本、
|
||||
依赖与兼容性写入 [DeepSeek Harness 文档](../deepseek-harness/README.md),远程部署事实写入
|
||||
[远程主机文档](../remote-host/README.md)。保持各自职责,不复制多个相互冲突的支持矩阵。
|
||||
|
||||
### 9.1 DS Web Backend, 2026-09-26
|
||||
|
||||
`src/main/agent/native-dsh-web-client.ts` exports `NativeDshWebClientService`.
|
||||
Construct it with `rootDirectory`, an async `resolveLaunchEnvironment` returning
|
||||
`{ nodeExecutablePath, environment }`, and `resourcesPath` in packaged builds.
|
||||
`start({ projectId, workspace, profile, workMode, configurationKey?, skillDirectories?, mcpServers? })`
|
||||
returns `{ id, url }`. Main opens this URL with `shell.openExternal`; it must not
|
||||
log the token-bearing URL or pass it to Renderer. `stop(id)` and `dispose()` close
|
||||
the owned process tree and bridge. A browser-open failure leaves the service ready
|
||||
for another call. Matching concurrent starts reuse one instance; changed model
|
||||
credentials, project, mode, or capability assignments create a separate instance.
|
||||
|
||||
The service uses the existing managed model bridge, AgentModelGateway, and loopback
|
||||
proxy. Provider credentials stay in Main. Each matching configuration has its own
|
||||
persistent DSH_HOME. Shutdown removes launch configuration and the bridge ledger,
|
||||
while retaining native history and settings. Startup authenticates through the
|
||||
official launch URL and calls `workspace/create` before returning.
|
||||
|
||||
The host-level `tools/execute` hook permits native `read` and `skill` in Ask.
|
||||
Assigned MCP servers supply their already-classified `readOnlyTools` as raw MCP
|
||||
tool names; all other tool names are denied in Ask. Execute uses native full-access
|
||||
permissions with no additional approval. The native permission picker is hidden;
|
||||
changing Plan or creating another native session does not change the launch policy.
|
||||
Skill directories and stdio/streamable-HTTP MCP configurations use official plugins.
|
||||
Knowledge, built-in MCP, and GoodBuddy confirmation/configuration tools require a
|
||||
caller-owned MCP adapter and are not automatically exposed by this service.
|
||||
|
||||
`@deepseek-ai/dsh@0.1.7-rc.2` is a pinned build dependency. The existing packaging
|
||||
hook copies its installed dependency tree, including frontend assets and nested
|
||||
dependency versions, to `resources/runtimes/dsh` outside ASAR. Target Sharp and
|
||||
Koffi packages come from exact lockfile entries through the existing artifact
|
||||
preparation code. The Web package itself needs no click-time npm install. The
|
||||
coordinator now honors the current custom Node selection from the local tool
|
||||
environment. Its managed fallback still installs `node-<platform>-<arch>@22.22.0`
|
||||
through npm; this does not yet satisfy the prepared-resource delivery requirement
|
||||
in section 6.3. No new download setting was added.
|
||||
|
||||
Focused tests use standard Node 24.19.0 on Windows x64 and the prepared resource
|
||||
tree. They exercise Web startup, authentication, project creation, reuse,
|
||||
mode isolation, stop/restart, retained history, and real Web API tool execution.
|
||||
Deterministic model responses travel through the production model bridge: Ask
|
||||
rejects writes, Execute creates the expected file, assigned skills load, read-only
|
||||
MCP executes, and writing MCP is rejected before dispatch in Ask. These backend
|
||||
tests make zero external model-provider calls. This evidence does not claim a
|
||||
signed installer, other platforms, or the complete shortcut UI has been verified.
|
||||
|
||||
Validation: seven focused tests passed against the prepared resource tree;
|
||||
the copied Sharp 0.35.4 native module encoded a PNG successfully; Main TypeScript
|
||||
checking and `npm run build:bundle` passed. Full `npm run build`/typecheck and
|
||||
`npm run lint` encountered concurrent Renderer errors in App.test.tsx and
|
||||
RightAssistantSidebar.tsx; the backend files passed focused lint. Remote Agent
|
||||
launch paths are unchanged because this service supports local DS Web only.
|
||||
|
||||
### 9.2 Local Coordinator Integration
|
||||
|
||||
The production coordinator resolves the saved conversation/project and current
|
||||
settings for both `get` and `open`. Matching includes the selected model profile
|
||||
and credentials, work mode, capability assignments, knowledge scope, Obsidian
|
||||
settings and local Node selection. Ready services keep their MCP gateway after an
|
||||
OS browser-open error and can be reopened or explicitly stopped by their owner.
|
||||
The coordinator passes its configuration key into the service's existing match
|
||||
hash, so the inner DS reuse decision also observes updated skill digests and
|
||||
launch settings even when directory paths are unchanged.
|
||||
|
||||
For DS Ask, the built-in gateway's existing read grant supplies the allowed raw
|
||||
tool names; the Web adapter maps these through the official MCP naming contract.
|
||||
Custom MCP is exposed in Execute, matching the existing Runtime behavior; custom
|
||||
`readOnlyHint` annotations do not introduce a separate Ask permission rule.
|
||||
Assigned skill directories containing `SKILL.md` load through the official skill
|
||||
plugin. Continue/OpenCode native Ask now retain Main-bound endpoints and map the
|
||||
granted read-tool names through both native permissions and execution hooks.
|
||||
OpenCode prefixes names with the bound MCP server name; Continue uses raw names.
|
||||
Story Graph additionally rechecks Supervisor enablement on every call.
|
||||
|
||||
The coordinator remains local-only at this checkpoint. The remote implementation
|
||||
is being developed separately and must be connected and verified on the shared
|
||||
Host before remote shortcut support can be claimed. Current checks and exact
|
||||
supplier counts are maintained in the workbar progress record linked above.
|
||||
@@ -70,6 +70,9 @@ schema 35 的存储修复与本方案独立,不能回退或删历史来改善
|
||||
| Cordis | 4.0.2 | Host 根组件与 Agent scope 的生命周期 |
|
||||
| Continue CLI | 1.5.47 | 实际受管补丁入口的单 `M.session`、QuizService 和权限状态 |
|
||||
|
||||
本表保留进程复用探针执行时的版本。2026-09-26 DS 已升级为 `0.1.7-rc.2`,
|
||||
Cordis 为 `4.0.4`;当前依赖及升级回归见 [DS 实现进度](../deepseek-harness/progress.md)。
|
||||
|
||||
已通过的三个隔离探针:
|
||||
|
||||
1. **OpenCode HTTP**:调用当前生产 Server launcher,只有一次 spawn;同一个 SDK client
|
||||
@@ -174,6 +177,29 @@ SelectedRuntimeManager
|
||||
健康检查也读取 owner 的总 activeRequests,不能从一个空闲 adapter 判断整个 Server
|
||||
无任务后重启。异常退出使该 owner 的全部绑定失效,明确结算受影响请求,不重放已执行工具。
|
||||
|
||||
### 4.1 本地 MCP 初始化失败恢复
|
||||
|
||||
桌面 HTTP 工具网关保持监听,MCP 注册和授权仍按请求创建、清理。本地 OpenCode 的内置
|
||||
工具和自定义 MCP 共用连接逻辑:仅对明确的连接拒绝、连接重置、断管或传输超时,在
|
||||
一秒内成功断开失败连接后重试一次。SDK 返回的无 HTTP response 网络错误和抛出的网络
|
||||
错误采用同一判定;HTTP/API 错误、鉴权或协议错误、未知失败不自动重试。
|
||||
取消立即终止后续尝试。Prompt 和工具调用不重放。
|
||||
|
||||
OpenCode 1.18.x 的 `mcp.add` 在服务端独立执行:客户端超时或取消不会中止初始化,
|
||||
`disconnect` 也只清理当时已登记的连接。晚到的初始化完成后会按名称写入状态,并关闭同名
|
||||
的现有连接。因此,`mcp.add` 未得到 HTTP 响应(抛错、超时、取消或无 response 的网络错误),
|
||||
或断开未确认成功时,该名称即作废;同一槽位之后改用本客户端内唯一的替代名称
|
||||
(前缀加 8 位 base-36 序号,仍为 12 个字符)。槽位随请求结束释放,不因断开失败而长期占用。
|
||||
已得到响应的正常失败继续复用原名称。
|
||||
|
||||
界面显示有界、脱敏的失败详情。`runtime.mcp.failed` 诊断记录连接或断开阶段、失败类别、
|
||||
耗时、尝试次数、内置或自定义类型及可用的 HTTP 状态;通过本轮令牌的 SHA-256 摘要与
|
||||
网关鉴权、初始化和工具发现失败记录关联。日志不保存令牌、地址、请求正文或原始错误。
|
||||
网关初始化抛错时也清理未完成会话,防止失败会话累积。
|
||||
|
||||
此恢复逻辑属于本地 `OpenCodeRuntime`。远程 Agent 使用 `RuntimeAcpBackend` 和
|
||||
`AgentImageToolMcp`,不经过本地 MCP 注册或网关 HTTP 处理;本节不代表远程恢复能力。
|
||||
|
||||
## 5. DeepSeek Harness
|
||||
|
||||
### 5.1 共享 Host 的最小改法
|
||||
|
||||
@@ -44,7 +44,7 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
### 3.1 工作栏应用
|
||||
|
||||
工作栏应用是可以在助手工作栏中打开的一个能力,例如任务中心、工作区、浏览器、成果或
|
||||
终端。每项应用通过统一注册表声明:
|
||||
终端、笔记。每项应用通过统一注册表声明:
|
||||
|
||||
- 稳定应用 ID。
|
||||
- 用户可见名称、图标和说明。
|
||||
@@ -54,7 +54,8 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
- 当前不可用时的原因和修复入口。
|
||||
|
||||
目录中的应用可发现性与实例是否已经打开相互独立。应用不可用时保留入口并说明原因,不以
|
||||
隐藏代替状态。
|
||||
隐藏代替状态。笔记遵循其业务启用设置:关闭魔法笔记时隐藏目录入口并移除对应 Tab,
|
||||
关闭前处理草稿,规则见[会话联动逻辑](../magic-notes/logic-design.md)。
|
||||
|
||||
注册表字段如下:
|
||||
|
||||
@@ -76,14 +77,15 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
`defaultOpen`、`required` 和 `closable` 不互相推导。例如浏览器默认打开但不是必需实例;任务
|
||||
中心和工作区既默认打开又必须存在。`required` 不表示锁定顺序,顺序只由 `reorderable` 控制。
|
||||
|
||||
当前五个应用的 `visibleAcrossContextSwitches` 均为 `true`。该属性记录应用目录的显示策略,
|
||||
当前六个应用的 `visibleAcrossContextSwitches` 均为 `true`。该属性记录应用目录的显示策略,
|
||||
不改变内容归属,也不授予其他会话的 MCP 访问权限;当前没有使用 `false` 的应用,尚未实现
|
||||
按上下文隐藏 Tab 的策略。
|
||||
|
||||
浏览器在创建时绑定当前 Conversation;切换会话后仍保留原 Tab、选中状态和页面,导航操作
|
||||
继续使用原 `targetRef.conversationId`。此时新建浏览器才绑定新会话。默认或旧布局中尚未绑定
|
||||
的浏览器在首次使用时绑定活动会话,此后不再随会话切换改绑。终端同样保留创建时执行目标;
|
||||
任务中心、工作区和成果的内容继续跟随当前项目。
|
||||
任务中心、工作区和成果的内容继续跟随当前项目。笔记使用应用级范围,选择与草稿不随项目或
|
||||
会话切换,不接受 `targetRef`;重启仅恢复工作栏 Tab 描述,不恢复笔记选择和草稿。
|
||||
|
||||
### 3.2 工作栏 Tab 实例
|
||||
|
||||
@@ -178,9 +180,9 @@ stdio fallback。首期远程终端随 SSH Channel 结束,不提供跨 SSH 或
|
||||
|
||||
- 已打开实例位于一个语义化 `tablist` 中。
|
||||
- 每个实例使用独立 `tab` 和 `tabpanel`。
|
||||
- “+”固定在 Tab 行末尾,但位于 `tablist` 之外。
|
||||
- Tab 过多时实例区域单行横向滚动,不换行、不自动隐藏实例。“+”紧随最后一个标签并随标签一起滚动,滚到末尾时可见。
|
||||
- 标签全部可见时隐藏左右滚动按钮;溢出时左右箭头透明浮动于工作区两端,不占标签布局宽度。鼠标移入标签栏时显示箭头,移出后隐藏;键盘聚焦箭头时显示,无悬停能力的设备保持可见。悬停箭头时显示轻微底色。点击滚动约一屏,边界方向禁用且不拦截下方标签的指针操作。切换或新增激活标签时将其滚入可见区域。未激活标签使用低对比度灰蓝底色和细边框,激活标签保留亮底与强调色顶线。
|
||||
- “+”固定在 Tab 行末尾,位于 `tablist` 和页签滚动容器之外,占用独立宽度。
|
||||
- Tab 过多时实例区域单行横向滚动,不换行、不自动隐藏实例。“+”在 `300px` 工作栏内也保持可见和可点击。
|
||||
- 标签全部可见时隐藏左右滚动按钮;溢出时左右箭头透明浮动于页签区域两端,不占标签布局宽度,也不进入“+”的点击区域。鼠标移入标签栏时显示可滚动方向的箭头,移出后隐藏;键盘聚焦箭头时显示,无悬停能力的设备保持可滚动方向的箭头可见。悬停箭头时显示轻微底色。点击滚动约一屏,边界方向禁用并隐藏,且不拦截下方标签的指针操作。切换或新增激活标签时将其滚入可见区域。未激活标签使用低对比度灰蓝底色和细边框,激活标签保留亮底与强调色顶线。
|
||||
- 终端 Tab 默认使用递增标题,例如“终端 1”“终端 2”;状态栏持续显示项目、Host、
|
||||
工作目录和 Shell。用户可以重命名终端。
|
||||
- 任务中心、工作区、成果及新建终端的默认标题随界面语言切换,恢复布局时也使用当前语言。
|
||||
@@ -218,6 +220,7 @@ stdio fallback。首期远程终端随 SSH Channel 结束,不提供跨 SSH 或
|
||||
| 浏览器 | `multiple` | 当前 Conversation | 是,一个实例 | 否 | 是 | 是 | 每次创建新 Tab |
|
||||
| 成果 | `single` | 当前项目 | 是 | 否 | 是 | 是 | 聚焦已有 Tab |
|
||||
| 终端 | `multiple` | 当前项目 | 否 | 否 | 是 | 是 | 每次创建新 Tab |
|
||||
| 笔记 | `single` | 应用级 | 否 | 否 | 是 | 是 | 聚焦已有 Tab |
|
||||
|
||||
实例策略、默认状态和可关闭策略都是应用注册数据,不能分散硬编码在多个点击处理器中。
|
||||
|
||||
@@ -562,7 +565,7 @@ Schema、假数据终端或不可用入口的中间产品。
|
||||
- [x] 连续选择浏览器会创建页面、导航状态和元素引用相互独立的浏览器 Tab。
|
||||
- [x] 连续选择终端会创建多个互相独立的终端 Tab。
|
||||
- [ ] 关闭可关闭实例、切换和重排实例后,“+”仍保持可用。
|
||||
- [ ] Tab 溢出时单行横向滚动,两端箭头固定,“+”跟随最后一个 Tab,滚到末尾可见,不把 Tab 换成下拉框。
|
||||
- [ ] Tab 溢出时单行横向滚动,页签区两端箭头固定,“+”在滚动区外持续可见,不把 Tab 换成下拉框。
|
||||
- [x] 关闭可关闭的活动 Tab 后激活正确的相邻 Tab 并恢复焦点。
|
||||
- [x] 当前 Tab 的背景、边框、顶部指示和字重清晰可辨;关闭按钮仅在悬停、焦点或无悬停
|
||||
设备上出现,且不引发布局位移。
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 会话 HTML 渲染实现进度
|
||||
|
||||
2026-09-27 浮层审查修复:全屏 iframe 已纳入共享焦点循环,跨文档 Escape 通过受限
|
||||
Main/Preload 通知返回外层。真实 App 中的带链接及纯正文预览均已验证键盘进入和 Escape,
|
||||
带链接预览另验证正反向 Tab 返回;没有开放 sandbox 权限或执行预览脚本。
|
||||
实现与测试范围见[浮层审查修复记录](../../quality/overlay-review-2026-09-27.md)。
|
||||
|
||||
## 已实现
|
||||
|
||||
- [x] 应用级持久开关,默认开启,并提供旧设置迁移。
|
||||
|
||||
@@ -56,6 +56,17 @@ iframe 无法按内容自适应高度,因为 `sandbox=""` 不含 `allow-same-o
|
||||
嵌入预览完全相同的清理后文档,不额外放宽 Sandbox 或 CSP。切换回复时,源码面板与全屏
|
||||
预览按当前 source 派生开合状态,不使用会引发级联渲染的重置 effect。
|
||||
|
||||
全屏 iframe 提供 `tabIndex=0`,共享焦点候选包含 iframe。关闭按钮的正向 Tab 显式进入
|
||||
预览,支持没有链接的长文;iframe 后的焦点守卫将原生 Tab 返回到后续 Modal 控件或关闭
|
||||
按钮。守卫本身不作为焦点循环的首尾,通知关闭按钮仍参与循环。
|
||||
|
||||
iframe 内的 Escape 不会冒泡到父文档。`registerWindowIpcHandlers` 只在主窗口直接子
|
||||
`about:srcdoc` frame 获得焦点且收到 Escape keyDown 时,向主 Renderer 发送
|
||||
`window:preview-escape`。Preload 暴露无参数订阅 `app.onPreviewEscape`;全屏组件仅在
|
||||
自己的 iframe 当前聚焦且所属 Modal 未被 inert 隔离时关闭。组件卸载移除订阅,窗口 IPC
|
||||
释放时移除输入监听。此路径不执行预览脚本、不授予同源权限,也不暴露原始键盘事件或
|
||||
Electron 对象;iframe 的 Sandbox/CSP 保持原值。
|
||||
|
||||
## 验证范围
|
||||
|
||||
- 应用设置默认值、关闭持久化和版本 10 迁移。
|
||||
@@ -65,4 +76,5 @@ iframe 无法按内容自适应高度,因为 `sandbox=""` 不含 `allow-same-o
|
||||
- 源码按钮的 `aria-expanded` 切换,以及全屏预览的初始焦点、背景 inert、Escape 关闭和
|
||||
焦点恢复。
|
||||
- 主 Agent、子 Agent、用户、推理和流式状态边界。
|
||||
- 真实 Electron 中带链接与纯正文 iframe 的进入、正反向 Tab 返回和内部 Escape;通过生产 Main/Preload 事件订阅完成关闭。
|
||||
- 从设置 Switch 到当前会话重新渲染的应用级集成路径。
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
|
||||
## 文档导航
|
||||
|
||||
主页面包含工作回顾、故事线图谱、自动监督、活动记录和设置。工作回顾阅读统一监督结果并选择历史,图谱定位同一结果;自动监督管理计划、概览、自动监督报告、记忆与行动建议和心跳审计。活动记录展示统一执行、进度及详情,可按计划 ID 筛选;设置只保留算法参数。当前布局以 [UI 设计](./ui-design.md#应用入口)为准。活动读取实际手动回顾及心跳执行,合并展示同一次心跳的报告与监督回顾阶段;状态规则、历史缺失和保留期限见[活动记录](./logic-design.md#活动记录)。
|
||||
主页面包含工作回顾、故事线图谱、自动监督、活动记录和设置。工作回顾阅读统一监督结果并选择历史,图谱定位同一结果;自动监督管理计划、监督建议和只读的旧报告。活动记录展示统一执行、进度、建议阶段及详情,可按计划 ID 筛选;设置只保留算法参数。当前布局以 [UI 设计](./ui-design.md#应用入口)为准。活动读取实际手动回顾及心跳执行,合并展示同一次心跳触发的监督回顾与建议阶段;状态规则、历史缺失和保留期限见[活动记录](./logic-design.md#活动记录)。
|
||||
|
||||
自动心跳报告和监督回顾已接入按来源版本及正文位置的增量处理,无变化时跳过模型。手动历史回顾继续重新整理所选区间;进度、失败重试和删除边界见[自动增量与手动重看](./logic-design.md#自动增量与手动重看)。
|
||||
心跳的职责为“定时触发增量回顾+按配置介入(建议)”,不再先生成独立报告;手动“回顾”默认增量,历史重看改为显式“重新整理”。规则见[心跳职责与介入](./logic-design.md#心跳职责与介入目标设计),需求 FR-S12,验收 US-S32、US-S33,2026-09-30 已实现(主动介入除外),验证见[实施进度](./progress.md#2026-09-30-心跳职责收敛与监督建议)。
|
||||
|
||||
监督回顾按来源版本及正文位置增量处理,手动回顾与心跳共享进度,无变化时跳过模型;“重新整理”才重读所选区间。旧的进度、失败重试和删除边界见[自动增量与手动重看](./logic-design.md#自动增量与手动重看)。
|
||||
|
||||
| 文档 | 权威职责 |
|
||||
| --- | --- |
|
||||
@@ -16,6 +18,7 @@
|
||||
| [UI 设计](./ui-design.md) | 应用导航、工作回顾、侧栏反馈及页面状态 |
|
||||
| [User Stories](./user-stories.md) | 监督者与故事线图谱的用户操作和验收场景 |
|
||||
| [技术设计](./technical-design.md) | Main/Renderer 分层、数据模型、IPC、安全边界和实施顺序 |
|
||||
| [时态 Story Graph MCP 设计](./story-graph-mcp-design.md) | 只读工具、时间与版本语义、Runtime 接入,以及后续跨范围事实复用和记忆过渡合同 |
|
||||
| [回顾分块调度设计](./review-scheduling-design.md) | 第 0 节定义生产分页、批次持久化、续跑、当前设置及剩余边界;其余章节保留改造前基线、目标设计和原型证据 |
|
||||
| [实施进度](./progress.md) | 已验证实现、验证证据和当前边界 |
|
||||
| [故事线图谱设计](../story-graph/prd.md) | 图谱对象、环绕时间轴与实体交互 |
|
||||
@@ -23,3 +26,5 @@
|
||||
生产入口已接通完整来源分页、叶子持久化、持续处理至完成、活动页主动暂停/继续及批次详情;设置可调页大小、批次正文/消息上限、单次响应容量、两个模型超时和共享并发。实际合同及限制见[生产接线](./review-scheduling-design.md#0-生产接线与剩余边界)。真实 DeepSeek 验证已覆盖一个完整的 27 条消息会话;较早的 129 条消息实验仍未完成。两次实验共 5 次付费请求,详情见进度。原始 AbortError 原因尚未由日志确定。
|
||||
|
||||
实施状态以代码和[实施进度](./progress.md)为准。逻辑待定项见[逻辑设计](./logic-design.md),架构边界见[技术设计](./technical-design.md)。现有心跳行为见[智能心跳](../smart-heartbeat/README.md),原型范围见[Story Graph 演示](../story-graph/README.md)。
|
||||
|
||||
2026-09-28:Agent 可按需通过三个只读 MCP 工具读取决定、演变和来源;监督者关闭后不暴露工具并拒绝旧会话调用。本地与远程接线及验证边界见[实施进度](./progress.md#2026-09-28-story-graph-只读工具)。当前 memory 读取、精确 scope 增量进度和候选身份保留;跨 scope 叶子复用、读取入口切换及 `as_of` 仍属后续能力。
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
报告、监督叶子与导航整理共用监督专用 FIFO 并发池,普通聊天不入池;监督服务外层 run 仍串行。报告在排队前冻结超时,获槽后领取,实际模型请求前校验并刷新租约;报告提交或无变化后先释放槽位,再执行监督。监督超时在 run 创建时保存,节点获槽并解析 Runtime 后计时。阶段超时、租约、传输时限、后台检查与活动轮询各自独立,取值及生效规则见[当前设置合同](./review-scheduling-design.md#当前设置合同)。
|
||||
|
||||
完整回顾的生产接线已增加分页来源清单、逐批输出/offset 事务和导航节点。预算耗尽显示 `paused`,模型或保存失败显示 `failed`;两者均保留此前成功批次,可继续同一 run。存在未读来源、覆盖空洞或未成功导航时不能标 `completed`。手动位置与自动 checkpoint 分开,自动位置只在最终发布事务推进。来源变更目前要求重新回顾,模型配置跨重启固定等差异见[生产接线与剩余边界](./review-scheduling-design.md#0-生产接线与剩余边界)。真实模型验证覆盖 27 条消息的完整会话,较大样本失败单独记录。
|
||||
完整回顾的生产接线已增加分页来源清单、逐批输出/offset 事务和导航节点。用户主动暂停后显示 `paused`,模型或保存失败显示 `failed`;两者均保留此前成功批次,可继续同一 run。回顾不按累计运行时长自动暂停。存在未读来源、覆盖空洞或未成功导航时不能标 `completed`。手动位置与自动 checkpoint 分开,自动位置只在最终发布事务推进。来源变更目前要求重新回顾,模型配置跨重启固定等差异见[生产接线与剩余边界](./review-scheduling-design.md#0-生产接线与剩余边界)。真实模型验证覆盖 27 条消息的完整会话,较大样本失败单独记录。
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
@@ -127,7 +127,7 @@ flowchart LR
|
||||
|
||||
## 状态与处理规则
|
||||
|
||||
下表包含目标规则;当前活动执行状态以本节后的“活动记录”为准,取消及部分完成尚未接入。
|
||||
下表包含目标规则;当前活动执行状态以本节后的“活动记录”为准,取消已接入,部分完成状态尚未接入。
|
||||
|
||||
| 规则 | 条件或状态 | 处理与用户可见结果 | 需求与场景 |
|
||||
| --- | --- | --- | --- |
|
||||
@@ -152,7 +152,9 @@ flowchart LR
|
||||
|
||||
旧监督成功记录继续显示;旧心跳与监督之间未保存关联时分别呈现,不用时间接近猜测关系。旧心跳未保存的执行范围显示不可用,不从当前计划反推。此前未保存的手动运行与失败无法恢复。心跳报告沿用计划的历史保留和删除规则;监督结果独立保留,原心跳被清理后仍可读取监督记录。活动不是永久审计库。
|
||||
|
||||
当前活动没有 `cancelled` 或 `partial` 状态,也不提供取消按钮。实体和关系修改只有当前状态及结果内容,没有按时间追加的人工修改记录。
|
||||
同一时刻只允许一个监督回顾执行,包括停止清理阶段;不同 scope 也共用此限制。手动新建或继续遇到占用时立即提示,不排队;自动回顾等待占用释放,再检查未完成运行和增量来源。暂停或失败后可以新建回顾,也可继续有效的原 run。
|
||||
|
||||
取消立即持久化 `cancelled`,但执行与清理尚未停止时 UI 显示“正在取消”,此时仍不能开始另一个回顾。停止后显示“已取消”,保留上次成功结果和本次已保存批次,不发布部分结果、不推进自动 checkpoint。已取消运行不能手动继续,自动检查也不恢复它;后续自动检查可新建 run 处理尚未提交的来源。关联心跳活动显示监督取消状态,已保存的报告保持原状态。界面入口及提示关闭规则见[UI 设计](./ui-design.md#活动)。当前没有 `partial` 状态;实体和关系修改仍没有按时间追加的人工修改记录。
|
||||
|
||||
收集、叶子整理、导航合并和发布分别展示。阶段推进只依据服务记录,最终完成只依据结果事务;“六批已保存、剩余零来源”仍可处于合并失败或发布失败。继续保留成功叶子和导航节点,缺失阶段不得靠错误文本或来源数猜测。导航摘要允许省略事实数组,叶子缺少事实数组仍失败;导航不得生成替代叶子事实的非空数组。阶段及输出合同见[生产调度](./review-scheduling-design.md#已接入的调度与存储)。
|
||||
|
||||
@@ -164,12 +166,57 @@ flowchart LR
|
||||
|
||||
工作回顾的手动操作重新整理所选区间,沿用有界历史收集,不读取或推进自动进度。自动监督计划列表中的“立即运行”重新生成心跳报告,其下游监督仍按自动进度处理。删除报告或计划不重置来源进度;重看历史、删除报告和重建图谱是不同操作。当前没有清空或重建图谱功能。
|
||||
|
||||
回顾默认增量,重看历史改为显式重新整理。
|
||||
|
||||
### 心跳职责与介入(目标设计)
|
||||
|
||||
对应 FR-S4、FR-S12,US-S27、US-S32、US-S33。本节为已确认的目标规则,尚未实现;当前代码仍先生成心跳报告再执行监督整理,实际进度以[实施进度](./progress.md)为准。“回顾”默认增量,重看历史改为显式“重新整理”。
|
||||
|
||||
### 心跳职责与介入(目标设计)
|
||||
|
||||
对应 FR-S4、FR-S12,US-S27、US-S32、US-S33。本节为已确认的目标规则,尚未实现;当前代码仍先生成心跳报告再执行监督整理,实际进度以[实施进度](./progress.md)为准。
|
||||
|
||||
回顾整理只有一套流程,手动和自动共用:确定范围 → 分页采集来源 → 分批整理 → 汇总 → 发布到 Story Graph。心跳不参与整理本身,只在其外增加两件事:
|
||||
|
||||
1. **定时触发**:计划到期时代替用户发起一次增量回顾。
|
||||
2. **介入**:回顾发布后,按计划配置的介入方式处理本次图谱变化。
|
||||
|
||||
```text
|
||||
触发(点击“回顾” / 计划到期)
|
||||
↓
|
||||
变化检查:比较来源版本与已处理位置,不调用模型
|
||||
↓ 无变化 → 记录“无新变化”,结束
|
||||
↓ 有变化
|
||||
增量整理:只处理新增、修订和未完成片段,关联已有实体(唯一读取原文的阶段)
|
||||
↓
|
||||
发布:写入 Story Graph,推进增量进度
|
||||
↓ 仅心跳触发
|
||||
介入:读取本次发布的图谱变化,按计划配置生成建议
|
||||
```
|
||||
|
||||
| 规则 | 内容 |
|
||||
| --- | --- |
|
||||
| H1 原文只读一次 | 同一来源版本在一次触发中只由整理阶段读取;介入阶段的输入是本次图谱变化及其来源引用,不重新读取原文 |
|
||||
| H2 不再生成独立报告 | 取消“心跳报告”阶段及其独立增量进度;旧报告只读保留,不再新建 |
|
||||
| H3 手动默认增量 | “回顾”按钮与心跳整理行为一致,跳过已处理且未变化的来源;手动触发不生成建议 |
|
||||
重新整理放在更多中,确认后重新分析所选时间区间;不推进也不重置自动进度,不覆盖用户确认内容 |“重新整理”放在“更多”中,确认后重新分析所选时间区间;不推进也不重置自动进度,不覆盖用户确认内容 |
|
||||
| H5 介入方式 | 计划字段:`仅更新记忆`、`生成建议`(新计划默认)、`主动介入`(会话级实时,暂不实现,不显示为可选项) |
|
||||
| H6 建议来源 | 候选仅来自本次图谱变化:批次中的未解决事项、无明确取代关系的分歧(contrasts 关系)、由至少三处不同原始来源支持的未确认实体(候选约定)、被修订的实体(revised 变化)。长期未推进的判定尚未实现 |
|
||||
| H7 建议成本 | 先按规则挑选候选,不调用模型;存在候选时才发起一次输入有界的措辞调用,输入仅为候选及其引用 |
|
||||
| H8 建议可信 | 每条建议显示依据并可打开来源;用户忽略后,只有出现新证据才再次提出;确认候选约定或偏好后才作为长期背景 |
|
||||
| H9 频率与成本 | 提高频率只增加变化检查次数;模型调用次数由实际变化决定:无变化 0 次,有变化无候选仅整理,有候选再加一次建议调用 |
|
||||
| H10 失败隔离 | 建议阶段失败不回滚已发布的图谱与增量进度;活动显示“已更新,建议生成失败”,可单独重试建议 |
|
||||
|
||||
介入产物替代旧心跳的报告、记忆建议与行动建议:未解决事项可转任务,候选约定确认后进入长期背景,旧的报告阅读由按时间查看图谱变化替代。已有计划的范围、频率和启停状态保留,迁移后介入方式默认为“生成建议”;已确认记忆与待处理建议保留并逐步迁入,不补造来源。
|
||||
|
||||
计划 Modal 的新建草稿不产生持久化或执行副作用,显式保存时创建并启用;编辑沿用已有 enabled。保存失败保留草稿,提交期间禁止关闭,未保存关闭须确认。活动筛选只改变读取范围,不触发执行;同名同范围计划仍按 configId 区分,筛选在分页前应用,结果跳转继续按 resultId 定位。
|
||||
|
||||
规则冲突时,先满足所选范围与既有观察边界,再保留用户修订和来源事实,最后应用自动归纳和展示策略。新增证据与已确认结论冲突时显示待核对差异,不能自动断言旧观点失效。
|
||||
|
||||
## 完整性与待定项
|
||||
|
||||
FR-S11、US-S28 至 US-S31 的规则由[时态 Story Graph MCP 设计](./story-graph-mcp-design.md)统一定义:时间/确认与有效性见第 3 节,读取范围与分页见第 4 节,应用关闭与 Runtime 接入见第 6 节,跨 scope 复用与记忆过渡见第 7、8 节。D1 读取已接入,后两项仍待实现;Global/项目独立 checkpoint 和同 scope 候选身份保留。MCP 不接受 `as_of`,较晚生成的结果也不自动使旧决定失效。
|
||||
|
||||
本设计覆盖触发、证据输入、静默检查、正常整理、取消与失败、跨视图共享结果、用户纠正、知识库写入及历史回放。它补充产品逻辑,不代表接口、持久化或迁移方案已经完成。
|
||||
|
||||
仍待产品决策:事件触发与阶段识别条件、反馈频率与静默判定、实体合并与拆分的交互、时间轴比例和集中度含义。应用启停按[应用启停与执行](#应用启停与执行)处理;既有入口偏好、计划与运行记录的保留要求见 FR-S1、S2 和 US-S14。
|
||||
|
||||
@@ -1,11 +1,91 @@
|
||||
# 监督者实施进度
|
||||
|
||||
日期:2026-09-24。
|
||||
日期:2026-09-30。
|
||||
|
||||
当前记录以已验证生产行为为准。监督者尚未覆盖全部 user stories。
|
||||
|
||||
## 2026-09-30 心跳职责收敛与监督建议
|
||||
|
||||
对应 FR-S4、FR-S12、US-S32、US-S33,规则见[心跳职责与介入](./logic-design.md#心跳职责与介入目标设计)。
|
||||
|
||||
实现:
|
||||
|
||||
- `HeartbeatService` 不再读取来源或调用模型。领取计划后立即完成自身运行,再通过 `review` 触发共享的 `SupervisorService.run({ trigger: 'heartbeat' })`;审查结果 `no_change` 时标记心跳为无变化。计划领取、单次补跑、单回顾排队和失败记录沿用原有机制。
|
||||
- 手动“回顾”默认增量:`supervisionRunRequestSchema` 新增可选 `reanalyze`,`isIncrementalReview` 决定是否读取、推进 `review_checkpoints`。只有 `reanalyze: true` 重读区间,且不推进也不重置共享进度。自动检查不再续跑用户主动暂停的回顾,改为新建运行处理未提交来源。
|
||||
- 计划新增 `intervention`(`suggest` / `memory`,默认 `suggest`)。`supervision-suggestions.ts` 从本次发布结果按规则挑选候选:批次未决事项、`revised` 实体变化、`contrasts` 关系、由至少三处不同原始来源支持的未确认实体。没有候选时不调用模型;有候选时 `supervision-suggester.ts` 只把候选文本交给一次建议调用,不读原文。待处理建议不重复,已处理建议仅在依据变化后再次提出。
|
||||
- 建议失败写入 `heartbeat_runs.suggestion_status/error`,图谱和进度保留;活动页显示“回顾已更新,建议生成失败”并可单独重试。
|
||||
- 接受未决事项生成暂停任务,接受候选约定确认为长期背景(记忆)并确认对应实体;分歧和修订标记已核对。
|
||||
- Schema 50:`heartbeat_configs.intervention`、`heartbeat_runs.suggestion_status/suggestion_error`、`supervision_suggestions` 表。升级时把旧心跳报告中仍为 `proposed` 的记忆迁入为待确认约定,不确认、不删除;旧报告只读保留。
|
||||
- 界面:工作回顾主按钮改为“回顾”,“更多 → 重新整理…”经确认后执行;计划 Modal 增加“介入方式”;自动监督页用“监督建议”替代成功率、趋势、记忆/行动建议和运行审计,建议可查看依据、打开会话、在图谱中查看;设置移除心跳报告超时;导航角标统计待处理建议。
|
||||
|
||||
验证:
|
||||
|
||||
- 定向单元与集成测试:`src/main/assistant`、`src/shared`、`src/preload` 共 589 项;`src/main/ipc.test.ts` 心跳与监督相关 29 项;Renderer 监督者、自动监督、活动、设置相关组件测试及 `App.test.tsx` 全文件均通过。新增覆盖:手动增量与重新整理不动进度、不续跑已暂停回顾、候选规则与去重、忽略后仅新证据重提、建议失败隔离、IPC 启停门控、Schema 49 升级迁移。
|
||||
- Electron 布局:`GOODBUDDY_SUPERVISOR_RECAP`、`AUTOMATIC_OVERVIEW`、`ACTIVITY`、`PLAN_MODAL` 场景通过,覆盖 1440/390px 下监督建议、介入方式字段、重新整理确认和工具栏两行布局,无横向溢出。
|
||||
- 真实模型(DeepSeek,`deepseek-flash`,隔离 SQLite,`scripts/heartbeat-deepseek.mjs`):首次心跳 1 次回顾调用 + 1 次建议调用(建议输入约 1,150 字符,不含原文),生成分歧、修订、未决事项三条建议且依据均指向本次来源;无变化心跳与默认手动回顾均 0 次调用;追加一条消息后只处理 1 个来源,复用全部 5 个既有实体,再调用 1 次回顾、1 次建议。共 4 次付费请求。
|
||||
- 未运行全量测试。
|
||||
|
||||
边界:主动介入(会话级实时)未实现,界面不显示;项目与全局仍各自维护处理进度(US-S31)。
|
||||
|
||||
## 2026-09-28 Story Graph 只读工具
|
||||
|
||||
对应 FR-S11、US-S28 至 US-S30 的 D1 读取实现。输入、分页与版本语义由[专项设计](./story-graph-mcp-design.md)负责。US-S31 的跨范围事实复用和 memory 读取切换仍待实现。
|
||||
|
||||
实现路径:
|
||||
|
||||
- [共享工具合同](../../../src/shared/story-graph-tools.ts)定义 `story_graph_search`、`story_graph_get_context`、`story_graph_read_source`。内置目录与能力设置支持 Model、OpenCode、Continue、DeepSeek Harness 分配;应用关闭时 Main 不签发图谱读取权限。
|
||||
- [只读 SQLite 投影](../../../src/main/assistant/story-graph-reader.ts)读取精确 scope 下的历史结果、当前对象、事件、变化、关系、来源和成功叶子描述。保留旧决定与修订依据,确认状态和有效性分别返回,未知有效性不按时间推断。没有新增 schema、业务写入或模型调用。
|
||||
- [Main gateway](../../../src/main/agent/knowledge-mcp-gateway.ts)在发现、读取前和返回前复核监督者开关及 Runtime 分配;IPC 将项目和 Runtime 固定到请求。Model 和 Harness 代理、本地 MCP、原生客户端共用此入口。Harness 的目录、scope schema 转换及 Host Ask 执行钩子均已接通。
|
||||
- 远程沿用 `ProtocolRemoteRuntimeChannel`、`MainImageToolSession`、`AgentImageToolMcp` 和 `RuntimeAcpBackend` 的现有工具通道。Ask 可以只有图谱描述,没有图像生成描述。OpenCode 根/子会话仅放行当前端点;Continue Ask 保留 Main 会话 MCP,并由原生只读工具名和 Main 双重校验。
|
||||
- 对象页为 10/50 项,正文页为 4,000/8,000 码点(默认/上限)。Context 用带位置的 JSON 片段续读长对象;游标绑定过滤、scope 和读取修订,变更后返回 `stale_cursor`。来源默认读保存片段;显式 current 通过 locator 读当前记录,version 仅接受可验证的现存版本。知识引用片段不声称是整份知识原文,来源迁出项目、删除、未知历史和响应过大均有明确结果。
|
||||
|
||||
定向验证:
|
||||
|
||||
```text
|
||||
npx vitest run src/main/assistant/story-graph-reader.test.ts src/agent-daemon/story-graph-integration.test.ts src/main/assistant/supervision-production.test.ts src/main/capabilities/capability-service.test.ts src/main/ipc.test.ts src/main/remote-agent/protocol-remote-runtime-channel.test.ts src/agent-daemon/runtime-acp-backend.test.ts src/agent-daemon/continue-acp-helper.test.ts src/agent-daemon/opencode-subagent-plugin.test.ts src/main/agent/native-terminal-client.test.ts
|
||||
```
|
||||
|
||||
10 文件、337 项通过,1 项既有条件测试跳过。覆盖真实 SQLite、HTTP MCP、Main/Agent 消息往返、协议准备和释放、四个 Runtime 的 IPC 项目绑定、Supervisor 关闭后不再读取、取消、来源删除/迁移、旧游标、Unicode 正文续页、超长响应及 A → B 修订后 C 仍为选项。冷启动审查发现 current 来源读取依赖运行回顾后才注册的 SQLite 函数,改为按现存 context 直接计算同一修订;新连接回归通过。最终读取相关 3 文件、28 项再次通过。
|
||||
|
||||
其他受影响路径也已定向验证:
|
||||
|
||||
- `continue-runtime.test.ts`、`opencode-runtime.test.ts`、`deepseek-harness-runtime.test.ts`、`native-client-coordinator.test.ts`、`protocol-remote-runtime-channel.test.ts`、`knowledge-mcp-gateway.test.ts`:6 文件、243 项通过。
|
||||
- `goodbuddy-harness-control-plane.test.ts`、`continue-host-adapter.test.ts` 及相关桥接/读取测试:6 文件、98 项通过。`model-tool-provider.test.ts`、能力设置及 Continue helper 组合:3 文件、92 项通过。
|
||||
- `npx vitest run src/main/agent/deepseek-harness-acp-e2e.test.ts -t "reads Story Graph"`:1 项通过、13 项按名称跳过。真实受控 Harness Host 经 ACP 和 Main 代理执行 Ask/Execute 读取,随后关闭监督者并确认工具移除;推理使用测试实现,没有外部模型请求。
|
||||
- `npx tsc --noEmit -p tsconfig.node.json`、`tsconfig.agent.json`、`tsconfig.web.json` 均通过;最终 Main 类型检查再次通过。本次变更的 TypeScript 源码和测试定向 ESLint 通过,`git diff --check` 通过。
|
||||
|
||||
### Linux Host 验证
|
||||
|
||||
[SSH 探针](../../../scripts/story-graph-host-probe.ts)从当前源码临时打包,在共享 Linux x64 Host 运行 `AgentImageToolMcp`、`AgentOwnedAcpPrompt` 和 `ContinueHostAdapter`,使用 Host 安装的 OpenCode 和 Continue(1.5.47)。桌面启动隔离内存 SQLite、Main gateway 和 `MainImageToolSession`,通过 SSH 搬运工具通道消息;用户数据库、模型凭据和正文库没有复制到 Host。Host 临时运行目录在结束时清理。
|
||||
|
||||
探针通过:HTTP 发现三个只读工具、搜索/上下文/来源读取及分页、`as_of` 拒绝、OpenCode Ask/Execute、Continue Ask/Execute 的实际工具调用,以及关闭后的发现和旧会话调用拦截。成功探针有 10 次本机确定性推理请求,其中 2 次为 Runtime 标题生成,桌面读取 10 次,付费调用 0 次。RPC blob framing 与 prompt 生命周期另由上述 `runtime-acp-backend` 和 `protocol-remote-runtime-channel` 测试覆盖;该 SSH 探针使用标准输入输出承载工具消息,没有执行安装包升级或完整桌面 UI 操作。
|
||||
|
||||
复跑时在仓库使用 esbuild 将脚本输出到临时目录,再通过已有 SSH 身份传至 Host 的 GoodBuddy 测试目录。桌面命令参数为:
|
||||
|
||||
```text
|
||||
node <local-probe.cjs> <ssh-host> <remote-probe.cjs> <host-opencode-path> <host-continue-cn.js-path>
|
||||
```
|
||||
|
||||
### 保留边界
|
||||
|
||||
没有执行全量测试、付费模型请求、提交、推送或发布。真实模型如何根据冲突证据形成最终建议、跨平台安装包和完整桌面 UI 仍未在本次验收;没有据此声明 US-S28 的建议质量已验证。查询目前同步扫描所选 scope 的已发布事实,大库延迟和运行中断粒度没有性能验收。`replaces`/`contradicts`、历史有效期、`as_of`、跨 scope 事实复用和 memory 消费切换均没有伪造实现;已有记忆与 checkpoint 保留。中文设计扫描无阻断项,复核项是时间、范围和证据限制,按技术含义保留。
|
||||
|
||||
## 已验证
|
||||
|
||||
### 2026-09-26 单次执行与取消集成复核
|
||||
|
||||
对应 FR-S4、FR-S6、FR-S10、US-S24、US-S26。复核当前 Main、SQLite、IPC、Preload 与 Renderer diff,确认手动新建/继续遇到占用立即拒绝,自动回顾等待;取消立即落库,执行位置保留至并行批次及 Runtime 清理结束。UI 在此期间显示正在取消,X 仅关闭提示;已取消运行不能继续,也不会被自动恢复。实现合同见[单次执行与取消](./technical-design.md#单次执行与取消),界面见[UI 设计](./ui-design.md)。
|
||||
|
||||
发现并修复一个可达问题:活动页等待整个 `resume` 请求结束才释放操作锁,继续运行后的暂停和取消按钮因此一直禁用。现在发出继续请求后释放提交锁,独立处理完成/失败,Main 仍保证唯一执行。新增回归在修复前因暂停按钮禁用而失败,修复后验证继续中的取消、停止提示,以及原继续请求返回时不清除后续取消操作的状态。
|
||||
|
||||
本轮验证:
|
||||
|
||||
- `npx vitest run src/renderer/src/SupervisorActivity.test.tsx src/renderer/src/SupervisorWorkspace.test.tsx`:38 项通过,包含上述新增回归、取消清理期间的状态、重新进入页面、手动重复提示及 X 不取消。
|
||||
- `npx vitest run src/main/assistant/supervision-review.test.ts src/preload/supervision-activity.test.ts src/main/ipc.test.ts -t "reserves before setup|persists cancellation|allows a new review after|cancels navigation|projects cancellation|wakes waiting automatic|production supervision IPC cancels|supervision"`:27 项通过、144 项按名称跳过;其中 Preload 文件未命中过滤,另用 `npx vitest run src/preload/supervision-activity.test.ts` 单独验证,1 项通过。
|
||||
- `npx eslint src/renderer/src/SupervisorActivity.tsx src/renderer/src/SupervisorActivity.test.tsx` 通过;本轮文件的 `git diff --check` 通过。中文新增内容按 `deai-writing` 清单人工审校,文档链接目标已核对。
|
||||
|
||||
上述测试使用隔离 SQLite、生产 handler/工厂及可控 Runtime、Renderer API 替身;本轮未运行 Electron 端到端、全量测试或类型检查,真实模型调用 0 次。用户提供的后端与前端实现代理测试通过记录作为先前证据,不并入本轮计数。远程不受影响的依据是 `ipc.ts` 生产工厂调用 `resolveRequestRuntime({ workMode: 'ask' })`,无项目、Runtime 选择或执行空间,解析直接返回桌面默认 Runtime;不进入 SSH/Agent 路径,未修改远程协议或取消实现。未运行远程实测,未改动其他工作的 Runtime/package 文件,未提交。
|
||||
|
||||
### 2026-09-26 移除回顾自动时间预算暂停
|
||||
|
||||
对应 FR-S4、FR-S6、FR-S10。生产服务移除提取循环和导航合并中的整次执行期限判断,持续处理至完成;已保存运行中的 `executionSeconds` 继续兼容读取,但不再控制暂停。设置页移除该控件,中英文帮助和活动配置改为持续处理说明。单次模型超时、共享并发、逐批保存、主动暂停及失败续跑保持原路径,具体合同见[生产接线](./review-scheduling-design.md#0-生产接线与剩余边界)。主动暂停仍中断在途请求,仅保留此前已保存批次。
|
||||
@@ -409,10 +489,19 @@ npx eslint scripts/review-algorithm.mjs scripts/review-algorithm.test.mjs script
|
||||
- 结束时间收尾:手动心跳使用真实报告完成时间,下游失败单独记录结束时间。`npx vitest run src/main/assistant/supervision-activity.test.ts src/main/assistant/heartbeat-service.test.ts src/main/assistant/heartbeat-database.test.ts src/main/assistant/supervision-history.test.ts`:4 个文件、21 项通过,新增受控时钟用例区分 10:00 开始、10:02 报告完成、10:03 下游失败。随后 Node typecheck 和这 3 个改动源码/测试文件的 ESLint 通过。
|
||||
- 已存在的手动失败无法补回;旧心跳没有冻结范围和关联 ID,保留缺失提示。心跳仍按原保留期限清理,监督结果独立保存。取消和人工修改时间序列审计未实现;`no_change` 的后续接入见下节。
|
||||
|
||||
### 2026-09-28 继续讨论正文与布局
|
||||
|
||||
侧栏与图谱来源详情直接显示可编辑的发送正文,移除隐藏上下文拼接及附带提示。目标会话独立分隔,底部复用共享右对齐操作区。失败保留草稿,取消不发送,目标切换继续使旧预览失效。Main 的来源筛选与发送契约未修改。
|
||||
|
||||
- `npx vitest run src/renderer/src/SupervisionDiscussion.test.tsx src/renderer/src/SupervisionCard.test.tsx`:10 项通过,覆盖正文可见、编辑后精确提交、删除引用后不补回、失败重试、取消、重复提交和目标切换。
|
||||
- `npx vitest run src/main/ipc.test.ts -t 'scopes supervision continuation|dispatches supervision continuation'`:2 项通过,使用真实 SQLite 与队列解析器核验来源范围及空附件发送。
|
||||
- `npx vitest run tests/supervisor-layout.electron.test.ts` 分别设置 `GOODBUDDY_SUPERVISOR_DISCUSSION=1`、`GOODBUDDY_SUPERVISOR_SIDEBAR=1` 运行通过。图谱覆盖 1440/390px,侧栏覆盖 480/300/200px,均含浅深主题;检查 16px 区块间距、8px 字段间距、目标分隔、右对齐及无横向溢出,侧栏另检查滚动后按钮可命中。截图与测量保存在临时目录 `opencode/discussion-feedback-graph`、`opencode/discussion-feedback-sidebar`。
|
||||
- Renderer 类型检查 `npx tsc --noEmit -p tsconfig.web.json`、8 个改动 TS/TSX/MJS 文件的定向 ESLint 与改动文件 `git diff --check` 通过。Electron 使用生产组件和模拟数据,未调用模型;未跑全套测试,未提交。
|
||||
|
||||
### 其他边界
|
||||
|
||||
- 新批次来源读取按 messageId 返回已保存片段及版本;旧历史缺少消息 ID 时保留会话/时间定位。本地知识引用通过现有 `KnowledgeService` 解析文档/分块,失效时显示不可用;外部引用只使用已保存 locator,不调用远端全库。
|
||||
- 继续讨论和知识库写入使用现有本地会话队列与知识库实体接口,并要求先预览、再由用户确认提交。侧栏已支持结果直达图谱,尚无可编辑的上下文预览。
|
||||
- 继续讨论和知识库写入使用现有本地会话队列与知识库实体接口,并要求先预览、再由用户确认提交。侧栏支持结果直达图谱;继续讨论的侧栏与图谱入口均已提供可编辑的实际上下文正文,发送规则见 [UI 设计](./ui-design.md)。
|
||||
- 关系移除保留撤销状态及原始来源;界面没有提供恢复入口。
|
||||
- 候选集最多 100 个实体,复用依赖模型显式选择;不会自动合并历史重复实体或跨 scope 合并。结果级历史内容已保存,事件滑块仍不重建逐事件的实体演变。Experiment 和完整图谱回放尚未实现;批次暂停/继续已接通。
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ schema 47 增加运行配置、来源清单、成功批次、导航节点四张
|
||||
|
||||
`supervision:pause` 将父 signal 传入排队及在途模型;取消后的输出不提交。`supervision:resume` 恢复已保存 run;`supervision:batches` 默认每页 10 批、最多 20 批,返回完整叶子及来源。活动返回已保存批次、码点数、剩余来源、当前阶段、排队或执行中的模型任务数及已保存配置。提取和导航汇总持续运行至完成,不按累计运行时长暂停;用户暂停会中断在途请求,仅保留已保存批次。完成判定不依赖摘要措辞。
|
||||
|
||||
2026-09-26 已接入整次回顾 single-flight、`supervision:cancel` 及实时 `supervision:execution`。手动重复请求不排队,自动请求等待;已取消运行从自动未完成查询中排除,也不能手动继续。持久取消与实际停止分开呈现,准入保留至 Runtime 清理结束。完整生命周期见[单次执行与取消](./technical-design.md#单次执行与取消),第 1 节关于 `pending` 队列和缺少取消入口的描述仅为改造前基线。
|
||||
|
||||
当前阶段以 `phase` 写入既有 `supervision_review_runs.state_json`,取值为 `collecting / extracting / summarizing / saving`;无新表或迁移。它记录服务最后进入的阶段,失败和重启后保留;完成仍由 `supervision_runs.status` 的发布事务决定。活动的 `navigationNodes` 从已保存导航表计数,`inFlight` 仍来自进程内计数。旧运行没有 phase 时不回填推测值。清单和最终发布为同步事务,短阶段不保证被轮询看到,清单事务失败也不会留下部分阶段记录。批次接口只有成功记录,没有逐个失败/在途任务或项目、会话聚合状态;界面仅按分页返回的真实归属组织详情。
|
||||
|
||||
### 当前设置合同
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# 时态 Story Graph 内置 MCP 设计
|
||||
|
||||
日期:2026-09-28。状态:D1 只读工具及本地、远程接线已实现,验证记录见[实施进度](./progress.md#2026-09-28-story-graph-只读工具)。D2 跨范围复用、D3 记忆读取切换及历史重建仍未实现。
|
||||
|
||||
本文负责 FR-S11 的 MCP 工具契约、时间语义、范围复用和记忆过渡设计。产品要求见[监督者产品设计](./supervisor-prd.md),用户验收见 [US-S28 至 US-S31](./user-stories.md#us-s28-依据决定演变继续工作)。既有图谱对象与交互仍由[图谱 PRD](../story-graph/prd.md)定义。可执行输入以[共享工具合同](../../../src/shared/story-graph-tools.ts)为准,数据投影见 [Story Graph Reader](../../../src/main/assistant/story-graph-reader.ts);本文件同时保留后续阶段目标。
|
||||
|
||||
## 1. 目标与现状
|
||||
|
||||
监督者的主要产出是带时间、演变关系和来源的 Story Graph。工作回顾、侧栏和 Agent 上下文从同一组事实中组织内容。扁平记忆条目无法独立表达“当时决定了什么、后来为何修订、现在应采用什么”,因此不再作为目标架构的主要产物。
|
||||
|
||||
用户侧统一为监督者维护的工作记忆:包含长期偏好、决定、事件、未解决事项及其依据。“替代记忆”指统一概念与后续读取入口,保留已确认偏好、用户修订和已有数据。它不授权删除 `memory_items`、抹掉历史或给旧内容补造事件。
|
||||
|
||||
| 能力 | 当前代码事实 | 本设计目标 |
|
||||
| --- | --- | --- |
|
||||
| 图谱与来源 | 已有结果、事件、实体、关系、结果图谱快照及成功叶子;历史归属存在缺失边界 | 按对象、时间和相关性读取事实与演变,并返回来源版本和覆盖信息 |
|
||||
| MCP | [内置目录](../../../src/shared/builtin-mcp-servers.ts)和[能力合同](../../../src/shared/capability-contracts.ts)已有 `story-graph`,包含三个只读工具 | 按需读取,沿用应用启停及 Runtime 分配 |
|
||||
| 时间与关系 | [监督合同](../../../src/shared/supervision-contracts.ts)已有 `occurredAt`、确认状态和 `revised`;关系枚举没有明确替代/矛盾类型 | 分离发生、生成、记录时间;用有证据的关系表达替代和矛盾 |
|
||||
| 范围与身份 | checkpoint 按阶段、精确 scope、来源区分;候选实体只取同 scope | 同一来源版本的有效叶子事实可跨 scope 复用,范围仍控制可见性与解释 |
|
||||
| 记忆 | `reviewBackground` 仍读已确认记忆;最多四条、每条 500 字符,作为当前背景 | 逐步由统一查询承接,保留确认状态与适用范围 |
|
||||
| 历史重建 | 有结果快照,不具备完整来源版本及人工修改时间序列 | 首期只提供 `current`、`timeline`;`as_of` 留待历史重建能力具备后设计交付 |
|
||||
|
||||
现状依据还包括 [AssistantDatabase](../../../src/main/assistant/assistant-database.ts) 的 `saveReviewCheckpoints`、`listSupervisionCandidates`、`reviewBackground`,以及[生产分块调度](./review-scheduling-design.md#0-生产接线与剩余边界)。现有结果快照只证明某次回顾保存过哪些内容,不能据此声称能还原任意时刻的认识。
|
||||
|
||||
## 2. 对象与稳定身份
|
||||
|
||||
复用现有 SQLite、领域对象和来源定位。设计不要求图数据库、独立向量库、完整正文副本、新持久化日志或通用历史快照层。所需读取视图先从已有结果、叶子、关系和 locator 推导;无法推导的内容明确返回未知。
|
||||
|
||||
| 对象 | 概念合同 | 身份与关联规则 |
|
||||
| --- | --- | --- |
|
||||
| 故事线 `story_line` | `id`、主题、范围、事件与实体引用 | 沿用故事线 ID;不把项目名当 ID |
|
||||
| 事件 `event` | `id`、类型、描述、发生时间、实体及来源引用 | 决定、讨论、变化、里程碑是事件类型;一次回顾运行不是工作事件 |
|
||||
| 实体 `entity` | `id`、描述、确认状态、有效性、演变引用 | 对象 ID 与内容修订分离;同名或模型局部 ID 不证明同一实体 |
|
||||
| 变化 `entity_change` | 实体、事件、变化类型、依据、适用时间 | 指向具体对象版本;无独立主键时以已有所属对象和稳定关联键定位,不以页内下标造身份 |
|
||||
| 关系 `relation` | `id`、两端引用、类型、理由、来源、确认状态 | 替代/矛盾关系必须能定位两端主张及支持该关系的证据 |
|
||||
| 阶段总结 `summary` | 结果 ID、范围、区间、正文、事实引用 | 用于导航;检索与上下文仍能访问完整叶子事实 |
|
||||
| 来源引用 `source_reference` | 引用 ID、来源类型与原 ID、版本、locator、可用性 | 引用 ID 与原消息/任务 ID 分开;跨结果的引用 UUID 不等于新的原始来源 |
|
||||
|
||||
偏好、方案、决定涉及的概念沿用实体及事件表达,不为每个业务名词另建基础设施。业务上的“已决定”(`decided`)与“已完成”(`completed`)是不同状态,这里不声明新增任务状态枚举;运行 `completed` 仅表示整理发布成功。决定采用方案、计划执行、模型写出“已决定”均不能推出任务完成,完成须有任务记录或明确执行证据。
|
||||
|
||||
返回对象携带 `object_ref`(类型和稳定 ID)、`object_revision`、`result_id` 及适用 scope。版本可使用已有结果身份与可用修订信息表达;没有可靠对象版本时返回 `unknown`,不把 `updated_at` 伪装成完整版本链。旧文本主键及 Main 精确别名映射继续保留,`candidateRef` 只是一次模型输入内的候选引用,不作为 MCP 持久 ID。跨 scope 身份合并须有明确映射依据,不能因复用叶子事实而自动合并同名实体。
|
||||
|
||||
## 3. 时间、确认与有效性
|
||||
|
||||
| 维度 | 含义 | 禁止的推断 |
|
||||
| --- | --- | --- |
|
||||
| `event_time` | 原记录描述的事件发生时刻或区间;带精度、来源依据,未知可空 | 不以回顾时间填补未知发生时间;消息发送时间只有在确实表示该事件时才可采用 |
|
||||
| `review_generated_at` | 产生该归纳的回顾时间 | 较晚生成不表示事件较晚发生或旧决定已被替代 |
|
||||
| `recorded_at` | 对象或版本实际写入系统的时间 | 迟录、补录不改变事件先后,也不证明当时已知 |
|
||||
| `validity` | 该主张适用的区间及当前有效、被替代、存在争议或未知状态 | 不用确认时间、记录时间直接推导有效起止 |
|
||||
| `confirmation_state` | 自动归纳、已确认、用户修订、已撤销等内容审核状态 | 已确认不等于永久有效;未确认不等于已失效 |
|
||||
|
||||
`replaces` 表示有明确证据的新主张替代旧主张,记录方向、两端版本、适用范围、理由和来源。`contradicts` 表示两项主张存在证据支持的冲突,不自动决定谁正确。它们是目标关系语义,不能将当前 `contrasts` 或单纯 `revised` 无条件映射为这两类关系。新增选项、日期较新、措辞更肯定都不足以建立替代关系;没有证据时保留并列主张或待核对差异。
|
||||
|
||||
时间区间输入使用带时区的 ISO 8601 时间,查询归一化为 UTC。概念 `time_range` 使用闭区间 `[from, to]`,与现有监督范围保持一致;区间事件按相交判定。检索支持明确的 `time_basis`:默认 `event_time`,也可指定 `review_generated_at` 或 `recorded_at`。响应回显所用维度。未知时间不冒充命中区间,返回可计算的排除数量或 `unknown`,允许通过不限定时间的查询另行查找。
|
||||
|
||||
`timeline` 按发生时间和稳定 ID 排序,未知时间单列,展示目前保存的演变及缺口。它可以包含后来补录的旧事件,因而不等于“当时已知”。`current` 给出截至读取时、在已覆盖证据内可支持的当前理解;有冲突或缺口时保留并说明,不能仅挑最新摘要作为答案。
|
||||
|
||||
`as_of` 是未来能力,首期输入 schema 不接受该模式或参数,调用必须明确返回不支持,不能悄悄降级为 `current`。只有具备所需对象版本、人工修订记录以及可用来源版本/历史重建,并能验证不会泄漏当时未知的信息后,才另行定义其语义和验收。本文不批准为它新建持久化日志或快照体系。
|
||||
|
||||
## 4. 公共读取合同
|
||||
|
||||
三个工具都只读已有数据,不调用模型、不自动发起回顾、不更新 checkpoint、不确认或修订对象、不创建任务,也不写入记忆或知识库。检索采用已有数据的确定性过滤与相关性排序,不能在调用中借模型补齐缺失事实。生成面向用户的建议由调用方 Agent 完成,必须引用返回证据并遵守其范围与限制。
|
||||
|
||||
默认 scope 为调用会话的当前项目,由 Main 解析并冻结;没有当前项目时要求显式选择 scope,不默认为 Global。调用方可显式请求 Global 或指定项目集合,沿用已有范围与能力授权校验。分页继续使用首请求范围,切换 UI 当前项目不改变旧游标。对象与来源读取也要重新校验归属,稳定 ID 不能绕过 scope。
|
||||
|
||||
首期沿用现有精确 scope 结果归属,不把 Global 摘要冒充单项目结论,也不隐式把 Global 结果投影为项目上下文。项目查询缺少该 scope 数据时明确返回空结果及覆盖状态。未来跨 scope 复用只接纳能按来源项目和事实依据正确筛选的叶子,跨项目归纳仍保留真实范围。
|
||||
|
||||
| 响应部分 | 必须表达的信息 |
|
||||
| --- | --- |
|
||||
| 范围 | `requested_scope`、`resolved_scope`、每项原始 scope、所选时间区间和时间维度 |
|
||||
| 修订 | 对象/结果修订引用、来源版本、读取时间;区分已知版本与 `unknown` |
|
||||
| 覆盖 `coverage` | 已知处理范围、来源版本和片段区间、缺失或未处理部分、未纳入来源类型;缺少数据时为 `unknown`,不能用零代替未知 |
|
||||
| 分页 `page` | `returned_count`、`has_more`、`next_cursor`、本页是否完整及限制原因;集合数量不能计算时为 `unknown` |
|
||||
| 证据 | 来源引用与 locator、关系依据、确认与有效性、已知冲突和历史缺口 |
|
||||
|
||||
覆盖与分页独立:最后一页只证明匹配结果读完,不能证明所有原始消息已被整理;已处理全部入选正文也不证明模型识别了全部事实。旧 `coverage_json` 只有条数时,不能推导完整的时间、版本或语义覆盖。
|
||||
|
||||
列表及长字段都需有界分页,超过响应容量时提供可续读的位置,无法分页的响应明确失败。不得静默裁剪后标完整。游标绑定过滤条件、排序和可用结果修订;分页期间内容变化、无法维持同一读取版本时返回 `stale_cursor` 并要求重新查询,不混入新旧页。该规则可基于现有修订检查完成,不要求持久化查询快照。取消、读取失败与真实空页分别返回。
|
||||
|
||||
## 5. 工具定义
|
||||
|
||||
### `story_graph_search`
|
||||
|
||||
输入:`query`、可选 `scope`、`object_types`、`time_range`、`time_basis`、`page_size` 和 `cursor`。`object_types` 对应第 2 节的对象类型;省略时检索全部支持类型。默认 scope 及时间规则按第 3、4 节执行。对象页默认 10 项,上限 50 项。匹配为不区分大小写的连续文本匹配,标题、实体标签和摘要字段权重高于其他字段;同分按类型、稳定 ID 和结果 ID 排序。
|
||||
|
||||
输出相关对象页,包含匹配原因或命中字段、明确标为摘录的预览、稳定引用、修订、相关演变和来源入口,以及公共响应信息。过滤须先于分页,按相关性排序并以稳定 ID 消除同分歧义。不能只在最近若干摘要中筛选后声称查完历史,也不能将摘要中的命中替代叶子事实。
|
||||
|
||||
### `story_graph_get_context`
|
||||
|
||||
输入:`object_ref`、可选 `scope`、`mode: current | timeline`(默认 `current`)、可选时间范围与维度、页大小及游标。`current` 表达当前理解;时间过滤只限定证据集合,响应需标明“在所选证据范围内”,不能称作该区间终点时的历史状态。
|
||||
|
||||
输出对象当前描述、明确的决定/工作状态、偏好与适用范围、未解决事项、相关实体及关系、演变和证据引用。`timeline` 分页列出提出、补充、验证、修订、替代和冲突证据,保留旧决定及新修订;多组集合或长正文须各自提供续读位置,不能只对顶层对象分页。返回的是存储事实及其组织视图,不在工具内生成新建议。
|
||||
|
||||
D1 返回各结果快照、当前投影、事件、变化、关系、来源及成功叶子的独立描述。既有存储没有可靠的有效期和替代关系枚举,因此 `validity` 返回 `unknown`,保留 `revised`、`contrasts` 及原始理由供调用方核对。当前实体投影不会遮掉旧结果或叶子描述。`content` 是可拼接的 JSON 文本片段,每项附零基码点位置;按对象引用和结果 ID 拼接后解析。`content_page_size` 默认 4,000、上限 8,000 码点,游标可停在对象内部。完整响应超过 100,000 字节时明确失败,要求缩小页大小。
|
||||
|
||||
对象不存在、scope 不匹配、版本缺失或只有部分历史时分别说明。已存在的某个结果快照可作为具体版本读取依据,但不能作为任意 `as_of` 查询的替代品。
|
||||
|
||||
### `story_graph_read_source`
|
||||
|
||||
输入:`source_reference_id`、可选 `scope`、明确的读取种类 `snapshot | version | current`、所需 `source_version`(读取指定版本时必填)及片段页位置。默认 `snapshot`,读取该引用实际保存的证据片段;不默认换成当前原文。
|
||||
|
||||
输出正文页、`content_kind`、请求版本与实际返回版本、`source_location`、原来源 ID、已保存片段与整份来源的范围和长度、可用时间元数据,以及公共覆盖和分页信息。位置用零基、左闭右开的 Unicode 码点 `[start, end)`;消息 locator 尽量保留项目、会话、消息、顺序和角色,本地资料保留文档/分块,外部片段保留已有 locator。缺少位置时明确标记,不伪造链接。
|
||||
|
||||
`snapshot` 只声称返回当次实际保存的片段;`version` 仅在该来源支持并保留指定版本时成功;`current` 显式读取当前内容并报告与引用版本是否不同。历史版本不可用时返回 `historical_version_unavailable` 及可用读取选项,由调用方决定是否另读当前版本。来源删除或不可访问时返回对应可用性;已保存片段仍可读时准确标注其范围。读取完一个片段不能称整份原文已读完,超长内容必须可续页,无静默截断。
|
||||
|
||||
D1 来源页默认 4,000、上限 8,000 码点。`current` 通过既有 locator 精确读取消息、任务状态正文或保存的知识引用片段;不拉取外部知识库原文。`version` 仅在当前可读来源的修订恰好等于请求版本时返回该版正文。旧版正文没有保留时明确不可用;无 locator 的旧引用仍可读 snapshot。当前来源迁出所选项目时拒绝读取。已保存引用的范围与当前位置分别校验。
|
||||
|
||||
## 6. 内置 MCP 与 Runtime 接入
|
||||
|
||||
内置 MCP 列表提供 `Story Graph`,能力 ID 为 `story-graph`,默认分配给 Model、OpenCode、Continue 和 DeepSeek Harness;监督者应用默认关闭,开启应用后才可发现工具。工具描述说明适用于“继续上次工作”“此前如何决定”“方案为何改变”等请求。普通聊天不强制查询,也不把整份图谱自动注入每轮上下文;Agent 先搜索、再取相关对象上下文,在需要核对原话、处理冲突或详细引用时读取来源。
|
||||
|
||||
| 配置或目录 | 当前状态 | 目标映射 |
|
||||
| --- | --- | --- |
|
||||
| `heartbeatEnabled` | 监督者应用开关,新设置默认关闭 | 为 Story Graph 暴露和每次调用的必要条件;关闭后不列出三个工具,旧会话直接调用也拒绝 |
|
||||
| 内置能力 `enabled` 与 `assignments` | [CapabilityService](../../../src/main/capabilities/capability-service.ts)管理现有 MCP 开关与 Runtime 分配 | `story-graph` 沿用同一管理方式;应用关闭时不得由内置能力开关绕过,保留用户原分配 |
|
||||
| 内置工具目录 | 已有 Story Graph 条目 | 映射 `story_graph_search`、`story_graph_get_context`、`story_graph_read_source`,全部 `access: read`、`readOnlyHint: true` |
|
||||
| 监督整理参数 | 超时、并发、来源页与批次设置已存在 | 控制后台整理;不让一次 MCP 查询启动整理,也不以正文批次预算截断检索结果 |
|
||||
| 计划 `enabled` | 决定自动回顾是否到期执行 | 不决定已有图谱能否读取;应用开启且能力可用时,无计划也能查已有结果 |
|
||||
|
||||
Main 在工具发现和调用分发时共同检查应用启用、能力启用、Runtime 分配和 scope;只隐藏菜单不足以阻止旧会话调用。关闭后拒绝新的读取请求,已在途响应交付前复核状态,避免旧绑定继续返回数据。启用工具本身不产生回顾或数据写入。Ask 与 Execute 均可读取,同样没有写工具,也不借此扩大 Execute 权限。
|
||||
|
||||
本地 OpenCode、Continue 和原生客户端复用 [KnowledgeMcpGateway](../../../src/main/agent/knowledge-mcp-gateway.ts) 的 MCP 注册和分发;直连 Model 与 DeepSeek Harness Main 代理调用同一服务。远程 OpenCode/Continue 复用现有图像工具的受管 HTTP MCP 和二进制通道,`storyGraph` 描述独立于图像生成描述,Ask 可只携带图谱读取。请求仍由桌面 Main 解析范围和读取 SQLite,不把数据库、正文库或凭据复制到 Host。
|
||||
|
||||
远程发现每次向 Main 复核启用状态;调用复用同一个范围、分页及版本读取入口。OpenCode 根会话和子会话精确放行当前受管端点的图谱工具;Continue Ask 保留 Main 绑定的会话端点并只允许共享只读工具名。DeepSeek Harness 的 Main 目录、参数转换和 Host 执行钩子均接入这三个工具;其他普通内置 MCP 的 Harness 限制保留。当前远程 Runtime 支持 OpenCode/Continue,不新增远程 Harness。桥接不可用时明确失败。
|
||||
|
||||
远程使用须配套部署含此接线的 Desktop 与 Agent;旧 Agent 不识别新增的工具描述字段。本次没有发布或更新受管包,源码验证不代表已发布客户端具备该能力。
|
||||
|
||||
## 7. Global 与项目复用
|
||||
|
||||
当前 Global、单项目和不同项目集合分别维护 checkpoint 和故事线候选身份,项目集合排序归一化后才比较。项目 A 已处理某消息,不会使 Global 的相同消息自动成为已处理;Global 当前会按自身范围重新收集原始来源,不能描述为“只聚合已有项目图谱”。报告与监督也是独立阶段,不能互相推进位置。当前手动重看还会重新整理所选历史。
|
||||
|
||||
目标是同一来源版本的事实提取成功一次后,在 Global 和项目查询/整理中复用可用叶子事实,包括事件、实体变化、关系证据及来源位置,不只复用项目摘要。Global 可在已提取事实之上组织跨项目关系和摘要;范围变化本身不应造成相同正文再次提取。范围控制查询归属和综合判断,不再充当重复提取的唯一分界。
|
||||
|
||||
复用须核对原来源身份、版本、已覆盖片段及提取合同是否仍适用。仅部分成功时继续缺失部分;来源改版或用户明确要求重新分析时可产生新的提取结果,不能覆盖已确认内容。任务的当前状态、偏好背景和既有摘要仍须标明时间角色,不能作为跨 scope 复用时新发生的事件。共享事实的可见范围不能被 Global 摘要扩大。
|
||||
|
||||
这一目标尚未实现。本轮不批准具体数据迁移、跨 scope 主键重写、历史实体合并、checkpoint 转换或缓存表方案。实施前应从已有成功叶子和来源版本定位验证最小复用方案,列出旧数据的可复用程度与缺口;保留现有精确 scope 行为直到替代方案完成验证,不提前修改现有 checkpoint 含义。
|
||||
|
||||
## 8. 记忆过渡与分阶段交付
|
||||
|
||||
已确认的长期偏好必须继续可用,并保留 Global/项目适用范围。旧记忆只有更新时间时,只能显示为当前偏好背景和实际更新时间,不能补造“首次决定”“当时生效”或替代关系。新的图谱归纳与已确认偏好冲突时返回待核对差异,不以较新生成时间覆盖用户选择。
|
||||
|
||||
| 阶段 | 交付内容与退出条件 | 当前状态 |
|
||||
| --- | --- | --- |
|
||||
| D0 设计 | 记录工具、时间、范围、过渡与验收合同 | 已记录 |
|
||||
| D1 只读查询 | 基于现有数据实现三个工具及本地/远程接线、配置目录、关闭拦截和分页;缺失版本与覆盖返回未知,对应 US-S28 至 US-S30 | 已实现;验证范围见实施进度,当前 memory 读取继续保留 |
|
||||
| D2 事实复用 | 验证同一来源版本跨 scope 复用完整叶子;明确身份、版本变化与已有数据处理方案,达到 US-S31 的范围验收 | 待设计具体存储调整并实施;无已批准迁移方案 |
|
||||
| D3 概念与读取统一 | 让统一入口承接已确认偏好及图谱上下文;核对引用、范围、冲突和旧数据可读性后,才切换现有 memory 消费路径 | 待实现;不以删除旧记录作为退出条件 |
|
||||
| 未来历史重建 | 单独定义并验证 `as_of` 所需版本与当时可知性 | 不属于首期,不承诺交付时间 |
|
||||
|
||||
D1 可将现有已确认偏好作为明确标记的背景投影,原读取路径在过渡期仍工作。重复背景按原记忆身份识别,图谱未知历史不能由记忆更新时间补齐。具体迁移与旧入口退出时点须根据实现证据确定,本文没有要求立即删除旧 memory API、设置或 UI。
|
||||
|
||||
## 9. 验收映射
|
||||
|
||||
核心场景使用可核对的旧决定 A、后来明确修订为 B 的证据,以及“现在继续做应采用什么”的请求。工具返回 A、修订事件、替代依据与 B;Agent 基于它们推荐 B,并引用旧决定和修订来源。新增选项 C 但没有替代依据时,不得把 B 判为失效;决定 B 也不能被回答为 B 已执行完成。
|
||||
|
||||
| 验收 | 对应故事 | 通过条件 |
|
||||
| --- | --- | --- |
|
||||
| 决定演变 | US-S28 | 完成上述旧决定 → 有证据修订 → 当前建议及引用链;冲突没有证据解决时保持待核对 |
|
||||
| 时间 | US-S28、US-S29 | 迟录旧事件不变成新事件;确认与有效性分开;timeline 不声称当时已知;`as_of` 明确不支持 |
|
||||
| 分页与来源 | US-S29 | 匹配项、演变和长原文均可读到末页;覆盖未知与零命中可区分;游标失效不混页;旧版不可用不返回伪历史 |
|
||||
| 启停与只读 | US-S30 | 应用关闭后发现与直接调用均不可用;开启但无计划可读已有数据;工具自身模型调用与业务写入均为零 |
|
||||
| Runtime 一致性 | US-S30 | 本地及 GoodBuddy Agent 远程实际链路具有相同 scope、版本、分页、引用与关闭行为,不能以共享 schema 代替接线验收 |
|
||||
| 记忆及范围复用 | US-S31 | 确认偏好与已有引用保留;同版本成功叶子跨 scope 复用且能检索事实,不只返回摘要;历史缺口不补造 |
|
||||
|
||||
验证命令和证据集中记录在[实施进度](./progress.md#2026-09-28-story-graph-只读工具)。本次只运行定向测试、类型检查、限定文件 lint 和确定性 Host 探针,没有全量测试、付费模型请求或发布操作。真实模型如何根据冲突证据形成最终建议,仍需与工具读取正确性分开验收。
|
||||
@@ -11,7 +11,7 @@
|
||||
| 名称 | 职责 |
|
||||
| --- | --- |
|
||||
| 监督者 | 应用名称,负责观察、回顾和解释工作进展 |
|
||||
| 智能心跳 | 按计划唤醒监督者的机制,保留计划与运行管理 |
|
||||
| 智能心跳 | 按计划触发增量回顾,并按配置的介入方式生成建议;不单独读取原文或生成报告(FR-S12) |
|
||||
| 监督反馈 | 会话右侧的阶段回顾、问题提示与证据入口 |
|
||||
| 故事线图谱(Story Graph) | 呈现事件、知识实体及其随时间发展的关系 |
|
||||
|
||||
@@ -33,6 +33,10 @@ FR-S3:首次启用时选择项目、会话及可用来源,生成前显示范
|
||||
|
||||
FR-S4:支持手动回顾,并复用已有定时检查机制。自动报告和监督回顾分别只处理所选范围、回顾窗口内新增、修订或尚未处理的来源片段;没有待处理输入时跳过模型及结果生成。失败输入保留重试资格,预算遗漏不得记为已处理。手动回顾重新整理所选历史区间。具体规则见[自动增量与手动重看](./logic-design.md#自动增量与手动重看)。事件触发和阶段自动判定仍待设计。
|
||||
|
||||
回顾默认增量“回顾”默认增量,与心跳整理一致;重看历史改为“更多”中的显式“重新整理”。心跳不再先生成独立报告,同一来源版本在一次触发中只读取一次。规则见[心跳职责与介入](./logic-design.md#心跳职责与介入目标设计)。
|
||||
|
||||
FR-S12(已实现,主动介入除外):智能心跳的职责限定为**定时触发增量回顾**和**按计划配置介入**。介入方式为“仅更新记忆”“生成建议”(默认);会话级“主动介入”后续交付,当前不显示。建议只根据本次图谱变化产生,附来源依据,替代旧心跳报告、记忆建议和行动建议;无变化不调用模型,有变化而无建议候选时不发起建议调用。验收见 US-S32、US-S33。
|
||||
|
||||
FR-S5:会话右侧在跟随模式下展示当前会话的监督反馈;固定到 Conversation、Task 或 Experiment 时保持所选目标并显示其名称,切换聊天不改变监督目标。跨会话总结在完整应用中展示。反馈包含结论、来源和“在图谱中查看”定位入口。用户主动选择“发到当前会话”才加入聊天消息,同一结果不重复触发侧栏和全局通知。
|
||||
|
||||
FR-S6:监督者可提出整理与修改建议;已有会话监督的观察边界继续生效。自动更新图谱不能静默覆盖用户修改的描述、已确认的关系或已有知识库正文。取消整理后保留上次结果;失败说明受影响范围并允许重试,部分结果不得显示为完整回顾。
|
||||
@@ -51,6 +55,8 @@ FR-S9:来源事实、自动归纳、待核对关联和用户确认内容分别
|
||||
|
||||
## 落地范围
|
||||
|
||||
FR-S11(D1 已实现,D2/D3 待实现):监督者以时态 Story Graph 为主要产出,统一用户侧工作记忆概念并保留已确认偏好与已有数据。Agent 在继续工作、查询此前决定及其修订时,按需使用只读的 `story_graph_search`、`story_graph_get_context`、`story_graph_read_source`,读取范围、时间、演变、覆盖及可引用来源;工具不调用模型或触发回顾,监督者关闭时不暴露且拒绝调用。本地和远程 Runtime 共用读取语义。后续目标为同一来源版本提取一次并跨 scope 复用叶子事实;当前精确 scope 独立处理及 memory 读取继续保留。`as_of` 仅在历史重建能力具备后另行交付。合同与过渡阶段由[专项设计](./story-graph-mcp-design.md)定义,验收见 US-S28 至 US-S31;本轮没有数据迁移。
|
||||
|
||||
触发、整理与结果共享规则,以及整体架构和图谱对象关系见[逻辑设计](./logic-design.md)。
|
||||
|
||||
首个完整流程为:启用监督者、选择范围、生成回顾、进入图谱、核对来源、携带选定上下文继续讨论。知识库双向定位与内容补充随后接入同一流程。图谱关系辅助检索需单独验证效果,不作为首版默认检索策略。
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
| 产品设计 | [监督者应用产品设计](./supervisor-prd.md) |
|
||||
| 行为规则 | [监督者逻辑设计](./logic-design.md) |
|
||||
| 界面设计 | [监督者 UI 设计](./ui-design.md) |
|
||||
| 实施进度 | SQLite schema 47;当前算法、设置和验收边界见[生产接线](./review-scheduling-design.md#0-生产接线与剩余边界) |
|
||||
| 实施进度 | SQLite schema 50(心跳介入与监督建议见[心跳触发与建议](#心跳触发与建议2026-09-30));当前算法、设置和验收边界见[生产接线](./review-scheduling-design.md#0-生产接线与剩余边界) |
|
||||
|
||||
本文回答如何在现有 GoodBuddy 桌面端中实现监督者。它不改变产品范围,也不把模拟 Demo 当作生产数据模型。
|
||||
|
||||
FR-S11 的读取架构见[时态 Story Graph 内置 MCP 设计](./story-graph-mcp-design.md)。三个只读工具通过 `readStoryGraph` 投影现有 SQLite,Main 在发现、调用和返回前检查监督者启用及 Runtime 分配。本地 MCP、Model、Harness Main 代理和远程受管工具通道共用此入口;无 schema 迁移。该文独立定义对象/版本合同、时间语义、配置映射及后续跨 scope 复用和记忆过渡。当前 memory 背景读取、精确 scope checkpoint 与候选身份保留;结果快照不支持 `as_of` 历史重建。
|
||||
|
||||
生产入口由 `supervision-production.ts` 组装服务、SQLite、共享池和 ask Runtime。`supervision-review-store.ts` 保存冻结来源清单,按有界页和片段供 `SupervisorService` 派发;叶子及连续位置先提交,导航和完整结果之后发布。消息已有知识引用保留本地或外部 locator,已确认记忆通过独立背景输入提供。不会检索外部全库。详细存储、调度及当前限制统一见[分块调度第 0 节](./review-scheduling-design.md#0-生产接线与剩余边界)。
|
||||
|
||||
模型实体 `id` 只在单次输出内有效。Main 从同一 scope 的故事线提供最多 100 个未撤销实体候选,生产提示只暴露 `candidateRef`(如 `known_1`)、名称和说明。模型显式选择候选后,Main 转换为严格 UUID 类型的内部 `persistedId`。服务校验候选集成员和重复映射,保存事务再次按实体主键校验故事线归属及撤销状态。没有有效候选引用时分配新 UUID,不按名称或裸模型 ID 合并。来源仍按每次结果分配 UUID,保留原始 `source_id` 和 locator。
|
||||
@@ -33,7 +35,7 @@ schema 43 在结果上增加 `graph_snapshot_json`,保存当次实体名称、
|
||||
|
||||
侧栏通过 `onOpenSupervisionGraph(resultId)` 交给 App 导航;App 遵守现有离页检查,向 HeartbeatCenter / SupervisorWorkspace 传递类型化 `graphNavigation`,复用 `heartbeat` 路由及 keepalive 页面。每次点击创建新的导航请求,打开 graph 页签并更新历史选择共用的 resultId。overview 未包含该 ID 时仍直接请求其 graph;旧 overview、graph、来源和操作响应通过同一请求序号失效,不覆盖新结果。没有新增 window 事件、页面或持久化字段。
|
||||
|
||||
继续讨论入队时,无附件请求省略 `serializedContexts`;请求未指定 Runtime 时使用会话保存的选择。知识库预览与提交均检查目标库存在且为本地可写库,更新实体还检查其实际所属库。侧栏确认框展示 Main 返回的实体字段、目标库和来源正文,取消或写入失败后可以重新预览。
|
||||
继续讨论预览将 `supervision:continue-context` 返回的 `prompt` 直接作为可编辑草稿。侧栏与图谱入口发送当前草稿,不重新拼接原始上下文。`supervision:continue` 沿用现有正文校验(去除首尾空白,最多 12,000 字符),使用空 `attachments` 入队,无附件请求省略 `serializedContexts`;请求未指定 Runtime 时使用会话保存的选择。会话已有的记忆和知识库配置仍按普通会话发送规则处理。知识库预览与提交均检查目标库存在且为本地可写库,更新实体还检查其实际所属库。侧栏确认框展示 Main 返回的实体字段、目标库和来源正文,取消或写入失败后可以重新预览。
|
||||
|
||||
监督来源清单将 UI 时间区间归一化为 UTC,先筛选再按稳定键分页。项目必须存在且 active;消息按闭区间筛选,任务按区间内创建或完成时间筛选。手动和自动监督共用该路径,自动清单另读取 supervisor checkpoint;手动心跳报告保留原有 collector。
|
||||
|
||||
@@ -43,7 +45,7 @@ schema 43 在结果上增加 `graph_snapshot_json`,保存当次实体名称、
|
||||
|
||||
监督整理超时由 run 创建时冻结;共享模型池仍采用实时设置上限。`supervision:pause` 取消该 run 的排队和在途工作,`supervision:resume` 继续已保存批次;监督整理输出在流中按 `supervisionReview.responseKiB` 检查响应容量,默认 1024 KiB,可在设置页调整为 100 至 16384 KiB。该容量每次请求读取当前设置,继续旧运行也采用新值;超限保留成功批次并提示调高后继续。生成摘要及事实内容不设独立短字符限制,监督旧摘要读取保留全文,具体边界见[生产接线](./review-scheduling-design.md#0-生产接线与剩余边界)。以下报告领取和租约规则继续适用。
|
||||
|
||||
手动和自动监督均在桌面 Main 调用生产工厂,Runtime 解析请求只有 `workMode: ask`,不携带 SSH 项目或执行空间。摘要校验、合并和持久化在 Main 完成;本次取消内容长度限制不改变 `gbagent`、远端 Runtime 启动或桌面到 Agent 协议。
|
||||
手动和自动监督均在桌面 Main 调用生产工厂,Runtime 解析请求只有 `workMode: ask`,不携带项目、Runtime 选择或执行空间。`resolveRequestRuntime` 因而返回桌面默认 Runtime,不进入 SSH 项目或 `selectedRuntimes.getRuntime` 分支;回顾 scope 只筛选证据。摘要校验、合并和持久化在 Main 完成,single-flight、取消及 UI 控制不改变 `gbagent`、远端 Runtime 启动或桌面到 Agent 协议。
|
||||
|
||||
`ApplicationSettingsStore` 持久化报告和整理模型超时,均为 30..600 整数秒,默认 240。报告排队前冻结,监督创建 run 时冻结;计时从获槽及 Runtime 解析后开始,覆盖模型执行及其内部重试。流结束校验 signal 和完成事件,finally 释放临时会话,心跳报告保持原有 100KB 上限,监督整理使用上文的可调响应容量。采集、排队、保存和清理不计入模型超时。
|
||||
|
||||
@@ -55,8 +57,27 @@ schema 47 的四张批次相关表使用外键随监督运行清理,未完成
|
||||
|
||||
当前设置及冻结范围见[当前设置合同](./review-scheduling-design.md#当前设置合同)。未实现的高级参数继续保留在目标清单,不显示为可保存控件;没有兼容原型数据库的读取器。
|
||||
|
||||
### 单次执行与取消
|
||||
|
||||
对应 FR-S4、FR-S6、FR-S10;状态规则见[活动记录](./logic-design.md#活动记录)。同一个 `SupervisorService` 在异步配置读取前占用唯一执行位置,`run` 和 `resume` 共用准入。已有执行或停止清理时,手动新建及继续立即返回 `SUPERVISION_REVIEW_BUSY`;`trigger: heartbeat` 等待当前 Promise 结束,醒来后重新检查占用。等待中的自动请求尚未创建监督 run,不占模型池;心跳报告在进入下游监督前已释放自己的槽位。
|
||||
|
||||
`supervision:execution` 返回进程内 `{ active, runId?, stopping? }`,配置读取期间可有 `active: true` 而尚无 runId。`supervision:cancel({ runId })` 先在既有 `supervision_runs` 写入 `cancelled`、清除错误并保存取消时间,再向父 controller 传播 abort;重复取消保留原时间。该接口等待执行 Promise 结束,包含并行批次的 `allSettled` 和 Runtime `releaseConversation`,之后才释放准入。暂停只请求 abort,执行停止后保存 `paused`;取消优先于暂停。迟到模型输出不得保存叶子、导航或完整结果,成功批次保留,自动 checkpoint 不推进。发布是同步 SQLite 事务,已完成或无变化的运行拒绝取消,不撤销已发布结果;本次无 schema 迁移。
|
||||
|
||||
Preload 暴露类型化 `execution`、`cancel`,取消输入使用 UUID schema 并校验可信 sender。活动 UI 用实时执行状态覆盖持久记录的停止显示;工作回顾挂载期间每两秒读取执行状态,发起前再次查询,Main 仍作最终准入判断。`resume` IPC 直到运行结束才返回,Renderer 发出请求后释放提交锁并独立处理结果,确保继续中的回顾仍可暂停或取消。状态条 X 仅修改本地显示状态。
|
||||
|
||||
### 心跳触发与建议(2026-09-30)
|
||||
|
||||
对应 FR-S12,规则见[心跳职责与介入](./logic-design.md#心跳职责与介入目标设计)。`HeartbeatService` 只依赖 `HeartbeatActions { review, suggest? }`:领取后 `completeHeartbeatTrigger` 立即提交心跳自身运行(租约 5 分钟,仅覆盖交接),再调用 `review`,由 `ipc.ts` 转为 `supervisorService.run({ trigger: 'heartbeat' }, heartbeatRunId)`。审查失败写 `projection_status/error`,结果为 `no_change` 时标记心跳无变化。心跳不再占用模型池,也不读取 `heartbeatReportTimeoutSeconds`;该设置字段保留兼容,界面不显示。下文关于心跳报告阶段、报告租约与报告增量的描述均为历史行为。
|
||||
|
||||
`isIncrementalReview(request)` 统一判断:`trigger: heartbeat` 或未设 `reanalyze` 的手动请求读取并在发布事务中推进 `review_checkpoints`;`reanalyze: true` 从零读取且不写进度。`SupervisionReviewStore.unfinished` 只续跑 `failed/running` 的心跳运行,用户暂停的保持暂停。
|
||||
|
||||
计划 `intervention` 为 `suggest` 时,`deriveSuggestions` 调用 `SupervisionSuggestionStore.candidates(supervisionRunId)`:读取该运行叶子批次的 `openItems`(按原始来源映射到本结果 `supervision_sources`)、`revised` 实体变化、快照内 `contrasts` 关系,以及事件关联中不同原始来源数不少于 3 的 `automatic` 实体。指纹按类型与实体、关系或规范化文本生成;依据键使用原始来源类型、ID 与内容哈希,不用每次结果新生成的来源行 ID。每次最多 20 条。有候选时 `createProductionSuggestionPhraser` 发起一次无工具请求,共享监督模型池与整理超时;模型只返回 `ref/title/detail`,未知 ref 丢弃,缺失措辞回退规则文本。建议失败写 `suggestion_status = 'failed'` 与错误,`supervision:retry-suggestions` 只重跑建议。
|
||||
|
||||
IPC `supervision:suggestions`、`supervision:suggestion-action`、`supervision:retry-suggestions` 校验可信 sender 与 Zod 输入;监督者关闭时列表返回空、操作拒绝。接受未决事项创建暂停任务,接受候选约定确认迁入记忆或新建已确认记忆并确认实体。Schema 50 内容见[实施进度](./progress.md#2026-09-30-心跳职责收敛与监督建议)。
|
||||
|
||||
## 自动增量收集
|
||||
|
||||
|
||||
本节的 100 来源/2,000 码点批次查询现用于原心跳报告及旧服务测试;生产监督使用 schema 47 清单及批次位置,自动 checkpoint 只在完整发布时提交。已有 schema 46 指纹算法和 checkpoint 仍复用,不重置用户已处理位置。
|
||||
|
||||
对应 FR-S4、FR-S10 和 US-S27,行为定义见[自动增量与手动重看](./logic-design.md#自动增量与手动重看)。schema 46 在现有数据库增加 `review_checkpoints`,主键为阶段、规范化 scope 和来源标识,保存版本指纹、已处理位置和来源长度。来源标识区分消息 ID、任务 ID 和消息内知识引用位置,不使用消息时间戳作为身份。
|
||||
@@ -154,7 +175,7 @@ sequenceDiagram
|
||||
|
||||
运行状态与内容确认状态分开保存:
|
||||
|
||||
- 当前监督运行状态:`running`、`paused`、`completed`、`failed`、`no_change`。心跳及合并活动的映射见[活动记录](./logic-design.md#活动记录)。
|
||||
- 当前监督运行状态:`running`、`paused`、`cancelled`、`completed`、`failed`、`no_change`。心跳及合并活动的映射见[活动记录](./logic-design.md#活动记录)。
|
||||
- 内容状态:来源事实、自动归纳、待核对、用户确认、用户修订、已移除关系。
|
||||
- 运行成功只表示模型结果已按契约保存,不表示所有实体和关系已经被用户确认。
|
||||
- 失败保留上次完整结果和本次已保存批次;暂停不生成完整结果,继续入口恢复同一 run。
|
||||
@@ -213,6 +234,8 @@ erDiagram
|
||||
| `supervision:overview` | 工作回顾、运行状态、未解决事项和最近结果 |
|
||||
| `supervision:run` | 手动开始一次整理,完成后返回包含 runId 的结果 |
|
||||
| `supervision:activity` | 有界读取真实执行和阶段状态 |
|
||||
| `supervision:execution` | 读取唯一执行位置及停止清理状态 |
|
||||
| `supervision:pause` / `supervision:cancel` / `supervision:resume` | 暂停、终止或继续指定回顾;生命周期见上文 |
|
||||
| `supervision:graph` | 按故事线、时间区间和回放时刻分页读取图谱 |
|
||||
| `supervision:object` | 读取事件、实体、关系及来源详情 |
|
||||
| `supervision:confirm` | 确认、修订或移除自动关系和实体变化 |
|
||||
@@ -229,7 +252,7 @@ IPC 返回图谱查询结果时使用分页和有界字段;详情中的来源
|
||||
- 监督者模型调用固定为 `ask` 语义,输入来自 `EvidenceCollector` 的有界快照,工具授权始终拒绝。
|
||||
- `Global`、Project、多项目和固定 Conversation/Task/Experiment 目标在 Main 冻结;模型不能生成或改变范围。
|
||||
- 每个来源引用必须属于本次冻结范围,跨范围引用、伪造项目 ID 和不存在的来源 ID 直接使结果失败。
|
||||
- 心跳运行沿用现有 `heartbeat_runs` 的领取、租约和重试机制;新增监督运行按心跳运行 ID 关联,活动据此合并阶段。没有新增取消协议。
|
||||
- 心跳运行沿用现有 `heartbeat_runs` 的领取、租约和重试机制;监督运行按心跳运行 ID 关联,活动据此合并阶段。监督取消不撤销已保存的心跳报告,合并活动优先显示监督已取消状态。
|
||||
- 同一配置同时触发手动和定时运行时,沿用现有幂等键和运行领取规则;已完成结果不能重复写入。
|
||||
- 用户确认或修订后的实体、关系不被后续整理静默覆盖;新证据以补充或冲突待核对状态写入。
|
||||
- 外部知识库只读。图谱可以引用保存到本地的外部片段和定位信息,不调用远端写入、不承诺打开远端原文。
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
应用中心中的智能心跳入口升级为“监督者”,沿用既有启用、常驻与排序能力。未来应用市场使用同一应用身份。应用已启用时,停用单条自动心跳计划仍可手动回顾;关闭应用后,已打开页面显示关闭状态并禁用工作区操作。默认值及运行边界见[应用启停与执行](./logic-design.md#应用启停与执行)。
|
||||
|
||||
当前应用页只使用一套共享 PageTabs:“工作回顾 / 故事线图谱 / 自动监督 / 活动记录 / 设置”(英文活动标签为 Activity records)。自动监督独立管理计划;设置只显示模型超时与并发、回顾算法,不含计划、报告、审计或内部页签,也不显示整页全局徽标或独立刷新行。计划范围仍在表单和每条计划内显示。整个页面只有一个一级标题;监督者 bridge 不可用时显示明确错误,设置仍可访问,不回退到旧心跳概览。共享页签保留方向键、Home/End、游标焦点和单一激活面板,窄窗口横向滚动。
|
||||
当前应用页的顶层导航只使用一套共享 PageTabs:“工作回顾 / 故事线图谱 / 智能心跳 / 活动记录 / 设置”(英文活动标签为 Activity records)。智能心跳独立管理心跳计划;设置只显示模型超时与并发、回顾算法,不含计划、报告、审计或内部页签,也不显示整页全局徽标或独立刷新行。计划范围仍在表单和每条计划内显示。整个页面只有一个一级标题;监督者 bridge 不可用时显示明确错误,设置仍可访问,不回退到旧心跳概览。共享页签保留方向键、Home/End、游标焦点和单一激活面板,窄窗口横向滚动。故事线图谱面板内另有分类页签,见[故事线图谱](#故事线图谱)。
|
||||
|
||||
工作回顾只读取统一监督结果。顶部紧凑排列范围、时间、发起与刷新控件,不重复显示“新回顾”标题和来源说明,不新增 Modal。历史结果选择与图谱入口位于正文之前,即使只有一条结果也显示选择器。新回顾工具栏、状态、历史选择和结果面板铺满监督者页面壳层的可用内容宽度,与页签左右对齐,不另设阅读宽度上限;结果内部按面板内边距排版,不再单独居中窄正文。正文使用“监督结果”标题,常显生成日期、真实范围和覆盖区间,历史结果不标为最新。工作总结按原有空行分段并保留换行;本次变化和未解决事项直接使用已有字段,不补写结论或截断正文。390px 下新请求字段与操作各占两列,结果元数据可换行。
|
||||
|
||||
新回顾运行中保留已显示结果及其日期、范围,禁用重复提交,并显示简短状态和活动记录入口;该入口清除计划筛选并聚焦活动页签。工作回顾不读取自动监督报告,也不显示自动报告空态、记忆与行动建议或第二行全局范围与刷新。无监督结果时,空态独占工具栏下方整行,标题与手动回顾入口水平居中;自动报告是否为空不影响此判断。运行中和暂停后使用独立状态条,提示当前状态及活动记录入口。
|
||||
新回顾运行中保留已显示结果及其日期、范围,范围、时间、发起和刷新控件保持可用;重复点击发起只重新显示当前运行提示,不排入新回顾。状态条提供活动记录入口,清除计划筛选并聚焦活动页签;右侧 X 只关闭提示,不暂停或取消执行,同一次运行的轮询不重新打开已关闭提示。范围、时间和活动计划筛选保留可访问名称,不再重复显示字段标题。工作回顾不读取历史心跳报告,也不显示自动报告空态、记忆与行动建议或第二行全局范围与刷新。无监督结果时,空态独占工具栏下方整行,标题与手动回顾入口水平居中;自动报告是否为空不影响此判断。运行中和暂停后使用独立状态条,提示当前状态及活动记录入口。
|
||||
|
||||
## 活动
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
对应 FR-S10、US-S26。活动按开始时间倒序,每页 50 条,提供较新/更早记录和刷新。列表保留触发方式、执行范围、开始/结束时间、实际状态、阶段状态、错误及已保存摘要。没有结果时不显示结果按钮;有监督结果时可分别进入该结果的工作回顾和故事线图谱,焦点移到目标页签。超过最近 20 条的结果仍按 ID 读取,不能回退最新结果。
|
||||
|
||||
活动页只展示统一监督活动、进度、详情及结果入口,不在列表下方重复显示自动监督概览或心跳审计。计划“执行记录”打开此页并按精确 ID 筛选,筛选器显示所选计划并提供清除;监督查询在分页前过滤。同名计划仍按 ID 区分;没有匹配记录时显示筛选无结果,不回退全部数据。自动报告正文和建议处理位于自动监督。
|
||||
活动页只展示统一监督活动、进度、详情及结果入口,不在列表下方重复显示心跳概览或心跳审计。计划“执行记录”打开此页并按精确 ID 筛选,筛选器显示所选计划并提供清除;监督查询在分页前过滤。同名计划仍按 ID 区分;没有匹配记录时显示筛选无结果,不回退全部数据。监督建议和历史心跳报告位于智能心跳。
|
||||
|
||||
自动监督页依次展示范围与“刷新自动监督”、当前状态及计划列表、运行指标、报告趋势、待确认记忆与行动建议、“自动监督报告”历史、心跳报告阶段审计。刷新统一更新此页数据。报告与运行历史每次追加 20 条,报告可展开全部摘要和洞察,切换页签保留展开与分页位置;不再单独复制最近报告。建议保留确认、忽略、带入对话、标记完成及长内容展开。活动的计划筛选不改变自动监督的统计范围。当前状态下复用计划列表的唯一创建按钮,无计划时只显示列表的未配置说明,不叠加第二个计划空态或创建入口;点击直接打开现有 Modal。报告为空时明确写“暂无自动监督报告”,与工作回顾的结果状态区分。
|
||||
“智能心跳”页依次展示范围与“刷新智能心跳”、“心跳计划”卡片、监督建议,以及只读的历史心跳报告。心跳计划卡片内不再嵌套第二层边框:标题行右侧显示运行状态点,下方一行说明文字与“创建心跳计划”按钮同行,其后直接是计划列表。说明文字按状态三选一:无计划显示“尚未配置心跳计划,目前仅支持手动回顾”,全部暂停显示暂停说明,否则显示频率帮助;不叠加第二个空态或创建入口,点击按钮打开现有 Modal。
|
||||
|
||||
加载、空记录和读取失败分开显示;读取失败保留已显示记录并提供就地重试。活动页面激活时,存在运行中记录则在上次读取结束 2 秒后刷新,否则 10 秒后刷新;每次最多一个请求。切换顶层页签、离开监督者或关闭应用后停止定时器,迟到响应不更新界面。错误后等待用户重试,不持续重发失败查询。
|
||||
加载、空记录和读取失败分开显示;读取失败保留已显示记录并提供就地重试。活动页面激活时,同轮读取活动和实时执行状态;有活动执行(包括停止清理)或运行中记录则在上次读取结束 2 秒后刷新,否则 10 秒后刷新,不重叠轮询。切换顶层页签、离开监督者或关闭应用后停止活动定时器,迟到响应不更新界面。错误后等待用户重试,不持续重发失败查询。
|
||||
|
||||
活动列表与工具栏铺满监督者页面壳层的可用内容宽度,与页签左右对齐,不另设仪表盘宽度上限。范围、计划筛选、清除筛选和刷新紧邻排列,空间不足时换行。列表使用共享表面、边框、状态颜色和按钮。每条运行首先显示类型、状态、开始时间和范围;恢复与事实操作紧随其后,再展示“收集来源 / 整理批次 / 合并摘要 / 发布回顾”。阶段使用编号圆点和连接线,宽窗口四项等宽,窄于 720px 时两列;当前及已完成阶段突出显示,不为每个阶段铺设独立色块卡片。阶段读取已保存位置和真实运行状态,剩余来源为零不表示发布成功。旧运行没有阶段字段时显示“未记录”,不猜测失败位置;已提交来源清单可确认收集结束。无变化运行不显示新结果跳转,后续无需执行的阶段单独标注。
|
||||
|
||||
@@ -30,7 +30,11 @@
|
||||
|
||||
“已保留事实与来源”展开后才查询既有批次接口,每页 10 批,按本页持久记录组成项目、会话、批次层级。项目使用可用名称,会话优先使用保存来源的标题;只有已保存批次标记“已保存”,不创建未落库的待执行、在途或失败叶子,也不把本页数量当作项目总量。批次摘要收起时最多两行,展开后保留完整摘要、事件、实体、变化、关系及原文片段。来源显示消息 ID、码点范围及版本;长原文局部滚动。原生 details/summary 保留键盘展开和可见焦点,轮询不主动展开用户收起的会话。加载、空批次和读取失败分开显示,失败可重试;换页失败不显示上一页批次,切换 run 后旧响应失效。暂停状态为“未完成,可继续”,手动回顾主动暂停后在工作回顾页提示去活动继续,不显示完成通知。
|
||||
|
||||
## 自动监督设置
|
||||
活动页运行中同时提供“暂停回顾”和“取消回顾”,继续后的运行也可操作。停止期间禁用两项操作,并在运行标题和当前阶段显示“正在暂停”或“正在取消”;即使持久记录已经为已取消,只要执行尚未停止就继续显示“正在取消”。重新进入活动页通过实时执行状态恢复该提示。停止后显示“已取消”,保留事实详情,不显示继续按钮或失败恢复提示;任一回顾执行或停止清理期间,其他记录的继续按钮禁用。
|
||||
|
||||
## 智能心跳设置
|
||||
|
||||
没有自动运行、报告或关联建议时,只展示计划配置和已有计划,不显示零值统计、空趋势、建议、报告或审计区。手动回顾不计入心跳统计;产生自动运行或报告后展示对应结果区。
|
||||
|
||||
2026-09-23 当前已实现“模型超时与并发”表单:心跳报告与监督者整理分别设置,均为 30 至 600 的整数秒,默认 240;监督模型并发数为 1 至 4 的整数,默认 1。保存真实字段 `heartbeatReportTimeoutSeconds`、`supervisorOrganizeTimeoutSeconds`、`supervisorModelConcurrency`;无效输入不能提交,设置加载/保存中或锁定时禁用,失败保留草稿并提供重试。超时以阶段读取设置的时点为准,不改变已冻结的值;并发数影响后续派发,降低上限不打断在途请求。
|
||||
|
||||
@@ -38,15 +42,15 @@
|
||||
|
||||
模型超时不包含数据收集与保存,直连模型另有独立 600 秒传输超时。“回顾算法”表单提供“每次读取来源条数”“每批文本量”“每批消息数”和“单次响应容量”,显示默认值及合法范围,使用“保存回顾算法”独立提交。文本量内部仍按 UTF-16 单元计算,界面不要求用户理解编码单位。保存经 App 的现有设置回调进入共享设置存储,加载/保存/锁定时禁用,失败保留草稿。取值以[当前设置合同](./review-scheduling-design.md#当前设置合同)为准。帮助说明回顾持续处理至完成,每批保存进度,可从活动记录主动暂停并继续;已保存配置用“同时处理任务数”解释并发,说明实际并发还受当前监督设置限制。
|
||||
|
||||
对应 US-S22 至 US-S24。“自动监督”先显示计划列表,点击创建或编辑才打开 Modal;复用原表单,不保留页面内副本。表单展示名称、项目范围、每日或每周频率、指定时间、回顾窗口(1 至 720 小时)和历史保留(1 至 365 天);每周显示星期选择。时区常显,新建使用本机时区,编辑保留计划原时区。列表上方帮助说明选择每日或每周时间、保存并启用后自动运行。
|
||||
对应 US-S22 至 US-S24。“智能心跳”先显示心跳计划列表,点击创建或编辑才打开 Modal;复用原表单,不保留页面内副本。表单展示名称、项目范围、每日或每周频率、指定时间、回顾窗口(1 至 720 小时)和历史保留(1 至 365 天);每周显示星期选择。时区常显,新建使用本机时区,编辑保留计划原时区。列表上方帮助说明选择每日或每周时间、保存并启用后自动运行。
|
||||
|
||||
无计划时显示“尚未配置自动监督,目前仅支持手动回顾”;全部暂停时另行说明。加载或首次读取失败不显示未配置状态。打开页面、Modal 或填写字段均不创建计划,只有点击“保存并启用计划”才提交创建。已有计划显示范围、周期、时区、回顾窗口、保留期限和启停状态,保留编辑、暂停、恢复、立即运行、执行记录和确认删除;暂停时不显示待执行的下次时间,编辑保存不改变暂停状态。
|
||||
无计划时显示“尚未配置心跳计划,目前仅支持手动回顾”;全部暂停时另行说明。加载或首次读取失败不显示未配置状态。打开页面、Modal 或填写字段均不创建计划,只有点击“保存并启用计划”才提交创建。已有计划显示范围、周期、时区、回顾窗口、保留期限和启停状态,保留编辑、暂停、恢复、立即运行、执行记录和确认删除;暂停时不显示待执行的下次时间,编辑保存不改变暂停状态。
|
||||
|
||||
Modal 按[共享表单 Modal 规则](../../../UI-DESIGN.md#615-表单-modal)复用 header、body、footer:标题左侧、带本地化名称和工具提示的 X 右侧;底部取消次按钮、保存主按钮整体右对齐。标题和操作区保持可见,仅表单内容滚动。表单使用独立字段容器,不嵌套设置表单;窄窗口表单单列,保留共享窗口安全边距。
|
||||
|
||||
沿用整窗 Portal、共享遮罩、背景 inert、焦点循环与关闭后焦点恢复;初始焦点进入名称。X、Escape、取消或点击遮罩关闭时,有未保存修改先确认;确认初始焦点为继续编辑,Escape 或 X 只返回编辑,点击遮罩不放弃修改。保存期间禁止关闭和重复提交,失败在表单内显示并保留草稿。
|
||||
|
||||
界面及可访问名称统一使用“自动监督 / 回顾”,保留内部 heartbeat 标识及已有计划名称、报告正文。表单继续使用共享控件和容器响应式布局,建议及审计无需先进入即可配置计划。
|
||||
界面及可访问名称统一使用“智能心跳 / 心跳计划 / 回顾”;心跳负责定时触发回顾和按计划介入,回顾本身由监督者完成,保留内部 heartbeat 标识及已有计划名称、报告正文。表单继续使用共享控件和容器响应式布局,建议及审计无需先进入即可配置计划。
|
||||
|
||||
### 算法配置设置目标
|
||||
|
||||
@@ -64,11 +68,13 @@ Modal 按[共享表单 Modal 规则](../../../UI-DESIGN.md#615-表单-modal)复
|
||||
|
||||
## 工作回顾
|
||||
|
||||
2026-09-30 已实现(规则见[心跳职责与介入](./logic-design.md#心跳职责与介入目标设计)):主按钮“回顾”执行增量整理,文案不再称“重新分析”;旁边“更多”菜单提供“重新整理…”,确认对话说明将重新分析所选区间并可能产生模型费用。计划 Modal 增加“介入方式”单选:“生成建议”“仅更新记忆”;主动介入上线前不显示。最近建议替代,每条建议显示依据、打开来源及转任务/确认/忽略。“最近建议”替代,每条建议显示依据、打开来源及转任务/确认/忽略。
|
||||
|
||||
当前页面提供全局或单项目范围,以及 1、7、30 天时间区间选择。没有自动计划也能手动回顾;成功结果显示自身冻结的范围、时间和未解决事项,可选择历史结果或进入图谱。来源筛选由本次回顾范围和时间限制;图谱详情只列出所选事件的关联来源,实体或关系列出相关事件的来源。独立的来源类型选择器尚未实现。
|
||||
|
||||
选择历史结果后,图谱读取该结果的成员和内容,标题显示其回顾区间和生成时间。切换时清空旧图谱和详情并显示加载状态,迟到请求不得替换新选择。确认、修订和移除反馈更新当前所选结果,后续自动回顾不改写旧结果。
|
||||
|
||||
手动“回顾当前进展”生成中禁用重复提交。该操作新建回顾,活动页“继续”恢复原 run;两者不得混淆。失败保留上次结果、本次范围和成功批次。手动操作不推进自动位置,删除报告也不重置自动位置。
|
||||
手动“回顾当前进展”新建回顾,活动页“继续”恢复原 run;运行中再次发起按上文显示提示,停止清理结束后才能开始新回顾。失败保留上次结果、本次范围和成功批次;已取消回顾不能继续。手动操作不推进自动位置,删除报告也不重置自动位置。
|
||||
|
||||
## 会话侧栏
|
||||
|
||||
@@ -85,10 +91,16 @@ Modal 按[共享表单 Modal 规则](../../../UI-DESIGN.md#615-表单-modal)复
|
||||
|
||||
有匹配结果时提供“在图谱中查看”,打开现有监督者页面的图谱页签并读取该结果;无匹配结果不显示入口。按钮保留原生键盘操作,进入后焦点落在图谱页签,继续使用共享 PageTabs 的方向键导航。固定目标不因跳转改变;再次点击相同或不同结果均重新定位,包括页面缓存后再次进入。结果不可用时显示错误并重试原 ID,不展示默认最新结果。
|
||||
|
||||
当前“继续讨论”预览实际发送会话名称、ID 和上下文,确认后发送到该会话;固定任务使用其关联会话,无法确定发送会话时禁用。切换目标使旧来源请求和预览失效。编辑预览中的引用仍属后续工作。
|
||||
“继续讨论”直接准备上下文,不要求先查看来源。预览顶部单独显示目标会话,下方“发送内容”文本域直接填入实际回顾与来源正文,用户可编辑或删除其中任意内容。发送仅提交当前文本域内容,不再暗中拼接上下文,也不提供额外的展开区。只有点击“发送”才提交,取消不发送,失败保留整份草稿。固定任务使用其关联会话,无法确定发送会话时禁用。上下文仅包含所选来源关联的事件、实体、关系及原文快照,不带入整份全局回顾摘要;没有关联事件时只使用来源。切换目标使旧来源请求和预览失效。查看来源不自动跳转,用户点击“打开会话”才导航。侧栏不再显示实体写入或知识库选择器,现有知识库数据不受影响。
|
||||
|
||||
侧栏与图谱来源详情共用编辑区样式:目标区底部使用弱分隔线,区块间距为 `--space-4`,标签与文本域间距为 `--space-2`。文本域默认十行,可纵向调整大小;长内容在文本域内滚动。底部复用 `custom-task-dialog__actions`,取消在前、发送在后,整体右对齐。
|
||||
|
||||
## 故事线图谱
|
||||
|
||||
关联来源详情属于会话时,显示“打开会话”按钮,使用来源保存的会话 ID 跳转并切换到所属项目;不发送消息或启动回顾。另提供“继续讨论”,使用上述可编辑正文预览,点击发送后提交到来源会话并打开它。详情继续展示整理时保存的原文快照。会话已删除或读取失败时,沿用应用会话导航的提示;其他来源类型不显示此按钮。
|
||||
|
||||
左侧使用共享 PageTabs 切换“事件 / 实体 / 关系”,显示各类数量,一次只展示一类列表,无记录时显示本次回顾的分类空态。页签固定在顶部,列表占满剩余高度并独立滚动。切换页签不清除当前图谱选择;从画布、事件浏览或详情选择对象时同步切到对应页签。支持方向键、Home/End 和面板键盘聚焦。
|
||||
|
||||
使用 `supervisor` 页面壳层,最大内容宽度为 `1440px`。当前生产图谱左侧为紧凑的事件、实体和关系列表,中间为 SVG 画布,右侧为详情与来源。桌面列宽为 `216px minmax(0, 1fr) 280px`,画布获得主要空间。外圈事件按发生时间排序后等距逆时针排列,不表示实际时间间隔;起止之间保留缺口和方向箭头。内部显示真实实体名称,实线仅连接实际事件与实体,虚线仅连接实际实体关系。
|
||||
|
||||
实体及其影响连线复用现有 `--graph-node-*-border` 令牌;颜色用于辅助辨认实体,不代表故事分类或确认状态。选中项加粗并突出连线,其余节点降低图形强调度但保留可读文字。详情分为名称与说明、图谱关联、确认操作和来源,来源正文按需读取。图例常显,读图说明可展开。
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
|
||||
### US-S24 手动回顾当前进展
|
||||
|
||||
**状态:待实现;当前智能心跳已有“立即运行一次心跳”。**
|
||||
**状态:已接入工作回顾;执行状态与取消规则见[活动记录](./logic-design.md#活动记录)。**
|
||||
|
||||
作为工作使用者,我希望主动检查当前范围,而不必等待下一次计划运行。
|
||||
|
||||
@@ -163,14 +163,15 @@
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 范围有效且有来源 | 点击“回顾当前进展” | 页面显示整理中状态、进度说明和取消操作 |
|
||||
| 范围有效且有来源 | 点击“回顾当前进展” | 页面显示整理中状态和活动入口,活动页提供暂停与取消 |
|
||||
| 整理完成并有新变化 | 返回结果 | 工作回顾、监督反馈和图谱引用同一次结果 |
|
||||
| 没有有效新变化 | 整理完成 | 显示检查时间和“暂无新进展”,不重复推送旧内容 |
|
||||
| 用户点击取消 | 整理仍在运行 | 显示已取消,保留上一次成功结果 |
|
||||
| 用户点击取消 | 整理仍在运行 | 清理期间显示正在取消,停止后显示已取消,保留上一次成功结果和成功批次 |
|
||||
| 回顾正在执行或停止清理 | 再次点击手动发起 | 显示当前运行提示,不新建或排队;关闭提示不取消执行 |
|
||||
|
||||
**界面行为**
|
||||
|
||||
- 运行按钮在整理期间禁用,取消后可以重试。
|
||||
- 运行按钮在整理期间保持可用,重复点击按上表提示;取消停止后可以新建,已取消运行不能继续。
|
||||
- “无新进展”与“失败”使用不同状态和文案。
|
||||
- 结果必须显示本次冻结的范围,不能因用户后来切换项目而改变解释。
|
||||
|
||||
@@ -537,7 +538,7 @@
|
||||
| 已保存批次跨多个项目和会话 | 展开事实并翻页 | 按本页真实归属分层,标明本页数量;原文可读,失败叶子不伪造为已保存 |
|
||||
| 原始错误是多行校验 JSON | 展开错误详情 | 默认折叠,展开后有界滚动,完整文本可选择复制;恢复操作和阶段仍在其前面 |
|
||||
|
||||
取消和人工修改时间序列审计不属于当前已实现范围;实际状态及保留规则见[活动记录](./logic-design.md#活动记录)。
|
||||
继续后的运行仍可暂停或取消;任一运行执行或停止清理期间,其他运行不能继续。重新进入页面仍显示实际停止状态。人工修改时间序列审计不属于当前已实现范围;实际状态及保留规则见[活动记录](./logic-design.md#活动记录)。
|
||||
|
||||
### US-S27 自动增量与历史重看
|
||||
|
||||
@@ -545,13 +546,89 @@
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 自动报告和监督已成功处理窗口内来源 | 同范围再次自动检查且来源未修改 | 两阶段均不调用模型,活动显示无变化,不新增报告和图谱事件 |
|
||||
| 监督已成功处理窗口内来源 | 同范围再次自动检查且来源未修改 | 不调用模型,活动显示无变化,不新增图谱事件或建议 |
|
||||
| 消息正文、知识引用或任务状态有修改 | 再次自动检查 | 只处理修改版本及未读片段,结合已有摘要和实体说明,允许复用已有实体 ID |
|
||||
| 来源多于单次预算或正文较长 | 一次结果成功保存后再次检查 | 继续处理窗口内遗漏或剩余片段,已送入且保存成功的部分不重复处理 |
|
||||
| 模型、校验或保存失败 | 再次检查相同输入 | 失败阶段仍可重试;已成功的另一个阶段不重复付费 |
|
||||
| 来源已经自动处理 | 用户手动回顾所选区间 | 重新整理有界历史,保留自动进度;删除报告不等同重看或重建 |
|
||||
| 来源已经自动处理 | 用户点击
|
||||
| 只有已确认记忆或背景摘要变化 | 自动检查 | 背景不单独触发模型调用 |
|
||||
|
||||
### US-S32 点击回顾只整理变化
|
||||
|
||||
**状态:已实现(2026-09-30)。** 对应 FR-S4、FR-S12,规则 H3、H4。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 所选范围已有成功回顾,来源未变化 | 点击“回顾” | 不调用模型,活动显示“无新变化”,保留原结果 |
|
||||
| 有新增或修订的消息 | 点击“回顾” | 只处理变化部分,关联已有实体后发布;不生成建议 |
|
||||
| 用户需要重看一段历史 | 在“更多”中选择“重新整理”并确认 | 重新分析所选区间,保留用户确认内容,不改变自动进度 |
|
||||
| 首次对某范围回顾 | 点击“回顾” | 完整分批处理所选时间区间 |
|
||||
|
||||
### US-S33 心跳按配置给出建议
|
||||
|
||||
**状态:已实现(2026-09-30),主动介入除外。** 对应 FR-S12,规则 H1、H5 至 H10。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 计划介入方式为“生成建议”,来源无变化 | 计划到期 | 不调用模型,不产生建议或通知 |
|
||||
| 有变化,但图谱变化中没有建议候选 | 计划到期 | 完成增量整理;不发起建议调用 |
|
||||
| 有变化,出现新的未解决事项或分歧 | 计划到期 | 整理后按候选生成建议,每条附依据并可打开来源;原文不重复读取 |
|
||||
| 介入方式为“仅更新记忆” | 计划到期 | 只更新图谱,不生成建议 |
|
||||
| 用户忽略一条建议 | 后续检查没有新证据 | 不再重复提出 |
|
||||
| 建议生成失败 | 查看活动 | 显示“已更新,建议生成失败”;图谱与进度保留,可单独重试建议 |
|
||||
| 旧计划升级 | 打开自动监督 | 范围、频率和启停状态不变,介入方式为“生成建议”;旧报告只读可查 |
|
||||
|
||||
|
||||
## 时态图谱与 Agent 读取
|
||||
|
||||
### US-S28 依据决定演变继续工作
|
||||
|
||||
**状态:D1 工具读取已实现;真实模型建议质量尚未验收。** 对应 FR-S11,读取合同见[时态 Story Graph MCP 设计](./story-graph-mcp-design.md),验证范围见[实施进度](./progress.md#2026-09-28-story-graph-只读工具)。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 已保存旧决定 A,后来有明确证据将其修订为 B | 用户询问“继续上次工作,现在采用什么” | Agent 按需读取图谱,说明 A 到 B 的变化、推荐 B 的依据,并引用旧决定与修订来源 |
|
||||
| 新记录只是增加选项 C | Agent 查询当前理解 | B 不因 C 更新而自动失效;替代或矛盾关系必须有明确证据 |
|
||||
| 记录只表明决定采用 B,没有完成证据 | 用户询问执行进度 | 回答已决定且完成状态未知,不推断已完成 |
|
||||
| 已确认旧认识与新证据冲突 | Agent 组织当前建议 | 分别展示确认状态、有效性与待核对差异,不静默覆盖 |
|
||||
|
||||
### US-S29 分页核对时间与来源
|
||||
|
||||
**状态:D1 已实现,缺失历史版本明确返回不可用。** 对应 FR-S11、US-S13。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 旧事件在较晚回顾中才生成并记录 | 按发生时间查询并查看 timeline | 区分事件、回顾生成和记录时间;不把补录当成新发生,也不声称当时已知 |
|
||||
| 搜索、演变或原文超过一页 | Agent 继续读取 | 每页说明范围、修订、覆盖与剩余页,能读取全部匹配内容,无静默截断 |
|
||||
| 旧记录只有证据条数,没有完整覆盖信息 | Agent 读完最后一页 | 返回覆盖未知,不称已覆盖全部原始工作记录 |
|
||||
| 引用版本原文已不可用或当前内容已修改 | 读取历史来源 | 返回实际保存片段或明确版本不可用;读取当前版本须显式选择并标注差异 |
|
||||
| 分页期间对象版本变化 | 继续使用旧游标 | 明确提示游标失效并重新查询,不混合新旧版本 |
|
||||
| 用户要求截至过去时刻的完整认识 | 调用 `as_of` | 明确不支持,不用 current 或 timeline 冒充历史重建 |
|
||||
|
||||
### US-S30 按需读取并遵守应用开关
|
||||
|
||||
**状态:D1 已实现;跨平台安装包验收未执行。** 对应 FR-S11、US-S14、US-S20。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 会话属于当前项目 | Agent 未显式指定 scope 搜索 | 只查该项目;无项目时要求明确范围,不自动扩大为 Global |
|
||||
| 用户进行普通聊天 | 没有继续工作或历史依据需求 | 不强制每轮查询或注入完整图谱;需要核对原话时才进一步读来源 |
|
||||
| 监督者开启且内置能力已分配,没有自动计划 | 查询已有结果 | 可以读取;查询不触发模型、回顾或业务写入 |
|
||||
| 监督者关闭,旧会话仍缓存工具 | 列出工具或直接调用 | 不暴露工具,调用被拒绝;已有数据保留 |
|
||||
| 相同范围与证据分别通过本地和远程 Runtime 查询 | 翻页、读取版本或关闭监督者 | 返回相同业务语义与引用,远程实际桥接须通过验收 |
|
||||
|
||||
### US-S31 保留偏好并复用跨范围事实
|
||||
|
||||
**状态:待实现;当前仍独立处理精确 scope,读取现有已确认 memory。** 对应 FR-S11、US-S16、US-S27。
|
||||
|
||||
| Given | When | Then |
|
||||
| --- | --- | --- |
|
||||
| 用户已有已确认的 Global 或项目偏好 | 逐步切换统一工作记忆入口 | 原内容、确认状态、适用范围和引用保留,不删除旧数据 |
|
||||
| 旧偏好只有更新时间 | 查询演变 | 标记为当前背景和历史未知,不补造决定时间或替代关系 |
|
||||
| 项目 A 的来源版本已有成功叶子事实 | 目标复用能力交付后进行 Global 整理 | 复用该版本的事件、变化、关系和来源,不因 scope 改变重复提取相同正文,也不只复用摘要 |
|
||||
| 仅部分片段成功或原来源已改版 | 再次整理 | 识别未覆盖或变更部分,不把旧版本覆盖算作新版本完成 |
|
||||
| Global 结果含多个项目的归纳 | 从单项目查询 | 不把跨项目摘要伪装成项目结论,复用事实仍保留来源归属 |
|
||||
|
||||
## 验收优先级与依赖
|
||||
|
||||
首个可用版本应先打通以下路径:
|
||||
|
||||
@@ -16,3 +16,12 @@
|
||||
[Runtime 进程复用技术设计](../assistant-workbar/runtime-process-reuse-technical-design.md)
|
||||
统一维护;本 Runtime 的生命周期见[技术设计 §9](./technical-design.md#9-runtime-生命周期),
|
||||
未发布实现的验收状态见[工作栏进度](../assistant-workbar/progress.md#2026-09-14-runtime-进程复用实施中)。
|
||||
|
||||
The separate official Web client is pinned to `@deepseek-ai/dsh@0.1.7-rc.2`.
|
||||
Its Main service API, Ask/Execute policy, capability adapters, packaged resource
|
||||
layout, and Windows validation are documented in
|
||||
[Native Client Proposal, section 9.1](../assistant-workbar/runtime-native-client-proposal.md#91-ds-web-backend-2026-09-26).
|
||||
This Web resource tree is prepared separately from the background Harness Host.
|
||||
Current shortcut/coordinator behavior and configured-model evidence are tracked in
|
||||
[local native client progress](../assistant-workbar/progress.md#2026-09-27-local-native-client-validation),
|
||||
including the remaining managed Node delivery gap.
|
||||
|
||||
@@ -1,5 +1,91 @@
|
||||
# DeepSeek Harness 实现进度
|
||||
|
||||
## 2026-09-26 真实模型与官方 Web 验证
|
||||
|
||||
本轮验证 `0.1.7-rc.2` 后台对话/工具路径与同版本官方 Web 的本地接入可行性,关联
|
||||
[原生客户端方案](../assistant-workbar/runtime-native-client-proposal.md)的 FR-2、3、5,
|
||||
US-2 和 P1/P2。快捷按钮与完整客户端集成本轮未实现。
|
||||
|
||||
环境:Windows x64,标准 Node `24.19.0`,Edge `154.0.4258.37`,官方
|
||||
`@deepseek-ai/dsh@0.1.7-rc.2`,仓库 HEAD `51166136157a646530e1ad9f6a0242c1c6390e95`
|
||||
加当前未提交修改。源码哈希记录在本机临时报告 `dsh-017-verify/source.json`。
|
||||
供应商实际模型为当前 DS 配置中的 `deepseek-flash`,协议为 `openai-chat-completions`。
|
||||
|
||||
| 场景 | 实测结果 | HTTP dispatch |
|
||||
| --- | --- | ---: |
|
||||
| 后台 Ask | `read` 返回未出现在 prompt 中的随机校验码 | 2 |
|
||||
| 同会话切 Execute | `write` 创建文件,实际内容为 `DSH_EXECUTE_OK` | 2 |
|
||||
| Execute Shell | `pwsh` 执行 `Get-Content execute-marker.txt`,返回正确内容 | 2 |
|
||||
| 官方 Web 页面提交 | 当前模型读工作区文件并返回另一随机校验码;刷新仍保留回答 | 3 |
|
||||
| 本轮合计 | 9 次均请求 `deepseek-flash`,9 次均返回 HTTP 200 | 9 |
|
||||
|
||||
计数在 `AgentModelGateway` 向供应商执行 `fetch` 时记录,包含 Web 的 1 次无工具请求;
|
||||
4 次用户提交实际产生 9 次供应商请求。后台 3 轮均收到 `done`、工具 `completed`
|
||||
和每轮 2 个用量事件。调用经过现有 `createManagedModelBridge`、`AgentModelGateway`
|
||||
和 `ModelBridgeLoopbackProxy`,由隔离 Electron profile 中的 safeStorage 解密配置副本。
|
||||
供应商凭据未写入 Web 配置或报告;正式 `runtime-settings.json` 测前测后逐字节一致。
|
||||
环境继承 `NODE_TLS_REJECT_UNAUTHORIZED=0`,本轮不证明严格 TLS 证书校验可用。
|
||||
|
||||
官方 Web 以标准 Node、独立 `DSH_HOME` 和回环随机端口启动。通过官方 patch 配置 provider
|
||||
和默认模型,再调用 `workspace/create`;首次创建和已有目录复用均通过。根页面自动选中
|
||||
测试工作区和当前模型,无需手动填供应商密钥。保留并通过官方“内测声明”的“继续”按钮,
|
||||
真实页面输入、发送、回答、刷新及截图检查通过。配置/API 细节统一维护在方案第 6.3 节。
|
||||
|
||||
本轮驱动曾因缺少 `skillPackages` 默认值和临时目录动态模块解析失败退出,均为 0 次请求;
|
||||
修正驱动后后台成功。首次 Web `fill` 后发送按钮未启用,没有发出 Web 模型请求;改为键盘
|
||||
输入并仅重跑 Web 后成功,未重复后台调用。本轮 9 次 dispatch 逐次记录于同一 `calls.json`。
|
||||
|
||||
补查发现此前 `dsh-017-live/calls.json` 已有 7 次 HTTP 200 记录,其中后台 4 次、Web 3 次;
|
||||
对应历史报告记录模型 `deepseek-flash`、工作区与模型选中、文件结果及配置未改。本轮保留
|
||||
这些文件,未覆盖或重算为新增调用。该历史批次与本轮合计可核查 16 次,下面依赖升级阶段
|
||||
“0 次”仅指升级回归本身。
|
||||
|
||||
定向命令使用标准 Node 执行 `node_modules/vitest/vitest.mjs run`,目标为
|
||||
`src/main/agent/deepseek-harness-acp-e2e.test.ts`、
|
||||
`src/main/agent/goodbuddy-harness-control-plane.test.ts` 和
|
||||
`src/main/agent/deepseek-harness-runtime.test.ts`:3 个文件、52 项通过、3 项跳过,11.12 秒。
|
||||
3 个环境开关 live case 未在 Vitest 中启用;上表为独立真实模型驱动结果,不把跳过项算通过。
|
||||
确定性回归包含 Ask 写入拒绝和 Execute 工作区外写入,无需为验证重复调用真实模型。
|
||||
|
||||
本机证据位于临时 `dsh-017-verify/`:`calls.json`、`backend-result.json`、`result.json`、
|
||||
`main-result.json`、`source.json` 和 `web-conversation.png`。报告保留首次 Web 驱动失败,
|
||||
最终 Web 结果另见 `result.json`。桥接、worker、Web 和浏览器已关闭,进程检查未发现本轮
|
||||
目录所属的残留进程;临时 profile、测试工作区和 DS home 清理后仅保留脚本及脱敏证据。
|
||||
这些本机临时文件不作为仓库长期资源。
|
||||
|
||||
证据范围:后台运行真实 ACP/Host/控制面和供应商模型,Host 在测试进程内组合;Web 为
|
||||
官方 CLI 子进程与真实浏览器页面。未重新验收 GoodBuddy Composer/Utility Process,
|
||||
也未实现 Web 的 GoodBuddy Ask/Execute 适配。官方 Plan 只控制规划状态,默认
|
||||
“工作区内修改”也不等同于 Execute;后续复用现有工具命令名判断,不增加权限层级、
|
||||
目录限制或逐工具二次授权。Skills/MCP 承接、取消、产品生命周期及交付资源仍待验证。
|
||||
未改远程源码;DS 仍不支持 SSH execution space,本轮没有远程模型调用或 Linux Host 验证。
|
||||
|
||||
## 2026-09-26 依赖升级至 0.1.7-rc.2
|
||||
|
||||
23 个直接引用的 `@deepseek-ai/dsh-*` 包统一锁定为 `0.1.7-rc.2`,Cordis
|
||||
升级为上游要求的 `4.0.4`,同步更新依赖锁文件、Runtime 版本及打包测试夹具。
|
||||
版本取自 npm 发布列表与 `next` 标签;查询时 `latest` 仍指向 `0.1.0-rc.6`。
|
||||
|
||||
控制面改为监听 `agent/assistant-stream` 的 chunk 帧,以转发文本、推理和用量;
|
||||
工具结果从 message 层读取 `toolCallId` 和 `isError`。测试同步适配新版本的
|
||||
Agent 配置、Shell 执行和系统消息接口。
|
||||
|
||||
- DS 定向回归:152 项通过、5 项跳过。
|
||||
- 最终复跑 DS、Runtime discovery 和发布打包夹具:12 个文件通过、2 个跳过,
|
||||
170 项通过、5 项跳过,耗时 19 秒。
|
||||
- 扩大至打包夹具和设置面板:196 项通过、5 项跳过;设置面板套件因并行
|
||||
Obsidian 修改缺少 `obsidian-tools` 模块而未能加载。
|
||||
- `npm run smoke:deepseek-harness`:开发构建通过,真实 Electron Utility Host 返回 `ready`。
|
||||
- 升级后的首次类型检查与 lint 通过;后续类型检查受到并行 Obsidian 修改中的
|
||||
模块缺失、项目文件列表和类型错误阻塞,不能将当前整个工作区标为检查通过。
|
||||
- 全量测试两次运行分别在 200 秒、600 秒超时,期间出现 App、SupervisorActivity
|
||||
和 Electron UI 测试失败;未取得全量通过结果,未修改这些并行工作的文件。
|
||||
|
||||
本次依赖升级回归的真实供应商模型调用为 0 次;后续真实模型及 Web 实测见上节。上述升级验证不包含官方 Web 应用,
|
||||
“在浏览器中打开”入口仍按[原生客户端方案](../assistant-workbar/runtime-native-client-proposal.md)实施。
|
||||
远程启动契约和资源打包仅支持 Continue、OpenCode,`create-runtime.ts` 拒绝 SSH
|
||||
执行空间使用 DS,因此本次升级未改变远程 Runtime 路径,也未进行 Linux Host 验证。
|
||||
|
||||
## 2026-09-14 Windows 工作区路径修复
|
||||
|
||||
本机 Runtime 的 Host 启动与 `newSession.cwd` 已共用初始化时解析的 `realpath`,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| 文档状态 | 实现与发布验收基线 |
|
||||
| 设计目标 | 将 DeepSeek Harness 作为 GoodBuddy 的第三个 Agent Runtime |
|
||||
| Runtime 标识 | `deepseek-harness` |
|
||||
| 当前依赖基线 | 实际使用的 `@deepseek-ai/dsh-*` 底层库,精确锁定 `0.1.2-rc.1` |
|
||||
| 当前依赖基线 | 实际使用的 `@deepseek-ai/dsh-*` 底层库,精确锁定 `0.1.7-rc.2`,Cordis 为 `4.0.4` |
|
||||
| 上游状态 | Developer Preview,允许出现破坏性变更 |
|
||||
| 上游许可证 | MIT |
|
||||
| GoodBuddy 目标平台 | Windows、macOS、Linux,x64 与 arm64 |
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
DeepSeek Harness 的底层库使用 Cordis 组合服务。GoodBuddy 不采用官方产品 profile,也不允许用户配置覆盖内部 Host 或控制服务;GoodBuddy 自行维护 Host、控制协议和生命周期,同时提供一个由 Main 管理、默认关闭的 npm 插件市场。用户显式开启后,市场只搜索带精确 `dsh-plugin` 关键字的公共 npm 包,不代表 GoodBuddy 审核、推荐或承诺兼容这些包。
|
||||
|
||||
用户明确安装并启用的插件以当前用户权限运行。Ask/Execute 只控制模型经过 `tools/execute` 发起的工具调用:Ask 只允许 Host 中真实注册的 `read`、`skill` 和 Main 管理的 Web Search/Fetch 代理,Execute 放行 Host 中全部已注册工具。插件不能用同名工具冒充 Ask 允许项。插件安装脚本和初始化代码不属于模型工具调用,不能由 Ask 限制,因此界面在安装前必须明确确认这一边界。
|
||||
用户明确安装并启用的插件以当前用户权限运行。Ask/Execute 只控制模型经过 `tools/execute` 发起的工具调用:Ask 只允许 Host 中真实注册的 `read`、`skill` 和 Main 管理的 Web Search/Fetch、Story Graph 只读代理,Execute 放行 Host 中全部已注册工具。插件不能用同名工具冒充 Ask 允许项。插件安装脚本和初始化代码不属于模型工具调用,不能由 Ask 限制,因此界面在安装前必须明确确认这一边界。
|
||||
|
||||
整体分成两个互相约束的部分:
|
||||
|
||||
@@ -145,7 +145,7 @@ Harness 子进程内控制面不能取代 Main 控制面,Main 控制面也不
|
||||
|
||||
Harness Session 只在当前 Runtime 进程生命周期内存在。释放 GoodBuddy 会话时必须同步释放对应 Harness Agent。
|
||||
固定 Host 显式加载 `dsh-session-projection` 的内存 SessionProjectionRegistry,这是
|
||||
`0.1.2-rc.1` AgentLoop 的必需依赖;不加载 Session persistence,也不新增磁盘会话副本。
|
||||
`0.1.7-rc.2` AgentLoop 的必需依赖;不加载 Session persistence,也不新增磁盘会话副本。
|
||||
该依赖与其余 DSH 依赖一起由 Vite 打入 Host,不能从 `app.asar.unpacked` 外部导入
|
||||
仅存在于 `app.asar` 的 npm 包。最终打包检查及 Windows CI 的真实 UtilityProcess
|
||||
启动探针见 [Runtime 资源与打包](../../../BUILD.md#runtime-资源)。
|
||||
@@ -368,7 +368,7 @@ GoodBuddy conversationId -> Harness sessionId + workspace + process generation
|
||||
|
||||
### 9.5 跨项目复用
|
||||
|
||||
锁定 0.1.2-rc.1 的文件和 Bash/PowerShell 工具已按原生 Session header.cwd 路由,
|
||||
锁定 0.1.7-rc.2 的文件和 Bash/PowerShell 工具已按原生 Session header.cwd 路由,
|
||||
Provider 的根 cwd 只是默认值。不为每工作区复制本地 Provider;
|
||||
Main 的 Web/MCP ToolProvider 按工作区保存,最后一个对应 Session 释放时 dispose。
|
||||
|
||||
@@ -386,11 +386,17 @@ Main 的 Web/MCP ToolProvider 按工作区保存,最后一个对应 Session
|
||||
| Ask | 只允许 Host Registry 中真实注册的 `read` 与 `skill`;其他 Host/插件工具一律拒绝 | 能力启用时注册 Main 的精确代理对象,无逐次审批 | 不注册 | 模型工具调用保持只读 |
|
||||
| Execute | 放行 Host 中全部已注册的内置与插件工具 | 能力启用时注册 Main 代理 | 按分配注册并经过既有 RuntimeAuthorizer | 不增加插件权限层,以当前用户权限运行 |
|
||||
|
||||
2026-09-28:内置 Story Graph 的三个读取工具在 Ask/Execute 均通过 Main 代理提供,
|
||||
Host 只接受 Main 注册的具体工具对象。Main 逐次检查监督者启用、Harness 分配及请求项目范围,
|
||||
不逐次审批。其他普通内置 MCP 仍不支持 Harness 分配;合同与证据见
|
||||
[Story Graph 设计](../conversation-supervision/story-graph-mcp-design.md)和
|
||||
[验证进度](../conversation-supervision/progress.md#2026-09-28-story-graph-只读工具)。
|
||||
|
||||
### 10.2 Ask 模式
|
||||
|
||||
- Harness Control Plane 在 `tools/execute` 分发边界识别当前 Session 和在途请求。
|
||||
- 采用所有权感知的只读允许列表,只接受 Registry 中真实的 `read`、`skill` 和 Main 注册的 Web 代理对象;`write`、`edit`、Shell、MCP 及任意新插件工具默认拒绝。只比较工具名不足以授权,插件注册同名工具仍会被拒绝。
|
||||
- Ask 不注册 Main 代理的 MCP 工具。
|
||||
- 采用所有权感知的只读允许列表,只接受 Registry 中真实的 `read`、`skill` 和 Main 注册的 Web/Story Graph 代理对象;`write`、`edit`、Shell、自定义 MCP 及任意新插件工具默认拒绝。只比较工具名不足以授权,插件注册同名工具仍会被拒绝。
|
||||
- Ask 不注册 Main 代理的自定义 MCP;Story Graph 使用共享只读合同,scope 的互斥分支转换为 Harness 支持的 `oneOf`,完整参数仍由 Main 的 Zod schema 校验。
|
||||
- Web Search/Fetch 的凭据、传输与结果限制保留在 Main;Utility 只看到有界 schema 和结果。
|
||||
- 只读不等于无限输出,读取仍受字节和工具结果上限控制。
|
||||
- 插件安装脚本和 Cordis 初始化生命周期不经过 `tools/execute`。Ask 不能把已启用第三方代码变成沙箱,也不能保证第三方代码没有启动副作用。
|
||||
@@ -405,7 +411,7 @@ Main 的 Web/MCP ToolProvider 按工作区保存,最后一个对应 Session
|
||||
`goodbuddy/tools/list` 按 Session 保存本次发现的工具定义;`goodbuddy/tools/call` 复用该定义
|
||||
校验参数与授权,不因调用健康工具而重新等待故障 MCP 的发现。发现重试留在清单刷新,
|
||||
Session 释放及 Runtime dispose 清除内存定义,不持久化第二份能力状态。
|
||||
- 所有工具调用仍作为活动事件记录;Ask 和 delegation 路径继续固定拒绝。
|
||||
- 所有工具调用仍作为活动事件记录;自定义 MCP 的 Ask 和 delegation 路径继续固定拒绝。
|
||||
|
||||
### 10.4 Runtime OS 沙箱
|
||||
|
||||
@@ -418,7 +424,7 @@ Main 的 Web/MCP ToolProvider 按工作区保存,最后一个对应 Session
|
||||
|
||||
- 使用环境变量白名单构造 utilityProcess 环境。
|
||||
- 不继承 `NODE_OPTIONS`、调试端口、任意 npm 配置、用户 `DSH_*` 覆盖或白名单之外的凭据。
|
||||
- `DSH_TELEMETRY_DISABLED=1` 必须固定设置。
|
||||
- `DSH_TELEMETRY_DISABLED=1` 必须固定设置。后台 Host 与独立 Web 启动器均叠加 `src/shared/runtime-privacy-environment.ts` 的通用遥测关闭配置,设置 `DO_NOT_TRACK=1`、`OTEL_SDK_DISABLED=true`,并关闭日志、指标和追踪 exporter。模型、MCP 和用户主动联网请求不受此配置限制。
|
||||
- Harness Home 指向 GoodBuddy 管理的隔离目录。
|
||||
- 不调用官方 `loadEnv` 或 `loadLayeredEnv`。
|
||||
- API Key 由 Main 从加密设置中解析。
|
||||
@@ -546,7 +552,7 @@ Runtime: GoodBuddy 内置 DeepSeek Harness
|
||||
模型配置: 跟随 GoodBuddy · 企业网关(qwen-plus)
|
||||
状态: 已就绪
|
||||
路径: <受控 Host 路径>
|
||||
版本: 0.1.2-rc.1
|
||||
版本: 0.1.7-rc.2
|
||||
执行权限: 当前用户权限
|
||||
|
||||
Host 始终由当前 GoodBuddy 版本提供,不存在自定义 Host 入口。
|
||||
@@ -689,11 +695,11 @@ Renderer 只接收公开 npm 元数据和受管插件状态。任何凭据、完
|
||||
- 二进制检测、版本解析和路径规范化。
|
||||
- ACP 握手、事件转换和请求关联。
|
||||
- 每个会话单请求、跨会话并行。
|
||||
- Ask 在工具分发边界只允许真实注册的 `read`、`skill` 与 Main Web 代理,并拒绝同名冒充和任意新插件工具;Execute 放行插件工具。
|
||||
- Ask 在工具分发边界只允许真实注册的 `read`、`skill` 与 Main Web/Story Graph 代理,并拒绝同名冒充和任意新插件工具;Execute 放行插件工具。
|
||||
- 握手只接受明确的 `execution.mode = 'host'`。
|
||||
- 未分配 Skill/MCP 不可见;分配后的 Skill catalog 可调用 `skill` 加载。
|
||||
- 原生能力快照只包含 Host/插件原生 Skills,不包含 GoodBuddy 分配的 Skills 或 MCP。
|
||||
- Ask 不注册 MCP 工具;Web 代理可用于 Ask 与 Execute;Execute 每轮刷新有界 MCP schema,并在调用前再次校验活动请求、模式、参数和 RuntimeAuthorizer 结果。
|
||||
- Ask 不注册自定义 MCP 工具;Web 和 Story Graph 代理可用于 Ask 与 Execute;Execute 每轮刷新有界自定义 MCP schema,并在调用前再次校验活动请求、模式、参数和 RuntimeAuthorizer 结果。
|
||||
- MCP URL、启动命令和凭据不进入 Utility 启动配置或协议结果。
|
||||
- 未知授权结果失败关闭。
|
||||
- 超时、取消、迟到帧和进程意外退出。
|
||||
@@ -760,7 +766,7 @@ npm run build
|
||||
|
||||
- `deepseek-harness` 可被保存、选择、检测和显示。
|
||||
- Runtime 详情卡内显示状态、路径、版本和当前用户执行权限。
|
||||
- Skills 与自定义 MCP 设置可把能力分配给 DeepSeek Harness;请求级 GoodBuddy 内置 MCP 当前不支持分配,并在内置 MCP 卡片中以置灰、未选择状态明确显示。布局、键盘语义、文案和保存回显通过真机检查。
|
||||
- 该阶段的 Skills 与自定义 MCP 设置可把能力分配给 DeepSeek Harness;当时请求级 GoodBuddy 内置 MCP 不支持分配,并在卡片中置灰。布局、键盘语义、文案和保存回显通过真机检查。2026-09-28 的 Story Graph 源码另接入 Harness 分配与 Main 只读代理,验证证据见上文专项记录。
|
||||
- DSH 市场初始关闭且不加载 npm 目录;显式开启后可以搜索、安装、启停、配置和移除插件,安装前只出现一次准确的当前用户权限确认。关闭市场后已有启用插件继续运行,重新开启后管理状态不变。
|
||||
- Ask 写入测试在 Runtime 边界失败。
|
||||
- Ask 可使用已启用的 Main Web Search/Fetch,且插件无法通过同名工具绕过所有权校验。
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# 设备发现与共享
|
||||
|
||||
本功能是 GoodBuddy 桌面端管理附近设备、本机共享和 ShareServer 连接的唯一入口。默认连接
|
||||
方式是局域网;网关由用户额外添加。功能不包含 ShareServer 的组织管理 Web 界面。
|
||||
设备共享从“应用 → 设备共享”或“管理应用 → 设备共享 → 打开”进入。当前首期连接本地未认证
|
||||
ShareServer 元数据服务,默认地址为 `http://127.0.0.1:8787`,可注册本机、浏览设备与发布目录、
|
||||
发布能力或知识的元数据并撤销本机 ID 的条目。设备 ID 只用于识别,不是所有权认证。
|
||||
|
||||
当前实现不执行远程能力,不读取、搜索或下载知识正文;来源模式和权限均为元数据声明。
|
||||
局域网发现、配对、组织网关和远程调用仍是后续设计,不是首期交付内容。
|
||||
|
||||
## 文档导航
|
||||
|
||||
@@ -9,12 +13,13 @@
|
||||
| --- | --- |
|
||||
| [PRD](./prd.md) | 用户问题、范围、功能需求和产品验收 |
|
||||
| [功能逻辑](./logic-design.md) | 不变量、状态、授权优先级和失败结果 |
|
||||
| [UI 设计](./ui-design.md) | 设置入口、四个页签、配对与调用交互 |
|
||||
| [UI 设计](./ui-design.md) | 当前应用入口、单页表单与列表,以及后续发现、配对界面 |
|
||||
| [技术设计](./technical-design.md) | Desktop 进程边界、持久化、IPC、网络和验证 |
|
||||
| [实施进度](./progress.md) | 首期实现、检查命令、真实 Electron 联调证据及未测范围 |
|
||||
| [共享网络总体设计](../../architecture/share-network-architecture.md) | 跨端身份、能力、授权、任务、更新和协议权威 |
|
||||
|
||||
当前没有单独的 User Stories:正常、失败、撤销、权限和兼容场景已直接进入 PRD 验收与逻辑
|
||||
决策表。功能尚未实施,因此不创建 `progress.md`。
|
||||
当前没有单独的 User Stories:首期验收见 PRD 的 `FR-M1` 至 `FR-M5`;后续场景仍在原有
|
||||
需求与逻辑决策表中保留。下列 Peer、配对、网关术语仅用于后续设计。
|
||||
|
||||
## 术语
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 状态 | 本地元数据首期已接入;完整共享网络为后续设计 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-09-03 |
|
||||
| 关联 PRD | [设备发现与共享 PRD](./prd.md) |
|
||||
@@ -12,6 +12,23 @@
|
||||
|
||||
本文负责桌面端状态、不变量和决策规则,不重复跨端协议定义。
|
||||
|
||||
## 当前首期规则
|
||||
|
||||
本节对应 [FR-M1 至 FR-M5](./prd.md#当前首期本地元数据)。后文发现、配对、授权和任务状态均为
|
||||
后续设计,不适用于本地未认证元数据服务。
|
||||
|
||||
本机 ID 在首次读取设置时生成并原子保存;并发首次读取共用一次加载。名称与服务 URL 更新
|
||||
串行保存,不接受 Renderer 写入设备 ID。已存在设置无法读取或解析时直接报错,避免静默
|
||||
更换身份。切换服务保持本机 ID,但目标服务必须有本机注册记录才能发布。
|
||||
|
||||
页面初次加载读取真实目录,空列表、加载中和读取失败分别展示。刷新失败保留旧列表并标记
|
||||
可能过期,禁用发布和撤销;用户可修改配置或重试。每次请求固定使用开始时读取的服务地址。
|
||||
页面操作期间锁定重复提交。保存失败保留设置草稿,发布失败保留条目草稿。
|
||||
|
||||
发布状态只有 `published` 与 `revoked`。撤销入口匹配本机 ID,Main 再查询本机发布列表并确认
|
||||
条目 ID;这只是防止误操作,不是认证。撤销只改变元数据状态。能力类型发送三个 `false`
|
||||
权限;知识类型按独立选择发送。目录读取无需注册,注册记录不表示在线。
|
||||
|
||||
## 1. 核心不变量
|
||||
|
||||
### INV-1 连接方式独立
|
||||
|
||||
@@ -4,13 +4,37 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 状态 | 本地元数据首期已接入;完整共享网络为后续设计 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-09-03 |
|
||||
| 适用产品 | GoodBuddy Desktop |
|
||||
| 关联架构 | [共享网络总体设计](../../architecture/share-network-architecture.md) |
|
||||
| 关联文档 | [功能逻辑](./logic-design.md)、[UI 设计](./ui-design.md)、[技术设计](./technical-design.md) |
|
||||
|
||||
## 当前首期:本地元数据
|
||||
|
||||
2026-10-01 首期范围由 `FR-M1` 至 `FR-M5` 定义。后文 `FR-1` 至 `FR-14` 保留为后续共享网络
|
||||
设计,不能用来推断首期已有发现、认证、调用或内容传输能力。
|
||||
|
||||
- **FR-M1 入口与设置**:应用中心及应用菜单提供“设备共享”。本机设备 ID 稳定保存,用户可
|
||||
修改服务 URL 和设备名称。设置保存后重启仍保留;新设备默认连接 `http://127.0.0.1:8787`。
|
||||
- **FR-M2 注册与浏览**:用户显式注册本机,随后查看服务实际返回的设备及发布列表。注册
|
||||
包含 ID、名称、平台、应用版本;时间来自服务记录,不从更新时间推断在线状态。
|
||||
- **FR-M3 元数据发布**:注册本机后可发布名称、描述、能力或知识类型、设备或服务器来源。
|
||||
知识的搜索、读取、下载三个标志独立选择。服务器来源不会上传、同步或托管内容;权限
|
||||
标志不提供内容访问实现。
|
||||
- **FR-M4 撤销与刷新**:只给匹配本机 ID 的已发布条目提供撤销入口,确认后更新服务记录并
|
||||
刷新目录,显示已撤销状态。该筛选不构成认证,服务本身没有所有权鉴权。
|
||||
- **FR-M5 失败恢复**:请求有超时,错误可见;失败保留用户输入,列表失败不伪装为空目录。
|
||||
修改服务 URL 后必须先保存,再向新服务注册或发布。既有应用设置、排序和常驻偏好保留。
|
||||
|
||||
验收顺序为保存配置、注册本机、浏览返回列表、发布知识元数据、检查三个独立标志、撤销、
|
||||
刷新并重启读取设备 ID。网络请求由 Main 发出,Renderer 只调用显式 preload 方法。
|
||||
|
||||
## 后续设计
|
||||
|
||||
以下章节为完整共享网络计划,尚未实施。
|
||||
|
||||
## 1. 背景
|
||||
|
||||
GoodBuddy 的能力当前主要在本机执行,SSH 远程项目则要求用户预先配置具体 Host。个人和组织
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# 设备共享实施进度
|
||||
|
||||
日期:2026-10-01。当前实现范围见 [README](./README.md)。
|
||||
|
||||
`a3b41bf` 已接入应用入口、Main 服务、可信 IPC、preload 与页面,
|
||||
支持配置 ShareServer、注册设备、读取目录、发布/撤销元数据及本机 ID 持久化。
|
||||
设备 ID 不是认证凭据,权限字段不代表已实现远程操作;正文传输、能力调用、
|
||||
发现和配对仍不属于本期实现。
|
||||
|
||||
当前组合源码类型检查和 lint 通过。仓库包含服务、IPC、页面测试和需指定
|
||||
`GOODBUDDY_SHARING_SERVER_ROOT` 的真实 ShareServer/Electron 联调用例。
|
||||
本轮发布准备中的定向测试被用户中断,并要求直接推送交 CI 验证;
|
||||
不据此声明测试或真实服务联调通过。发布结果以最终候选 CI 为准,
|
||||
条件跳过的真实服务用例不能计入已验证能力。
|
||||
|
||||
## 2026-10-01:桌面实现轮次的独立验证
|
||||
|
||||
以下记录来自设备共享实现会话,独立于上文发布准备轮次;已实际运行,不作为发布 CI 或安装包
|
||||
验收的替代。对应 [FR-M1 至 FR-M5](./prd.md#当前首期本地元数据)。
|
||||
|
||||
| 检查 | 结果与覆盖范围 |
|
||||
| --- | --- |
|
||||
| 定向 7 文件 | 114 项通过:Main HTTP 契约、稳定 ID、设置重读、可信 IPC、超时与错误、页面发布/撤销、输入保留、旧设置迁移与应用排序 |
|
||||
| 完整 `App.test.tsx` | 320 项通过,含新增设备共享入口与既有设置 Modal 回归 |
|
||||
| `goodbuddy-config-contracts.test.ts` | 8 项通过;修正旧四项写入样例,保留重复、未知及缺失项拒绝断言 |
|
||||
| 真实 Electron/ShareServer | 1 项通过,使用相邻后端源码、独立端口和临时数据目录,真实窗口运行生产页面、preload、可信 IPC 和 Main 服务 |
|
||||
| 类型与静态检查 | `npm run typecheck`、`npm run lint`、`git diff --check` 通过 |
|
||||
|
||||
Electron 联调从应用中心打开页面,注册本机,发布知识元数据,服务返回确认
|
||||
`sourceMode=server`、`search=true/read=false/download=true`,随后撤销并刷新至
|
||||
`status=revoked`。注册、发布、撤销确认和刷新使用原生鼠标输入;重读磁盘保持设备 ID。
|
||||
浅深主题的 480px 视口均无横向溢出。首次窄窗口检查因系统缩放与预期 CSS 宽度不一致失败,
|
||||
沿用现有 Electron 测试的固定设备缩放设置后通过。该测试是组件组合,未启动完整生产 App,
|
||||
也未验证安装包、截图视觉效果或 macOS/Linux 窗口。
|
||||
|
||||
全仓 `npm test` 用时 760.82 秒:468 文件通过、13 文件跳过、2 文件失败;5,549 项通过、88 项
|
||||
跳过、2 项失败。设备共享真实 Electron 联调在这次全仓运行中也通过。两项失败分别为:
|
||||
|
||||
- 配置工具样例仍提交四项顺序。运行期间修正后独立复跑 8 项通过;随后与服务测试合跑
|
||||
11 项也通过,服务测试包含对尚不存在设置文件的并发首次读取。
|
||||
- `inline-help.electron.test.ts` 的 `Hover Escape closed modal: dark 360x320` 断言失败。
|
||||
未修改该文件或帮助组件,独立复跑 1 项通过,原因未确定;不把复跑结果写成全仓一次全绿。
|
||||
|
||||
完整日志位于本次工作机临时目录 `opencode/goodbuddy-sharing-full-tests.log`。没有再次执行整套
|
||||
全仓测试。本功能测试没有模型调用。中文设备共享文档经 `deai-writing` 扫描无阻断项,复核项
|
||||
中的权限边界、真实字段及测试列表按事实保留。
|
||||
|
||||
### 复现命令
|
||||
|
||||
在 GoodBuddy 仓库执行:
|
||||
|
||||
```powershell
|
||||
npx vitest run src/main/device-sharing-service.test.ts src/main/device-sharing-ipc.test.ts src/main/application-settings-store.test.ts src/renderer/src/DeviceSharingPage.test.tsx src/renderer/src/ApplicationCenter.test.tsx src/renderer/src/ApplicationMenu.test.tsx src/preload/preload-sandbox.test.ts
|
||||
npx vitest run src/renderer/src/App.test.tsx
|
||||
npx vitest run src/shared/goodbuddy-config-contracts.test.ts
|
||||
$env:GOODBUDDY_SHARING_SERVER_ROOT = (Resolve-Path ../goodbuddy-shareserver).Path
|
||||
npx vitest run tests/device-sharing.electron.test.ts
|
||||
npx vitest run tests/inline-help.electron.test.ts
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
npm test
|
||||
```
|
||||
|
||||
跨仓 Electron 测试需要后端已安装依赖;未设置 `GOODBUDDY_SHARING_SERVER_ROOT` 时明确跳过。
|
||||
测试会关闭自己启动的服务并清理临时数据,不写后端源码。
|
||||
|
||||
### 手工体验
|
||||
|
||||
在 ShareServer 仓库运行 `npm run dev:api`,在 GoodBuddy 仓库运行 `npm run dev`。从“应用”
|
||||
打开“设备共享”,默认地址为 `http://127.0.0.1:8787`。先保存名称或地址修改,再注册本机、
|
||||
发布条目、检查目录、撤销并刷新。知识类型提供三个独立权限框;重启后可比较同一设备 ID。
|
||||
服务关闭时刷新应显示错误并保留旧列表,不应显示为空目录或推断设备离线。
|
||||
@@ -4,13 +4,44 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 状态 | 本地元数据首期已接入;完整共享网络为后续设计 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-09-03 |
|
||||
| 关联 PRD | [设备发现与共享 PRD](./prd.md) |
|
||||
| 功能逻辑 | [功能逻辑设计](./logic-design.md) |
|
||||
| 共享协议 | [共享网络总体设计](../../architecture/share-network-architecture.md) |
|
||||
|
||||
## 当前首期实现
|
||||
|
||||
本节实现 [FR-M1 至 FR-M5](./prd.md#当前首期本地元数据)。后文模块树、SQLite 表、共享协议包、
|
||||
局域网与网关协议都是后续设计,当前不创建这些基础设施。
|
||||
|
||||
`src/shared/device-sharing-contracts.ts` 定义严格输入和返回类型;`DesktopApi.sharing` 暴露
|
||||
`getSettings`、`saveSettings`、`registerDevice`、`getCatalog`、`publish`、`revoke` 六个方法。
|
||||
生产 preload 对应六个固定 IPC 通道,`device-sharing-ipc.ts` 对每次调用检查可信主窗口主帧,
|
||||
对变更输入进行 Zod 校验,不暴露通用网络入口。
|
||||
|
||||
`DeviceSharingService` 在 Main 内使用 `fetch`,每个请求含响应体读取采用 10 秒超时,非成功
|
||||
响应保留 HTTP 状态;响应再经 Zod 校验。请求只在页面读取或用户动作时发出,不启动后台发现。
|
||||
URL 接受 HTTP/HTTPS,禁止内嵌凭据、查询和片段。没有令牌或 Agent/Runtime 改动。
|
||||
|
||||
| 方法 | HTTP 请求 |
|
||||
| --- | --- |
|
||||
| 注册 | `POST /api/v1/sharing/devices/register`,字段为 `id,name,platform,appVersion` |
|
||||
| 设备列表 | `GET /api/v1/sharing/devices`,读取 `{devices:[]}` |
|
||||
| 发布列表 | `GET /api/v1/sharing/publications`,读取 `{publications:[]}` |
|
||||
| 发布 | `POST /api/v1/sharing/publications`,Main 生成条目 ID 并填入本机设备 ID |
|
||||
| 撤销 | 先按 `?deviceId=` 获取本机条目,再 `POST /api/v1/sharing/publications/:id/revoke` |
|
||||
|
||||
设备 ID、名称与服务 URL 存在用户数据目录的 `device-sharing-settings.json`,版本为 1;
|
||||
复用 `writeJsonFileAtomically`,加载 Promise 去重、保存串行。损坏设置报错而不重置 ID。
|
||||
此文件不保存目录副本或凭据。导航沿用已有存储归一化,把 `device-sharing` 追加到旧顺序,
|
||||
保留既有应用相对顺序与设置;新入口可排序,无启用或常驻开关,始终可从应用菜单进入。
|
||||
|
||||
服务测试使用真实 loopback HTTP,验证契约、独立权限、识别范围、持久化、错误和超时;
|
||||
Electron 测试通过环境变量选择相邻真实 ShareServer 源码,使用临时服务数据与桌面设置。
|
||||
具体命令和实测边界见[实施进度](./progress.md)。
|
||||
|
||||
## 1. 进程边界
|
||||
|
||||
```text
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 状态 | 本地元数据首期已接入;完整共享网络为后续设计 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-09-03 |
|
||||
| 关联 PRD | [设备发现与共享 PRD](./prd.md) |
|
||||
@@ -14,6 +14,24 @@
|
||||
本文只定义桌面端界面。所有颜色、间距、字体、通知、Switch、PageTabs、焦点和响应式行为以
|
||||
全局设计系统为准。
|
||||
|
||||
## 当前首期页面
|
||||
|
||||
本节对应 [FR-M1 至 FR-M5](./prd.md#当前首期本地元数据),后文四页签、配对及调用界面为后续设计。
|
||||
|
||||
入口在应用菜单和应用中心,主内容区使用 `standard` PageShell、PageHeader 与全局范围徽标。
|
||||
标题下常显未认证、ID 识别用途和无执行/内容访问的边界。内容依次为本机设置、已注册设备、
|
||||
发布表单和发布目录。服务 URL 与设备名称可编辑,设备 ID 只读;注册、保存与刷新为次操作,
|
||||
“发布元数据”为唯一主按钮。
|
||||
|
||||
类型与来源使用短标签原生选择框;知识的搜索、读取、下载使用三个独立 Checkbox。服务器来源
|
||||
不上传或同步内容的说明常显。发布按钮附近显示已保存的目标服务及设备名称,尚未注册或
|
||||
配置未保存时给出操作提示。列表展示服务返回的名称、标识、平台/类型、更新时间和发布状态,
|
||||
不展示在线灯或执行按钮。
|
||||
|
||||
撤销使用共享危险入口和就地确认,说明保留记录且不删除本机内容。成功与操作失败通过应用
|
||||
通知反馈;目录加载失败在页面显示并由刷新按钮恢复。宽度收窄时按钮换行,长 URL 和 ID 换行;
|
||||
表单复用 `.field`,颜色与间距使用共享令牌。页面文案提供中英文。
|
||||
|
||||
## 1. 信息架构
|
||||
|
||||
设置中心新增一级分类“设备发现与共享”,使用 `standard` PageShell:
|
||||
|
||||
@@ -261,6 +261,29 @@ DeepSeek Harness 和托管 SSH 路径不注入这些工具。既有功能的 Win
|
||||
MCP 代理复用 Provider 发现快照规则,托管 SSH Runtime 不经过该本机构造路径。本次未
|
||||
修改远端 Agent、桥接或启动器。
|
||||
|
||||
## 2026-09-28 本地直连手动压缩
|
||||
|
||||
- 本地直连文本会话复用“压缩上下文”按钮、摘要状态和会话保存路径,支持关闭自动压缩时
|
||||
手动执行。当前连接选择、图像排除、强制压缩和最新轮次保留规则见
|
||||
[技术设计](./technical-design.md#101-本地直连手动压缩)。未修改远端 Agent、桥接或启动器;
|
||||
model 入口排除远程会话与 SSH 项目,本地 IPC 仍拒绝 SSH 执行空间。
|
||||
- 三个目标文件 `App.test.tsx`、`ipc.test.ts`、`model-runtime.test.ts`:569 passed、2 skipped。
|
||||
覆盖入口点击、自动关闭和低于阈值、运行中禁用、图像排除、摘要保存与后续请求、当前及指定
|
||||
摘要连接选择。补入远程通道入口排除后,App 手动压缩专项复跑 7 passed;最终类型检查和
|
||||
本次文件 ESLint 再次通过。
|
||||
- `manual-compaction.electron.test.ts`:真实 App、preload、IPC、模型工厂和 SQLite 路径通过。
|
||||
2 次本机 HTTP fixture 请求验证较早历史被摘要替换、最新轮次保留、完整历史仍在数据库,
|
||||
页面重载后摘要可读,新建 Runtime 实际使用该摘要。
|
||||
- `manual-compaction-live.electron.test.ts`:真实配置文本模型最终通过,2 次请求完成摘要及
|
||||
新 Runtime 续问。三轮探针累计 6 次真实文本模型请求;前两轮失败来自探针用未转义摘要
|
||||
匹配 JSON payload,修正断言后通过。原设置文件未改变,未记录凭据。
|
||||
- `npm run typecheck` 和本次涉及文件的 ESLint 通过。全仓 `npm run lint` 有 10 个错误,
|
||||
位于已有侧栏探针 `sidebar-final-probe.ts`、`sidebar-final-run.mjs`,保留未修改。
|
||||
- 全量 `npm test`:5407 passed、85 skipped、2 failed。失败分别为已有侧栏探针的新建按钮
|
||||
溢出断言(`magic-notes-capture.electron.test.ts`)及魔法笔记布局 Electron 超时
|
||||
(`magic-notes-layout.electron.test.ts`);手动压缩 Electron 回归通过。未执行构建或跨平台
|
||||
真机测试,不将全仓验证记为全绿。
|
||||
|
||||
## 进度维护要求
|
||||
|
||||
- 只有真实生产路径完成并验证后才能勾选实施项。
|
||||
|
||||
@@ -451,6 +451,18 @@ type SubagentActor =
|
||||
处理。Continue 接收完整历史,已有有效摘要只替换其覆盖的前缀,剩余消息全部交给原生
|
||||
Runtime;GoodBuddy 不再额外保留最后 20 条或限制为 128,000 字符。
|
||||
|
||||
### 10.1 本地直连手动压缩
|
||||
|
||||
`agentCompactConversation` 接受 `model`,结果保留实际 provider,压缩策略为
|
||||
`goodbuddy-summary`。摘要来源为 `current` 时,IPC 使用 `applyRuntimeSelection`
|
||||
解析后的当前直连连接;来源为 `profile` 时,使用既有指定摘要连接配置。
|
||||
图像连接不进入文本摘要路径,SSH 执行空间仍由本地 IPC 拒绝。
|
||||
|
||||
`ModelAgentRuntime.compactConversation` 复用 `prepareCompressedRequest` 的强制压缩,
|
||||
跳过自动开关和触发阈值,保留最新轮次。返回的 `contextCompressionState` 沿用会话保存,
|
||||
不删除历史正文。后续请求校验摘要覆盖范围后,用摘要替换已覆盖前缀;即使关闭自动压缩,
|
||||
已保存的有效摘要仍会使用。
|
||||
|
||||
## 11. 性能
|
||||
|
||||
- Shell 探测按执行服务实例缓存,不在每轮模型调用重复探测。
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
|
||||
Job、Subjob 和 Run 继续是内部对象,不创建树形 UI、独立路由或操作菜单。
|
||||
|
||||
本地直连文本会话复用输入区已有的“压缩上下文”按钮,不依赖原生 Runtime 快照,
|
||||
也不因自动压缩关闭或上下文低于触发阈值而隐藏。运行中或压缩中按钮禁用;图像连接、
|
||||
远程通道会话和 SSH 项目不显示直连模型压缩入口。完成后沿用应用通知及压缩后上下文估算,
|
||||
摘要随会话保存。压缩行为见[技术设计](./technical-design.md#101-本地直连手动压缩)。
|
||||
|
||||
## 2. 设置中的能力目录
|
||||
|
||||
直连模型工具目录使用两个本机开发分组:
|
||||
|
||||
@@ -64,6 +64,10 @@ Main 先保存资产,再保存草稿或接受队列;消息、分支建立独
|
||||
会话删除、项目删除及清空数据均核对引用,启动回收已无归属的记录和孤立 UUID 目录。
|
||||
清理失败保留无引用数据库记录供下次重试,不回滚已接受的草稿。
|
||||
|
||||
引用保存按输入顺序去重并查询资产。已有引用的顺序、会话归属均相同,且资产无需从临时目录
|
||||
转存时,直接返回,不重复开启写事务或删除、插入引用。空引用同样适用;顺序、归属或附件
|
||||
发生变化时仍按原事务更新,临时资产仍须转存。
|
||||
|
||||
助手库 schema 39 标记新附件元数据,阻止旧客户端将其当旧格式读取;没有批量改写历史附件。
|
||||
知识库 schema 13 新增 `metadata.parsedResultId` 表达式索引,结果按主键定位,不扫描全部文档。
|
||||
知识库新结果先写入独立 resultId 目录,数据库正文/chunks 发布成功后替换引用,再清理旧目录。
|
||||
|
||||
@@ -50,7 +50,7 @@ reading 与知识库 master-detail 壳层,KnowledgeWorkspace 不再嵌套壳
|
||||
| 应用中心 → 本机推理监控 | [应用定义](../../../src/renderer/src/ApplicationCenter.tsx)仍为四项;[监控](../../../src/renderer/src/LocalInferencePage.tsx)显示本地服务并加载/释放 OCR | 不承担远程 OCR 配置或管理;关闭监控入口不等于关闭解析能力 |
|
||||
| 监控 → 模型与连接设置 | [IPC](../../../src/main/ipc.ts)的 `localInferenceOpenSettings` 只发出无分类的 `settingsOpen`;[App](../../../src/renderer/src/App.tsx)仅打开设置,[SettingsPanel](../../../src/renderer/src/SettingsPanel.tsx)默认分类为 `runtime` | 文案与默认落点不一致,未直达模型或文档解析;本轮仅记录,产品跳转未修复 |
|
||||
| 聊天附件 | App 的附件按钮直接选文件;当前卡片显示名称、容量、缩略图或图标、文本 tooltip 和移除 | 尚无逐附件更多菜单、显式 OCR、解析结果预览、重解析或文档选图 |
|
||||
| 知识库文档 | [DocumentsView](../../../src/renderer/src/KnowledgeWorkspace.tsx)提供任务、打开来源、失败文档重试和分块管理;来源行另有同步,库页头另有“用于当前对话” | 解析文档详情、成功文档重解析及选图须新增,不能把分块管理 Modal 当作已有完整解析预览 |
|
||||
| 知识库文档 | 当时位于 `KnowledgeWorkspace.tsx` 的 DocumentsView 提供任务、打开来源、失败文档重试和分块管理;来源行另有同步,库页头另有“用于当前对话” | 解析文档详情、成功文档重解析及选图须新增,不能把分块管理 Modal 当作已有完整解析预览 |
|
||||
| 新建选图目标会话 | App 的 `startNewConversation` 返回布尔值,拒绝消息通道项目,并在复用空会话或新建后切到聊天 | 预览保留、目标 ID 取得及返回确认仍需接线;直接调用不满足 US-I9 |
|
||||
|
||||
本轮更正文档中“既有文档详情”的描述,补齐菜单矩阵及 US-H16 / A-15;队列修改统一先
|
||||
@@ -58,6 +58,12 @@ reading 与知识库 master-detail 壳层,KnowledgeWorkspace 不再嵌套壳
|
||||
同步标明本轮范围;本地 OCR 仍为现有能力,HTTP 和新附件流程仍为规划。
|
||||
未修改产品代码、探索脚本或既有应用排序,OCR、文本及视觉模型调用均为 0。
|
||||
|
||||
2026-09-27 模块归属复核:上述表格保留实施前状态。当前
|
||||
[DocumentsView](../../../src/renderer/src/knowledge-workspace/DocumentsView.tsx)
|
||||
已从工作区入口拆出,提供解析预览、返回列表、重新解析及预览内选图;工作区入口保留库选择、
|
||||
检索与分块管理。文档与来源统一列表的行为及验证见
|
||||
[知识库进度](../knowledge-base/progress.md#2026-09-27-文档与来源统一列表)。
|
||||
|
||||
## 2026-09-19 实现与验证
|
||||
|
||||
HTTP PaddleOCR-VL 已接入 `DocumentParsingService` 的生产 PDF/PPTX 路径,设置支持来源切换、
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
|
||||
## 1. 容器与共享组件
|
||||
|
||||
遵循根目录 [UI 设计系统](../../../UI-DESIGN.md),保留当前应用容器结构。下表依据
|
||||
2026-09-18 源码核对,标为新增的内容需要实现,不能当作现有 API。
|
||||
遵循根目录 [UI 设计系统](../../../UI-DESIGN.md),保留当前应用容器结构。下表的知识库
|
||||
模块归属已于 2026-09-27 复核;各入口的实现与验证状态见[进度](./progress.md)。
|
||||
|
||||
| 位置 | 现有结构及设计用法 |
|
||||
| --- | --- |
|
||||
| 设置中心 | `SettingsPanel.tsx` 整窗 Modal 内的 `DocumentParsingSettingsSection.tsx`;继续使用 `SettingsCategoryHeader`、`settings-section`、`field`,不套第二个 PageShell 或一级标题 |
|
||||
| 聊天 | `App.tsx` 的 `PageShell variant="reading"`;附件卡位于原 Composer 内,待发送队列仍在 Composer 外,不在助手工作栏增加附件栏目 |
|
||||
| 知识库 | `App.tsx` 已提供 `PageShell variant="master-detail"`,`KnowledgeWorkspace.tsx` 内含库导航与 DocumentsView;需在文档区域新增解析详情及返回列表,不再嵌套页面壳层或新建知识库级页签 |
|
||||
| 解析预览 | 新增共享内容视图,分别嵌入设置诊断 Modal、聊天附件 Modal 和知识库文档详情;共享数据和交互,外层容器负责标题、范围、关闭与滚动 |
|
||||
| 知识库 | `App.tsx` 提供 `PageShell variant="master-detail"`,`KnowledgeWorkspace.tsx` 保留库导航并挂载 `knowledge-workspace/DocumentsView.tsx`;文档区域内切换解析详情与列表,不嵌套页面壳层或新建知识库级页签 |
|
||||
| 解析预览 | `DocumentResultPreview.tsx` 分别嵌入设置诊断 Modal、聊天附件 Modal 和知识库文档详情;共享数据和交互,外层容器负责标题、范围、关闭与滚动 |
|
||||
| 页签与选择 | `WorkspacePrimitives.tsx` 的 `PageTabs variant="segmented"` 承载正文、图片、详情;来源及过滤模式使用 `SegmentedControl`,不能用它替换页签语义 |
|
||||
| 浮层 | Modal 沿用 body Portal、`activateModalFocus` 与 `trapTabFocus`;测试及附件菜单复用 `AnchoredMenu`,由共享 `FloatingPortal` 挂入所属 Modal 并在 top layer 绘制。通知遵循根 UI 规范 |
|
||||
| 图文内容 | 复用 `MarkdownRenderer.tsx` 的排版、表格滚动和静态 HTML 处理边界;补齐受管图片与 OCR HTML 表格适配,现有 Markdown 渲染器并未直接支持这些资源 |
|
||||
@@ -36,8 +36,8 @@
|
||||
| 管理本地 OCR 文件 | 同一“文档解析”分类的本地模型区 | 下载、校验、ZIP、删除和目录操作;全局模型下载源仍在“平台功能 / 通用设置”,与 OCR 来源选择分开 |
|
||||
| 查看或释放本地 OCR 内存 | “应用中心” → “本机推理监控”(`local-inference` Modal),或其常驻入口 | 只管理本机执行服务;应用启用及常驻控制入口,不控制解析功能;HTTP 服务不出现在本机服务列表,也不提供远程启停 |
|
||||
| 添加文件或图片 | “当前对话” → “添加附件”,或输入框粘贴 | 先加入当前草稿,再按输入类型处理;上传按钮继续直接选文件,不改成先选 OCR 的菜单 |
|
||||
| 查看聊天解析结果 | 草稿或历史消息的附件卡 | 规划中的共享预览;来源消息与目标草稿分别显示,历史输入只读 |
|
||||
| 查看知识文档结果 | “知识库” → 选库 → “文档与来源”中的文档操作 | 规划新增“查看解析结果”和文档详情;返回恢复库、列表筛选和位置;不改变活动会话 |
|
||||
| 查看聊天解析结果 | 草稿或历史消息的附件卡 | 打开共享预览;来源消息与目标草稿分别显示,历史输入只读 |
|
||||
| 查看知识文档结果 | “知识库” → 选库 → “文档与来源”中的文档操作 | “查看解析结果”进入文档详情;返回恢复库、列表筛选和位置;不改变活动会话 |
|
||||
| 把文档插图用于聊天 | 聊天或知识文档预览 → “图片” → “添加所选图片” | 明确目标会话草稿后复制;设置测试预览无此操作;已有“用于当前对话”仍负责知识库检索范围,不代替选图 |
|
||||
|
||||
从解析失败或未配置提示提供“前往文档解析设置”时,须直达 `document-parsing` 分类并保留
|
||||
@@ -51,6 +51,10 @@
|
||||
菜单项包含附件名称以区分多个文件。普通图片的“提取图片文字”可作为就近次操作,不能和
|
||||
菜单形成两套状态或重复执行。菜单复用 `AnchoredMenu` 的定位、键盘和焦点恢复。
|
||||
|
||||
草稿与队列中的图片缩略图可点击进入共享图片查看器,优先显示已保存的完整图片,只有
|
||||
缩略图时使用缩略图预览;查看不触发 OCR。队列附件菜单只提供打开原文件,不读取 OCR
|
||||
来源或显示解析设置;修改发送方式须先恢复到草稿。解析结果入口仅在已有结果时显示。
|
||||
|
||||
草稿、历史消息和队列预览中的“查看解析结果”“更多附件操作”使用共享 `icon-button`
|
||||
视觉,图标分别为文档查阅和省略号,点击区域为 `32px × 32px`,在独立操作行内排列。
|
||||
按钮提供含文件名的可访问名称、悬停提示及键盘焦点提示;草稿移除和导入取消使用同尺寸
|
||||
@@ -65,7 +69,7 @@
|
||||
| 草稿图片,发送提取文字 | 查看解析结果、打开原图 | 改为发送原图、使用当前设置重新提取文字、移除 |
|
||||
| 历史消息附件 | 查看已保存结果、打开原件 | 需要重解析或改变发送方式时先添加到当前可编辑草稿;不修改原消息 |
|
||||
| 已入队附件 | 仅有附件时显示“查看附件”,查看入队时冻结的结果与发送方式;无附件时隐藏入口 | 修改整条输入使用“恢复到草稿”,按 L-H7 合并;不直接修改队列附件 |
|
||||
| 知识文档 | 查看解析结果、打开来源、管理分块 | 使用当前设置重新解析;失败时使用重试,不再并列一个同义重解析按钮;来源同步仍属于来源级操作 |
|
||||
| 知识文档 | 查看解析结果、打开来源、管理分块 | 重新解析;失败时使用重试,不再并列一个同义重解析按钮;来源同步仍属于来源级操作 |
|
||||
| 设置测试结果 | 查看正文、图片、详情及原件 | 重新测试、关闭;没有加入草稿、知识库或发送操作 |
|
||||
|
||||
操作依据对象、资源和任务状态显示。解析中仅保留可用旧结果的查看、进度和取消,不允许重复
|
||||
@@ -138,6 +142,10 @@
|
||||
聊天标明会话,知识库显示库名与 `ScopeBadge`。下一行固定正文、图片、详情三个 PageTabs,
|
||||
页签及直接包装层 `flex: 0 0 auto`,仅当前面板滚动。查看已存结果不发 OCR 请求。
|
||||
|
||||
知识库将原件与维护操作收进详情头部的共享菜单,并将添加图片工具限制在图片页;聊天与
|
||||
设置预览保持原有入口。具体顺序、来源与解析时原件的区别及返回规则见
|
||||
[知识库来源操作](../knowledge-base/ui-design.md#6-来源操作)。
|
||||
|
||||
正文面板按来源页或章节呈现 Markdown、HTML 表格及受管图片。页面导航显示真实页号;
|
||||
PPTX 显示“幻灯片 N”,没有分页的原生文档显示工作表或标题定位,不生成假页码。点击图片
|
||||
旁的“第 N 页”或“查看正文位置”切到正文并聚焦对应标题;正文图片的“在图片中查看”反向
|
||||
@@ -172,7 +180,7 @@ reference 使用原路径。reference 原件失效时显示“原文件不可用
|
||||
和“重试”;有部分产物时可以查看,但不能标为成功。关闭测试预览后释放无引用测试资源。
|
||||
测试预览不提供“添加到会话”,防止诊断文件进入用户草稿或知识库。
|
||||
|
||||
“使用当前设置重新解析”是聊天草稿和知识库文档的次操作,点击前显示将使用的已保存来源。
|
||||
“使用当前设置重新解析”是聊天草稿的次操作;知识库列表和预览中的同一操作简写为“重新解析”,仍使用当前已保存的设置。
|
||||
历史消息和队列冻结已接受的输入;其预览只读。历史消息使用“添加到当前草稿重新解析”,
|
||||
产生草稿附件而不改写已发送正文;队列修改使用“恢复到草稿”,避免原队列和修改稿重复发送。
|
||||
重解析期间旧结果仍可查看,顶部显示“正在重新解析,
|
||||
|
||||
@@ -129,7 +129,10 @@ Main 进程职责、公共 API 对接、失败处理和验收方法。反馈平
|
||||
> 以及你主动添加的截图。默认不上传桌面诊断;只有勾选后才会把有界诊断摘要追加到描述。
|
||||
> 不会发送对话、Prompt、凭据、文件内容、路径、Provider 原始响应或远端 Agent 日志。
|
||||
|
||||
Checkbox 下方持续说明:诊断摘要只含时间、组件、阶段、稳定错误码、错误类型和固定短消息。
|
||||
Checkbox 下方持续说明:诊断摘要含时间、组件、阶段、稳定错误码、错误类型和固定短消息,
|
||||
以及工具连接失败的类别、耗时、HTTP 状态、尝试次数、工具类型和匿名关联标识。
|
||||
MCP 附加字段由 `normalizeDesktopDiagnosticRecord` 在写入、读取和反馈导出时按白名单
|
||||
校验;关联标识为请求令牌的 SHA-256 摘要,不含原始令牌、地址或错误正文。
|
||||
Renderer 不预览、不读取也不接收诊断内容或路径。勾选后详细描述上限为 3,398 字符,为附加
|
||||
摘要预留 1,600 字符以及分隔换行;超长草稿保留在表单中并显示字段错误,不静默截断。
|
||||
|
||||
|
||||
@@ -33,10 +33,28 @@
|
||||
| `src/shared/external-knowledge-contracts.ts` | Provider 配置、实例与绑定输入、目录、测试结果和外部引用定位契约 |
|
||||
| `src/shared/knowledge-contracts.ts`、`contracts.ts`、`assistant-contracts.ts` | 现有知识结果、列表和会话引用增加外部字段 |
|
||||
| `src/shared/knowledge-reference.ts` | 预检索与 MCP 共用的引用转换和去重键 |
|
||||
| `src/main/ipc.ts`、`src/preload/index.ts`、`src/shared/ipc-channels.ts` | 可信发送方检查、Zod 输入解析、类型化跨进程调用 |
|
||||
| `src/main/ipc.ts`、`src/main/knowledge/knowledge-ipc.ts`、`src/preload/index.ts`、`src/shared/ipc-channels.ts` | 可信发送方检查、Zod 输入解析、类型化跨进程调用 |
|
||||
| `src/renderer/src/ExternalKnowledge.tsx` | 实例 Modal、绑定表单、Provider 配置、外部详情与检索结果 |
|
||||
| `KnowledgeWorkspace.tsx`、`App.tsx`、`KnowledgeCitationDialog.tsx` | 统一列表、聊天选择、刷新及历史引用显示 |
|
||||
|
||||
Renderer 的 `KnowledgeWorkspace.tsx` 保留库选择、页签路由、检索与分块管理状态及回调。
|
||||
原有子组件位于 `src/renderer/src/knowledge-workspace/`:
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --- | --- |
|
||||
| `DocumentsView.tsx` | 来源导入、文档列表与解析结果预览 |
|
||||
| `KnowledgeSettingsView.tsx` | 索引、分块及图谱配置,向量索引状态轮询 |
|
||||
| `KnowledgeTasksView.tsx` | 任务筛选、层级展示、取消和重试 |
|
||||
| `GraphView.tsx`、`GraphEditors.tsx` | 图谱浏览、实体与关系编辑 |
|
||||
| `KnowledgeGraphChartLoader.tsx` | 图谱画布延迟加载及失败重试 |
|
||||
| `LibraryDialogs.tsx`、`RemoveSourceDialog.tsx`、`GraphDestructiveDialog.tsx` | 建库表单、库编辑与删除、来源移除及图谱破坏性操作确认 |
|
||||
| `types.ts` | 工作区 Props 与组件间使用的类型 |
|
||||
| `formatting.ts`、`helpers.ts` | 多个组件共用的本地化格式化、标签、别名解析、进度和错误处理 |
|
||||
|
||||
子组件直接导入所需模块,不反向依赖工作区入口。单个视图专用的格式化与标签留在该视图,
|
||||
检索结果转换留在入口。模块拆分保留组件 Props、挂载位置、key 与副作用顺序;文档与来源
|
||||
合并后的列表结构及操作归属见 [UI 设计](./ui-design.md#6-来源操作)。
|
||||
|
||||
`ExternalKnowledge.tsx` 的字段改用全局 `.field`,修正 body Portal 脱离知识库祖先后
|
||||
丢失 scoped 控件样式的问题。CSS 提供 560px 紧凑弹窗和粘附底部操作区;实例选择复用
|
||||
既有 picker 样式并实现菜单键盘行为。没有新增 Main 模块,具体控件规则由
|
||||
|
||||
@@ -16,6 +16,69 @@
|
||||
|
||||
## 验证证据
|
||||
|
||||
### 2026-09-27 独立评审 P2 修复
|
||||
|
||||
- `DocumentsView` 将任务来源 ID 与维护用来源分开传递。目录和一对多 URL 的文档预览
|
||||
只筛选当前文档任务,父批次作为上下文保留,同组 B 的任务不再因来源 ID 被纳入。
|
||||
真正单文档合并行在列表和预览中均保留来源、文档双 ID;判定使用完整文档集合。
|
||||
- 在飞状态由全局单 ID 改为按操作 ID 计数,完成或失败时只清理本次操作。来源暂停、
|
||||
同步及文档操作使用各自 ID 判断禁用,A 同步或重解析期间仍可暂停 B。
|
||||
- 新增 9 项行为回归:目录及一对多 URL 各覆盖列表、预览入口,并在搜索只剩 A 时确认
|
||||
不纳入 B 或其他来源级任务;单文档合并预览覆盖双 ID。四组 deferred 用例验证
|
||||
A 同步/重解析与 B 暂停的调用 ID、重复提交禁用、A 先完成及 B 先失败后的独立状态。
|
||||
预览测试同时确认所属来源的同步和移除入口仍可用。
|
||||
- `npx vitest run src/renderer/src/KnowledgeWorkspace.test.tsx src/renderer/src/DocumentResultPreview.test.tsx`:
|
||||
2 个文件、66 项通过;`npm run typecheck`、`npm run lint`、`git diff --check` 通过。
|
||||
- 本轮仅修改上述组件、工作区测试及本地知识库 UI/进度文档。未重跑全量或 Electron
|
||||
渲染验收,未提交;此前全量结果及渲染验证边界见下方记录。
|
||||
|
||||
### 2026-09-27 文档入口与任务历史整理
|
||||
|
||||
对应 US-D1、US-D2、US-D4,完成文档行、解析预览与知识任务中心的界面修改。当前交互
|
||||
以 [来源操作](./ui-design.md#6-来源操作) 和 [任务历史](./ui-design.md#8-任务批次与历史)
|
||||
为准,替代下方同日早期记录中的原生折叠操作区。
|
||||
|
||||
- 合并 URL 行恢复地址,保留查询参数与片段;同标题、不同查询参数的两条 URL 已验证
|
||||
可以区分、分别搜索并打开正确来源。
|
||||
- 文档与来源行使用一个主要按钮和共享菜单,分块、任务、重解析、同步、暂停、重试及
|
||||
移除继续可达。预览按返回、标题、维护操作分层,保留搜索、焦点与滚动恢复;解析时
|
||||
原件与当前来源使用各自原有 API。共享菜单补充向下翻转及缩窗后的视口高度限制。
|
||||
- 任务中心按真实父子记录计批次,对象筛选同步影响计数。历史包含已结束失败批次,
|
||||
运行批次中的成功子步骤不会单独混入历史。取消、重试继续服从服务契约。
|
||||
- 最终定向命令 `npx vitest run src/renderer/src/ApplicationMenu.test.tsx src/renderer/src/KnowledgeWorkspace.test.tsx src/renderer/src/DocumentResultPreview.test.tsx src/renderer/src/KnowledgeChunkManager.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx tests/knowledge-layout.electron.test.ts tests/attachment-layout.electron.test.ts tests/overlay-layering.electron.test.ts`:8 个文件、106 项通过。
|
||||
- `tests/knowledge-layout.electron.test.ts` 使用真实 DocumentsView、KnowledgeTasksView、
|
||||
DocumentResultPreview、菜单与 CSS,覆盖浅深主题及 1100×720、720×720、420×480。
|
||||
验证页面无横向溢出、表格内部滚动、菜单展开不改变行高、顶部菜单翻转、原生 End/Escape、
|
||||
预览焦点恢复及历史默认折叠。截图已检查宽屏列表、窄屏预览与菜单、任务历史。
|
||||
截图复核发现文档 Grid 原先会被表格最小宽度撑开;列宽改用 `minmax(0, 1fr)`,
|
||||
并增加内部页面容器无横向溢出的断言,确保导入工具栏不随表格横向滚动。
|
||||
隐藏窗口无截图时曾停在帧等待;改用可见窗口并确认真实焦点后,无截图运行通过。
|
||||
- 附件布局和 Modal 浮层的真实 Electron 回归通过,验证共享菜单修改没有破坏这两个入口。
|
||||
- 完整 `npm test` 最后一次完成:448 个文件通过、1 个失败、11 个跳过;5291 项通过、
|
||||
2 项失败、83 项跳过。失败仅为下方已记录的 HeartbeatCenter 中英文 tablist 数量断言。
|
||||
此后补回解析时原件菜单入口、补测锚点滚出视口,并修正窄屏 Grid,均通过上述最终定向回归。
|
||||
- `npm run typecheck`、`npm run lint`、`git diff --check` 通过。布局 fixture 使用合成数据与桥接替身,
|
||||
本轮未从完整 App 重做 UI → Main 的文件导入及真实解析服务验收;没有新增外部模型调用。
|
||||
|
||||
### 2026-09-27 文档与来源统一列表
|
||||
|
||||
在现有 `knowledge-workspace` 拆分基础上修改 `DocumentsView.tsx`,单文件、单 URL 与
|
||||
唯一关联文档合成一行;目录及一对多来源保留组标题,零文档来源和孤立文档继续可见。
|
||||
统一搜索、完整移除数量、次要操作折叠及预览返回规则见 [UI 设计](./ui-design.md#6-来源操作)。
|
||||
`KnowledgeTasksView.tsx` 支持合并行同时传入来源和文档上下文,展示两者相关任务。
|
||||
|
||||
- `npx vitest run src/renderer/src/KnowledgeWorkspace.test.tsx src/renderer/src/DocumentResultPreview.test.tsx src/renderer/src/KnowledgeChunkManager.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx`:4 个文件、94 项通过。
|
||||
- 新增用例覆盖单文件与 URL 去重、来源和文档搜索、一对多过滤、零文档来源重试与暂停、
|
||||
孤立文档、完整移除数量、合并任务入口、拖放,以及预览返回后的搜索、焦点和滚动恢复。
|
||||
工作区测试使用解析预览替身;真实预览组件由同次运行的 `DocumentResultPreview.test.tsx` 验证。
|
||||
- `npm run typecheck`、`npm run lint` 和 `git diff --check` 通过。
|
||||
- 完整 `npm test` 运行 200 秒后超时,超时前输出 `HeartbeatCenter.test.tsx` 两项失败,
|
||||
全量测试未完成。独立运行 `npm test -- src/renderer/src/HeartbeatCenter.test.tsx`
|
||||
复现 40 项通过、2 项失败:zh-CN/en-US 的 `keeps tab titles unique...` 用例在第 213 行
|
||||
期望 1 个 `tablist`,实际为 2 个。该失败与本次知识库修改无关,本轮未修改心跳中心。
|
||||
- 未做真实 Electron 浅深主题、窄窗口、原生键盘及 UI → Main 导入验收。
|
||||
未调用外部模型或知识服务,未提交改动。
|
||||
|
||||
### 2026-09-20 清理孤立的内存图谱搜索
|
||||
|
||||
- 删除仅剩测试调用的 `searchGraph`、专属评分/遍历辅助函数、搜索上限及测试 fixture。
|
||||
|
||||
@@ -51,8 +51,8 @@ Conversation 的检索范围,返回对话并聚焦输入框。
|
||||
- 向量状态。
|
||||
- 启用图谱时的图谱状态。
|
||||
|
||||
失败文档保留错误信息和“重新处理”。只要仍有可用分块,就允许打开分块管理,避免隐藏
|
||||
上一版可用索引。
|
||||
失败文档保留错误信息和“重新处理”,入口位置见第 6 节。只要仍有可用分块,就允许
|
||||
打开分块管理,避免隐藏上一版可用索引。
|
||||
|
||||
## 5. 问答效果与高级参数
|
||||
|
||||
@@ -64,6 +64,42 @@ Conversation 的检索范围,返回对话并聚焦输入框。
|
||||
|
||||
## 6. 来源操作
|
||||
|
||||
“文档与来源”使用一张按来源组织的表格。单文件、单 URL 来源只有一篇关联文档时,
|
||||
来源与文档合成一行,以文档名为主标题,同步状态、同步时间和索引状态就近显示。
|
||||
不再单独展示同名来源行,也不重复任务入口。目录及其他一对多来源保留来源组标题,
|
||||
文档紧随其后;零文档和失败来源仍保留同步、暂停、重试及移除入口。
|
||||
没有 `sourceId` 或找不到对应来源的文档独立显示。
|
||||
|
||||
搜索同时匹配来源名称、来源位置、文档名称和路径。来源命中时显示该组全部文档;
|
||||
仅文档命中时保留组标题和命中文档。一对多关系按完整数据判断,搜索不能将其临时合成
|
||||
单文档行。移除确认使用来源的完整文档数量,不使用搜索结果数。
|
||||
|
||||
导入文件、目录、URL 及拖放入口保持可用,拖放区使用紧凑的图标与文字提示。
|
||||
合并行继续显示 URL,包含路径、查询参数和片段,使同标题的不同页面可以区分;
|
||||
长地址允许换行。本地文件沿用文件名摘要。来源组中的 URL 同样可见。
|
||||
|
||||
每行只直接显示一个主要动作及一个“更多操作”按钮。有解析结果时主要动作是
|
||||
“查看解析结果”;没有结果时,失败文档显示“重新处理”,其余文档有任务时显示
|
||||
“查看任务”,否则显示“打开来源”。来源组优先提供失败重试或查看任务,没有任务时
|
||||
提供同步或暂停。状态与错误始终在行内可见。
|
||||
|
||||
更多操作复用 `AnchoredMenu`,依次放置打开来源、打开解析时原件、文档分块、查看任务,
|
||||
再用分隔线区分重新处理、来源同步和移除来源。仅在有对应资源时显示原件或任务入口;
|
||||
没有分块时禁用分块入口。来源组的菜单提供任务及来源维护。菜单支持方向键、Home、End、
|
||||
Escape 和焦点返回,展开不改变行高;空间不足时翻转方向或在菜单内滚动。
|
||||
大小与分块数保持单行,窄窗口在表格内部横向滚动。
|
||||
操作文案使用“打开来源 / 重新解析 / 同步 / 暂停 / 重试 / 移除来源”,不附带对象名称;更多操作按钮的可访问名称和移除确认框仍保留对象名称。
|
||||
列表和预览的操作菜单宽度为 `220px`,小视口下收窄并保留左右各 `16px` 边距。
|
||||
|
||||
解析预览头部按返回、文档标题与库名及全局范围、维护菜单排列,地址仍可辨认。
|
||||
正文、图片和详情使用共享结果组件;知识库的会话选择及添加图片工具仅在图片页显示,
|
||||
切换页签保留选择。返回列表恢复搜索、原触发按钮焦点及页面滚动位置。重新解析继续
|
||||
调用文档重建,使用当前设置并保留上次结果,失败时显示可恢复错误。维护菜单同时保留
|
||||
当前来源与解析时原件的打开操作,两者分别读取知识来源和已保存的解析资产。
|
||||
|
||||
在飞操作只禁用对应的操作入口。同步或重解析 A 期间,其他来源 B 的暂停仍可用;
|
||||
并发操作分别恢复可用状态,A 结束不能提前解除仍在执行的 B。
|
||||
|
||||
文档行提供“打开来源”,Main 根据知识库和文档归属重新读取保存的文件路径或 URL。
|
||||
移除来源使用确认对话框,说明文档数、索引、图谱证据和托管副本影响。初始焦点位于
|
||||
取消,提交期间禁止重复操作,失败时保留对话框和错误。
|
||||
@@ -77,3 +113,30 @@ Conversation 的检索范围,返回对话并聚焦输入框。
|
||||
均切换一次选择;选中背景和整行焦点环保持可见。Tab 聚焦、Space 切换,Escape 关闭并
|
||||
返回触发按钮。点击行内非焦点元素时产生的空目标失焦不关闭弹层;点击外部或焦点明确
|
||||
移到外部时才关闭,避免原生标签完成勾选前被卸载。
|
||||
|
||||
## 8. 任务批次与历史
|
||||
|
||||
任务中心按服务返回的 `parentTaskId` 组织一次操作及其文档、阶段子任务。顶层操作按
|
||||
创建时间倒序排列,一个操作计为一个批次;缺失父记录的旧任务仍独立显示。重试产生的
|
||||
新操作保留真实历史,使用已有 `attempt` 显示尝试次数,不按标题猜测合并关系。
|
||||
|
||||
文档或来源进入任务中心后,列表与计数使用同一对象范围,并保留命中任务的父级上下文。
|
||||
合并文档行同时匹配来源 ID 和文档 ID,包括没有来源 ID 的文档任务。“清除对象筛选”
|
||||
恢复当前库的任务集合。
|
||||
|
||||
列表与解析预览使用相同的文档任务范围。目录及一对多来源下的文档只按文档 ID 筛选,
|
||||
即使搜索后只剩一篇也不扩大到整个来源;只有真正的单文档合并行同时包含来源 ID。
|
||||
预览菜单中的来源同步、暂停和移除仍作用于所属来源,来源维护范围独立于任务筛选。
|
||||
|
||||
- 进行中:批次内有排队或运行记录。
|
||||
- 失败:批次内有失败或中断记录;运行批次也可能同时存在失败子任务。
|
||||
- 历史:批次内没有排队或运行记录,包含完成、失败、中断、取消和跳过。
|
||||
|
||||
计数均按批次计算,失败与历史可以重叠。标题旁的共享帮助解释口径。运行批次中已成功的
|
||||
阶段不会单独进入历史。切换到进行中或失败时展开相关批次;全部和历史默认收起子任务,
|
||||
用户仍可逐项展开。批次状态保留服务原值,子任务失败以额外文字提示,不改写父状态。
|
||||
|
||||
只有进行中的记录显示进度条;失败和中断保留停止阶段、错误及处理建议。已结束记录
|
||||
不再显示“当前阶段”、百分比或默认“等待处理”。摘要保留时间、服务消息、子任务数及
|
||||
重试次数。取消和重试严格使用服务返回的 `canCancel`、`canRetry`,提交期间禁用重复
|
||||
操作,失败后保留筛选、任务内容及就地错误。
|
||||
|
||||
@@ -8,8 +8,17 @@ stdio MCP 提供明确、可诊断的 Node.js 与 Python 环境,同时允许
|
||||
用户从设置中心的“能力与工具”进入,并在 `Skills`、`MCP`、`工具执行环境` 三个水平
|
||||
Tab 之间切换。
|
||||
|
||||
[Obsidian 接入](../obsidian/README.md)复用本功能的 `LaunchEnvironmentProvider` 启动
|
||||
随包交付的 MCPVault,不新增 Node 安装或下载源设置。生产组件自动化已覆盖真实 MCPVault
|
||||
调用,Electron 托管 Node 离线冒烟仍待完成,具体见[验证记录](../obsidian/progress.md)。
|
||||
|
||||
## 文档导航
|
||||
|
||||
Local native Continue and DS Web clients now honor the current custom Node
|
||||
selection. They require standard Node rather than Electron's Node mode; the
|
||||
remaining managed fallback and validation are tracked in
|
||||
[native client progress](../assistant-workbar/progress.md#2026-09-27-local-native-client-validation).
|
||||
|
||||
| 文档 | 权威职责 |
|
||||
| --- | --- |
|
||||
| [PRD](./prd.md) | 用户问题、产品目标、范围、需求和产品验收 |
|
||||
|
||||
@@ -81,6 +81,49 @@
|
||||
|
||||
## 已验证证据
|
||||
|
||||
### 2026-09-27 MCP 编辑器遮挡修复
|
||||
|
||||
真实 Electron App 经“设置 → 能力与工具 → MCP → 自定义 MCP → 添加 Server”复现。
|
||||
修复前编辑器层级为 `70`、设置为 `130`,输入框中心命中设置页签容器;名称输入框虽已
|
||||
获得焦点,父设置仍为 `inert=false`。添加和编辑现接入共享 Modal 层级与背景隔离,
|
||||
遮罩关闭保留触发按钮焦点。没有修改 Runtime、Agent 或 MCP 传输实现。
|
||||
|
||||
`overlay-layering.electron.test.ts` 新增真实 App 用例,复用生产 preload、IPC、
|
||||
`CapabilityService`、设置存储与 `BrowserService`。已通过的场景:
|
||||
|
||||
| 场景 | 验证结果 |
|
||||
| --- | --- |
|
||||
| 无浏览器,浅色 `1280 × 900`、深色 `960 × 420` | 添加/编辑鼠标命中、文字输入、父设置隔离、Tab/Shift+Tab 循环通过 |
|
||||
| 右侧原生浏览器打开,浅色 `1280 × 900`、深色 `1280 × 420` | 设置及 MCP 期间原生视图隐藏;设置关闭后恢复相同 webContents ID、URL 和页面内标记,无重建或刷新 |
|
||||
| 关闭与焦点 | X、取消、Escape、遮罩、保存成功返回原触发按钮;关闭子层保留设置,关闭设置返回其入口 |
|
||||
| 持久化 | 四次 UI 保存经生产 IPC 写入临时配置,新建 `CapabilityService` 重读四条记录;编辑重开回显名称 |
|
||||
|
||||
原有 overlay Electron 用例也通过,继续覆盖解析菜单、二级结果、通知、应用中心、本机
|
||||
推理监控和原生 `dialog`。回归禁用 Windows 原生窗口遮挡节流,避免其他桌面窗口暂停
|
||||
测试的帧等待;未改变产品窗口选项。浏览器页面使用本地 HTTP 服务;MCP 测试配置保存为
|
||||
停用状态,不启动外部 MCP 命令。真实模型调用 **0 次**。
|
||||
|
||||
证据范围为 Windows x64 开发态 Electron。无关启动服务使用 harness 替身,未配置的
|
||||
向量模型与 Runtime 原生能力服务会返回不可用;未验收这些服务、外部 MCP 连接、远程
|
||||
Agent 或其他操作系统。短窗口从已打开设置调整尺寸;宽度跨越工作栏自动收起阈值的路径
|
||||
不作为浏览器保持打开的验收场景。
|
||||
|
||||
最终 focused 集合为 6 文件、215 项通过;`npm run typecheck`、`npm run lint` 和
|
||||
`git diff --check` 通过。本轮未运行全仓 `npm test` 或打包。验证命令:
|
||||
|
||||
```text
|
||||
npx vitest run tests/overlay-layering.electron.test.ts src/renderer/src/McpSettingsSection.test.tsx src/renderer/src/SettingsPanel.test.tsx src/renderer/src/FloatingPortal.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx src/renderer/src/RightAssistantSidebar.resize.test.tsx
|
||||
npm run typecheck
|
||||
npm run lint
|
||||
git diff --check
|
||||
```
|
||||
|
||||
调试期间的失败记录:旧代码在真实鼠标命中断言失败;接入共享焦点后补修遮罩关闭的默认
|
||||
焦点转移。harness 的帧等待曾受 Windows 窗口遮挡节流影响,浏览器导航曾在创建或输入
|
||||
状态提交前触发;分别关闭测试进程的遮挡节流,并等待可用控件与实际页面加载后验证。
|
||||
这些失败未计为产品验收通过。中文文档扫描无阻断项;本节的并列项是实测关闭入口和覆盖
|
||||
组件清单,保留以便核对。
|
||||
|
||||
### 2026-09-03 `v0.12.0` 失败标签恢复
|
||||
|
||||
- 不可变标签工作流 `33704483505` 的 Windows x64/ARM64 与 macOS x64/ARM64 托管 Python
|
||||
|
||||
@@ -279,6 +279,14 @@ stdio MCP:
|
||||
Tab、不渲染占位面板。
|
||||
- 页签直接包装层使用 `flex: 0 0 auto`,并由 CSS 回归测试保证在滚动设置布局中不可收缩。
|
||||
|
||||
`McpSettingsSection` 的添加与编辑共用 body Portal,遮罩使用 `--z-dialog`。
|
||||
打开前记录并聚焦触发按钮,再由 `activateModalFocus` 隔离父设置、聚焦名称并在关闭时
|
||||
恢复原隔离状态与焦点;键盘事件在子层停止传播。遮罩的 `mousedown` 关闭分支阻止默认
|
||||
焦点转移,避免恢复到触发按钮后又失焦。原生浏览器继续复用
|
||||
`browser-viewport-occlusion.ts`,无需 MCP 专用隐藏条件。
|
||||
真实 App 回归位于 `tests/overlay-layering.electron.test.ts`,使用生产 preload、IPC、
|
||||
配置存储及 `BrowserService`,验证添加、持久化、编辑、父层隔离与原生浏览器恢复。
|
||||
|
||||
### 11.2 工具环境状态与 IPC
|
||||
|
||||
Renderer 接收:
|
||||
|
||||
@@ -113,6 +113,12 @@ MCP 面板
|
||||
- MCP 原有四个内层页签继续保留,外层和内层使用不同的 `aria-label` 与 `idPrefix`。
|
||||
- 窄屏时外层页签保持单行并允许水平滚动,不折成多行,不替换为下拉框。
|
||||
|
||||
“MCP / 自定义 MCP”的添加和编辑共用设置上方的子 Modal。打开后聚焦名称输入框,
|
||||
父设置与工作区保持不可交互;Tab 和 Shift+Tab 在编辑器内循环。X、取消、Escape、
|
||||
遮罩及保存成功均返回原添加或编辑按钮,Escape 只关闭编辑器。保存期间禁止关闭,
|
||||
失败保留输入。右侧浏览器沿用应用级 Modal 的视图释放规则,编辑器关闭后仍由父设置
|
||||
保持隔离,设置关闭后恢复网页。
|
||||
|
||||
## 4. 工具下载源
|
||||
|
||||
使用原生 Radio Group:
|
||||
|
||||
@@ -6,9 +6,12 @@ metadata and indexes, and local files for entry bodies and binary assets.
|
||||
The open workbench subscribes to successful writes so users can see external
|
||||
changes without leaving the page or clicking a refresh button.
|
||||
|
||||
The workbench opens on a responsive note-card overview. Opening a note replaces
|
||||
the overview with a continuous record stream, a narrow left index and independent
|
||||
right AI comments. Both side panes can collapse. Index items show one real
|
||||
The desktop workbench keeps a compact all-notes list on the left and the selected
|
||||
note on the right. The list supports search, creation, pin/delete menus, resizing
|
||||
and collapse. Switching notes preserves list position and remembers each note's
|
||||
reading position while the workspace remains mounted. Narrow workspaces switch
|
||||
between list and detail. Note detail contains a continuous record stream, a narrow
|
||||
record index and independent AI comments. Both detail side panes can collapse. Index items show one real
|
||||
first-page canvas thumbnail with page count, or a text summary; clicking scrolls
|
||||
without replacing the editor or losing a draft. Opening a note shows a blank composer
|
||||
above the history, with text/canvas selection and Save. Creating a record resets
|
||||
@@ -19,16 +22,35 @@ comments. The divider can be dragged and remembers its width; each note group
|
||||
can independently collapse its tasks while retaining its title and count.
|
||||
Narrow containers use on-demand detail with an explicit return to the
|
||||
mounted list. One content-sized button switches to the other view in the page
|
||||
header immediately before New note; status filters sit beside search and wrap
|
||||
header when note detail is closed; New note is always the primary page-header
|
||||
action to the right of the view switch or Back to overview. The notes list
|
||||
heading keeps only Manage tags. Status filters sit beside search and wrap
|
||||
when needed. Note detail removes the surrounding frame and stream padding while
|
||||
keeping editor borders and the AI divider. Returning from a source note restores the task
|
||||
context and protects unsaved editor changes. A successful save followed by no
|
||||
further edits does not prompt again on return. Narrow note layouts use an index
|
||||
drawer and bounded bottom AI pane.
|
||||
|
||||
Conversation capture and the compact Notes workbar panel are implemented. Users
|
||||
can preview and edit one assistant response or the complete conversation text,
|
||||
then append it to an existing note or create a note with its first entry. Quick
|
||||
notes opens the same panel for search, browsing and text appends. Saved entries
|
||||
carry structured conversation sources with return navigation. The panel and full
|
||||
workspace share storage and change notifications; drafts remain in App memory.
|
||||
Real Electron acceptance passed through the App UI, production preload, IPC and
|
||||
SQLite. Repository validation is not all green; the [progress record](./progress.md)
|
||||
separates focused passes, repaired schema fixtures and execution-time failures.
|
||||
|
||||
## Documents
|
||||
|
||||
- [Technical design](./technical-design.md): file storage, schema 38 migration,
|
||||
- [Conversation integration PRD](./prd.md): scope and acceptance for
|
||||
conversation capture and the compact workbar panel.
|
||||
- [Conversation integration logic](./logic-design.md): capture boundaries, source
|
||||
lifetime, panel state, draft protection and application availability.
|
||||
- [Conversation integration UI](./ui-design.md): implemented entry points, compact
|
||||
panel, capture preview and source navigation, following the root UI system.
|
||||
- [Technical design](./technical-design.md): file storage, schema 38 body migration,
|
||||
schema 48 source metadata, desktop search and atomic initial-entry creation,
|
||||
backup boundaries, database notifications, process boundaries, canvas and AI
|
||||
contracts, refresh lifecycle and regression coverage.
|
||||
- [Progress](./progress.md): implementation and validation evidence.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# 会话联动逻辑设计
|
||||
|
||||
状态:已按当前实现核对,验证进度见 [progress.md](./progress.md)。需求编号来自 [PRD](./prd.md)。
|
||||
|
||||
## 内容与来源
|
||||
|
||||
FR-2、FR-3:单条采集读取所选助手消息的非空正文;整段采集先加载该会话完整历史,再按消息顺序收录用户和助手的非空正文,保留角色分隔。预览建立后,切换会话或收到新消息不会替换正文及来源标识。生成中的消息不可采集,停止或失败后已有正文可保存,单条预览注明回答未完成。整个会话正在生成时禁用整段采集,提示等待完成或停止生成。
|
||||
|
||||
首版按文字保存,保留原始 Markdown 文本、换行和代码文本,不承诺还原聊天渲染效果。推理、工具调用日志、系统提示、附件二进制和图片不进入正文;预览来源旁提供保存范围帮助,按需展开。用户可编辑预览,来源仍指向本次采集的会话。读取完整会话失败时不以屏幕上已有消息代替。
|
||||
|
||||
FR-5:来源独立于可编辑正文。单条来源包含会话和消息标识;整段来源包含会话标识、此次收录的消息标识及采集时间。预览使用采集时的会话标题和项目名称;保存时主进程校验消息归属,并以当时数据库中的会话标题和项目名称写入来源,无项目时显示全局。若预览期间源会话或消息已删除,保存失败并保留预览。保存完成后,修改或删除源消息不回写笔记正文和来源。
|
||||
|
||||
点击来源时读取完整会话。消息不存在但会话仍在时打开会话并提示“原消息已不存在”;确认会话不存在后保留来源文字,并在当前来源条禁用跳转。其他读取失败显示可重试错误。打开未渲染的来源消息时扩大聊天历史显示范围,再滚动定位并聚焦。编辑笔记正文不移除来源;删除笔记不影响源会话。
|
||||
|
||||
## 面板与草稿
|
||||
|
||||
FR-1、FR-4:笔记应用为可关闭、可排序的单实例工作栏 Tab,新布局默认不打开。再次触发入口激活现有 Tab;笔记选择属于应用级状态,切换项目或会话不改写它。列表按置顶优先、最近更新时间排列,搜索匹配标题与记录文字,同一笔记只显示一次。当前应用会话内保留最近选择,重启不恢复笔记选择或草稿。该笔记已删除时回到列表,清除失效保存目标并保留待保存文字。
|
||||
|
||||
FR-2、FR-3:面板有浏览、采集编辑、保存中三个状态。触发采集进入编辑态;选择目标只改变写入位置;明确点击“加入笔记”才写入。每次提交新增一条记录,不覆盖旧记录。新建目标时先填写标题,会话标题作为可修改默认值;提交一次创建笔记和首条记录,取消不遗留空笔记。普通“新建笔记”仍可显式创建空笔记。
|
||||
|
||||
保存中禁用重复提交和面板离开操作,结果返回后可再次操作。成功后清除本次草稿,显示响应返回的新增记录;失败保留预览、标题和目标。目标已删除时提示重新选择。容量校验使用现有文字记录限制,超限由用户缩减正文后重试;一次提交始终对应一条完整记录。
|
||||
|
||||
关闭 Tab、返回面板列表、从面板打开完整工作区、禁用应用或以另一条采集替换草稿前,显示“继续编辑 / 放弃草稿并切换”确认。普通主页面、项目和会话切换以及隐藏工作栏保留 App 持有的草稿及来源。取消采集只在正文或标题相对预览初值有修改时确认;未修改预览可直接取消。完整工作区自身的编辑草稿仍由其离开确认保护。
|
||||
|
||||
FR-6:成功写入触发现有通知刷新视图;面板重新挂载或工作栏重新展开时读取最新数据。面板挂载期间保留搜索词;笔记选择和草稿由 App 保留,不受搜索响应或后台刷新覆盖。既有记录编辑继续使用原修订号处理冲突。此处同步仅指本机共享存储的视图更新。
|
||||
|
||||
## 启用与评论
|
||||
|
||||
FR-1~FR-4:遵循魔法笔记应用的启用状态。禁用时隐藏会话采集及工作栏目录入口,并移除笔记 Tab;禁用前处理草稿。外部设置变更要求禁用时,选择继续编辑会尝试恢复启用设置,失败显示设置错误。应用未常驻不影响会话采集或工作栏可用性。设置继续由应用中心管理。
|
||||
|
||||
会话采集和快速追加本身不调用模型。保存后沿用现有 AI 评论模式;只有已有设置要求保存后自动评论时才触发,失败不撤销保存,也不自动重新追加。
|
||||
|
||||
## 完整性检查
|
||||
|
||||
当前实现覆盖首次创建、追加、取消、重复点击、写入失败、目标删除、来源删除、跨会话切换及刷新与草稿的关系。完整历史读取、来源定位和存储接口已接入;产品范围无待决项。真实 Electron 已验证采集、保存、定位、窄面板键盘操作和持久化,具体范围见进展记录。全仓测试和类型检查仍有执行时记录的失败,聚焦复跑通过不等于全仓通过。
|
||||
@@ -0,0 +1,39 @@
|
||||
# 魔法笔记与会话联动
|
||||
|
||||
状态:会话联动前后端已实现,真实 Electron 验收通过;全仓验证未全绿。聚焦结果、fixture 修复后复跑及执行时的全仓失败见 [progress.md](./progress.md)。
|
||||
|
||||
## 目标与范围
|
||||
|
||||
用户在阅读回答时,可将内容保存到已有笔记或新笔记,并从笔记返回原会话。会话界面提供文字预览和保存位置选择,与已有 Agent 笔记工具共用存储。
|
||||
|
||||
独立工作区继续承载完整编辑、画布、待办和 AI 评论;右侧笔记面板提供浏览和快速追加。笔记仍属于全局,不因入口所在项目改变归属。
|
||||
|
||||
## 功能要求
|
||||
|
||||
| 编号 | 要求 |
|
||||
| --- | --- |
|
||||
| FR-1 | 右侧助手工作栏增加“笔记”应用,支持搜索、打开已有笔记、新建笔记、查看记录摘要、快速追加文字,以及打开对应完整工作区。 |
|
||||
| FR-2 | 助手消息操作栏提供“加入笔记”,打开可编辑预览,用户选择已有笔记或新建后明确提交。 |
|
||||
| FR-3 | 会话标题的更多菜单提供“保存当前对话到笔记”,按触发时的会话内容生成预览,保存为目标笔记中的一条记录。 |
|
||||
| FR-4 | 通过右侧工作栏“+ → 笔记”打开面板并恢复当前应用会话中最近选择的笔记,首次使用显示列表,不隐式保存当前对话。左侧底部和聊天页头不再提供重复的“快速笔记”入口。 |
|
||||
| FR-5 | 从会话保存的记录保留结构化来源,显示会话名称、所属项目(如有)和采集时间,支持返回原会话及单条来源消息。源会话删除后保留笔记内容。 |
|
||||
| FR-6 | 面板、完整工作区和 Agent 写入使用同一份笔记数据,成功写入后更新已打开视图,同时保护未保存草稿。 |
|
||||
| FR-7 | 笔记支持手动标签。每篇最多 10 个,单个标签最长 24 字,不区分大小写,同名只保留首次写法。在笔记标题下添加或移除标签;添加时提示已有标签,也可以直接新建。 |
|
||||
| FR-8 | 总览可按标签筛选,多选时只显示同时带有全部所选标签的笔记;搜索框也能匹配标签名。打开笔记后,左侧列表沿用当前筛选,并提供清除入口。 |
|
||||
| FR-9 | 提供“管理标签”入口,列出全部标签及使用篇数。可以重命名标签;新名称与已有标签相同时,两个标签合并。删除标签时,它会从所有笔记中移除,笔记本身保留。 |
|
||||
| FR-10 | Agent 笔记工具可在创建、修改笔记时设置标签,并可按标签列出笔记。只在用户要求时修改标签,不自动打标签。 |
|
||||
|
||||
标签第一版不提供颜色和层级(如“工作/项目A”),“/”只作为普通字符保存。没有笔记使用的标签会自动删除。
|
||||
|
||||
首版不包含自动总结、自动分类、自动选择保存目标、选中文本采集、多条消息勾选、附件文件复制或跨设备同步。“总结后加入”和选区采集作为后续扩展,不预留不可用按钮。
|
||||
|
||||
## 产品验收
|
||||
|
||||
- 首次使用且没有笔记时,可从一条助手回答创建笔记并保存首条记录;已有笔记时可搜索并追加,原记录保持不变。
|
||||
- 保存当前对话包含未在屏幕上渲染的历史正文;预览范围明确,超出容量时提示缩减内容,不静默截断。
|
||||
- 保存成功后显示目标笔记并定位新增记录;取消不写入,失败保留内容和目标供重试。
|
||||
- 从来源条可返回对应会话;会话已删除时显示“原会话已不存在”,已保存正文仍可阅读和编辑。
|
||||
- 面板追加后完整工作区可见,Agent 修改后面板可见;后台刷新和切换会话不覆盖未保存文字。
|
||||
- 给两篇笔记加上“Work”和“work”,只会得到一个标签,计数为 2。选中两个标签后,只显示同时带有这两个标签的笔记。把“Work”重命名为已有的“发布”后,两个标签合并,两篇笔记都不会丢失。删除标签不会删除任何笔记。
|
||||
|
||||
状态与内容范围见 [逻辑设计](./logic-design.md),入口和操作细节见 [界面设计](./ui-design.md),接口与存储见 [技术设计](./technical-design.md#conversation-integration)。
|
||||
@@ -1,5 +1,251 @@
|
||||
# Magic Notes Progress
|
||||
|
||||
## 2026-10-01: Header New Note Action
|
||||
|
||||
New note is now one primary page-header button that always follows the view
|
||||
switch (overview, to-dos) or Back to overview (note detail). The `+` icon in the
|
||||
notes list heading was removed; the heading keeps only Manage tags. From note
|
||||
detail the button opens the list's title form (desktop reopens a collapsed list;
|
||||
narrow returns to the list first). Workspace tests (133) and the Electron layout
|
||||
test pass, with overview and detail screenshots checked at 1280px; the App note
|
||||
subset (11), typecheck, and lint on changed files pass.
|
||||
|
||||
## 2026-09-30: Navigate After Record Mount
|
||||
|
||||
Quick Notes navigation now scrolls after React commits the target record, rather
|
||||
than scheduling from the data request's completion. A regression that runs the
|
||||
animation-frame callback immediately fails before this fix and passes afterward.
|
||||
The complete App/workspace tests and Electron navigation/compaction checks pass:
|
||||
450 tests across four files, plus typecheck and lint. No provider calls were made.
|
||||
|
||||
## 2026-09-30: Manual Note Tags
|
||||
|
||||
Implemented FR-7 to FR-10 as described in
|
||||
[Note Tags](./technical-design.md#note-tags): schema 51 tag tables, tag
|
||||
replacement on note update, AND filtering, rename/merge/delete with note
|
||||
revision bumps, IPC and preload methods, the overview filter row, card chips,
|
||||
note-header tag editor, the "Manage tags" dialog, and tag support in
|
||||
`note_create`, `note_update` and `note_list`. No colours or hierarchy.
|
||||
|
||||
- New tests: database tag lifecycle (`assistant-database.test.ts`), MCP tag
|
||||
normalization and filtering (`knowledge-mcp-gateway.test.ts`), and four
|
||||
workspace tag tests (filtering, search, keyboard add/remove, manager
|
||||
rename/merge/delete).
|
||||
- `npx vitest run` over the workspace, panel, `src/main/agent`,
|
||||
`src/main/magic-notes`, `src/main/assistant`, storage startup, preload, shared
|
||||
and the five Magic Notes Electron tests: 142 files passed (4 skipped), 1706
|
||||
tests passed. `App.test.tsx -t note`: 4 passed.
|
||||
- The Electron layout test checks the overview filter row and card chips fit
|
||||
their containers; screenshots of the overview, tag manager and note header
|
||||
checked at 1280px.
|
||||
- `npm run typecheck` and eslint on the changed files passed. Full `npm test`
|
||||
was not rerun.
|
||||
|
||||
## 2026-09-30: Overview Page And Header Back Button
|
||||
|
||||
"Back to overview" returned to the page header's top-right as a labelled button.
|
||||
It now leads to a full-width all-notes card grid instead of a list beside an
|
||||
empty detail pane; the split list appears only while a note is open.
|
||||
`MagicNotesWorkspace.test.tsx` (129) and the Electron layout, analysis and
|
||||
navigation tests passed; screenshots checked at 1280 and 720px.
|
||||
|
||||
## 2026-09-30: Compact Note Detail
|
||||
|
||||
The note detail now prioritizes content: the notes list uses two-line rows
|
||||
(about 54px instead of 88px); note controls moved from text buttons in the page
|
||||
header to a sticky icon toolbar; the title appears once as the stream heading;
|
||||
the record index starts collapsed; AI opens only with comment activity or a pin;
|
||||
the idle composer is one line; entry actions are hover icons. At 1280x800 with
|
||||
the list open the stream is about 990px wide (content capped at 880px), versus
|
||||
525px before, and the first entry starts about 240px from the top of the stream.
|
||||
|
||||
- Electron screenshots checked at 1280 (light/dark), 1000 and 720px, with and
|
||||
without the index and AI panes.
|
||||
- `MagicNotesWorkspace.test.tsx` 129 tests, `App.test.tsx` 315 tests, and the
|
||||
Electron layout, analysis, navigation, footer and capture tests passed.
|
||||
The analysis and navigation fixtures now locate icon buttons by `aria-label`.
|
||||
- `npm run typecheck` and eslint on the changed files passed. Full `npm test`
|
||||
was not rerun.
|
||||
|
||||
## 2026-09-30: Persistent Notes List
|
||||
|
||||
Desktop notes now retain the all-notes list beside the current note. The list
|
||||
supports independent scrolling, selected state, creation, action menus, resizing
|
||||
and collapse. Narrow workspaces switch between the mounted list and detail.
|
||||
Switching notes restores reading positions within the mounted workspace and
|
||||
protects unsaved titles and bodies. Current-note deletion uses the same draft
|
||||
guard; failed deletion and deleting another note retain current drafts.
|
||||
|
||||
- Workspace, Electron layout, navigation and analysis regression tests passed:
|
||||
4 files, 132 tests. The analysis fixture no longer waits for Cancel after Save
|
||||
changes has already closed the editor.
|
||||
- The full-suite run also passed the production App/preload/IPC/SQLite note-capture
|
||||
scenario, including reopening the database and returning to conversation sources.
|
||||
- `npm run typecheck`, `npm run lint` and `git diff --check` passed.
|
||||
- Full `npm test` did not finish within 600 seconds. It reported two analysis
|
||||
failures subsequently fixed and passed above, and one supervisor-layout failure.
|
||||
There is no all-green full-suite result for this change.
|
||||
- Layout fix, same day: with the list occupying 289px, a 930-1100px window left
|
||||
the detail container under 800px, so AI stacked below a short stream. At about
|
||||
880px a CSS container query and the React width state disagreed, briefly
|
||||
rendering the list above the stacked detail. AI now stays beside the editor
|
||||
down to a 600px detail width; the record index uses a drawer from 800px; the
|
||||
list/detail switch uses only the measured workspace width. Electron screenshots
|
||||
were checked at 1280, 1100, 1000, 930, 880, 700 and 560px.
|
||||
`MagicNotesWorkspace.test.tsx`, the Electron layout test and the analysis
|
||||
regression passed: 3 files, 131 tests.
|
||||
|
||||
## 2026-09-28: Startup Body Read Reuse
|
||||
|
||||
Startup repair now reuses the asset references collected during revision
|
||||
inspection, as described in [file reconciliation](./technical-design.md#schema-38-migration).
|
||||
The persisted format and revision recovery rules are unchanged.
|
||||
|
||||
- Real temporary SQLite/filesystem fixture: 120 entries across 120 notes,
|
||||
half rich text and half canvas, with 4,039,560 bytes of body JSON.
|
||||
Five initializations each read 240 bodies before and 120 after the change.
|
||||
Logical bytes read fell from 8,079,120 to 4,039,560 per initialization.
|
||||
- Baseline durations were 148.23, 134.42, 131.06, 140.66 and 172.90 ms;
|
||||
after durations were 136.89, 119.11, 116.41, 115.14 and 116.26 ms.
|
||||
Medians were 140.66 and 116.41 ms. These Windows runs used warm filesystem
|
||||
caches on a shared machine; they do not measure cold application startup.
|
||||
- `npx vitest run src/main/magic-notes/magic-note-storage.test.ts src/main/assistant/assistant-database.test.ts src/main/assistant/assistant-storage-upgrade.test.ts src/main/assistant-storage-startup.test.ts tests/assistant-storage-worker.test.ts`
|
||||
passed 154 tests. Coverage includes failed media inspection, missing/invalid
|
||||
bodies, retained shared assets, revision mismatch recovery and migration.
|
||||
- Full `npm test`: 5382 passed, 84 skipped, 3 failed. The failures were the
|
||||
App question-round request wait and Electron note capture focus/layout waits.
|
||||
All three passed in targeted reruns; the full run was not all green.
|
||||
The capture rerun exercised production App/preload/IPC/SQLite and reopening.
|
||||
- `npm run typecheck` passed. Full lint still reports 10 errors in the existing
|
||||
untracked `sidebar-final-probe.ts` and `sidebar-final-run.mjs`; lint excluding
|
||||
those two files passed. No provider calls were made for these storage benchmarks.
|
||||
|
||||
## 2026-09-27: Shared Destructive Button Styles
|
||||
|
||||
The draft discard Portal now receives the global `danger-solid` styles. The
|
||||
shared rule also covers note deletion, HeartbeatSettings, SupervisorWorkspace,
|
||||
WorkspaceActionDialog and ToolEnvironmentSettingsSection without caller changes.
|
||||
Sizing, typography and disabled feedback share the primary/secondary button
|
||||
rules; theme tokens provide default and hover backgrounds. See
|
||||
[shared destructive controls](../../../UI-DESIGN.md#66-危险操作).
|
||||
|
||||
- `npm test -- tests/magic-notes-capture.electron.test.ts src/renderer/src/WorkspacePrimitives.test.tsx`
|
||||
passed 2 files / 37 tests. The real App/preload/IPC/SQLite capture test opens the
|
||||
draft guard outside the notes page ancestor. Both themes render a 36px-high,
|
||||
10px-radius button with the same font and padding as Continue editing. Native
|
||||
Tab reaches the visible shared focus ring; continuing editing retains the draft.
|
||||
- Hover uses Chromium `CSS.forcePseudoState`; disabled is set on the rendered
|
||||
button to check opacity, cursor and suppressed hover. These are CSS state
|
||||
checks, not verification of native pointer targeting or an asynchronous submit.
|
||||
Theme contrast checks include both default and hover backgrounds.
|
||||
- Windows Electron screenshots were captured and visually inspected for both
|
||||
themes with keyboard focus. Set `GB_CAPTURE_SCREENSHOT_DIRECTORY` to an existing
|
||||
directory to retain `draft-danger-light.png` and `draft-danger-dark.png`.
|
||||
Model calls: 0. Other callers and other OSes were not individually rendered.
|
||||
- `npm run typecheck` and `npm run lint` passed. Repository-wide
|
||||
`npm test -- --bail=1` stopped at the unrelated
|
||||
`HeartbeatCenter.test.tsx:213` assertion (expected one tablist, received two);
|
||||
this is not an all-green full-suite result.
|
||||
|
||||
## 2026-09-27: Analysis IPC Extraction
|
||||
|
||||
The three analysis handlers now live in `magic-notes-analysis-ipc.ts`, with
|
||||
the existing tracked registration injected at the original positions around
|
||||
note and todo CRUD. Model selection and lifecycle are documented in
|
||||
[Main IPC Ownership](./technical-design.md#main-ipc-ownership) and
|
||||
[Canvas Analysis and Comments](./technical-design.md#canvas-analysis-and-comments).
|
||||
No runtime factory, model-selection rule or Agent protocol changed.
|
||||
|
||||
- Before and after extraction, with `GB_NOTES_LIVE=0`:
|
||||
`npm test -- src/main/ipc.test.ts src/main/magic-notes src/preload/magic-notes-events.test.ts tests/magic-note-canvas-text.test.ts tests/magic-notes-analysis.electron.test.ts`
|
||||
passed 8 files, 232 tests, with 1 skipped (96.49s baseline, 97.90s after).
|
||||
Electron exercised vision and text-only analysis through production UI/preload/IPC
|
||||
with a local model stub; real provider calls for these checks: 0.
|
||||
- `npm run lint` passed. `npm run typecheck` stopped in the Node project with
|
||||
11 unrelated missing-`forwardLoopback` errors in `ssh-connection-pool.test.ts`,
|
||||
`ssh-host-directory-browser.test.ts` and `ssh-terminal-session.test.ts`.
|
||||
Separate `npx tsc --noEmit -p tsconfig.agent.json` and
|
||||
`npx tsc --noEmit -p tsconfig.web.json` passed.
|
||||
- A 120-second-bounded `npm test -- --bail=1` stopped after 94.45s:
|
||||
20 files passed, 1 failed; 1004 tests passed, 1 failed, 25 skipped.
|
||||
`RightAssistantSidebar.resize.test.tsx:387` expected two persisted terminal
|
||||
titles but received one. This was not a complete full-suite run, and the
|
||||
unrelated failure was not changed.
|
||||
- `git diff --check` passed with existing LF/CRLF warnings.
|
||||
|
||||
## 2026-09-26: Conversation Capture and Compact Notes Panel
|
||||
|
||||
- FR-1/FR-4: `notes` is an application-scoped optional singleton in the workbar.
|
||||
The compact panel supports title/body search, browsing, text appends and full
|
||||
workspace navigation. Quick notes uses the same tab; app enablement controls
|
||||
availability independently of sidebar pinning.
|
||||
- FR-2/FR-3: Assistant-message and conversation-header actions open editable text
|
||||
previews. Whole-conversation capture loads complete history. App owns drafts
|
||||
and selection; close, replacement and disable actions use the draft guard.
|
||||
Success focuses the returned entry ID; failed saves retain input.
|
||||
- FR-5: Schema 48 adds nullable source metadata. Main validates message ownership
|
||||
and resolves display labels at save time. Panel and workspace share source
|
||||
navigation, including missing-message and missing-conversation handling.
|
||||
- FR-6: Desktop search, preload/IPC and note-level SQL results are connected.
|
||||
Creating a note with initial content commits note/entry membership in one
|
||||
transaction. Both views use existing change notifications; file reconciliation
|
||||
and workspace optimistic revisions retain their existing boundaries. See
|
||||
[the implemented contract](./technical-design.md#conversation-integration).
|
||||
|
||||
Validation reported by implementation subagents in this session:
|
||||
|
||||
| Scope | Reported result | Evidence boundary |
|
||||
| --- | --- | --- |
|
||||
| Backend focused checks | 362 tests passed | Subagent handoff; not a repository-wide result |
|
||||
| Frontend focused checks | 8 files / 592 tests passed | Subagent handoff; not real Electron acceptance |
|
||||
| Web TypeScript and lint | Passed | Subagent handoff; does not establish full-repository typecheck/lint |
|
||||
|
||||
The coordinating agent subsequently reported real Electron acceptance passing.
|
||||
[magic-notes-capture.electron.test.ts](../../../tests/magic-notes-capture.electron.test.ts)
|
||||
and its [Main driver](../../../tests/support/magic-notes-capture-main.ts) /
|
||||
[renderer](../../../tests/support/magic-notes-capture-renderer.tsx) mount the real
|
||||
App UI and use production preload, registered IPC and SQLite/file storage.
|
||||
Unrelated services use test dependencies; the renderer bridge is not replaced.
|
||||
|
||||
- Saving an assistant response to an existing note retains its earlier entry;
|
||||
whole-conversation capture creates a new note with its first entry.
|
||||
- All 502 historical messages are compared verbatim in the preview and saved
|
||||
content, including history initially outside the rendered timeline.
|
||||
- Full-workspace navigation locates the exact saved entry; source navigation
|
||||
restores the conversation and focuses the source message. The coordinating
|
||||
agent also reports source-history expansion coverage.
|
||||
- Native Electron keyboard input covers returning to the list, opening a note
|
||||
and appending text in a measured 214px panel, without horizontal overflow.
|
||||
- SQLite close/reopen preserves both notes. Deleting the source conversation
|
||||
retains their saved content and source metadata. Model calls: **0**.
|
||||
|
||||
The combined Electron, `canvas-ipc.integration`, `MagicNotesPanel` and
|
||||
`ChatTimeline` run passed **4 files / 70 tests**. Lint and web TypeScript passed.
|
||||
This validates the App capture path in a test Electron window with isolated data;
|
||||
it does not establish release-package or cross-platform acceptance.
|
||||
|
||||
Repository validation and subsequent fixture repairs:
|
||||
|
||||
| Check | Result at execution time | Follow-up |
|
||||
| --- | --- | --- |
|
||||
| `npm test` | 457 files / 5,359 cases: 5,272 passed, 4 failed, 83 skipped | No all-green full-suite rerun reported |
|
||||
| Three schema-fixture failures | Activity-history and two worker fixture variants omitted `DROP COLUMN source_json` when reconstructing old schemas | Fixed; the five-file regression run below passed |
|
||||
| Remaining test failure | `tests/build-release.test.ts`: missing DSH resources | Unrelated to notes; not fixed in this validation pass |
|
||||
| Full-repository typecheck | Failed on parallel SSH mocks missing `forwardLoopback`, an IPC native-terminal fixture referencing undefined `terminalManager`, and mismatched arguments in `obsidian-runtime-acceptance` | Execution-time findings; later concurrent changes may alter them |
|
||||
|
||||
After fixture repairs, **5 files / 58 tests passed**:
|
||||
`src/main/assistant/activity-history-io.test.ts`,
|
||||
`tests/assistant-storage-worker.test.ts`,
|
||||
`src/main/assistant/assistant-storage-upgrade.test.ts`,
|
||||
`src/main/magic-notes/magic-note-storage.test.ts` and
|
||||
`src/main/magic-notes/canvas-ipc.integration.test.ts`.
|
||||
This focused rerun does not replace the failed full-suite/typecheck results.
|
||||
|
||||
Status: **implemented; real Electron acceptance passed; repository validation is
|
||||
not all green**. Results above come from the session handoffs, not a rerun by this
|
||||
documentation task. Later fixes require their own verification evidence; older
|
||||
Electron/full-suite results below do not validate this integration.
|
||||
|
||||
## 2026-09-24: Resizable Todo List and Collapsible Note Groups
|
||||
|
||||
- Todo list/detail uses a 1px divider with a transparent 9px pointer target and
|
||||
|
||||
@@ -1,7 +1,37 @@
|
||||
# Magic Notes Technical Design
|
||||
|
||||
## Main IPC Ownership
|
||||
|
||||
[magic-notes-ipc.ts](../../../src/main/magic-notes/magic-notes-ipc.ts) owns
|
||||
note search/list/get/create/update/delete, entry create/update/delete and todo
|
||||
list/status/update handlers, including conversation-source validation and entry
|
||||
content mapping. Its two registration functions receive the existing tracked
|
||||
`registerHandler`, window and database from [ipc.ts](../../../src/main/ipc.ts),
|
||||
preserving registration order: note CRUD, entry/draft analysis, todo CRUD, then
|
||||
todo analysis. [magic-notes-analysis-ipc.ts](../../../src/main/magic-notes/magic-notes-analysis-ipc.ts)
|
||||
owns the three analysis handlers through two registration functions. It receives
|
||||
the window, database, settings readers, usage persistence callback and existing
|
||||
error formatter; it imports `createDefaultModelRuntime` directly. `ipc.ts` retains
|
||||
tracked registration/removal and shared usage persistence.
|
||||
Sender checks and shared input schemas stay at each handler boundary.
|
||||
[rich-content.ts](../../../src/main/magic-notes/rich-content.ts) remains shared
|
||||
by CRUD and draft analysis. Analysis retains revision checks, hidden task status,
|
||||
stream events, error causes and nested release/dispose cleanup.
|
||||
|
||||
## Continuous Record Workspace
|
||||
|
||||
The outer workspace separates the persistent notes list from the detail container.
|
||||
The list defaults to 280px, resizes within 240-420px and stores `notesPaneWidth`
|
||||
and `notesPaneOpen` in `goodbuddy.magic-notes-layout.v1`. At workspace widths up to
|
||||
900px, selection replaces the visible list with detail while retaining the mounted
|
||||
list. The right-hand `magic-notes-detail` query container and its ResizeObserver
|
||||
measure the detail width for two breakpoints: at 800px or less the record index
|
||||
becomes a drawer while AI stays beside the editor; at 600px or less AI stacks
|
||||
below the stream. The 900px list/detail switch is driven by the same measured
|
||||
workspace width in both CSS class and React state, so the two cannot disagree.
|
||||
Per-note stream scroll positions live in a workspace-local map; explicit entry
|
||||
navigation takes precedence over reading-position restoration.
|
||||
|
||||
The detail mounts every entry in a continuous newest-first stream. The left index
|
||||
and AI source buttons scroll to an entry ID without changing the active editor,
|
||||
clearing a composer, flushing content or invoking the draft-switch guard. Opening
|
||||
@@ -49,22 +79,38 @@ content and streamed draft comments through the shared draft-analysis cleanup.
|
||||
The context counter rejects late results and prevents dispatch after abandoned
|
||||
settings preparation. This cleanup does not clear the new-entry composer's content.
|
||||
|
||||
The left index defaults to 168px and resizes from its right edge between 140px
|
||||
The left index is collapsed by default (`recordIndexOpen`, default `false`); when
|
||||
open it defaults to 168px and resizes from its right edge between 140px
|
||||
and 320px. It shares the AI pane's pointer-capture handlers, separator styling
|
||||
and keyboard semantics (16px arrow steps, Home/End limits). Both widths are
|
||||
stored in `goodbuddy.magic-notes-layout.v1`; missing index width defaults to
|
||||
168px. Displayed widths clamp together to reserve at least 300px for the stream,
|
||||
without overwriting saved widths when the window shrinks. The page header places
|
||||
the index toggle immediately after the back button, followed by the AI toggle.
|
||||
All three use icons and visible localized text; pane toggle labels reflect their
|
||||
current show/hide action. Collapsing hides the entire index and removes its grid column,
|
||||
border, resize separator and occupied width. AI has a separate
|
||||
right pane with its existing resize separator and header toggle. Both panes scroll
|
||||
independently and persist independent desktop visibility. At container widths of
|
||||
800px or less, the index defaults to hidden and the same header toggle opens or
|
||||
closes a fixed 168px drawer below the header, without reserving a rail or showing
|
||||
without overwriting saved widths when the window shrinks. The legacy
|
||||
`indexPaneOpen`/`aiPaneOpen` flags are ignored so existing users get the compact
|
||||
defaults once. With no note open the workspace renders only the list, full
|
||||
width, as a card grid (`magic-notes-workspace--overview`); the split layout
|
||||
(`--notes`) exists only while a note is open on a wide workspace. The page
|
||||
header shows the library switch in the overview and a labelled "Back to
|
||||
overview" button while a note is open. Note controls live in a sticky icon
|
||||
toolbar at the top of the stream (notes list, record index, entry count/updated
|
||||
time, AI). Collapsing hides the entire
|
||||
index and removes its grid column, border, resize separator and occupied width.
|
||||
|
||||
AI visibility is derived, not stored directly: `aiPaneOpen = aiPanePinned ||
|
||||
(hasAiActivity && dismissedNoteId !== detail.id)`, where activity means saved
|
||||
comments, draft analyses, or a running/streaming analysis. Hiding records the
|
||||
current note as dismissed and clears the pin; starting a new analysis clears the
|
||||
dismissal. Opening AI with no activity sets `aiPanePinned`, which is persisted.
|
||||
|
||||
The new-entry composer stays mounted. It collapses with CSS
|
||||
(`:not(.magic-note-composer--active):not(:focus-within)`) so drafts, focus
|
||||
management and the unsaved-draft guard are unchanged; `composerHasDraft` tracks
|
||||
non-empty text so a draft never collapses after blur. At container widths of
|
||||
800px or less, the index defaults to hidden and the same toolbar toggle opens or
|
||||
closes a fixed 168px drawer over the stream, without reserving a rail or showing
|
||||
an index resize separator; choosing
|
||||
an item or pressing Escape closes it. AI moves below the stream, limited to 40%
|
||||
an item or pressing Escape closes it. AI remains a resizable right column until the
|
||||
detail container is 600px or less, then moves below the stream, limited to 40%
|
||||
of layout height and 280px. Overview search, scroll, task selection and return
|
||||
focus stay mounted.
|
||||
|
||||
@@ -155,7 +201,12 @@ empty content. Failed creates leave no accepted database membership; their
|
||||
unaccepted files are removed on the next access or reopen.
|
||||
|
||||
After commit, reconciliation derives `note.json` from database membership and
|
||||
scans all retained entry files before removing unreferenced assets. Manifest or
|
||||
inspects all retained entry files before removing unreferenced assets. Startup
|
||||
repair reads each current body once to inspect its revision and collect asset
|
||||
references, then passes the complete per-note reference set to reconciliation.
|
||||
If media inspection fails, cleanup uses its existing deferred retry path rather
|
||||
than trusting a partial set. Revision mismatch recovery still hydrates the body;
|
||||
legacy conversion still verifies its written content. Manifest or
|
||||
GC failures log `console.warn` with the note ID and error and remain in an
|
||||
in-memory retry set. Later database access retries; reopening derives cleanup
|
||||
again from membership. These cleanup failures do not turn a committed save,
|
||||
@@ -252,7 +303,13 @@ Draft, saved-entry and todo analysis use the existing typed preload/IPC methods
|
||||
and `createDefaultModelRuntime`. Each canvas request reads the current default
|
||||
model profile's `supportsImageInput` (or the resolved default setting when no
|
||||
profile is selected). Main resolves settings again for the actual request. This
|
||||
does not change an Agent runtime or desktop-to-Agent protocol.
|
||||
does not change an Agent runtime or desktop-to-Agent protocol. All three handlers
|
||||
read global resolved settings per request, without applying chat/project runtime
|
||||
selection. The factory creates a tool-free direct `ModelAgentRuntime`, using the
|
||||
resolved default model connection and that profile's headers, body options and
|
||||
output limit. Environment-managed default credentials retain the settings store's
|
||||
environment overrides. The existing context-compression configuration can select
|
||||
a separate summary model; it does not select the main analysis model.
|
||||
|
||||
`magicNoteCanvasPageCount` is an application preference: an integer from 1 to 8,
|
||||
defaulting to 1 when absent in historical settings. The application center and
|
||||
@@ -346,8 +403,9 @@ objects and returns a function removing that listener. The existing
|
||||
|
||||
The overview's `libraryView` and the optional note-only `detailView` are independent:
|
||||
opening a todo's source note does not lose the originating task view.
|
||||
The overview remains mounted but hidden while detail is open, retaining scroll
|
||||
position and filters. Returning restores the initiating control's focus and
|
||||
The notes list remains visible beside detail on desktop unless collapsed. On
|
||||
narrow screens, or when opening a source note from To-dos, the originating list
|
||||
remains mounted but hidden, retaining scroll position and filters. Returning restores the initiating control's focus and
|
||||
invalidates outstanding detail requests. Initial loading fetches summaries and
|
||||
todos without selecting the first note or task. Navigation away from unsaved content or
|
||||
an unsaved title uses the existing draft confirmation; active writes finish
|
||||
@@ -407,7 +465,7 @@ Groups start expanded and can independently hide their mounted rows without
|
||||
clearing the selected detail. Collapse state lasts while the group is mounted.
|
||||
Note detail retains its existing AI pane preferences.
|
||||
|
||||
A single secondary button lives in `PageHeader.actions` before New note. Its
|
||||
A single secondary button lives in `PageHeader.actions` while note detail is closed. Its
|
||||
label and icon describe the destination, and `requestDraftSwitch` retains the
|
||||
existing draft guard. Focus returns to the same `magic-library-switch` button
|
||||
after switching. The overview section keeps its localized list `aria-label`;
|
||||
@@ -417,12 +475,15 @@ search in one wrapping toolbar.
|
||||
|
||||
Only note detail applies `magic-notes-layout--detail` to remove the layout frame
|
||||
and corner radius. Its stream pane has no extra padding; editor borders and the
|
||||
AI divider remain. Overview cards and the independent todo layout keep their
|
||||
existing frame and spacing. These changes do not affect Main, preload or storage.
|
||||
AI divider remain. The compact notes list and independent todo layout retain their
|
||||
own spacing. These changes do not affect Main, preload or storage.
|
||||
|
||||
## Note List Actions
|
||||
|
||||
Each overview card has an open-detail button and a sibling action-menu button. The menu
|
||||
Each notes-list row has an open-detail button and a sibling action-menu button,
|
||||
available while detail is open. Deleting the selected note passes through the
|
||||
existing draft guard; drafts clear only after deletion succeeds. Deleting another
|
||||
note retains current selection and drafts. The menu
|
||||
uses the conversation action styles and shared `DestructiveConfirmActions`, and
|
||||
is portalled to `document.body`. Its position follows the trigger on scrolling,
|
||||
window resizing and confirmation-size changes. Entering detail, filtering out the
|
||||
@@ -435,6 +496,58 @@ target ID and refreshes the overview after success, without opening another note
|
||||
These actions are available only in the overview. Database and Agent contracts
|
||||
are unchanged.
|
||||
|
||||
## Note Tags
|
||||
|
||||
Implements [FR-7 to FR-10](./prd.md#功能要求). Schema 51 adds two tables:
|
||||
|
||||
- `magic_note_tags(id, name, name_key UNIQUE, created_at, updated_at)`. `name_key`
|
||||
is the NFC-normalized, trimmed, lower-cased name, so `Work` and `work` share one
|
||||
row and the first spelling is kept.
|
||||
- `magic_note_tag_links(note_id, tag_id, position, created_at)` with a composite
|
||||
primary key and `ON DELETE CASCADE` on both sides. `position` keeps the order
|
||||
the user added tags in.
|
||||
|
||||
`magicNoteTagNameSchema` and `magicNoteTagListSchema` in
|
||||
`src/shared/magic-notes-contracts.ts` hold all name rules: collapse whitespace,
|
||||
1–24 characters, no commas, `#` or control characters; case-insensitive dedup;
|
||||
at most 10 per note. IPC and MCP inputs go through these schemas before reaching
|
||||
the database. The MCP tool schemas stay plain string arrays so the published
|
||||
JSON schema remains simple; the gateway normalizes them.
|
||||
|
||||
Database behavior (`AssistantDatabase`):
|
||||
|
||||
- Summaries carry `tags: string[]` via one `json_group_array` subquery shared by
|
||||
list, get and summary search. The summary search also matches tag names.
|
||||
- `updateMagicNote({ tags })` replaces the full list inside the same
|
||||
`BEGIN IMMEDIATE` transaction as the revision check, so a stale revision
|
||||
changes nothing. `createMagicNote` accepts initial tags.
|
||||
- Tags with no remaining links are deleted by the write that orphaned them
|
||||
(tag replacement and note deletion). `listMagicNoteTags()` returns only
|
||||
linked tags with `noteCount`, ordered by count then name.
|
||||
- `listMagicNotes({ tags })` is an AND filter on `name_key`.
|
||||
- `renameMagicNoteTag` updates the name, or merges when the new key belongs to
|
||||
another tag: links move with `INSERT OR IGNORE`, then the source tag is
|
||||
deleted. `deleteMagicNoteTag` removes the tag and its links. Both bump the
|
||||
revision and `updated_at` of every affected note so open editors do not save
|
||||
over the change, and both emit one `onMagicNotesChanged`.
|
||||
|
||||
IPC: `magic-notes:list` now returns `{ notes, tags }`; new channels
|
||||
`magic-notes:rename-tag` and `magic-notes:delete-tag`; `magic-notes:update`
|
||||
accepts `tags`. Preload exposes `renameTag` and `removeTag`.
|
||||
|
||||
Renderer: tag UI lives in `MagicNoteTags.tsx`. The workspace filters the loaded
|
||||
summaries on the client (AND by tag key, plus tag names in the search box), so
|
||||
filter changes do not refetch. Filter keys that no longer exist after a refresh
|
||||
are ignored; renaming a filtered tag carries the filter to the new key. Tag edits
|
||||
from the note header use the detail revision and `applyDetail`, so title and
|
||||
composer drafts are kept.
|
||||
|
||||
Agent tools: `note_create` and `note_update` accept `tags` (update replaces the
|
||||
list; `[]` clears it), `note_list` accepts a `tags` AND filter, and note
|
||||
summaries returned to tools include `tags`. Descriptions tell the model to change
|
||||
tags only when the user asks. The conversation capture panel does not edit tags
|
||||
in this version.
|
||||
|
||||
## Agent Search Contract
|
||||
|
||||
`note_search` accepts an integer `limit` from 1 to 100, defaulting to 8.
|
||||
@@ -445,10 +558,135 @@ The built-in MCP gateway returns invalid scoped-tool arguments as an
|
||||
the model to correct its arguments without an MCP internal-error response.
|
||||
Validation failures do not execute the tool.
|
||||
|
||||
Note tools can be authorized with the knowledge-base switch off. The shared
|
||||
desktop gateway binds authorization to each request, without a fixed elapsed-time
|
||||
expiry, so long-running requests retain tool access. Request completion,
|
||||
cancellation, failure cleanup, or gateway disposal revokes the token. Invalid or
|
||||
revoked tokens report unavailable tool authorization rather than a knowledge-base
|
||||
expiry error.
|
||||
|
||||
These note tools run in the desktop gateway. Remote gbagent ACP sessions
|
||||
currently inject only the image MCP server, so this change requires no
|
||||
daemon implementation update.
|
||||
|
||||
## Conversation Integration
|
||||
|
||||
The desktop API and renderer integration are implemented. Scope and behavior
|
||||
are owned by the [PRD](./prd.md), [logic design](./logic-design.md) and
|
||||
[UI design](./ui-design.md). Real Electron acceptance passed; focused results,
|
||||
fixture repairs and non-green repository checks are recorded in [progress](./progress.md).
|
||||
|
||||
### Workbar and Capture
|
||||
|
||||
`WORKBAR_APP_DEFINITIONS` registers `notes` as an optional, closable, reorderable
|
||||
singleton with application scope, no `targetRef` and `defaultOpen: false`.
|
||||
`RightAssistantSidebar` opens or activates it through the existing
|
||||
[workbar tab model](../assistant-workbar/terminal-tabs-prd.md), and removes it when
|
||||
Magic Notes is disabled. Sidebar pinning does not control this availability.
|
||||
`MagicNotesPanel` renders the compact view; `WorkbarShell` supplies the shared tab
|
||||
controls. The footer shortcut and collapsed-sidebar chat-header shortcut both
|
||||
activate the same instance.
|
||||
|
||||
`App.captureToNote` receives the message identity from `ChatTimeline`, or calls
|
||||
`ensureConversationHistory` for whole-conversation capture. It freezes text and
|
||||
source IDs before opening the preview and waits for queued conversation persistence
|
||||
so Main can validate newly completed messages. Whole-conversation text includes
|
||||
nonempty user/assistant bodies with role headings. It excludes reasoning, tool
|
||||
logs and attachment binaries, and rejects streaming conversations.
|
||||
|
||||
`useMagicNoteDraft` lives in App and owns the draft, selected note, saving state
|
||||
and one shared confirmation promise. Selection and drafts survive panel remounts
|
||||
and conversation/project switches, but are not persisted across app restarts.
|
||||
The guard rejects leaving while saving and confirms discarding pending input;
|
||||
explicit cancellation compares text/title with their initial preview values.
|
||||
Application disablement and tab closing call the same guard. Workspace navigation
|
||||
also passes through the full workspace's existing leave check.
|
||||
|
||||
`capturedNoteContent` converts text into v1 Quill string inserts, preserving
|
||||
newlines and adding the terminal newline when needed. It splits inserts at the
|
||||
200,000-code-unit operation limit without splitting surrogate pairs; the complete
|
||||
record still passes the shared rich-content schema. Markdown stays literal text.
|
||||
No summarization or attachment copying runs during capture. New-note titles are
|
||||
limited to 100 characters. A synchronous submission ref prevents duplicate writes.
|
||||
|
||||
`magicNotes.create({ title, content?, source? })` returns `MagicNoteCreateResult`,
|
||||
with `createdEntryId` when initial content exists. `createMagicNote` inserts the
|
||||
note, first entry, source and derived todos inside one SQLite transaction; failure
|
||||
leaves no committed empty note and sends no success notification. This atomicity
|
||||
applies to database membership; filesystem writes retain the reconciliation
|
||||
boundary in [File Storage and Writes](#file-storage-and-writes).
|
||||
`magicNotes.createEntry({ noteId, content, source? })` always returns the exact
|
||||
`createdEntryId`. The panel uses that ID to scroll, focus and briefly highlight the
|
||||
new record. Opening the full workspace passes `{noteId, entryId?, requestId}` into
|
||||
its existing guarded note-navigation path.
|
||||
|
||||
`magicNotes.search({ query, limit? })` is exposed by `DesktopApi`, preload and
|
||||
`magic-notes:search`. Trusted-sender and shared-schema validation precede
|
||||
`AssistantDatabase.searchMagicNoteSummaries`. The trimmed query has a 1,000-character
|
||||
limit; result limits are 1-200, defaulting to 200. The panel requests 100 results
|
||||
and debounces nonempty queries by 180 ms. SQL searches note titles or indexed entry
|
||||
text using `EXISTS`, so each note occurs once before `LIMIT`. Empty queries list
|
||||
notes; ordering is pinned first, then updated time and row ID descending.
|
||||
`%`, `_` and backslashes are escaped for literal matching. Agent `note_search`
|
||||
retains its separate entry-level output and 1-100 limit.
|
||||
|
||||
### Source Metadata
|
||||
|
||||
`magicNoteSourceSchema` defines `kind` (`message` or `conversation`),
|
||||
`conversationId`, nonempty unique `messageIds`, ISO `capturedAt`,
|
||||
`conversationTitle`, and optional `projectId` / `projectName`. A message source
|
||||
requires exactly one message ID. Create/create-entry inputs accept `source`;
|
||||
note creation requires initial content when source is supplied. Entry reads
|
||||
return it independently of editable content, while update inputs cannot replace it.
|
||||
|
||||
The IPC helper `resolveMagicNoteSource` loads the stored conversation and verifies
|
||||
that every message ID belongs to it; a single-message source must identify an
|
||||
assistant message. It replaces renderer-supplied title/project labels with current
|
||||
database values while retaining the supplied capture time and IDs. Preview labels
|
||||
therefore describe capture time, but stored labels describe save time. Missing
|
||||
source rows reject creation; later source deletion does not block note reads or edits.
|
||||
|
||||
Schema 48 adds nullable `magic_note_entries.source_json` in a transaction and
|
||||
advances `PRAGMA user_version`. Existing entries read without a source. It adds no
|
||||
conversation foreign key or deletion cascade, and does not rewrite file-backed
|
||||
bodies. Schema 38 remains the historical body migration. Structure-only upgrade
|
||||
does not independently trigger body conversion or VACUUM; see the
|
||||
[database migration guide](../../development/database-migrations.md). Coordinated
|
||||
SQLite/files backups include the source metadata.
|
||||
|
||||
`MagicNoteSource` is shared by panel summaries and workspace records. Its callback
|
||||
`App.openNoteSource` reads `conversations.get`, then navigates through the workspace
|
||||
leave guard. Message navigation increases the mounted timeline range before
|
||||
scrolling and focusing. A missing message opens its conversation with a notice;
|
||||
a confirmed missing conversation disables that source bar's jump buttons. Other
|
||||
read errors remain retryable. No deleted-source flag is stored.
|
||||
|
||||
### Refresh and Validation
|
||||
|
||||
Both views use the same Main store and `magic-notes:changed` notification. The
|
||||
panel reloads search and selected detail when active, and ignores superseded
|
||||
responses. Search/loading state belongs to the mounted panel; input and selected
|
||||
note belong to App. A deleted selected note clears the selection and matching
|
||||
target ID while preserving draft text. Read and save failures have local recovery
|
||||
feedback. The full workspace retains its existing revision and dirty-editor rules.
|
||||
|
||||
After a successful save, only `after-save-auto` starts entry analysis using the
|
||||
returned `createdEntryId` and configured comment format. Analysis errors notify
|
||||
without undoing the save or recreating the entry. Other comment modes perform no
|
||||
panel analysis.
|
||||
|
||||
Regression cases are in `MagicNotesPanel.test.tsx`, `App.test.tsx`,
|
||||
`ChatTimeline.test.tsx`, `MagicNotesWorkspace.test.tsx`, workbar contract tests,
|
||||
database/storage tests and production preload/IPC integration tests.
|
||||
`tests/magic-notes-capture.electron.test.ts` mounts the real App with production
|
||||
preload and capture IPC, backed by SQLite/files. It validates existing/new-note
|
||||
saves, verbatim 502-message history, workspace/source navigation, native keyboard
|
||||
input in a narrow panel, database reopen and retention after source deletion,
|
||||
with zero model calls. Failed writes and external refresh retain their focused
|
||||
regression coverage; this Electron result does not claim every failure path.
|
||||
Repository test/typecheck failures and repaired migration fixtures are documented
|
||||
separately in [progress](./progress.md).
|
||||
|
||||
## Validation
|
||||
|
||||
- `magic-note-storage.test.ts` uses real files and SQLite for migration equality,
|
||||
@@ -476,6 +714,6 @@ daemon implementation update.
|
||||
coverage includes portal placement, keyboard navigation, dismissal, delete
|
||||
confirmation, target selection, revision failures and draft preservation.
|
||||
|
||||
Schema 38 and the file layout above govern current persistence; refresh
|
||||
Schema 48 adds source metadata to the schema 38 file-backed body layout; refresh
|
||||
notifications need no separate storage or network service. Dated validation
|
||||
results and remaining repository checks are owned by [progress](./progress.md).
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# 会话联动界面设计
|
||||
|
||||
状态:已接入前端,真实 Electron 验收通过;全仓验证未全绿,结果见 [progress.md](./progress.md)。遵循根目录 [UI-DESIGN.md](../../../UI-DESIGN.md),需求和行为分别由 [PRD](./prd.md) 与 [逻辑设计](./logic-design.md)定义。独立工作区布局继续由根文档 13.7 节维护。
|
||||
|
||||
## 入口
|
||||
|
||||
| 位置 | 文案与动作 |
|
||||
| --- | --- |
|
||||
| 助手工作栏“+”菜单 | 增加“笔记”,打开或激活单个笔记 Tab。 |
|
||||
| 助手消息底部,复制旁 | 图标按钮“加入笔记”,进入该消息的采集预览。 |
|
||||
| 会话标题更多菜单 | “保存当前对话到笔记”,加载完整历史后进入整段采集预览;生成、采集加载或保存期间禁用。 |
|
||||
| 面板笔记标题旁 | “在完整工作区打开”,进入当前笔记;有待保存文字时先处理草稿。 |
|
||||
|
||||
左侧主导航中的“魔法笔记”继续打开独立工作区。紧凑面板通过工作栏“+ → 笔记”打开,左侧底部和聊天页头不再提供重复的“快速笔记”入口。
|
||||
|
||||
## 紧凑面板
|
||||
|
||||
面板按单列显示列表或笔记详情,不嵌入完整工作区的多栏布局。搜索位于列表顶部,“新建笔记”在列表之后;笔记行显示标题、置顶状态、两行摘要和更新时间。无笔记时提供新建动作;搜索无结果时保留搜索词并允许创建。
|
||||
|
||||
详情顶部提供返回列表、笔记标题和打开完整工作区,不显示“全局”标识。中间以可滚动记录摘要供浏览,每条文字摘要最多显示前 600 个字符,画布显示首页缩略图及页数;记录按钮可在完整工作区定位该记录。底部提供快速追加文字输入区与“加入笔记”按钮,画布编辑、待办管理和 AI 评论阅读仍在完整工作区。
|
||||
|
||||
从会话触发时,面板切到采集编辑视图:
|
||||
|
||||
```text
|
||||
加入笔记
|
||||
来自:项目 / 会话标题 · 单条回答或当前对话
|
||||
来源旁帮助按钮:按需查看保存范围
|
||||
|
||||
[可编辑文字预览]
|
||||
|
||||
保存到
|
||||
[搜索或选择已有笔记]
|
||||
[新建笔记 → 标题输入]
|
||||
|
||||
[取消] [加入笔记]
|
||||
```
|
||||
|
||||
范围说明随单条或整段来源调整,通过来源旁的 `InlineHelp` 按需查看;回答未完成的警告仍直接显示。预览初始包含完整待保存文字,可滚动编辑。新建目标标题默认取会话标题前 100 个字符,可修改;已有目标与新建目标使用共享 `SegmentedControl` 切换。采集内容为空或超限、缺少目标、新建标题为空或超限时禁用保存;初始不显示通用校验说明,正文和标题超限时在对应字段旁提示。普通新建允许创建空笔记。
|
||||
|
||||
底栏默认仅显示右对齐的操作按钮。保存失败时保留草稿,错误与按钮在宽面板中同行,窄面板中错误换行、按钮仍靠右。完整工作区的文字保存按钮在窄窗口中也保持内容宽度并右对齐。
|
||||
|
||||
预览和快速追加输入框通过无障碍名称“待加入内容”标识,不再显示重复标签。提交区仅显示校验或保存错误,不显示“全局”。提交与来源跳转按钮组均居右,可在窄面板换行;来源没有项目名时省略项目及分隔符,不补写“全局”。
|
||||
|
||||
读取失败显示就地重试按钮;保存失败保留输入并在提交区显示错误,用户可再次点击“加入笔记”。成功通过应用通知反馈,切回目标笔记详情,滚动定位、聚焦并高亮新增记录约 2.4 秒。仅“保存后自动评论”模式发起后续分析,分析失败另行通知,已保存内容保留。
|
||||
|
||||
## 来源与可访问性
|
||||
|
||||
记录摘要和完整工作区的已保存记录均显示“来自会话”来源条,内容含保存时标题、项目及采集时间。单条来源提供返回会话和定位原消息按钮,整段来源提供返回会话按钮。点击后确认原会话不存在才显示对应文案并禁用跳转;其他错误提供就地重试。来源条与正文分开,编辑正文时仍可识别来源。
|
||||
|
||||
Tab 使用工作栏现有的共享页签、焦点和关闭模式。搜索有持久标签,列表用可键盘访问的按钮;打开采集后聚焦预览,取消返回触发按钮,触发按钮已不可见时尝试返回会话标题菜单按钮。新建标题出现后聚焦输入框。面板中的 Escape 取消当前草稿,或从详情返回列表;需要放弃输入时先显示草稿确认。确认框初始聚焦“继续编辑”,限制 Tab 焦点范围,Escape 保留草稿并关闭确认。
|
||||
|
||||
面板服从工作栏现有宽度和停靠规则,以单列切换列表、详情和采集编辑。按钮组可换行,文字摘要保留换行并折行长文本;Markdown 和代码以原始文字显示。头部与快速追加区固定,中间内容独立滚动;完整预览输入区可纵向调整大小。配色、按钮、焦点环、通知和确认使用共享组件与令牌。真实 Electron 已在实测 214px 面板验证无横向溢出,以及原生键盘返回列表、打开笔记和追加保存。
|
||||
@@ -10,6 +10,7 @@ Provider 要求的附加元数据;GoodBuddy 只在直连链路或 Runtime 明
|
||||
| --- | --- |
|
||||
| [UI 设计](./ui-design.md) | 编辑入口、校验反馈、兼容性说明和无障碍行为 |
|
||||
| [技术设计](./technical-design.md) | 契约、持久化、合并优先级、Runtime 支持矩阵和验证 |
|
||||
| [执行方式与模型选择](./runtime-selection-design.md) | 会话/项目/全局分层解析、选择器行为、存储迁移、全局 `provider` 移除计划和用途模型规划 |
|
||||
| [功能进度](./progress.md) | 已验证实现、剩余工作和验证证据 |
|
||||
|
||||
模型连接选择准确性也在本目录维护:技术设计第 8 节定义通道直连回退修复,
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
# 模型连接请求定制进度
|
||||
|
||||
## 2026-09-29:执行方式与模型分层选择
|
||||
|
||||
设计见[执行方式与模型选择设计](./runtime-selection-design.md)。
|
||||
|
||||
### 已完成(未提交)
|
||||
|
||||
- 共享选择层契约、`resolveRuntimeChoice` 分层解析及失效回退;移除 `auto`。
|
||||
- 数据库版本 49 迁移旧选择形状;连接删除后清理所有项目和会话的失效引用。
|
||||
- Main 每次请求按会话层、项目层重新解析,不回写会话;排队输入在派发时重新解析。
|
||||
- 项目设置 `ProjectRuntimeSelector`(本地、远程、通道共用),输入框两栏
|
||||
`RuntimeModelPicker`;系统设置恢复各 Runtime 页签的默认模型选择。
|
||||
- 选择器修复:模型列不再与底栏重叠,长名称单行截断;“管理模型连接…”直接打开模型连接分类。
|
||||
|
||||
### 已验证
|
||||
|
||||
- `npm run typecheck` 与相关文件 eslint 通过。
|
||||
- Main、Shared、Daemon 测试集通过;`App.test.tsx` 与 `WorkspacePrimitives.test.tsx`
|
||||
350 项中 349 项通过,唯一失败为既有不稳定用例“renders, saves and reloads OpenCode
|
||||
answers across question rounds”,单独运行通过。
|
||||
|
||||
### 待办
|
||||
|
||||
- 在运行中的应用里目测两栏选择器(窄窗口、深色主题、长名称)。
|
||||
- 移除全局 `provider`,见[设计第 6 节](./runtime-selection-design.md#6-全局-provider历史遗留待移除)。
|
||||
- 用途模型,见[设计第 7 节](./runtime-selection-design.md#7-用途模型规划未实现)。
|
||||
|
||||
|
||||
## 2026-09-27:窄容器协议显示
|
||||
|
||||
连接管理布局改用命名容器查询,不超过 `640px` 时列表和表单上下排列;移除原先仅在
|
||||
窗口不超过 `720px` 时切换的规则。LLM、向量连接及角色编辑共用同一布局样式。
|
||||
Windows Electron 验证覆盖 `680/720/721/740/960/1180px` 窗宽、短窗口、中英文及浅深
|
||||
主题;另在 `1180px` 窗口中单独缩窄设置面板,确认布局由实际容器宽度决定。
|
||||
协议文字完整、表单无横向溢出,原生 Tab 与方向键可选择并还原协议。没有保存配置或发送
|
||||
模型请求。验证命令、截图说明和未测范围见
|
||||
[窄容器布局修复记录](../../quality/responsive-controls-review-2026-09-27.md)。
|
||||
|
||||
## 2026-09-20:模型设置可用性修复
|
||||
|
||||
- 模型接口 URL 保存失败时按连接名称显示错误,URL 字段同步提供 `aria-invalid` 和就地
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
# 执行方式与模型选择设计
|
||||
|
||||
本文件是执行方式(Runtime)与模型选择的唯一权威说明,覆盖分层解析、各入口的界面
|
||||
行为、存储迁移,以及尚未实现的“用途模型”规划。连接本身的请求定制见
|
||||
[技术设计](./technical-design.md),DeepSeek Harness 的平台来源解析见
|
||||
[Harness 技术设计](../deepseek-harness/technical-design.md#121-配置来源)。
|
||||
|
||||
## 1. 术语
|
||||
|
||||
| 术语 | 定义 |
|
||||
| --- | --- |
|
||||
| 执行方式 | `provider`:`model`(直连模型)、`opencode`、`continue`、`deepseek-harness` |
|
||||
| 模型选择 | `{ kind: 'profile', profileId }` 或 `{ kind: 'runtime-config' }`(Runtime 自有配置) |
|
||||
| 选择层 | `RuntimeSelectionLayer = { provider?, model? }`,两个字段都可缺省 |
|
||||
| 全局默认模型 | 每个执行方式在“系统设置”中的默认模型:直连用 `defaultModelProfileId`,其余用 `opencodeModelSource` / `continueModelSource` / `deepseekHarnessModelSource` |
|
||||
| 具体选择 | 解析结果 `AgentRuntimeSelection`,包含确定的 `provider`,以及 `profileId` 或 `runtimeConfig: true` 之一 |
|
||||
|
||||
## 2. 分层与优先级(已实现)
|
||||
|
||||
选择按“会话 → 项目 → 全局”逐字段解析,入口为共享函数 `resolveRuntimeChoice`
|
||||
(`src/shared/runtime-selection-contracts.ts`):
|
||||
|
||||
1. **执行方式**:会话层 `provider` → 项目层 `provider` → 全局兜底(见第 6 节)。
|
||||
2. **模型**:只继承与最终执行方式一致的层。会话单独切换执行方式时,丢弃会话层模型,
|
||||
沿用项目层(若项目执行方式相同)或该执行方式的全局默认模型。
|
||||
3. 结果附带 `providerSource` / `modelSource`(`global`、`project`、`conversation`),
|
||||
界面据此显示来源标记。
|
||||
|
||||
失效处理:
|
||||
|
||||
| 所选模型状态 | 行为 |
|
||||
| --- | --- |
|
||||
| 可用 | 使用 |
|
||||
| `unavailable`(缺少 API Key) | 保留选择;运行时明确报告缺少凭据,不静默换模型 |
|
||||
| `missing`(连接已删除) | 回退到下一层,并在选择器中提示回退原因 |
|
||||
| `incompatible`(协议或能力不匹配) | 同上 |
|
||||
|
||||
- 图像生成连接只对直连模型有效,且永远不作为回退默认值。
|
||||
- 远程项目只允许 OpenCode 与 Continue;其他执行方式按 `provider` 原因回退。
|
||||
- 全局 `defaultModelProfileId` 为空时解析为 `{ provider: 'model' }`,不生成空 `profileId`。
|
||||
- 不存在 `auto`。旧 `{ provider: 'auto' }` 在读取和 IPC 入口处去除,按上述顺序解析。
|
||||
|
||||
## 3. 各入口行为(已实现)
|
||||
|
||||
### 3.1 项目设置
|
||||
|
||||
本地、远程和通道项目共用 `ProjectRuntimeSelector`:
|
||||
|
||||
- “执行方式”必选,没有“继承”选项;保存时总是写入具体 `provider`
|
||||
(`ProjectSwitcher` 的 `withProjectProvider`、`ChannelProjectSettingsFields` 的
|
||||
`channelProjectDraft`)。
|
||||
- “模型”默认项为“跟随 xx 默认(…)”,其余为该执行方式可用的连接及“使用 xx 自有配置”。
|
||||
- 新建会话跟随项目,不再提供“默认执行方式”四选一。
|
||||
|
||||
### 3.2 输入框选择器
|
||||
|
||||
`RuntimeModelPicker` 为两栏菜单:左栏执行方式,右栏当前高亮执行方式的模型。
|
||||
|
||||
- 选择只写入会话层;左栏选择与项目相同的执行方式时写入 `undefined`,保持继承。
|
||||
- 右栏首项为“默认(…)”,带来源标记(全局 / 项目);已删除或不兼容的连接禁用,缺少
|
||||
API Key 的连接可选并标注。
|
||||
- 会话存在单独选择时,底栏显示“本会话单独选择”和“恢复为项目默认”;输入区按钮不在图标与 Runtime 名称之间添加圆点。
|
||||
- 模型列按最长列表预留高度,悬停切换执行方式时菜单不跳动;列内超出部分滚动,底栏
|
||||
固定在两栏下方。长名称单行截断,完整名称和模型 ID 通过 `title` 与可访问名称提供。
|
||||
- “管理模型连接…”打开“设置 → 模型连接”。
|
||||
- 键盘:左右键在两栏间切换,上下 / Home / End 在栏内移动,Esc 关闭并还焦点。
|
||||
|
||||
### 3.3 系统设置
|
||||
|
||||
“设置 → Agent Runtime”按 OpenCode / Continue / DeepSeek Harness 页签分别选择各自的
|
||||
全局默认模型;直连模型的默认值在“模型连接”中设置。设置页没有“全局执行方式”控件。
|
||||
|
||||
## 4. 执行时解析(已实现)
|
||||
|
||||
- Main 的 `resolveStoredRuntimeSelection` / `resolveLayeredRuntimeSelection` 在每次请求时
|
||||
读取会话层与项目层重新解析,不把解析结果回写到会话记录。
|
||||
- 排队的输入在真正派发时重新解析,不使用入队时的快照。
|
||||
- 定时任务的选择在创建时冻结在任务上;运行时优先任务选择,再到项目层。
|
||||
- 远程事件的 context metrics 按本次请求实际使用的具体选择记录
|
||||
(`remoteEventSelection`);未传入时数据库按会话层、项目层解析,缺省执行方式为
|
||||
OpenCode。
|
||||
|
||||
## 5. 存储与迁移(已实现)
|
||||
|
||||
- `projects.runtime_selection_json` 与 `conversations.runtime_selection_json` 保存紧凑
|
||||
的选择层;空层保存为 `NULL`。
|
||||
- 数据库版本 49(`migrateRuntimeSelectionLayers`)把旧的 `{ provider, profileId }` 和
|
||||
`{ provider: 'auto' }` 改写为选择层;读取时 schema 预处理也会升级旧形状。
|
||||
- `repairConversationRuntimeSelections` 在连接被删除后清除所有项目与会话中的失效
|
||||
`profileId`。
|
||||
- 通道项目创建为 `{ provider: 'model' }`;SSH 项目允许不保存选择。
|
||||
|
||||
## 6. 全局 `provider`(历史遗留,待移除)
|
||||
|
||||
`RuntimeSettings.provider` 来自项目层出现之前的“全局执行方式”。它已没有设置界面,
|
||||
但仍在以下位置被读取:
|
||||
|
||||
| 位置 | 用途 |
|
||||
| --- | --- |
|
||||
| `resolveRuntimeChoice` 的 `normalizedGlobalProvider` | 项目和会话都没有 `provider` 时的兜底(旧数据、无项目的状态查询) |
|
||||
| `getConfiguredRuntimeTarget` → `createConfiguredRuntime`(`src/main/index.ts`) | 启动和设置变更时创建默认 Runtime;监督者回顾、无唯一项目的心跳等不带项目的请求使用它 |
|
||||
| `runtime-settings-store.ts` | 归一化、`auto` → `model` 迁移和写回 |
|
||||
| `SettingsPanel` | 无界面地读入并原样保存 |
|
||||
|
||||
结论:该字段不应继续作为用户概念存在。移除方案与第 7 节一起实施:
|
||||
|
||||
1. 启动修复为所有 `provider` 为空的项目写入当时解析出的具体执行方式。
|
||||
2. 兜底固定为 `model`;默认 Runtime 固定为直连模型。
|
||||
3. 设置输入和公开设置不再包含 `provider`;存储保留该字段只用于读取旧文件,不再写入。
|
||||
|
||||
## 7. 用途模型(规划,未实现)
|
||||
|
||||
### 7.1 问题
|
||||
|
||||
后台功能各自隐式决定模型,用户无法控制,也无法从界面得知:
|
||||
|
||||
| 用途 | 当前行为 | 是否需要工具 |
|
||||
| --- | --- | --- |
|
||||
| 监督者回顾与整理 | 全局 `provider` 对应的默认 Runtime 与模型 | 否,工具调用被拒绝 |
|
||||
| 心跳报告 | 单一项目时跟随项目,否则同上 | 否 |
|
||||
| Magic Notes 分析 | 直连默认模型连接 | 否 |
|
||||
| 知识图谱抽取 | 直连默认模型连接(HTTP) | 否 |
|
||||
| 上下文压缩 | 已有 `contextCompression.modelSource`(当前模型 / 指定连接) | 否 |
|
||||
| 子代理 | 直连模型,可按专家覆盖 | 是,保持现状 |
|
||||
| 定时任务 | 任务或项目选择 | 是,保持现状 |
|
||||
|
||||
### 7.2 决策
|
||||
|
||||
- 用途只选择**模型连接**,统一走直连模型,不提供执行方式选择。上述用途都是无工具的
|
||||
文本请求,为其启动 OpenCode / Continue / DeepSeek Harness 只增加延迟、成本和故障面。
|
||||
- 每个用途的取值为“跟随默认模型”或一个文本模型连接;图像连接不可选。
|
||||
- 需要工具的子代理和定时任务不纳入本设置。
|
||||
|
||||
### 7.3 范围
|
||||
|
||||
“设置 → 模型连接”新增“用途模型”小节,包含:
|
||||
|
||||
- 监督者回顾与整理
|
||||
- 心跳报告(无唯一项目时)
|
||||
- Magic Notes 分析
|
||||
- 知识图谱抽取
|
||||
- 上下文压缩(迁入现有 `contextCompression.modelSource`,语义不变)
|
||||
|
||||
### 7.4 解析与失效
|
||||
|
||||
- 解析:用途设置的连接 → 全局 `defaultModelProfileId`。
|
||||
- 连接被删除:设置修复为“跟随默认模型”,与第 5 节的失效清理一致。
|
||||
- 连接缺少 API Key:保留选择,运行时明确失败,不静默改用默认模型。
|
||||
- 心跳在有唯一项目时仍跟随项目选择;用途设置只替代原先的全局兜底。
|
||||
|
||||
### 7.5 待定
|
||||
|
||||
- 设置字段形状(建议 `purposeModels: Record<Purpose, { kind: 'default' } | { kind: 'profile', profileId }>`)
|
||||
与设置文件版本号。
|
||||
- `contextCompression.modelSource` 的 `current`(跟随当前会话模型)是否保留为压缩用途
|
||||
专有的第三个选项。
|
||||
- 监督者模型并发(`supervisorModelConcurrency`)是否与所选连接绑定显示。
|
||||
@@ -125,3 +125,25 @@ Main 的 `toPublicSettings` 复用 `resolveDeepSeekHarnessModelProfile`,只在
|
||||
`source: 'profile'` 描述来源分支,不代表凭据来源:仅环境密钥或旧环境变量可能仍影响该
|
||||
GoodBuddy 连接,但不会被误报为完整管理员预置。连接解析不代替真实模型请求或可用性测试。
|
||||
UI 的未保存兼容候选只作草稿预览,保存后继续以 Main 返回的投影为准。
|
||||
|
||||
## 10. Settings IPC Ownership
|
||||
|
||||
[model-settings-ipc.ts](../../../src/main/model-settings-ipc.ts) registers the
|
||||
11 model/runtime settings handlers: public settings, customization reads and
|
||||
updates, native inventory, settings updates, workspace/file selection, runtime
|
||||
detection, config actions, and model/runtime connection tests. It owns sender
|
||||
checks, shared schema parsing, config-file metadata, and activation rollback.
|
||||
|
||||
[ipc.ts](../../../src/main/ipc.ts) calls this registrar at the original position
|
||||
and retains tracked registration, the shared settings-update queue, runtime
|
||||
activation, conversation-selection repair, and project execution-space resolution.
|
||||
These operations are injected as narrow callbacks. Runtime activation still
|
||||
cancels affected expert-team requests; failed activation restores the previous
|
||||
settings and reactivates them before the next queued update can run. Cleanup waits
|
||||
for the tracked handler promises. Usage recording, runtime refresh subscriptions,
|
||||
and runtime/Agent lifecycle ownership remain in the composition root.
|
||||
|
||||
The integration tests in [ipc.test.ts](../../../src/main/ipc.test.ts) exercise the
|
||||
production registrar through `registerIpcHandlers`, including registration order,
|
||||
trusted senders, serialized updates, rollback failures, cleanup waiting for reload,
|
||||
native inventory resolution, and connection/config actions.
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
`aria-invalid` 并关联就地错误,避免只显示无法定位的“Invalid URL”。
|
||||
- LLM 模型连接的分类标题和模型类型分段页签在内容滚动时共同粘附在内容区顶部;左侧连接
|
||||
列表仍可独立滚动。
|
||||
- 连接列表和编辑表单按自身容器宽度切换左右或上下排列,断点及列表滚动上限遵循
|
||||
[设置中心布局规则](../../../UI-DESIGN.md#138-设置中心)。窄窗口中收起的接口协议选择框
|
||||
保留完整中英文当前值,不能依赖展开选项才能辨认协议。
|
||||
- 每个已保存或正在编辑的 LLM 连接提供“复制连接”。复制会生成新的连接名称和 ID,保留
|
||||
地址、模型、协议、请求定制、认证方式及当前草稿 API Key。已保存的 API Key 通过 Main
|
||||
进程的加密凭据复制路径保存,不回传到 Renderer;原连接和默认连接不改变。
|
||||
@@ -49,10 +52,9 @@ OpenCode 与 DeepSeek Harness 不使用该值。
|
||||
|
||||
## 会话与项目 Runtime 选择
|
||||
|
||||
会话与项目选择器只提供直连模型和各 Runtime 入口,不再枚举每个 Runtime 与每个模型的
|
||||
组合;Runtime 模型在系统设置中配置。已保存的固定 Runtime 模型选择继续保留,项目
|
||||
选择器的选项与帮助文字均显示其固定模型,不能误报为跟随全局设置;用户可选择普通
|
||||
Runtime 入口恢复跟随。该展示规则不改变模型解析、远程 Agent 协议或执行权限。
|
||||
项目设置分“执行方式”和“模型”两个字段,输入框使用两栏选择器,全局默认模型仍在系统
|
||||
设置中按 Runtime 页签配置。分层规则、选择器状态、键盘行为和失效提示由
|
||||
[执行方式与模型选择设计](./runtime-selection-design.md#3-各入口行为已实现)唯一维护。
|
||||
|
||||
## Harness 模型来源展示
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Obsidian 本机仓库接入
|
||||
|
||||
GoodBuddy 通过内置 MCPVault 访问本机 Obsidian 仓库,供会话读取、搜索和修改笔记。功能默认关闭;默认范围为本机已注册的全部仓库,也可指定一个文件夹。接入直接访问本地文件,不要求 Obsidian 正在运行或安装插件。
|
||||
|
||||
当前源码已实现主服务、设置 IPC、HTTP 网关和直连工具提供器。自动化覆盖 19 个共享工具;Windows 真实 Electron 设置操作、原生目录对话框取消、键盘开关、浅深主题窄窗口,以及 OpenCode / Continue 从聊天输入框发起的实际笔记读写均已通过。Windows x64 解包应用也通过设置到随包 MCPVault 的连接与保存验证,测试限制了子进程 Node 网络 API 和 Chromium 代理。物理断网、安装器及其他目标系统仍待验收;命令、模型调用次数和全量检查阻塞见[进度](./progress.md)。
|
||||
|
||||
## 文档职责
|
||||
|
||||
| 文档 | 唯一职责 |
|
||||
| --- | --- |
|
||||
| [产品需求](./prd.md) | 用户问题、范围、稳定需求 ID 和产品验收 |
|
||||
| [用户故事](./user-stories.md) | 使用场景及 Given/When/Then 验收 |
|
||||
| [功能逻辑](./logic-design.md) | 范围决策、状态转换、失败和取消规则 |
|
||||
| [技术设计](./technical-design.md) | 模块、契约、打包、验证,以及独立章节中的 UI 设计 |
|
||||
| [进度](./progress.md) | 已核对的实现事实、剩余工作和验证记录 |
|
||||
|
||||
界面仅在现有 MCP 设置中增加一个卡片,因此不另设 `ui-design.md`。技术设计的“UI 设计”章节承担信息结构、控件、反馈、无障碍和窄窗口适配职责;全局视觉规范仍由 [UI-DESIGN.md](../../../UI-DESIGN.md)定义。
|
||||
|
||||
## 术语与依赖
|
||||
|
||||
| 术语 | 含义 |
|
||||
| --- | --- |
|
||||
| 仓库(vault) | 一个本机笔记文件夹;显示名称不作为调用身份 |
|
||||
| 注册仓库 | 本机 Obsidian 的 `obsidian.json` 中登记的仓库,包含当前未打开的仓库 |
|
||||
| `vaultPath` | 保存的范围设置;空字符串代表注册仓库集合,非空代表指定文件夹 |
|
||||
| `vaultId` | 一次工具调用选择的仓库标识,与文件相对路径分开传递 |
|
||||
| MCPVault | npm 包 `@bitbonsai/mcpvault`,本功能固定使用 `0.16.0` |
|
||||
| 草稿 | 设置页面尚未保存的范围,可单独测试 |
|
||||
|
||||
共享目录包含 `obsidian_list_vaults` 和 18 个加 `obsidian_` 前缀的上游工具。连接测试显示的上游工具数仍为 18。保存范围、切换开关或修改分配会撤销此前含 Obsidian 的请求授权,规则见[功能逻辑](./logic-design.md#授权撤销与清理)。
|
||||
|
||||
Node 启动环境复用[工具执行环境](../local-tool-environment/README.md),不建立第二套解释器安装或下载配置。接入目标为直连模型、GoodBuddy 管理的本机 OpenCode 和 Continue;DeepSeek Harness 与远程执行路径沿用现有不可用边界。本功能的仓库位于桌面所在设备。
|
||||
@@ -0,0 +1,60 @@
|
||||
# 功能逻辑
|
||||
|
||||
## 状态维度
|
||||
|
||||
启用状态、Runtime 分配、已保存范围和页面草稿分别管理。启用状态不表示服务已连接,测试成功也不表示会话可调用。会话使用已保存范围;测试使用本次提交的草稿。
|
||||
|
||||
测试状态为未测试、测试中、成功或失败。修改草稿使先前测试结果失效;测试结果只描述该次请求,不持久化为服务健康状态。
|
||||
|
||||
## 规则与追溯
|
||||
|
||||
| ID | 规则 | 需求 / 故事 |
|
||||
| --- | --- | --- |
|
||||
| LR-1 | 仅启用操作改变启用状态;仅保存操作改变持久化范围;测试不改变二者。 | FR-1、FR-7;US-1~US-3 |
|
||||
| LR-2 | 非空指定路径优先,完全绕过注册信息;空路径读取全部注册条目,忽略条目的打开状态。 | FR-2、FR-6;US-1、US-2、US-6 |
|
||||
| LR-3 | 先解析当前范围,再校验 `vaultId`,成功后才启动目标仓库的工具进程。 | FR-3;US-5 |
|
||||
| LR-4 | 上游能力完整保留;启用、分配和应用现有工作模式由既有会话入口执行,不另加 Obsidian 权限层。 | FR-4、FR-9;US-4、US-9~US-11 |
|
||||
| LR-5 | 范围解析失败使本次请求失败,不跳过失效注册条目,不选择替代仓库。 | FR-8;US-7 |
|
||||
| LR-6 | 测试仅发现仓库并列举工具,逐仓库连接;工具数按上游名称去重,不按仓库数相乘。 | FR-7;US-1、US-2 |
|
||||
| LR-7 | 操作结束或取消后关闭本次 MCP 连接和子进程;取消不承诺撤销已落盘写入。 | FR-8;US-8 |
|
||||
| LR-8 | 保存范围、切换开关和修改分配在输入校验后、持久化前撤销含 Obsidian 的旧请求授权并取消在途调用;网关销毁等待活动调用清理。 | FR-10;US-12 |
|
||||
|
||||
## 仓库决策
|
||||
|
||||
| 条件 | 结果 |
|
||||
| --- | --- |
|
||||
| 指定路径非空 | 验证为可访问的绝对目录,得到单仓库范围 |
|
||||
| 默认范围且注册信息有效 | 使用全部注册条目,保留各自注册 ID |
|
||||
| 注册文件不可读、无条目、条目无路径或任一目录不可访问 | 返回对应错误;用户可修复注册信息或选择文件夹 |
|
||||
| 范围只有一个仓库且请求省略 ID | 使用唯一仓库 |
|
||||
| 范围超过一个仓库且请求省略 ID | 拒绝调用,要求明确 ID |
|
||||
| 请求提供 ID 且属于当前范围 | 使用该 ID 对应仓库 |
|
||||
| 请求 ID 不属于当前范围 | 拒绝调用,不回退到唯一仓库或首个仓库 |
|
||||
|
||||
工具清单描述与实际文件操作分开。服务可用首个仓库读取固定版本的工具 schema,这不赋予首个仓库任何默认写入地位。跨仓库搜索或修改由调用方对明确的仓库 ID 分别发起请求,不把一次请求广播到全部仓库。
|
||||
|
||||
## 设置转换
|
||||
|
||||
| 动作 | 草稿与结果 | 持久化影响 |
|
||||
| --- | --- | --- |
|
||||
| 选择文件夹 | 更新草稿,切换为指定文件夹,清除旧测试结果 | 无 |
|
||||
| 取消文件夹选择 | 保留原草稿 | 无 |
|
||||
| 切换范围或编辑路径 | 清除旧结果和关联错误;指定文件夹模式空路径时报错 | 无 |
|
||||
| 测试 | 使用提交时的草稿;忙碌期间禁止重复提交,结束后显示结果或错误 | 无 |
|
||||
| 保存成功 | 使用返回快照显示已保存范围,结束当前草稿编辑状态 | 仅范围 |
|
||||
| 保存失败 | 保留草稿并显示错误,可修改后重试 | 已保存范围不变 |
|
||||
| 启用、关闭或调整分配 | 更新对应状态,草稿不自动保存 | 仅对应状态 |
|
||||
|
||||
上表仅列持久化影响;涉及授权的副作用按 LR-8 执行。连接测试不提供独立取消按钮,其临时连接不持有会话授权。
|
||||
|
||||
## 授权撤销与清理
|
||||
|
||||
Main 对范围保存、开关和分配请求先验证来源及输入,再撤销现存的含 Obsidian 授权,随后保存设置。提交相同值也触发撤销。输入无效时在撤销前返回错误;持久化失败时原设置保留,但旧授权已经失效。草稿编辑、文件夹选择和连接测试均不触发此撤销。
|
||||
|
||||
撤销按整个请求授权执行。若同一个授权同时含 Obsidian 和知识库等能力,该授权整体失效;独立的不含 Obsidian 授权保留。后续请求按当前保存的范围、开关、分配和工作模式重新取得授权;关闭后不再签发 Obsidian 能力。
|
||||
|
||||
撤销会立即移除旧授权并发出取消信号,设置响应不等待子进程完全退出。工具调用负责在结束路径关闭 transport 和 client;网关销毁则等待活动调用完成清理,包含先前已撤销但仍在关闭的调用。取消过程中已落盘的内容保留。
|
||||
|
||||
## 完整性检查
|
||||
|
||||
规则已覆盖首次使用、草稿测试、保存、范围恢复、单仓库、多仓库、失效路径、旧配置、工作模式,以及设置变更对旧授权和在途调用的影响。当前没有待定的产品决策。实现及各层自动化、Electron 与安装包验证状态见[进度](./progress.md)。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 产品需求
|
||||
|
||||
## 用户问题与目标
|
||||
|
||||
用户需要在会话中查找本机已有的 Obsidian 笔记,并将整理结果写回指定仓库。手动配置 Node、MCP 命令或 Obsidian 插件会增加首次使用步骤。接入应随应用提供依赖,支持先测试范围,再决定保存和启用。
|
||||
|
||||
## 功能需求
|
||||
|
||||
以下 ID 在后续实施中保持稳定。场景验收见[用户故事](./user-stories.md),行为决策见[功能逻辑](./logic-design.md)。
|
||||
|
||||
| ID | 产品要求 |
|
||||
| --- | --- |
|
||||
| FR-1 | 首次使用及旧设置缺少 Obsidian 字段时默认关闭。保存范围、测试连接和启用是独立操作,不互相隐式触发。 |
|
||||
| FR-2 | 默认 `vaultPath` 为空,访问本机已注册的全部仓库,包含未打开的仓库。用户可改选一个本机文件夹,也可恢复默认范围。 |
|
||||
| FR-3 | 工具调用使用仓库 ID 定位。可用仓库超过一个时必须明确指定 `vaultId`;缺失或无效时返回错误,不按顺序、名称或最近使用情况选择写入目标。 |
|
||||
| FR-4 | 提供 MCPVault 0.16.0 的全部 18 个上游工具及其参数能力。不得增加 Obsidian 专用只读设置、工具过滤或额外审批;应用现有 Ask/Execute 工作模式照常生效。 |
|
||||
| FR-5 | MCPVault 及完整运行依赖随安装包交付,使用现有托管 Node,首次调用无需联网安装 npm 包,也无需用户安装系统 Node。 |
|
||||
| FR-6 | 不依赖正在运行的 Obsidian、社区插件、REST 服务或 API 密钥。指定文件夹可绕过注册信息,不要求该文件夹已在 Obsidian 注册。 |
|
||||
| FR-7 | 功能关闭时也可测试未保存的草稿。测试返回仓库名称、路径和上游工具数,不修改笔记、不保存范围、不启用功能。 |
|
||||
| FR-8 | 范围无效、仓库不可访问、内置依赖缺失或工具执行失败时说明原因并保留草稿。取消文件夹选择不清空输入;会话调用取消后释放对应子进程。 |
|
||||
| FR-9 | 沿用内置 MCP 的启用与 Runtime 分配方式。设置范围属于桌面端全局配置,具体会话仍受既有能力分配和工作模式约束。 |
|
||||
| FR-10 | 提交保存范围、切换 Obsidian 开关或修改分配时,撤销此前含 Obsidian 的请求授权并取消其在途调用,避免继续使用旧范围或旧分配。应用关闭须等待活动工具清理;不回滚已经落盘的修改。 |
|
||||
|
||||
“离线”指本地 MCP 服务的启动和文件操作不需要下载依赖;模型服务是否联网由模型配置决定。工具返回的笔记内容会进入当前会话处理流程,不能将本地接入描述为模型推理也完全离线。
|
||||
|
||||
## 范围与非目标
|
||||
|
||||
本期接入原有仓库文件,不复制为 GoodBuddy 知识库,不提供同步服务、仓库管理器或 Obsidian 编辑器。附件相关能力按上游工具提供的范围开放,不承诺未包含在上游中的附件编辑能力。文件删除等参数沿用上游语义;上游参数校验不构成新增产品审批。
|
||||
|
||||
注册仓库发现不扫描整块磁盘,不推断最近活动仓库。接入支持直连模型、GoodBuddy 管理的本机 OpenCode 和 Continue;DeepSeek Harness 和远程执行路径保持不可用。远程 Host 仓库发现、跨设备同步和仓库迁移不在本期范围。
|
||||
|
||||
## 产品验收
|
||||
|
||||
发布前须完成[技术设计中的验证矩阵](./technical-design.md#验证与实施顺序),并在[进度](./progress.md)记录真实结果。验收至少覆盖:关闭状态测试草稿、保存后重新进入设置、恢复全部仓库、多仓库明确选择、实际读取和写回、工作模式约束,以及安装包断网启动。
|
||||
|
||||
18 个上游工具按名称和参数契约逐项比对;加上仓库发现,共有 19 个共享工具。自动化验证分别覆盖注册 IPC、HTTP 网关和直连工具提供器,安装包及完整 Electron 界面仍单独验收。配置提交时还须验证旧授权立即失效、在途调用收到取消,以及网关销毁等待子进程清理完成。
|
||||
@@ -0,0 +1,109 @@
|
||||
# 实施进度
|
||||
|
||||
## 当前状态
|
||||
|
||||
2026-09-27:主服务、设置 UI、Main IPC、HTTP 网关和直连工具提供器已实现,共享目录共 19 个工具。Windows 真实 Electron 设置操作与 OpenCode / Continue 聊天输入框读写已通过;Windows x64 解包应用通过受限网络下的设置连接和保存验证。物理断网、安装器及其他系统验收仍待完成,全量检查存在下述无关失败;当前状态不表示已发布。
|
||||
|
||||
| 阶段 | 已核对事实 | 剩余工作 |
|
||||
| --- | --- | --- |
|
||||
| TS-1 配置与服务 | 默认关闭、范围独立保存、注册发现及 ID 路由已实现;复制后的真实 MCPVault 已用于文件操作和错误传播测试 | 跨平台安装包验证归入 TS-4 |
|
||||
| TS-2 设置 UI | 真实 Electron 窗口中验证草稿测试不保存、不启用,保存和错误保留输入,Windows 原生目录对话框取消、键盘开关、19 工具展开及浅深主题窄窗口;修复表单横向撑宽 | 其他系统原生窗口验收 |
|
||||
| TS-3 网关与 IPC | 19 工具、Ask/Execute、撤销、取消及清理自动化通过;OpenCode / Continue 真实会话及聊天输入框读写通过 | 安装后的聊天读写与其他系统验收 |
|
||||
| TS-4 打包与交付 | 当前源码 `build:bundle` 和 Windows x64 `--dir` 打包通过;实际 `app.asar` UI 连接随包 MCPVault 并保存,子进程加载网络 API 限制,PATH 仅含 System32 | 物理断网或 OS 级隔离、安装器、macOS/Linux/其他架构原生资源验收 |
|
||||
|
||||
DeepSeek Harness 和远程执行保持既有不可用边界。本轮产品代码仅修改 Obsidian 表单布局,没有改变 Agent 或远程 Runtime 路径。
|
||||
|
||||
## 提交快照验证
|
||||
|
||||
提交前从 HEAD 与 Obsidian 暂存内容生成独立目录,排除并行开发的原生终端、DSH 升级、IPC 拆分与 Magic Notes 改动。锁文件从 HEAD 重新生成,仅添加固定版本 MCPVault 及其依赖,没有升级或删除既有依赖项;独立目录安装该锁文件后验证。
|
||||
|
||||
`npm run typecheck`、`npm run lint` 和 `npm run build` 均通过。聚焦服务、Electron、网关、直连工具、配置、Continue 适配器及共享 UI 的 11 个文件共 237 项通过;完整 IPC、设置面板与构建测试的 3 个文件共 303 项通过。合计 14 个文件、540 项测试通过。本次没有重跑全量套件、安装包或真实模型调用,新增模型调用为 0。下文全仓失败记录来自此前混合工作区,不代表此提交快照的类型检查或构建结果。
|
||||
|
||||
## 2026-09-27 验收补充
|
||||
|
||||
以下结果来自独立临时应用配置、项目和 vault。模型凭据通过临时复制的 `runtime-settings.json` 与配套 `Local State` 在 Electron Main 中解密;源配置和用户 vault 均未修改。测试结束删除临时配置、凭据副本和笔记;Windows 解包构建与检查日志保留在系统临时目录的 `opencode` 下。没有提交、发布、安装器或 portable 构建。
|
||||
|
||||
| 验证项 | 实际结果与边界 |
|
||||
| --- | --- |
|
||||
| 聚焦测试 | 8 文件、133 项通过,含 `obsidian-electron.test.ts` 和 Continue 适配器;IPC 定向 5 项通过、152 项跳过。布局修正后 MCP 设置、共享 UI 与 Electron 服务共 43 项通过 |
|
||||
| `npm run build` / `npm run typecheck` | `build` 停在类型检查;末次类型检查仍为 SSH pool、SSH directory browser 和 SSH terminal 测试替身缺少 `forwardLoopback`。本轮脚本类型错误已修复;未修改并行开发的 SSH 测试 |
|
||||
| `npm run build:bundle` | 当前源码通过,布局修改后再次通过;不能据此将 `npm run build` 记为通过 |
|
||||
| `npm run lint` | 当前工作区通过 |
|
||||
| 分项类型检查 | `npx tsc --noEmit -p tsconfig.web.json` 与 `npx tsc --noEmit -p tsconfig.agent.json` 均通过 |
|
||||
| `npm test` | 首次 200 秒超时;随后后台运行完整结束,691.25 秒,444 文件通过、3 失败、11 跳过;5,274 测试通过、3 失败、83 跳过 |
|
||||
| 全量失败定位 | `activity-history-io.test.ts`:迁移重复添加 `source_json`;`magic-notes-capture.electron.test.ts`:宽度 0、溢出 82 的布局断言;`build-release.test.ts`:fixture 缺少 `@deepseek-ai/dsh/package.json`。均属于并行改动范围,本轮保留原状 |
|
||||
| 真实设置 UI | [Electron runner](../../../build/run-obsidian-electron-acceptance.cjs) 导入生产 Main、使用生产 Preload/Renderer 和原生鼠标键盘,覆盖测试 18 个上游工具、保存、错误、目录对话框取消、Space 启用和展开 19 个工具。未替换 IPC 或 ObsidianService |
|
||||
| 布局缺陷与修复 | 原表单复用了横向 `.capability-diagnostic`;759 像素内容视口中卡片右边界达到 1116 像素。改为 Obsidian 纵向表单、按钮及路径换行后,普通状态右边界 691,含测试结果和工具展开时 732;浅深主题均无卡片内部横向溢出 |
|
||||
| 真实 Runtime 会话 | [Runtime runner](../../../tests/obsidian-runtime-acceptance.ts) 使用真实 OpenCode / Continue、生产 HTTP 网关和 MCPVault,断言工具事件、模型返回和实际文件。两轮各 Runtime 各 3 次模型 HTTP 请求,共 12 次;第二轮使用 UI 保存并启用的能力快照 |
|
||||
| 完整聊天输入框 | `--chat` 中 OpenCode 实际发送、读写及回复验证通过,计 4 次模型 HTTP 请求;该次随后在 Continue 菜单定位处失败。修正选择器后 `--chat --continue-only` 通过,同样 4 次请求。合计本轮 20 次真实模型 HTTP 请求,其他启动、菜单和凭据准备失败均为 0 次。聊天证据来自开发生产 bundle;没有将独立 Runtime harness 冒充聊天 UI |
|
||||
| Windows x64 解包应用 | 正常 electron-builder 配置以 `--dir --publish never` 生成 `GoodBuddy.exe` 和 `app.asar`,含解包 MCPVault 及 `windows-trash.exe`。[打包 runner](../../../build/run-obsidian-packaged-acceptance.cjs) 通过 CDP 驱动真实页面控件,设置连接返回 18 工具,保存快照匹配临时 vault;托管 node shim 指向该打包 EXE |
|
||||
| 网络限制 | 打包 EXE 的 PATH 仅含 System32,Chromium 指向不可用代理;Electron 启动会移除 `NODE_OPTIONS`,首次尝试未加载 guard。随后仅在测试 Main 的本机 inspector 中恢复该变量,审计确认真实 MCPVault 子进程加载 guard,入口为 `app.asar.unpacked/.../server.js`。Node guard 拒绝非 loopback socket 和 fetch;不覆盖 OS 全部联网方式,不算物理断网或防火墙隔离 |
|
||||
|
||||
复现命令如下。打包命令须使用真正的 Node 可执行文件;本机 PATH 中的 Electron Node shim 会使 electron-builder CLI 误读 argv。`--live` 和 `--chat` 会调用真实文本模型;默认读取当前用户 GoodBuddy 模型配置,也可用 `GOODBUDDY_ACCEPTANCE_SETTINGS` 指向含配套 `Local State` 的测试配置目录中的设置文件。
|
||||
|
||||
```powershell
|
||||
npx vitest run src/shared/obsidian-tools.test.ts src/main/obsidian/obsidian-service.test.ts src/main/obsidian/obsidian-electron.test.ts src/main/agent/knowledge-mcp-gateway.obsidian.test.ts src/main/agent/model-tool-provider.obsidian.test.ts src/main/capabilities/capability-service.test.ts src/renderer/src/McpSettingsSection.test.tsx src/main/agent/continue-host-adapter.test.ts
|
||||
npx vitest run src/main/ipc.test.ts -t Obsidian
|
||||
npx vitest run src/renderer/src/McpSettingsSection.test.tsx src/renderer/src/WorkspacePrimitives.test.tsx src/main/obsidian/obsidian-electron.test.ts
|
||||
npm run build:bundle
|
||||
node build/run-obsidian-electron-acceptance.cjs
|
||||
node build/run-obsidian-electron-acceptance.cjs --live
|
||||
node build/run-obsidian-electron-acceptance.cjs --chat
|
||||
node build/run-obsidian-electron-acceptance.cjs --chat --continue-only
|
||||
# 以下占位路径替换为本机 Node、临时构建目录及打包 EXE。
|
||||
& "<node.exe>" build/run-electron-builder.cjs --win --x64 --dir --publish never --config.directories.output="<temporary-output>"
|
||||
node build/run-obsidian-packaged-acceptance.cjs "<temporary-output>/win-unpacked/GoodBuddy.exe"
|
||||
```
|
||||
|
||||
本机打包输出为 `%TEMP%/opencode/obsidian-package-acceptance/win-unpacked`;全量日志为 `%TEMP%/opencode/obsidian-full-tests.log` 与 `.err`。以下保留 2026-09-26 的历史记录,不能用其中旧阻塞覆盖本节最新结果。
|
||||
|
||||
本轮文档 deai-writing 扫描 6 文件,0 个阻断项、12 个复核项;复核项均为测试条件、状态或能力范围限定,通读后保留。`git diff --check` 通过。
|
||||
|
||||
## 源码与测试证据
|
||||
|
||||
2026-09-26 核对以下源码与测试。本轮重新执行的结果见验证记录;此前构建结果保留原来源,不作为当前工作区构建通过的证明。
|
||||
|
||||
| 证据 | 可支持的结论 |
|
||||
| --- | --- |
|
||||
| [obsidian-service.ts](../../../src/main/obsidian/obsidian-service.ts) 与[服务测试](../../../src/main/obsidian/obsidian-service.test.ts) | 注册发现、真实复制包后的读写、许可证与资源、工具集合、多仓库 ID 以及取消后进程清理 |
|
||||
| [capability-service.test.ts](../../../src/main/capabilities/capability-service.test.ts) | 范围持久化、旧字段缺省和拒绝 `readOnly` 参数 |
|
||||
| [ipc.test.ts](../../../src/main/ipc.test.ts) | 设置组件调用正式注册的 IPC 处理器、真实配置服务及 MCPVault;Electron 传输和目录对话框由测试替代,不是安装后完整界面验证 |
|
||||
| [共享工具测试](../../../src/shared/obsidian-tools.test.ts) | 19 工具集合和 18 个上游工具的字段、默认值、必填项与约束对应 |
|
||||
| [HTTP 网关测试](../../../src/main/agent/knowledge-mcp-gateway.obsidian.test.ts) | 实际 HTTP MCP 发现 19 工具,真实多仓库读写、删除及错误返回;另覆盖撤销、取消和等待 transport 关闭 |
|
||||
| [直连提供器测试](../../../src/main/agent/model-tool-provider.obsidian.test.ts) | 通过实际服务执行全部 19 个工具并核验文件,包含笔记移动、二进制附件移动和删除;覆盖 Ask、失效令牌、原生错误及关闭清理 |
|
||||
| [index.ts](../../../src/main/index.ts)、[ipc.ts](../../../src/main/ipc.ts) 与[capability-ipc.ts](../../../src/main/capabilities/capability-ipc.ts) | 正式启动实例化、依赖注入和 IPC 注册;能力处理器位于 `capability-ipc.ts`,范围保存、开关及分配提交在持久化前撤销旧 Obsidian 请求授权 |
|
||||
| [package-mcpvault.ts](../../../src/main/obsidian/package-mcpvault.ts) 与[构建配置](../../../electron.vite.config.ts) | 构建期递归复制运行依赖,并固定上游版本 |
|
||||
|
||||
## 验证记录
|
||||
|
||||
| 验证项 | 2026-09-26 结果及范围 |
|
||||
| --- | --- |
|
||||
| 聚焦生产组件自动化 | 本轮 7 个文件、132 项测试通过,包含 Continue 适配器;另运行 IPC 的 Obsidian 用例,5 项通过、151 项跳过 |
|
||||
| `npm run build` | 此前主实施方反馈通过;本轮未重跑 |
|
||||
| `npm run typecheck` | 首次运行报原生终端依赖未列入项目的 TS6307;并行改动后复跑,该错误已消失,当前阻塞为 `native-terminal-client.test.ts:33` 的 TS2352 类型转换错误。未修改这部分并行开发代码 |
|
||||
| `npm run lint` | 本轮通过;最终测试文件改动另行定向检查 |
|
||||
| `npm test` | 本轮在 200 秒超时;结束前出现数据库迁移、Magic Notes 等失败。全量套件没有通过结论;Continue 适配器定向复跑通过 |
|
||||
| Electron 托管 Node 冒烟 | 将服务测试改为真实 Electron 可执行文件,以 `ELECTRON_RUN_AS_NODE=1` 启动复制后的包,10 项通过。Windows 子进程 PATH 仅保留测试 shim 与 System32;覆盖发现、读写、局部修改、属性、回收站和取消清理。没有隔离网络,物理断网安装包验收仍待完成 |
|
||||
| 安装后完整 Electron UI 与跨平台验收 | 待完成;组件自动化使用替代 Electron 传输,不能覆盖原生窗口及安装环境 |
|
||||
|
||||
2026-09-26 本次文档修订新增 FR-10、LR-8、US-12,保留原有 ID。交付检查结果:
|
||||
|
||||
| 文档检查 | 结果 |
|
||||
| --- | --- |
|
||||
| 相对链接及锚点 | 6 份功能文档的 53 个链接、4 份跨功能文档新增的 5 个引用通过 |
|
||||
| 稳定 ID 与工具清单 | FR-1~FR-10、US-1~US-12、LR-1~LR-8、TS-1~TS-4 唯一声明通过;18 个上游工具和 19 个共享工具映射一致 |
|
||||
| deai-writing 审校 | 功能文档 0 个阻断项、11 个复核项,逐项核对后保留状态和能力边界限定;跨功能新增段落单独扫描,0 个阻断项、0 个复核项 |
|
||||
| 差异与空白 | `git diff --check` 通过;临时脚本另检查未跟踪的功能文档,无行尾空白或旧网关接入状态 |
|
||||
|
||||
本轮修改服务测试和验证记录;测试使用独立临时仓库,未修改用户笔记或应用设置。
|
||||
|
||||
最终定向 ESLint 和 `git diff --check` 通过。README 与本进度文档经 deai-writing 扫描,0 个阻断项、3 个复核项;复核项均描述验收范围或草稿状态,保留事实限定。
|
||||
|
||||
聚焦测试复现入口如下;这些命令用于定位相关用例,不是全量通过证明:
|
||||
|
||||
```powershell
|
||||
npx vitest run src/shared/obsidian-tools.test.ts src/main/obsidian/obsidian-service.test.ts src/main/agent/knowledge-mcp-gateway.obsidian.test.ts src/main/agent/model-tool-provider.obsidian.test.ts src/main/capabilities/capability-service.test.ts src/renderer/src/McpSettingsSection.test.tsx
|
||||
npx vitest run src/main/ipc.test.ts -t Obsidian
|
||||
```
|
||||
|
||||
剩余验收以本文顶部阶段表为准,按[验证矩阵](./technical-design.md#验证与实施顺序)补充物理断网、安装后及其他目标系统证据。配置变更触发取消与销毁等待的具体语义以[功能逻辑](./logic-design.md#授权撤销与清理)为准。
|
||||
@@ -0,0 +1,103 @@
|
||||
# 技术设计
|
||||
|
||||
本文负责实现架构及 UI 设计,落实 [FR-1~FR-10](./prd.md) 和 [LR-1~LR-8](./logic-design.md)。实现与验证状态统一在[进度](./progress.md)记录。
|
||||
|
||||
## 模块边界
|
||||
|
||||
| 层 | 职责与源码 |
|
||||
| --- | --- |
|
||||
| Renderer | [McpSettingsSection.tsx](../../../src/renderer/src/McpSettingsSection.tsx) 编辑草稿、显示已保存范围和测试结果;不直接访问文件系统或启动 Node |
|
||||
| Shared / Preload | [capability-contracts.ts](../../../src/shared/capability-contracts.ts)、[contracts.ts](../../../src/shared/contracts.ts)、[ipc-channels.ts](../../../src/shared/ipc-channels.ts) 和 [preload/index.ts](../../../src/preload/index.ts) 定义窄接口 |
|
||||
| 配置服务 | [capability-service.ts](../../../src/main/capabilities/capability-service.ts) 保存范围,沿用内置 MCP 的启用和分配状态 |
|
||||
| Main 服务 | [obsidian-service.ts](../../../src/main/obsidian/obsidian-service.ts) 发现仓库、连接上游、列工具和调用工具 |
|
||||
| 会话网关 | [knowledge-mcp-gateway.ts](../../../src/main/agent/knowledge-mcp-gateway.ts) 提供 HTTP MCP、仓库发现、目标路由、请求授权撤销及活动调用清理 |
|
||||
| 共享目录与直连 | [obsidian-tools.ts](../../../src/shared/obsidian-tools.ts) 定义 19 个工具;[model-tool-provider.ts](../../../src/main/agent/model-tool-provider.ts) 发现并调用同一目录,保留上游错误详情 |
|
||||
| 构建 | [package-mcpvault.ts](../../../src/main/obsidian/package-mcpvault.ts) 复制依赖树,[electron.vite.config.ts](../../../electron.vite.config.ts) 调用打包函数,[package.json](../../../package.json) 配置版本及解包资源 |
|
||||
|
||||
正式链路为设置页面经 Preload、受信任的 Main IPC 处理器到配置服务或 ObsidianService;会话经既有能力入口到 ObsidianService,再通过 stdio 到 MCPVault。[index.ts](../../../src/main/index.ts) 创建服务并注入工具启动环境、网关及 IPC;[capability-ipc.ts](../../../src/main/capabilities/capability-ipc.ts) 注册设置、测试和目录选择处理器,接收 [ipc.ts](../../../src/main/ipc.ts) 的注册及刷新回调。`ipc.ts` 保留处理器跟踪、Runtime 重载和生命周期管理,并在会话入口按保存设置及工作模式签发请求授权。
|
||||
|
||||
## 配置与 IPC
|
||||
|
||||
`obsidianSettingsSchema` 是严格对象,仅有 `vaultPath`:字符串,去除首尾空白,最大 4096 字符,默认 `''`。不接收 `readOnly`。持久化范围为桌面全局,沿用 CapabilityService 的存储,不增加数据库或配置副本。
|
||||
|
||||
| 接口 | 输入与结果 | 副作用 |
|
||||
| --- | --- | --- |
|
||||
| `updateObsidianSettings` | `{ vaultPath }` → `CapabilitySnapshot` | 先撤销旧 Obsidian 请求授权,再保存范围;启用与分配值不变 |
|
||||
| `testObsidianConnection` | 草稿 `{ vaultPath }` → `{ vaults, toolCount }` | 临时连接,结束即清理,不保存设置 |
|
||||
| `selectObsidianVault` | 无输入 → 目录字符串或 `null` | Main 打开系统目录选择器,取消返回 `null` |
|
||||
|
||||
`vaults` 的元素为 `{ id, name, path }`。Main 处理器验证调用来源和共享 schema。范围保存只验证设置形状;目录存在性由发现或测试校验,保存成功不能显示为连接成功。已有配置缺少新字段时补默认值,其他能力设置保持原值。
|
||||
|
||||
设置更新、内置 MCP 开关及分配处理器在参数校验后调用 `knowledgeGateway.revokeObsidianCapabilities()`;后两者只在 `serverId === 'obsidian'` 时调用。撤销发生在持久化前,之后通过既有 `refreshCapabilities` 刷新配置;失败语义由 [LR-8](./logic-design.md#授权撤销与清理)定义。
|
||||
|
||||
## 仓库发现与路由
|
||||
|
||||
注册文件位置如下,优先使用相应环境变量:
|
||||
|
||||
| 系统 | 注册文件 |
|
||||
| --- | --- |
|
||||
| Windows | `%APPDATA%/obsidian/obsidian.json`,缺少变量时使用用户目录下 `AppData/Roaming` |
|
||||
| macOS | `~/Library/Application Support/obsidian/obsidian.json` |
|
||||
| Linux | `$XDG_CONFIG_HOME/obsidian/obsidian.json`,缺少变量时使用 `~/.config` |
|
||||
|
||||
注册条目的键直接用作 ID。指定文件夹经绝对路径规范化后生成 SHA-256 ID,Windows 对哈希输入转小写;这是路径身份,不是文件完整性校验或跨机器永久身份。目录移动或注册 ID 变化后,调用方须重新发现仓库。
|
||||
|
||||
`callTool` 接收 `{ vaultId?, name, arguments }`,按 LR-3 验证目标后转发。共享工具 `obsidian_list_vaults` 返回仓库列表,其余工具名称为 `obsidian_` 加上游名称,输入额外包含 `vaultId`。网关校验共享 schema,提取 `vaultId`,移除名称前缀后调用上游;其余参数原样保留。输入默认值保持可选,frontmatter 键不受外层严格对象限制。[共享契约测试](../../../src/shared/obsidian-tools.test.ts)逐项比对上游字段、必填项、默认值及约束。
|
||||
|
||||
## 上游工具契约
|
||||
|
||||
名称集合依据本地安装的 `@bitbonsai/mcpvault@0.16.0` 中 `dist/src/createServer.js` 核对。HTTP 网关和直连工具提供器共享 19 个工具:`obsidian_list_vaults` 加下表 18 个工具的带前缀映射。设置连接测试返回的 `toolCount` 为上游名称去重数,正常为 18,不包含仓库发现工具。
|
||||
|
||||
| 上游工具 | 能力 |
|
||||
| --- | --- |
|
||||
| `read_note` | 读取笔记 |
|
||||
| `write_note` | 写入笔记 |
|
||||
| `patch_note` | 局部替换笔记内容 |
|
||||
| `list_directory` | 列出目录 |
|
||||
| `delete_note` | 按上游删除参数处理笔记 |
|
||||
| `search_notes` | 搜索笔记 |
|
||||
| `move_note` | 移动或重命名笔记 |
|
||||
| `move_file` | 移动文件,包括上游支持的附件文件 |
|
||||
| `read_multiple_notes` | 批量读取笔记 |
|
||||
| `update_frontmatter` | 更新 frontmatter |
|
||||
| `get_notes_info` | 获取笔记信息 |
|
||||
| `get_frontmatter` | 获取 frontmatter |
|
||||
| `manage_tags` | 管理标签 |
|
||||
| `get_vault_stats` | 获取仓库统计 |
|
||||
| `list_all_tags` | 列出标签 |
|
||||
| `wiki_link` | 处理 wiki 链接 |
|
||||
| `get_note_outline` | 获取笔记大纲 |
|
||||
| `read_note_lines` | 按行读取笔记 |
|
||||
|
||||
服务分页读取上游工具,不设置功能白名单。读写属性供应用既有工作模式使用,不能据此增加 Obsidian 专用过滤。保留上游的错误结果与参数规则,例如删除参数 `confirmPath`;不把参数要求改造成额外确认弹窗。
|
||||
|
||||
## 离线打包与生命周期
|
||||
|
||||
构建固定 npm 版本为 `0.16.0`,复制包及递归运行依赖,保留许可证、模块相对资源和 `trash` 的原生辅助程序。资源位于 `out/main/obsidian-mcpvault/node_modules`,生产安装包将其放在 `app.asar.unpacked`。缺包或版本不符必须明确失败,不在运行时执行 `npx` 或回退到在线安装。
|
||||
|
||||
服务将 `app.asar` 路径映射到解包目录,检查 `@bitbonsai/mcpvault/dist/server.js` 存在,使用现有 `LaunchEnvironmentProvider` 注入命令环境后运行 `node <server.js> <vault.path>`,工作目录为目标仓库。托管 Node 的准备和用户自定义解释器规则由[工具执行环境技术设计](../local-tool-environment/technical-design.md)负责。Obsidian 不新增下载源;已有工具下载源不控制随包交付的 MCPVault。
|
||||
|
||||
每次列举或调用创建 stdio 连接,在 `finally` 中关闭 transport 和 client,初始化失败也清理。`callTool` 传递 `AbortSignal`,启动前已取消时不启动进程。连接测试逐仓库列工具,不调用写入工具;它没有独立取消 IPC。网关沿用现有 MCP 结果大小约束,保留上游原生内容和错误详情,超时沿用 SDK 与既有会话路径。
|
||||
|
||||
`callObsidianTool` 合并请求、授权撤销及单次调用的取消信号,并在结果返回前再次检查取消。`revokeObsidianCapabilities` 对含 Obsidian 的授权调用既有 `revoke`,移除令牌并中止其 controller;混合授权整体失效。网关以 `activeObsidianCalls` 跟踪调用 Promise,`dispose()` 先撤销授权,再等待这些 Promise 完成,随后关闭下游会话和 HTTP 服务。由于服务 Promise 包含 `finally` 中的 transport 关闭,等待范围包含真实子进程清理,也包含先前撤销后尚未关闭的调用。
|
||||
|
||||
## UI 设计
|
||||
|
||||
此章节独立承担功能 UI 设计职责,服从[统一界面设计系统](../../../UI-DESIGN.md)。入口为“能力与工具 → MCP → 内置 MCP”的 Obsidian 卡片,复用 `PageTabs`、卡片、表单、按钮、Switch 及 Runtime 分配 Checkbox。
|
||||
|
||||
卡片顺序为名称及状态、启用开关、能力说明、仓库范围、可选路径输入、已保存范围、选择/测试/保存操作、关联反馈、Runtime 分配和可展开工具列表。主按钮为“保存”,测试与选择文件夹为次按钮。范围选项为“所有本机仓库”和“指定文件夹”;指定模式才显示路径输入框。页面明确区分草稿与“已保存范围”。
|
||||
|
||||
关闭状态仍允许选择、测试和保存。快照尚未载入或操作忙碌时禁用相关提交,测试按钮显示进度。修改范围或路径清除旧结果;目录选择取消保留原值。连接结果在卡片内显示仓库名称、路径和工具数,作为可复查的诊断内容;字段错误及可立即重试的测试错误就近显示,保留输入。普通保存提示如需增加,使用应用通知,不重复显示同一事件。
|
||||
|
||||
启用控件使用 `role="switch"`;范围、路径和按钮具备可访问名称,路径错误使用 `aria-describedby`,错误用 `role="alert"`,测试结果用 `role="status"`。工具展开按钮提供 `aria-expanded` 和 `aria-controls`。沿用原生键盘行为和共享焦点样式。Obsidian 的多字段诊断表单采用纵向布局,操作按钮换行,结果中的长路径允许折行;浅色和深色主题均复用语义令牌。Windows 760 像素宽窗口的实际测量及原生输入结果见[进度](./progress.md)。
|
||||
|
||||
## 验证与实施顺序
|
||||
|
||||
| 阶段 | 验证内容 | 追溯 |
|
||||
| --- | --- | --- |
|
||||
| TS-1 配置与服务 | 缺省字段、持久化独立性、各平台注册路径、ID 路由、真实上游读写、取消清理 | LR-1~LR-3、LR-5~LR-7 |
|
||||
| TS-2 设置 UI | 草稿测试不保存不启用、切换范围、取消选择、失败保留输入、键盘与窄窗口 | US-1~US-3、US-7、US-8 |
|
||||
| TS-3 网关与 IPC | 正式 Main 处理器、19 个共享工具、分配、Ask/Execute、配置提交撤销旧授权、在途取消与销毁等待;核对 DeepSeek Harness 和远程执行不可用边界 | LR-3、LR-4、LR-7、LR-8;US-4、US-5、US-9~US-12 |
|
||||
| TS-4 安装包与端到端 | 在实际支持系统上断网且无系统 Node 测试;Obsidian 关闭;许可证及原生资源完整;从设置到真实会话读写 | FR-5、FR-6;US-6 |
|
||||
|
||||
当前分配目标为 `model`、`opencode`、`continue`;[DeepSeek Harness](../../../src/main/agent/deepseek-harness-runtime.ts)和[远程 ACP Runtime](../../../src/main/agent/acp-remote-runtime.ts)的 `supportsScopedDataTools` 为 `false`,沿用既有不可用边界。已通过的生产组件自动化包含设置组件到注册 IPC、HTTP 网关,以及直连工具提供器全部 19 个工具的实际执行。真实聊天会话、Electron 托管 Node、Windows 解包应用及网络限制的不同验证范围见[进度](./progress.md)。
|
||||
@@ -0,0 +1,20 @@
|
||||
# 用户故事
|
||||
|
||||
本期角色为使用本机笔记的桌面用户,以及替用户调用工具的会话助手。需求定义见[PRD](./prd.md)。下表描述验收条件,不表示场景已经通过。
|
||||
|
||||
| ID | 场景与需求 | Given(前提) | When(动作) | Then(预期结果) |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| US-1 | 首次检查,FR-1、FR-2、FR-7 | 本机有已注册仓库,功能尚未启用 | 用户进入 MCP 设置并测试默认范围 | 开关保持关闭;返回注册仓库列表和工具数;未保存配置,也未改动笔记 |
|
||||
| US-2 | 指定草稿范围,FR-2、FR-6、FR-7 | 用户选择一个未注册文件夹,尚未保存 | 用户测试该草稿 | 仅探测此文件夹;已保存范围及启用状态不变 |
|
||||
| US-3 | 保存与恢复默认,FR-1、FR-2 | 用户已测试指定文件夹 | 保存后重新进入设置,再切换为全部仓库并保存 | 保存结果可重新加载;恢复默认时保存空 `vaultPath`;两次保存均不自动启用 |
|
||||
| US-4 | 单仓库日常操作,FR-4、FR-9 | 功能已启用并分配给当前会话,范围只有一个仓库 | 助手在允许写入的既有工作模式下读取、修改并再次读取笔记 | 写回当前唯一仓库,结果可从文件核验;无需额外 Obsidian 审批 |
|
||||
| US-5 | 多仓库同名文件,FR-3 | 有两个仓库,都包含 `daily.md` | 助手先取得仓库 ID,再指定其中一个修改;另行尝试省略 ID 或传入无效 ID | 明确 ID 的请求仅作用于对应仓库;另两次调用返回错误,两个仓库均不因失败请求改变 |
|
||||
| US-6 | 离线与关闭 Obsidian,FR-5、FR-6 | 安装包已有依赖,Obsidian 未运行,系统未安装 Node,网络断开 | 使用内置服务测试、读取和写入测试仓库 | 本地操作通过现有托管 Node 完成,不请求 npm,也不要求插件;模型联网另行验证 |
|
||||
| US-7 | 范围失败恢复,FR-8 | 注册文件缺失或含失效路径,或者草稿路径不可访问 | 用户测试后改为有效文件夹并重试 | 显示具体原因,保留输入;重试使用新草稿,不偷偷跳过坏仓库或切换目标 |
|
||||
| US-8 | 取消与失败保留,FR-8 | 用户正在编辑草稿或执行会话工具 | 取消文件夹选择、遇到保存失败,或取消会话工具 | 选择取消和保存失败均保留草稿;工具取消关闭对应进程,不报告成功,也不宣称回滚已发生的写入 |
|
||||
| US-9 | 既有权限规则,FR-4、FR-9 | 功能启用且已分配,用户分别使用 Ask 和 Execute | 助手请求写入 | Ask 按应用现有规则保持只读;Execute 沿用正常执行规则,不增加 Obsidian 专用开关、过滤或审批 |
|
||||
| US-10 | 旧配置与分配,FR-1、FR-9 | 旧配置没有 Obsidian 字段,已有其他 MCP 配置 | 加载设置并修改 Obsidian 分配 | Obsidian 默认关闭,其他配置保留;修改分配不改写仓库范围;未分配的会话不可调用 |
|
||||
| US-11 | 上游能力完整,FR-4 | 在允许完整调用的工作模式下启用接入 | 获取工具集合并对照 MCPVault 0.16.0 | 18 个上游工具均有可调用映射,参数能力保留;仓库发现辅助工具不计入这 18 个 |
|
||||
| US-12 | 设置变更与旧调用,FR-10 | 有含 Obsidian 的旧请求授权和正在执行的工具 | 提交保存范围、切换开关或修改分配,随后关闭网关 | 旧授权失效,在途调用收到取消;网关等待工具关闭。保存失败也不恢复旧授权;后续请求按实际保存状态重新取得授权 |
|
||||
|
||||
跨平台注册路径和安装包测试分别取证。通过模拟平台字符串测试注册路径,不等于在对应操作系统上完成安装包验收。
|
||||
@@ -5,10 +5,10 @@
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 设计中 |
|
||||
| 版本 | 0.1 |
|
||||
| 日期 | 2026-09-09 |
|
||||
| 版本 | 0.2 |
|
||||
| 日期 | 2026-09-28 |
|
||||
| 适用产品 | GoodBuddy Desktop、ShareServer |
|
||||
| 推荐编辑引擎 | ONLYOFFICE Docs Developer Edition,最终采用前完成许可证与分发审核 |
|
||||
| 推荐编辑引擎 | 首选 ONLYOFFICE Docs Developer Edition;正式采用前验证实时编辑接口并确认授权与报价 |
|
||||
|
||||
## 1. 背景
|
||||
|
||||
@@ -21,7 +21,8 @@ XLSX 和 PPTX,也无法把当前选区交给 Agent 后在原位置应用修改
|
||||
- Windows、macOS 和 Linux Desktop 使用同一套浏览器编辑能力。
|
||||
- DOCX、XLSX、PPTX 在助手工作栏中以多个独立文档页签打开。
|
||||
- 用户可以手动编辑、保存、撤销和重做。
|
||||
- Agent 可以读取用户明确选择的内容,并将一次 AI 修改作为一个可撤销编辑事务应用。
|
||||
- 用户在左侧与 Agent 对话,在右侧助手工作栏看到当前文档的修改状态和结果,无需重新打开文件。
|
||||
- Agent 可以读取用户明确选择的最新内容,并将一次 AI 修改作为一个可撤销编辑事务应用。
|
||||
- 本地源文件只在用户明确打开后上传工作副本,保存时通过 Desktop 原子回写。
|
||||
- ShareServer 统一承载编辑器接入、短期会话、工作副本、回调、保留和服务端审计。
|
||||
|
||||
@@ -66,10 +67,18 @@ ONLYOFFICE 保存先形成 ShareServer 保存检查点。Desktop 下载并验证
|
||||
|
||||
### FR-6 AI 选区编辑
|
||||
|
||||
用户在编辑器中明确选择文字、单元格、对象、页面或幻灯片后,可以发起 AI 编辑。编辑器只提供
|
||||
本次选区的有界结构和必要上下文。Agent 返回编辑器支持的结构化操作,由编辑器插件应用;一次
|
||||
请求形成一个撤销事务,并在完成后标出修改位置。只有 Execute 模式可以应用修改;Ask 模式
|
||||
可以生成建议,但不得调用编辑器写入。
|
||||
用户在编辑器中明确选择文字、单元格、对象、页面或幻灯片后,可以发起 AI 编辑。编辑器提供
|
||||
当前会话内本次选区的最新内容、有界结构和必要上下文,包括尚未保存到源文件的人工修改。
|
||||
Agent 通过当前编辑会话应用受支持的结构化操作;一次请求形成一个撤销事务。只有 Execute
|
||||
模式可以应用修改;Ask 模式可以生成建议,但不得调用编辑器写入。
|
||||
|
||||
首期有界操作至少覆盖选区读取、指定文本替换、单元格区域公式与数字格式设置,以及指定幻灯片
|
||||
文本和对象属性修改。操作前明确目标文件与范围,完成后返回实际修改结果;不支持的操作说明
|
||||
限制,不以模型生成了建议或工具请求已发出作为成功依据。
|
||||
|
||||
Agent 思考期间用户可以继续编辑。应用前检查当前文档版本与目标是否仍符合本次请求;内容变化
|
||||
或目标失效时停止应用旧结果,保留人工修改并提示基于最新内容重试。切换页签或选区不得将已
|
||||
提交请求改发到其他目标。已打开文档的交互修改不得通过直接重写源文件并重载编辑器实现。
|
||||
|
||||
### FR-7 权限与数据去向
|
||||
|
||||
@@ -102,6 +111,34 @@ Desktop 记录本地打开、保存、另存为、冲突、AI 编辑请求和终
|
||||
Desktop 只连接用户已明确添加并认证的 ShareServer。ONLYOFFICE 地址、JWT 密钥、对象存储和
|
||||
回调配置由 ShareServer 管理,不进入 Desktop Renderer 或普通设置导出。
|
||||
|
||||
推荐由部署方在服务器 Docker 中独立运行 ONLYOFFICE Document Server,客户端加载编辑器;
|
||||
普通用户无需安装 Docker。启用前验证文件下载、保存回调和中文字体,并说明工作副本会进入
|
||||
所选服务的处理范围。完全离线编辑不属于此部署方案。
|
||||
|
||||
### FR-13 Agent 修改可见性
|
||||
|
||||
右侧文档页签与 Agent 使用同一个编辑会话。请求处理中显示当前目标与执行状态;编辑器确认
|
||||
应用后,内容在当前页签直接更新,用户可定位并看到修改范围的临时高亮。状态提示和高亮不写入
|
||||
文档正文,执行完成不等于源文件已保存。用户可以继续手动编辑,并对该次 AI 修改撤销或重做。
|
||||
|
||||
实时可见以一次已确认的编辑事务为单位,不要求模拟逐字输入。失败、取消或结果未知应明确
|
||||
显示实际状态;提交前取消不修改文档,已应用的事务通过撤销恢复,结果未知时先核实再重试。
|
||||
|
||||
### FR-14 选型验证与授权
|
||||
|
||||
ONLYOFFICE 是统一承载 Word、Excel、PPT 的首选方案。正式采用前,必须在同一嵌入编辑会话中
|
||||
验证选区读取、人工修改反馈、Agent 写入、修改定位与高亮、撤销重做,以及保存后重新打开。
|
||||
验证目标见第 6 节,不能以编辑器可打开或转换成功代替 Agent 编辑验证。
|
||||
|
||||
优先验证 Automation API 与 GoodBuddy 编辑器插件的配合方式。根据
|
||||
[官方 Automation API 文档](https://api.onlyoffice.com/docs/docs-api/usage-api/automation-api/)
|
||||
(2026-09-28 核对),该接口仅适用于 Docs Developer,且需额外付费。选型需取得覆盖桌面嵌入、
|
||||
私有部署、并发连接、分发和所需接口的授权条件及报价;社区版容器部署成功不代表取得这些权益。
|
||||
插件独立接入可作为备选验证,不预先认定与 Automation API 等价或免除商业授权要求。
|
||||
|
||||
三类文件的实际接口覆盖、单次撤销、高亮方式、中文字体与复杂格式兼容性,以及授权成本均为
|
||||
待验证项。未通过的操作记录具体限制,再决定补充实现或调整范围;本 PRD 不表示已有可用实现。
|
||||
|
||||
## 5. 文件范围
|
||||
|
||||
首期可编辑格式:
|
||||
@@ -121,7 +158,22 @@ PDF 保持预览或文档处理用途,不进入首期 Office 编辑。宏格
|
||||
- 同一工作栏至少可以同时保留两个独立文档页签,切换不会串文件、选区或保存状态。
|
||||
- 同名文件的页签可辨认,页签标题和完整来源一致。
|
||||
- 保存失败、回调失败和源文件冲突均不会破坏原文件。
|
||||
- 每次 AI 修改可以单次撤销,拒绝或取消不会产生部分修改。
|
||||
- 每次已完成 AI 修改可以单次撤销和重做;拒绝或提交前取消不修改文档,应用后取消按 FR-13 处理。
|
||||
- ShareServer 不可用时已有本地文件仍可由默认应用打开,但不能伪装成内置编辑可用。
|
||||
- Renderer、编辑器页面和日志中均不存在本机绝对路径、ShareServer 管理密钥或长期文件令牌。
|
||||
- 文档会话过期后,旧启动 URL、文件 URL 和回调令牌均不可重用。
|
||||
|
||||
以下场景按 [用户故事](./user-stories.md) 的 `US-C1` 至 `US-C7`、`US-F1` 和 `US-F2` 验证;
|
||||
记录编辑器版本、授权版本、样本和实际结果,不把待测能力标记为已通过。
|
||||
|
||||
| 样本/场景 | 操作 | 通过标准 |
|
||||
| --- | --- | --- |
|
||||
| Word | 改写选中段落 | 右侧原位更新,保留约定段落与文字格式,范围外内容不变 |
|
||||
| Excel | 修改指定区域公式并设为两位小数 | 公式重算与预期一致,显示格式正确,区域外内容不变 |
|
||||
| PPT | 修改指定页文本及一个对象属性 | 对象定位准确,非目标对象与布局不变 |
|
||||
| 人工修改反馈 | 人工修改后不保存,立即发起 AI 请求 | Agent 读取到会话内最新内容 |
|
||||
| 并行编辑 | Agent 思考期间用户修改文档 | 旧结果不覆盖新修改,支持基于最新内容重试 |
|
||||
| 共同编辑流程 | 应用、定位、高亮、撤销、重做、保存并重新打开 | 当前页签无需重载即可显示结果;保存后的文件内容与预期一致 |
|
||||
|
||||
文件兼容性使用包含中文字体、分页、表格、图表和公式的实际样本检查。目标平台的嵌入加载、
|
||||
焦点、快捷键与复制粘贴一并验收;接口验证和授权确认完成后再进入完整工作栏与生产部署实施。
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Office 协同编辑用户故事
|
||||
|
||||
日期:2026-09-28。状态:需求设计,尚未完成实现与真实编辑器验证。
|
||||
|
||||
需求范围见 [PRD](./prd.md)。本轮补充 ONLYOFFICE 同会话编辑、右侧修改展示和选型验证用例。
|
||||
|
||||
## US-A1 打开本地文档
|
||||
|
||||
**Given** 用户已连接支持 Office 编辑的 ShareServer,并在工作区选择一个受支持文件
|
||||
@@ -45,11 +49,15 @@
|
||||
|
||||
## US-C1 使用 AI 修改选区
|
||||
|
||||
关联:`FR-6`、`FR-13`。
|
||||
|
||||
**Given** 当前 Conversation 使用 Execute,用户在编辑器中选择受支持内容
|
||||
|
||||
**When** 用户提交 AI 修改要求
|
||||
|
||||
**Then** Agent 只接收有界选区和必要上下文,编辑器将完整结果作为一个事务应用并允许单次撤销。
|
||||
**Then** Agent 只接收当前会话的最新有界选区和必要上下文,右侧显示目标与处理状态;编辑器
|
||||
确认后原位更新、临时高亮并支持定位修改范围,无需重载。完整结果作为一个事务应用,可以
|
||||
单次撤销和重做;高亮不进入正文,完成状态不表示已写回源文件。
|
||||
|
||||
## US-C2 Ask 模式请求修改
|
||||
|
||||
@@ -60,6 +68,65 @@
|
||||
**Then** GoodBuddy 可以生成修改建议,但不会调用编辑器写入;界面提供切换 Execute 后重新应用
|
||||
的明确入口。
|
||||
|
||||
## US-C3 读取尚未保存的人工修改
|
||||
|
||||
关联:`FR-6`。
|
||||
|
||||
**Given** 用户已在右侧修改文档,但尚未保存到源文件
|
||||
|
||||
**When** 用户选择刚修改的内容并要求 Agent 继续编辑
|
||||
|
||||
**Then** Agent 基于当前编辑会话中的最新内容执行;磁盘旧文件和旧检查点不能替代本次上下文。
|
||||
|
||||
## US-C4 Agent 思考期间继续编辑
|
||||
|
||||
关联:`FR-6`、`FR-8`。
|
||||
|
||||
**Given** Agent 已读取选区,正在生成修改
|
||||
|
||||
**When** 用户继续修改文档,或切换到另一个文档页签与选区
|
||||
|
||||
**Then** 切换页签不改变原请求目标;原文档版本变化或目标失效时不应用旧结果,保留人工修改并
|
||||
提示基于最新内容重试。同一文档的其他页签也不能接收本次操作。源文件冲突仍按 `US-B2` 处理。
|
||||
|
||||
## US-C5 编辑 Word、Excel 和 PPT
|
||||
|
||||
关联:`FR-3`、`FR-6`、`FR-13`。
|
||||
|
||||
**Given** 已分别准备 DOCX、XLSX 和 PPTX 样本,当前 Conversation 使用 Execute
|
||||
|
||||
**When** 用户分别请求改写选中段落、修改选区公式及两位小数格式、修改指定幻灯片文本和对象属性
|
||||
|
||||
**Then** 按下表验证实际结果;每个样本均完成定位、高亮、单次撤销、重做、保存及重新打开检查。
|
||||
|
||||
| 样本 | 验收结果 |
|
||||
| --- | --- |
|
||||
| DOCX | 目标段落内容符合要求,约定文字与段落格式保留,范围外内容不变 |
|
||||
| XLSX | 目标区域公式及重算值符合预期,数字显示为两位小数,区域外内容不变 |
|
||||
| PPTX | 指定页面和对象定位正确,文本与属性变更符合要求,非目标对象及布局不变 |
|
||||
|
||||
## US-C6 不支持、取消和执行失败
|
||||
|
||||
关联:`FR-6`、`FR-13`。
|
||||
|
||||
**Given** 用户发起一次 AI 编辑请求
|
||||
|
||||
**When** 操作不受支持、用户取消或编辑器未能确认结果
|
||||
|
||||
**Then** 不支持时返回具体限制;提交前取消不修改文档,已应用事务提供撤销。未知结果明确显示
|
||||
待核实,不自动重复写入,不以建议生成成功代替编辑成功;执行失败保留原因和实际已应用状态。
|
||||
|
||||
## US-C7 编辑状态与源文件保存
|
||||
|
||||
关联:`FR-4`、`FR-13`。
|
||||
|
||||
**Given** 右侧已显示 Agent 修改完成,用户又进行了一次人工编辑
|
||||
|
||||
**When** 用户保存文档并重新打开源文件
|
||||
|
||||
**Then** 保存包含已确认的 AI 修改与后续人工修改;只有源文件回写成功才显示“已写回源文件”。
|
||||
回调或回写失败时保留失败状态及可用检查点,不因右侧已经更新而宣称保存完成。
|
||||
|
||||
## US-D1 网络中断后恢复
|
||||
|
||||
**Given** 编辑会话已经建立
|
||||
@@ -83,3 +150,26 @@
|
||||
**When** 用户继续访问旧页签
|
||||
|
||||
**Then** 新读取、保存和 AI 操作被拒绝,旧令牌不能重用,本地源文件不受服务端清理影响。
|
||||
|
||||
## US-F1 启用集中部署的 Office 服务
|
||||
|
||||
关联:`FR-7`、`FR-12`、`FR-14`。
|
||||
|
||||
**Given** 部署方已准备独立的 ONLYOFFICE 服务及所需授权,用户已连接 ShareServer
|
||||
|
||||
**When** 用户首次在 Desktop 打开 Office 文档
|
||||
|
||||
**Then** 无需在用户电脑安装 Docker;打开前能看到工作副本进入哪个服务及保留期限。实际验证
|
||||
文件下载、保存回调和中文字体;在 Windows、macOS 和 Linux 检查加载、焦点、快捷键与复制粘贴。
|
||||
|
||||
## US-F2 决定正式采用 ONLYOFFICE
|
||||
|
||||
关联:`FR-14`。
|
||||
|
||||
**Given** 产品团队以 ONLYOFFICE Docs Developer 为首选,正在进行接口与授权验证
|
||||
|
||||
**When** 评审是否进入完整功能实施
|
||||
|
||||
**Then** 提供 `US-C1` 至 `US-C7` 的真实会话验证结果、三类文件样本兼容性记录,以及覆盖实际
|
||||
部署与嵌入方式的授权条件和报价。Automation API 单独确认额外费用;插件替代方案单独验证。
|
||||
未通过项明确列出限制与范围决定,仅安装容器、打开文档或完成转换不能视为实时编辑验证通过。
|
||||
|
||||
@@ -3,15 +3,24 @@
|
||||
本功能负责 SSH Host 管理、Host Key、远程环境安装、GoodBuddy Agent、签名 Runtime、
|
||||
远程 Workspace 和 Ask/Execute 生产路径。
|
||||
|
||||
2026-09-28 新增待实现方向:主机管理迁入应用中心,与“云环境管理”成为同级应用;
|
||||
云平台发现已有实例,接入执行时复用 SSH 主机。产品范围见 [PRD](./prd.md)。
|
||||
本文中的平台连接指云账号或私有化 API 连接,云实例指平台中的虚拟机,主机指 GoodBuddy
|
||||
保存的 SSH 连接目标;三者不等同。现有实现和历史验收仍以下列技术文档为准。
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 文档 | 权威职责 |
|
||||
| --- | --- |
|
||||
| [产品需求](./prd.md) | 应用迁移、六平台适配范围、分期与产品验收;待实现 |
|
||||
| [功能逻辑](./logic-design.md) | 平台、实例、主机关系,独立状态、依赖和删除规则;待实现 |
|
||||
| [界面设计](./ui-design.md) | 独立工作页面、主机列表与详情、云实例接入和响应式交互;待实现 |
|
||||
| [远程主机与 Agent 技术设计](./technical-design.md) | 当前产品语义、Agent、Runtime、Workspace、协议、生命周期和验证事实 |
|
||||
| [远程环境准备技术设计](./environment-provisioning-technical-design.md) | Host 下载、GoodBuddy 传输、安装事务、更新和恢复边界 |
|
||||
| [执行清单验证记录](./runtime-checklist-validation.md) | 远程 OC/CN 原生清单、CN 开发包安装、取消及断线重放的实测结果与剩余验收 |
|
||||
|
||||
现有文档包含产品、功能逻辑和进度事实,后续修改远程功能时再按标准职责拆分。
|
||||
既有技术文档保留当前 SSH 行为及历史进度;新增 PRD、逻辑和 UI 文档只定义本次待实现范围,
|
||||
不替代已有验证事实。验收场景随 PRD 维护,本次不单独创建 User Stories 或进度占位文档。
|
||||
|
||||
跨会话共享 OpenCode 进程、ACP 连接与模型桥的实现设计,见
|
||||
[Runtime 进程复用技术设计](../assistant-workbar/runtime-process-reuse-technical-design.md#6-ssh-opencode-与-agent)。
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# 主机与云环境功能逻辑
|
||||
|
||||
状态:2026-09-28 设计,待实现。对应[产品需求 FR-RH-1 至 FR-RH-6](./prd.md),验收场景使用其中的 AC-RH 编号。
|
||||
|
||||
## 对象与关联
|
||||
|
||||
| 对象 | 所有权与关系 |
|
||||
| --- | --- |
|
||||
| 平台连接 | 云环境管理负责平台类型、账号或 API 端点、凭据引用与查询范围 |
|
||||
| 云实例 | 以平台连接及该平台稳定资源标识定位,保留必要的账号、区域或私有化资源范围;不能仅靠名称或 IP 判定同一实例 |
|
||||
| 主机 | 主机管理负责 SSH 地址、账号、认证、Host Key 和执行环境;可选关联云实例 |
|
||||
| 远程项目 | 继续引用主机与远端目录,执行空间保持 local / ssh |
|
||||
|
||||
首版一个云实例最多关联一个受管主机,一个主机最多关联一个云实例;一个主机可被多个项目引用。重复导入显示已关联主机;关联已有主机须由用户选择并验证连接目标,不能根据相同 IP 自动合并。平台凭据和 SSH 凭据分别管理,不复制到项目中。(FR-RH-3、FR-RH-5;AC-RH-3)
|
||||
|
||||
## 导入与状态
|
||||
|
||||
发现实例后先展示平台返回的事实。用户选择“接入主机”,选定地址和认证配置,复用主机验证流程,成功后保存主机与关联;失败或取消不留下半成品主机,也不改变已有有效关联。保存成功不自动安装环境,由用户显式触发。(FR-RH-2、FR-RH-3;AC-RH-2 至 AC-RH-4)
|
||||
|
||||
| 状态维度 | 来源与显示规则 |
|
||||
| --- | --- |
|
||||
| 实例运行状态 | 平台 API 查询结果;查询失败显示错误及上次成功时间,不能推断为已删除 |
|
||||
| SSH 连通性 | 所选主机的连接检查;未检查、成功、失败与检查时间独立显示 |
|
||||
| 执行环境 | Agent / Runtime 实际检查和安装结果;版本匹配不等于环境健康 |
|
||||
|
||||
进入主机页面只读取本地记录,不逐台连接 SSH。云资源刷新只查询平台 API,不顺带验证 SSH 或安装环境。变更连接目标后按现有规则重新验证,不用旧结果宣称新目标就绪。平台报告实例消失时保留主机及项目,显示关联异常并允许用户处理,不自动清理数据。(FR-RH-4;AC-RH-1、AC-RH-4)
|
||||
|
||||
## 导航与能力依赖
|
||||
|
||||
常驻只控制导航捷径,取消常驻不停止任务、禁用能力或删除数据。应用中心的主机管理设置承载共享远程能力启用状态,迁移保留原 `remoteProjectsEnabled` 值;旧设置不再维护第二个独立开关。云环境应用的启用单独控制云管理入口和新平台操作。(FR-RH-1、FR-RH-4、FR-RH-6)
|
||||
|
||||
| 操作 | 目标行为 |
|
||||
| --- | --- |
|
||||
| 打开云环境但远程能力未启用 | 允许配置平台及查询实例;接入主机时提供就地启用,保存成功后继续 |
|
||||
| 取消主机常驻 | 云环境仍可引用主机,已有关联和运行不变 |
|
||||
| 关闭共享远程能力 | 沿用现有远程项目停用语义,保留主机、凭据和项目;云资源浏览仍可用,依赖操作显示原因与启用入口 |
|
||||
| 关闭云环境应用 | 保留平台配置和主机关联;已接入的 SSH 主机及远程项目继续可用 |
|
||||
| 切换业务页面 | 保留搜索、选择与正在进行的操作状态,遵守未保存编辑离开检查 |
|
||||
|
||||
能力启用与校验须同时覆盖 UI 和 Main,不能仅移动开关或隐藏按钮。(AC-RH-5)
|
||||
|
||||
## 删除语义
|
||||
|
||||
移除主机沿用现有本地引用项目及关联数据删除确认,移除成功后清除云实例到该主机的关联,实例重新显示为未接入。操作不连接远端删除目录,也不调用实例销毁 API。
|
||||
|
||||
移除平台连接前列出关联主机;确认后移除平台凭据及关联,保留 SSH 主机、凭据和项目,使其继续作为独立主机使用。远端实例生命周期操作属于后续功能,须在云环境页面独立定义影响及结果。(FR-RH-5;AC-RH-6)
|
||||
|
||||
## 完整性与待定事项
|
||||
|
||||
本文覆盖导航迁移、发现与导入、状态来源、依赖关闭、重复关联及删除。各平台适配顺序、支持版本和验收环境待确认;私钥与私网连接方案属于后续技术选型。实例创建、销毁、网络编排及批量操作不在首版范围,不能从本设计推导其行为。
|
||||
@@ -0,0 +1,62 @@
|
||||
# 主机管理与云环境管理产品需求
|
||||
|
||||
状态:2026-09-28 确认产品方向,待实现。本次仅更新文档;现有 SSH 实现与验证范围见[技术设计](./technical-design.md)。
|
||||
|
||||
## 目标与范围
|
||||
|
||||
主机管理从设置中心迁入应用中心,在主内容区提供独立工作页面。云环境管理作为同级应用,管理公有云及私有化平台中的虚拟机,接入远程执行时复用主机管理。
|
||||
|
||||
首版围绕已有虚拟机完成“连接平台 → 发现实例 → 接入主机 → 验证 SSH → 安装远程环境 → 创建项目 → 执行任务”。先交付主机管理入口迁移与页面调整,再分批接入平台适配器。
|
||||
|
||||
| 平台范围 | 接入目标 |
|
||||
| --- | --- |
|
||||
| AWS | 已有 EC2 实例 |
|
||||
| Azure | 已有 Virtual Machines |
|
||||
| 阿里云 | 已有 ECS 实例 |
|
||||
| 腾讯云 | 已有 CVM 实例 |
|
||||
| VMware | 先聚焦 vCenter / vSphere 管理的虚拟机 |
|
||||
| ZStack | 已有云主机 |
|
||||
|
||||
六个平台纳入首版适配计划,逐批实现和验收,不把手工 SSH 接入计为平台 API 已适配。候选顺序为阿里云、腾讯云加一个私有化平台,再补其余平台;私有化平台优先级按真实客户与测试环境确定,该顺序尚未锁定。各平台支持版本、认证方式和可验收环境须在对应适配器开发前确认。
|
||||
|
||||
首版不包含自动创建、销毁虚拟机、网络编排、镜像管理和计费管理;已有实例启停作为后续增量。现有云服务器仍可手工通过 SSH 接入,受网络、认证和远端操作系统支持范围限制。
|
||||
|
||||
## 功能要求
|
||||
|
||||
### FR-RH-1 应用入口
|
||||
|
||||
应用中心分别提供“主机管理”和“云环境管理”,打开独立主内容区页面,支持排序与常驻。应用中心只负责访问和通用应用设置,主机和云资源操作位于业务页面。迁移后移除设置中心内的重复主机管理表单;旧入口可提供跳转。
|
||||
|
||||
### FR-RH-2 主机工作页面
|
||||
|
||||
主机作为全局资源,提供可搜索、按来源及状态筛选的列表与所选主机详情。保留现有新增、编辑、验证、Host Key、凭据管理、安装、更新、重装及删除能力。详情包含概览、连接配置、执行环境和关联项目。来源为手工添加或关联平台,不要求手工主机填写云字段。
|
||||
|
||||
### FR-RH-3 云平台连接与已有实例接入
|
||||
|
||||
一个平台连接管理多台实例。用户可先浏览云资源,再选择实例创建主机或关联已有主机。实例接入须选定可达地址和认证方式,经 SSH 验证后才成为可用主机;仅查询到实例不代表接入成功。认证或连接失败保留平台及实例上下文,允许修正后重试。
|
||||
|
||||
### FR-RH-4 依赖与状态
|
||||
|
||||
云环境浏览不要求存在主机;安装环境、创建远程项目和远程执行复用主机能力。云实例运行状态、SSH 连通性、执行环境就绪状态独立呈现,并显示检查时间或未检查状态。启用、常驻及共享远程能力的规则由[功能逻辑](./logic-design.md)定义。
|
||||
|
||||
### FR-RH-5 资源关联与删除
|
||||
|
||||
已接入实例可跳转至对应主机,主机可回到平台实例。移除本机主机记录、移除平台连接与销毁云实例是独立动作,不能相互隐式触发。主机删除沿用现有引用项目影响确认及本地数据清理语义,明确不会删除远端内容。
|
||||
|
||||
### FR-RH-6 迁移与接入条件
|
||||
|
||||
升级保留已有 Host ID、凭据、Host Key、项目引用、功能启用状态及原有应用导航偏好。私钥认证和私网连接路径属于云接入前的补齐项;在对应能力实际交付前,页面必须说明可用认证与网络条件,不能将平台 API 可达等同于 SSH 可达。具体私钥保存方式和跳板连接方案另行技术设计,不因本文而宣称已经支持。
|
||||
|
||||
## 产品验收
|
||||
|
||||
| 场景 | 操作与预期结果 |
|
||||
| --- | --- |
|
||||
| AC-RH-1 已有用户升级 | 打开主机管理,原有主机及项目引用可用;导航排序和原启用偏好保留,不自动连接远端 |
|
||||
| AC-RH-2 主机维护 | 从应用中心新增主机,完成验证、显式安装环境并创建远程项目;取消或失败可重试,页面跳转不重复安装 |
|
||||
| AC-RH-3 云实例导入 | 已配置平台连接时发现并选择实例,验证后创建或关联主机,进入同一主机详情;重复导入定位已有记录 |
|
||||
| AC-RH-4 网络或认证失败 | 实例运行中但 SSH 不通或认证失败时,分别显示实例状态和连接错误;不显示执行就绪,不安装环境 |
|
||||
| AC-RH-5 导航与依赖 | 取消主机常驻不影响云环境或执行能力;云环境接入流程可就地启用所需远程能力,无须寻找设置开关 |
|
||||
| AC-RH-6 移除关联资源 | 删除主机前列出受影响的本地项目;完成后云实例仍存在,云列表显示未接入。移除平台连接不删除主机和远端资源 |
|
||||
| AC-RH-7 页面与权限 | 窄窗口和键盘可完成列表、详情和返回;平台账号仅有查询权限时仍可发现和导入实例,不要求实例生命周期权限 |
|
||||
|
||||
每个平台必须通过真实 API 发现已有实例,并完成 SSH、环境安装、项目创建和真实任务执行的生产路径验收,才可标记该适配器已交付。UI、模拟响应和单独 SSH 测试不能替代平台验收。
|
||||
@@ -27,6 +27,12 @@ Agent `0.11.23` 提供,显式请求期限与取消仍有效。当前问答源
|
||||
|
||||
## 跨会话进程复用(未发布)
|
||||
|
||||
2026-09-28 Story Graph 补充:远程 OpenCode/Continue 的 Ask 和 Execute
|
||||
通过现有受管 HTTP MCP、工具二进制通道读取桌面图谱。Main 固定项目范围并复核监督者
|
||||
开关及 Runtime 分配;图谱读取不复制数据库到 Host,也不调用模型。三个只读工具、
|
||||
分页和版本限制由[专项设计](../conversation-supervision/story-graph-mcp-design.md)定义,
|
||||
源码 Host 探针及协议测试见[验证记录](../conversation-supervision/progress.md#2026-09-28-story-graph-只读工具)。
|
||||
|
||||
已发布版本的 `RuntimeAcpBackend` 按 binding 拥有原生进程,`AgentOwnedAcpPrompt` 的一条 ACP
|
||||
连接对应一个原生 Session;同一会话后续 Prompt 可复用,但不同会话不共用进程。
|
||||
上文“Host 共享 Runtime 环境”指安装与 Agent 环境,不代表原生 OpenCode 进程已共享。
|
||||
@@ -49,6 +55,9 @@ Agent `0.11.23` 提供,显式请求期限与取消仍有效。当前问答源
|
||||
|
||||
## 产品语义
|
||||
|
||||
本节记录现有实现。2026-09-28 确认的应用中心迁移与云环境管理目标见
|
||||
[PRD](./prd.md)、[功能逻辑](./logic-design.md)及[UI 设计](./ui-design.md),尚未接入源码。
|
||||
|
||||
远程 Host 与项目能力默认关闭。用户在“设置 > 平台功能”的独立
|
||||
“远程项目”页签启用开关后,Renderer 才显示 SSH Host 管理、托管 SSH 项目创建和已保存
|
||||
远程项目;Main 在 IPC 边界执行同一开关校验,避免隐藏界面被绕过。关闭开关不删除 Host、
|
||||
@@ -67,6 +76,30 @@ profile 和凭据作为有界、逐 Prompt 的控制消息交给 Agent;该凭
|
||||
|
||||
## 组件
|
||||
|
||||
### 应用迁移与云平台接入计划(待实现)
|
||||
|
||||
实现顺序对应 FR-RH-1 至 FR-RH-6:
|
||||
|
||||
1. 从 `SshHostsSettingsSection` 提取独立主机工作页面,接入 `ApplicationCenter` 和 `App`
|
||||
页面导航;复用现有 SSH 服务、验证弹窗、安装操作及通知,完成列表与详情改版。
|
||||
2. 扩展应用标识、排序、常驻和配置读取。读取已发布四应用配置时保留原相对顺序及偏好,
|
||||
新入口追加且默认不常驻;云管理初始关闭,共享远程能力继承 `remoteProjectsEnabled`。
|
||||
配置工具公开契约、默认值、持久化、Preload 和 Main 校验同步修改,不能仅扩展 Renderer。
|
||||
3. 按功能逻辑整理能力依赖,将共享远程开关的设置入口迁入应用中心。保留旧值、Host ID、
|
||||
加密凭据、Host Key 与项目引用;不为页面迁移重建主机或修改 Agent 协议。
|
||||
4. 云平台适配器在 Main 中查询真实 API,凭据复用加密存储;Renderer 仅接收脱敏配置、
|
||||
实例快照与操作结果。采用满足首批平台发现和导入的最小接口,不预建资源编排框架。
|
||||
平台连接和实例关联采用独立记录,SSH 主机仍为执行目标,项目继续使用 `local / ssh`。
|
||||
5. 确认首批平台版本及测试环境,补齐需要的私钥和私网连接路径,逐个验收发现、导入、
|
||||
SSH 验证、环境安装和真实任务执行。具体存储字段、迁移及适配 API 在实施时细化;
|
||||
变更已发布存储前遵守[数据库迁移规范](../../development/database-migrations.md)。
|
||||
|
||||
验证覆盖已有用户配置读取、重复实例关联、状态来源、平台查询失败、SSH 不通、删除影响、
|
||||
能力依赖与页面离开。平台 API 测试与原有远程 Agent 测试分别记录;导航迁移通过不代表
|
||||
云平台适配完成。新增能力交付前,本文件以下 SSH 组件及历史记录继续描述现有实现。
|
||||
|
||||
### 现有远程执行组件
|
||||
|
||||
桌面保存托管 SSH 子任务事件时,共用
|
||||
[执行记录差量存储](../assistant-workbar/execution-history-storage.md)。
|
||||
Agent transcript 与公共 Runtime 事件不改变;桌面的来源去重、消息投影事务和恢复序号
|
||||
@@ -452,8 +485,10 @@ Runtime 包。2026-09-19 完整桌面验证覆盖联合包安装、CN 项目创
|
||||
重连时,工具及原生子代理的状态也以已提交的远端活动事件为准,覆盖消息终态处理派生的
|
||||
失败状态,避免将未完成活动误判为可恢复错误,保证终态重放内容一致。
|
||||
- 远程 context metrics 与对话级压缩后的估算值按本次请求实际使用的 Runtime 选择写入
|
||||
`context_state_json`。实时接收与恢复入口都传入请求的选择;数据库在未传入时按对话、
|
||||
项目、auto 顺序解析。继承项目设置的对话保持 `runtime_selection_json = NULL`,
|
||||
`context_state_json`。实时接收与恢复入口都传入请求的选择;数据库在未传入时按对话层、
|
||||
项目层解析,缺省执行方式为 OpenCode(规则见
|
||||
[执行方式与模型选择设计](../model-connections/runtime-selection-design.md#4-执行时解析已实现))。
|
||||
继承项目设置的对话保持 `runtime_selection_json = NULL`,
|
||||
不为接收 usage 固定对话 Runtime;去重和消息/指标写入仍在同一 SQLite 事务中完成。
|
||||
- ACK 后 Agent 删除已确认事件,只保留小型操作终态与游标用于幂等核对;未 ACK 输出继续
|
||||
保留。Main 按 transcript page 的最高连续 sequence ACK,终态仍立即 ACK。单事件、单页、
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# 主机管理与云环境界面设计
|
||||
|
||||
状态:2026-09-28 设计,待实现。范围见[PRD](./prd.md),状态及依赖遵守[功能逻辑](./logic-design.md)。视觉、页面壳层和组件遵守[统一界面设计系统](../../../UI-DESIGN.md)。
|
||||
|
||||
## 应用入口
|
||||
|
||||
应用中心新增“主机管理”和“云环境管理”两个同级应用。应用菜单、管理应用中的“打开”和常驻侧栏入口进入同一主内容区页面,关闭来源菜单或管理 Modal,不在应用中心 Modal 内管理主机。业务页面使用全局范围标识;打开页面不切换当前项目、不连接主机或执行安装。
|
||||
|
||||
通用启用、常驻和排序遵守[应用导航设计](../application-tool-navigation/ui-design.md)。设置中心移除主机操作表单,保留必要的迁移跳转;共享远程能力开关归入主机管理的应用设置。Agent 包下载、导入等现有全局包管理暂留原位置,主机执行环境页提供相关入口,不复制包状态存储。
|
||||
|
||||
## 主机页面
|
||||
|
||||
页面使用共享 `dashboard` 壳层。标题区显示“主机管理”、全局范围和主操作“添加主机”。工具栏提供名称或地址搜索、来源筛选、连接状态筛选。列表显示名称、地址、来源、SSH 状态和执行环境摘要,避免每行展开安装表单。
|
||||
|
||||
宽窗口使用列表与详情两栏,点击主机只更新详情,不重排列或滚动列表。详情使用共享 `PageTabs`:
|
||||
|
||||
| 页签 | 内容与操作 |
|
||||
| --- | --- |
|
||||
| 概览 | 名称、来源、系统架构、独立状态及检查时间;关联云实例时提供“查看云实例” |
|
||||
| 连接配置 | 地址、端口、用户名、认证配置状态、Host Key;编辑与重新验证复用既有流程,不回显凭据 |
|
||||
| 执行环境 | Agent / Runtime 版本、检查结果、安装进度;保留安装、更新、重装及既有下载方式选择 |
|
||||
| 关联项目 | 所有引用该主机的项目,明确归档状态;提供打开项目和创建远程项目 |
|
||||
|
||||
云关联字段按需显示,手工主机不出现必填平台、区域和实例 ID。删除主机置于次要操作,确认内容列出本地项目影响及远端资源保留范围。
|
||||
|
||||
未选择主机时提示选择列表项;没有主机时提供添加入口;搜索无结果时提供清除筛选。连接失败、安装失败和数据读取失败分别显示原因与对应重试操作。用户主动检查所选主机时才连接远端,不能因列表渲染而检查全部主机。
|
||||
|
||||
## 云环境页面
|
||||
|
||||
标题区显示“云环境管理”、全局范围及“添加平台连接”。通过平台连接和适用的区域或资源范围筛选实例,列表展示名称、平台、位置、实例状态、地址和接入状态。刷新明确针对当前查询范围,并显示上次成功时间。
|
||||
|
||||
未接入实例提供“接入主机”,进入地址与认证选择,再完成现有验证向导。已接入实例提供“打开主机”;关联已有主机时可搜索选择,明确展示目标后验证。两个页面之间往返恢复来源筛选、所选记录和滚动位置。
|
||||
|
||||
实例运行、SSH 连接和环境就绪分别显示文字状态。只读平台账号可以查询实例并接入 SSH;权限不足时说明失败操作,不把整个平台笼统标为不可用。平台 API 可达但 SSH 不通时保留资源详情与修正连接的入口。
|
||||
|
||||
首版不展示尚未实现的创建、销毁或网络编排按钮。各适配器随真实能力交付,不能用不可操作的平台卡片代替接入功能。
|
||||
|
||||
## 响应式与交互
|
||||
|
||||
两栏无法满足共享最小宽度时改为单面板,选择主机进入详情并提供“返回主机列表”,返回恢复筛选、滚动和列表项焦点。页签可横向滚动,搜索与筛选换行,长地址和错误信息折行,页面不整体横向溢出。
|
||||
|
||||
列表项及操作使用语义按钮,提供可访问名称和可见焦点;页签沿用 `tablist`、`tab`、`tabpanel`、方向键及 Home/End。弹窗遵守共享焦点恢复及未保存编辑规则。通知使用全局应用通知,进行中的安装进度保留在对应主机,页面切换不重启操作。
|
||||
|
||||
验收对应 AC-RH-1 至 AC-RH-7,覆盖浅深主题、窄窗口、键盘操作、空列表、长名称、认证失败及安装取消;具体实施记录需附真实 UI 验证结果。
|
||||
@@ -4,6 +4,8 @@ Smart Heartbeat 已提供按计划或手动执行的有界回顾,生成报告
|
||||
|
||||
现有入口已升级为“监督者”,智能心跳作为其定期唤醒机制,驱动检查与整理;应用提供工作回顾、故事线图谱、自动监督、活动记录和设置五个页签。计划在自动监督管理,创建与编辑使用 Modal;设置只保留算法参数。定义见[监督者应用产品设计](../conversation-supervision/supervisor-prd.md),实施方案见[监督者技术设计](../conversation-supervision/technical-design.md)。现有计划和范围保留,监督调用继续禁止工具执行。
|
||||
|
||||
职责(2026-09-30 已实现):心跳只负责定时触发增量回顾,并按计划配置的介入方式(生成建议/仅更新记忆)处理本次图谱变化;不再单独读取原文或生成报告。见[心跳职责与介入](../conversation-supervision/logic-design.md#心跳职责与介入目标设计)。下文关于心跳报告、报告超时和报告增量的描述为历史行为,仅旧报告保持只读。
|
||||
|
||||
自动报告及监督回顾分别按来源版本和已读位置处理增量;没有待处理输入时记录无变化,跳过模型及新报告。手动历史重看和删除报告的边界见[自动增量规则](../conversation-supervision/logic-design.md#自动增量与手动重看)。
|
||||
|
||||
## 文档导航
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
# GoodBuddy 更新:故事图谱、Obsidian接入、Runtime原生终端
|
||||
|
||||
> **编辑标注说明(对外发布前删除):** 本稿汇总桌面版 0.13.8 至 0.15.2,以及此后截至 `86347af` 的已提交变化,更新于 2026-09-28。所述功能与修复均已开发完成并提交;0.15.2 之后的提交归属版本待确认。“待补图”表示缺少可发布素材,“待替换”表示发布信息未核验,“待核对”表示发布前需要确认的行为。本文是宣传草稿,尚未对外发布。
|
||||
|
||||
GoodBuddy 这一轮更新围绕工作记录的整理与使用展开:监督者按项目回顾进展,并通过图谱保留结论依据;新加入的笔记连接支持保存聊天正文、返回原会话,以及在聊天中读写本机 Obsidian 笔记。本地项目还可以从输入区打开 Continue、OpenCode 原生终端或 DS Web 客户端,沿用当前项目与模型配置。
|
||||
|
||||
本文接续上一份画布笔记与文档处理更新稿,覆盖 0.13.8 起的实际增量。远程故事图谱读取与 Runtime 配置修复配套 Desktop 0.15.2 和 Agent 0.15.0,请先升级桌面端,再更新 Host 环境。
|
||||
|
||||
> **【待替换 R01|版本与体验入口】** 最新已核查桌面 tag 为 `v0.15.2`,与 `agent-v0.15.0` 同指向 `47ba54f`;故事图谱读取、完整讨论正文编辑及上一轮笔记面板简化已纳入对应版本。本轮检查 `0cdf042..86347af`,手动压缩、长请求授权、终止提示及后续界面调整位于该 tag 之后,发布归属待确认。对外发布前核验最终版本、公开安装包、发布日期、下载地址和完整更新日志链接,并在此补入。桌面 0.13.14 的发布失败后由 0.13.15 承接。
|
||||
|
||||
**升级前,请先关闭应用并备份完整用户数据。** 数据库和相邻的 `notes/` 目录需要成套保留。本稿中的聊天采集功能将数据库格式升至 48,用于保存笔记来源;升级后旧客户端不能直接打开该数据库,回退需要升级前的备份。
|
||||
|
||||
## 新增功能
|
||||
|
||||
### 监督者:从工作记录中整理进展,查看每条结论的依据
|
||||
|
||||
项目讨论持续一段时间后,可以打开“监督者”的“工作回顾”,选择全局或一个项目,以及最近 1 天、7 天或 30 天的范围。回顾会整理工作总结、本次变化和未解决事项;历史结果保留各自的范围和生成时间,方便回看。
|
||||
|
||||
监督者默认关闭,在应用中心启用后即可手动回顾,无需先建立自动计划。当前分析来源包括范围内的用户与助手消息、任务标题与当前状态,以及消息中已有的知识引用片段。它不会自动遍历全部笔记、整个知识库或附件原件。
|
||||
|
||||
> **【待补图 01|必补|工作回顾结果】** 在隔离演示项目中通过正常聊天和任务操作形成公开、虚构的工作记录,运行一次真实回顾。截图同时展示范围、时间和实际生成的总结、未解决事项;不能用预置答案冒充模型结果。计划文件:`assets/01-work-review.png`。
|
||||
>
|
||||
> 建议图注:按项目回顾近期讨论与任务,查看进展和仍待处理的问题。
|
||||
|
||||
回顾中的事件、实体与关系可以在“故事线图谱”中查看。选中一个对象,就能检查它的说明、关联和保存的来源正文,再判断模型的归纳是否准确。实体支持确认、改名或撤销,关系可以确认或移除。
|
||||
|
||||
这适合检查“某个结论来自哪段讨论”“一个事项与哪些事件有关”。图谱按事件顺序提供浏览,但还不能逐时刻还原当时的全部实体状态;图上的间距也不表示实际时间间隔。
|
||||
|
||||
> **【待补图 02|必补|图谱与来源】** 使用图 01 同一份真实回顾结果,选中事件或实体,展示对应的来源正文。画面应能辨认对象与依据的关联;不使用设计原型代替生产结果。计划文件:`assets/02-story-sources.png`。
|
||||
>
|
||||
> 建议图注:从回顾图谱查看关联对象,并打开保存的讨论依据。
|
||||
|
||||
### 助手可以查阅故事图谱,接着已有决定继续工作
|
||||
|
||||
继续一个项目时,可以请助手“查一下此前选了哪个方案,依据是什么”,或“找出这项决定后来的修订”。助手可搜索监督者已经保存的事件、实体、关系和回顾结果,读取相关上下文,再查看来源片段,作为后续讨论的依据。
|
||||
|
||||
在应用中心启用监督者,并在 MCP 设置中保持 Story Graph 开启、分配给所用 Runtime 后即可使用。支持直连模型、DeepSeek Harness,以及本地和远程 OpenCode、Continue;Ask 与 Execute 均可只读查询。本地 Continue、OpenCode 原生终端也可读取。
|
||||
|
||||
查询默认使用当前项目,也可明确指定全局或项目集合;各范围读取各自保存的结果。工具只读取已有记录,不会为一次查询重新运行回顾或修改图谱;助手根据结果生成回答仍使用当前模型。保存的来源片段可以分页读取,但完整历史状态重建和跨范围事实自动复用不在本次功能范围内。
|
||||
|
||||
### 在任务中心跟踪当前会话或任务
|
||||
|
||||
右侧任务中心的项目概览下方新增监督反馈。选中任务时查看该任务的匹配结果,否则跟随当前会话;也可以固定目标,切换聊天后继续查看同一个事项。没有匹配回顾时会明确显示空状态。
|
||||
|
||||
监督反馈中的“继续讨论”可以直接使用,无需先打开来源。侧栏和图谱来源中的入口都会展示完整、可编辑的发送正文,包含相关回顾结论和来源内容;可以删改引用、补充问题,再确认单独显示的目标会话。发送以编辑后的正文为准,已删除的上下文不会被重新附加;发送失败保留草稿。在图谱来源中发送后会打开目标会话,需要先看原讨论时,也可单独点击“打开会话”。
|
||||
|
||||
带入的结论按所选来源关联的事件、实体与关系整理,方便围绕当前事项继续追问。监督界面已移除知识实体写回控件。
|
||||
|
||||
后续讨论的最终内容最多 12,000 字符。固定任务没有关联会话时,不能直接发送继续讨论;后续对话沿用目标会话的模型和工作模式。
|
||||
|
||||
### 聊天正文存入魔法笔记,并保留来源
|
||||
|
||||
遇到值得保留的回答,可以点击助手消息旁的“加入笔记”,预览并编辑文字,再追加到已有笔记,或新建笔记保存。需要保留整段讨论时,会话菜单中的“保存当前对话到笔记”会读取完整历史,收录用户与助手的正文,不局限于屏幕上已经显示的消息。
|
||||
|
||||
保存后的记录带有“来自会话”入口。单条回答可以返回对应消息;原会话或消息被删除后,已保存的笔记内容仍保留。每次采集新增一条记录,后续对话修改不会自动同步到笔记。
|
||||
|
||||
工作栏“+ → 笔记”可以打开紧凑面板,在聊天旁搜索笔记标题与正文、浏览摘要、追加文字。切换项目或会话时草稿保留,关闭有未保存内容的面板前会提示;草稿仅在本次应用运行期间保留。画布、待办和完整编辑继续在魔法笔记工作区中使用。
|
||||
|
||||
快速笔记入口集中在工作栏和聊天采集操作中,移除了侧栏与顶栏的重复快捷按钮。面板精简重复标签,采集范围说明按需展开,标题或正文超限时在对应输入位置提示。保存和来源操作统一靠右排列,窄面板中的保存按钮也保持紧凑。
|
||||
|
||||
采集保存文本与 Markdown,不复制推理过程、工具日志或附件图片。生成中的回答暂不可采集,单条记录上限为 500 KiB,超限会提示缩减。采集本身无需调用模型;保存后自动评论仍按已有设置执行。笔记继续属于全局,来源项目只用于帮助回看。
|
||||
|
||||
> **【待补图 06|必补|聊天采集与来源返回】** 用公开演示对话预览并保存一条回答,展示笔记记录中的来源入口,再验证能返回原消息。计划文件:`assets/06-chat-note-source.png`。
|
||||
>
|
||||
> 建议图注:把有用的回答存入笔记,需要上下文时返回原会话。
|
||||
|
||||
### 在聊天中查找和整理 Obsidian 笔记
|
||||
|
||||
已有 Obsidian 笔记可以直接接入 GoodBuddy。在“设置 → 能力与工具 → MCP”的 Obsidian 卡片中,选择本机已注册的仓库,或限定一个文件夹,测试连接并保存,然后启用并分配给所用 Runtime。无需启动 Obsidian,也无需额外安装 Obsidian 插件或配置 REST 服务。
|
||||
|
||||
接入后,可以请助手查找笔记、读取内容,或将讨论结果写回仓库;也支持追加、局部修改、目录浏览,以及标签和属性操作。笔记仍保存在原仓库,不会自动复制成 GoodBuddy 知识库。
|
||||
|
||||
目前支持直连模型及 GoodBuddy 管理的本机 OpenCode、Continue 聊天,默认关闭;DeepSeek Harness 和远程执行暂不支持。Ask 只读,Execute 可写入;多仓库调用需要明确目标仓库。接入本机文件不等于离线推理,读出的内容会随当前会话交给所选模型处理。
|
||||
|
||||
> **【待补图 07|建议|Obsidian 接入与读写】** 已有候选 `obsidian.png` 展示仓库范围和 Runtime 分配,尚需确认构建来源;正文主图优先补公开笔记的搜索、写入与回读结果。计划文件:`assets/07-obsidian-notes.png`。
|
||||
>
|
||||
> 建议图注:按仓库范围接入本机 Obsidian,在聊天中查找笔记并保存整理结果。
|
||||
|
||||
### 从输入区打开本地原生客户端
|
||||
|
||||
本地项目选择 Continue 或 OpenCode 后,输入框下方可以打开工作栏内的原生交互终端;选择 DS 后,可以在系统默认浏览器中打开官方 DeepSeek Harness Web 客户端。启动时沿用当前项目目录与所选模型,适合希望使用 Runtime 自身交互界面的用户。
|
||||
|
||||
原生客户端使用独立会话,不会自动接续或同步 GoodBuddy 中的聊天历史。DS 网页关闭后,本地服务继续运行,可以回到 GoodBuddy 重新打开或停止;退出应用会清理所属服务。
|
||||
|
||||
当前入口支持本地项目,远程原生客户端尚未接通。Continue 与 DS Web 需要可用的标准 Node 环境,首次准备环境可能需要下载。Continue、OpenCode 原生终端在 Ask 下可使用已分配的内置只读工具,包括故事图谱查询;自定义 MCP 仍仅在 Execute 下接入。
|
||||
|
||||
> **【待补图 08|建议|原生终端与 DS Web】** 已有 `continue.png`、`opencode.png`、`deepseekweb.png` 候选;发布前确认构建来源,并处理本机路径、浏览器书签及与演示无关的会话。Continue 图含模型能力警告,建议换用合适模型重拍;不能据启动画面宣称完整对话验收通过。计划文件:`assets/08-native-clients.png`。
|
||||
>
|
||||
> 建议图注:在工作栏打开原生终端,或在系统浏览器中使用 DS Web 的独立会话。
|
||||
|
||||
### 复制模型连接,保留已有配置
|
||||
|
||||
在“设置 → 模型连接”中打开一条 LLM 连接,点击“复制”,即可在副本中修改模型名称、地址或其他选项,再保存为新连接。协议、请求定制和认证配置随副本带入,已保存的 API Key 无需重新输入。
|
||||
|
||||
复制后仍需保存才会生效;当前最多保留 20 条连接。保存地址有误时,界面会指出对应连接并定位到地址字段,便于处理多条连接中的配置问题。
|
||||
|
||||
### Mermaid 图表可导出完整 PNG
|
||||
|
||||
聊天中的流程图或关系图可以打开大图窗口,再导出完整 PNG。导出内容不受当前缩放比例和拖动位置影响,适合插入报告、文档或演示材料。
|
||||
|
||||
图片沿用当前主题背景,最长边上限为 4096 像素。此功能用于 Mermaid 图表,故事线图谱的图片导出不在本轮范围内。
|
||||
|
||||
> **【待补图 03|建议|图表导出】** 在正常聊天中打开一张公开示例 Mermaid 图,执行 PNG 导出,并核对图片包含整张图。优先展示实际导出结果,图注注明它是导出图片。计划文件:`assets/03-mermaid-export.png`。
|
||||
>
|
||||
> 建议图注:从 Mermaid 大图窗口导出完整 PNG,保留图中的边缘节点。
|
||||
|
||||
### 桌面通知可以单独关闭
|
||||
|
||||
“设置 → 平台功能 → 通用设置”新增“桌面通知”开关,默认开启。关闭后,应用处于后台时的任务完成、失败或取消等系统提醒停止弹出,应用内通知仍然保留。设置保存后立即生效,重启后也会记住选择。
|
||||
|
||||
## 功能改进
|
||||
|
||||
### 会话搜索按需展开,快捷键提示集中在输入框
|
||||
|
||||
侧栏的搜索入口与“新建对话”放在同一行,点击后展开并自动聚焦,可查找会话标题或消息正文。切换会话保留关键词;点击关闭按钮,或在搜索控件行内按 Escape,可清空并收起搜索。展开和收起时,会话列表位置保持不变。
|
||||
|
||||
输入框的空白提示集中显示发送、换行、粘贴、新建对话及可用的快捷唤起按键,并按系统显示 Ctrl 或 Command。修改快捷键设置后提示随之更新;快捷唤起已关闭或注册失败时,不再显示不可用的按键。
|
||||
|
||||
侧栏底部的“应用”和“设置”保留文字并分开显示,应用菜单箭头与向上展开方向一致。会话列表独立滚动,短窗口中的入口仍可到达,滚动条和分隔线样式也作了统一。
|
||||
|
||||
### 知识库文档与来源集中浏览
|
||||
|
||||
知识库将内容来源与文档索引合并为统一列表。单文档来源合成一行,目录继续按组展示,导入失败、尚未生成文档的来源也保留恢复入口。搜索可以同时查找来源与文档,网址来源保留原网址,便于辨认同名资料。
|
||||
|
||||
列表突出查看入口,打开原文、分块管理、重新解析等操作收进更多菜单。解析结果页也整理了返回导航和图片操作,减少长名称、多个按钮挤在一行的情况。
|
||||
|
||||
任务历史改为按批次展示,可以展开处理步骤,查看进行中、失败与历史记录。筛选与计数跟随当前文档或来源,便于检查一次导入的处理情况。
|
||||
|
||||
### 图谱按事件、实体和关系切换
|
||||
|
||||
故事线图谱侧栏将原来上下堆叠的列表改为“事件、实体、关系”页签,各自显示数量并独立滚动。切换页签保留已有选中对象,在画布选中对象时,侧栏会切到对应类别,查看关联信息时少一些来回滚动。
|
||||
|
||||
### 自动监督与手动回顾分开管理
|
||||
|
||||
原有的每日、每周计划现在集中到“自动监督”。新建或编辑计划时,可以选择全局或多个项目,设置时间、时区、回顾窗口和历史保留期限;暂停的计划在编辑保存后仍保持暂停。
|
||||
|
||||
自动报告与监督回顾分别记录处理进度。对于对应阶段没有新增、修改或待处理内容的情况,会跳过模型调用;手动回顾则重新分析选择的时间范围。删除报告或计划不会重置已经记录的来源处理进度。
|
||||
|
||||
启用监督者不会自动创建计划。定时工作需要桌面应用保持运行,关闭监督者会停止发起新的回顾,并保留计划和历史;从导航取消常驻只改变入口显示。尚无活动时,自动监督页会隐藏空的统计、建议和历史区域,先展示计划入口。
|
||||
|
||||
监督分析会将入选内容交给配置的模型服务,可能产生费用。它以只读、无工具的方式分析记录;自动报告与回顾可能分别调用模型,长时间范围也可能分成多批。并发数和超时设置不等于总费用上限。
|
||||
|
||||
### 长回顾可以看进度、保留批次并继续处理
|
||||
|
||||
监督者的“活动记录”集中展示手动和自动执行情况。展开记录,可以查看当前阶段、已保存批次、剩余来源和失败原因,再按项目、会话、批次检查已保留事实与来源片段。
|
||||
|
||||
回顾会分页读取选定范围内的来源,将长内容拆成批次处理。成功批次保存后,后续阶段失败不会把这些内容一并丢弃;暂停或失败后可以继续。0.13.16 还取消了按固定累计时长自动暂停的行为,长回顾可以持续处理至完成,无需隔一段时间手动续跑。
|
||||
|
||||
需要调整处理方式时,可在“监督者 → 设置”中配置模型并发、单次模型超时、每次读取的来源条数、每批消息和文本量,以及单次响应容量。新建回顾会保存分批配置;来源已被修改或删除时,需要重新发起回顾。
|
||||
|
||||
> **【待补图 04|必补|回顾进度与来源批次】** 展开真实运行的活动记录,展示阶段、已保存批次和来源正文。若展示暂停后继续,须通过真实操作完成,不注入运行状态。图 01 的演示可复用同一份记录。计划文件:`assets/04-review-progress.png`。
|
||||
>
|
||||
> 建议图注:从活动记录查看处理阶段与已保存批次,展开核对来源。
|
||||
|
||||
> **【待核对 C01|暂停与取消配图】** `v0.15.0` 已包含 `5116613` 的暂停控件修复与取消入口,见末尾“回顾运行期间的控制”。截图须对应目标版本,展示实际暂停、继续和取消操作。
|
||||
|
||||
分页和批次记录便于核查处理范围,模型给出的总结、实体和关系仍需人工判断;来源处理完成不代表每个事实都被模型准确理解。
|
||||
|
||||
### 待办、任务与用量更便于浏览
|
||||
|
||||
魔法笔记的待办页可以拖动列表与详情之间的分隔条,调整后的宽度会保存。来源笔记标题支持独立折叠,收起一个分组不会清空正在查看的任务详情。分组折叠状态不跨重启保存,窄窗口下不提供横向拖宽。
|
||||
|
||||
笔记详情中的记录索引开关移到返回按钮旁,索引和 AI 评论开关都补上了文字标签。任务中心展开列表后,可以直接选择“全部、进行中、暂停、已结束”;默认显示进行中的任务,历史任务仍可通过切换状态查看。
|
||||
|
||||
> **【待补图 05|建议|待办布局】** 用虚构笔记创建不同来源的待办,拖动分隔条并折叠一个来源组,保持另一项详情可见。计划文件:`assets/05-note-todos.png`。
|
||||
>
|
||||
> 建议图注:调整待办列表宽度,按来源笔记收起暂时不看的任务。
|
||||
|
||||
运行记录中的 Token 用量先显示项目或会话总计,展开后再看 Runtime 和模型明细,按模型分组的视图继续保留。这里汇总的是应用已有的用量记录,并非服务商计费账单。
|
||||
|
||||
### 聊天与笔记启动减少重复处理
|
||||
|
||||
任务统计转到后台查询,隐藏的任务面板保留操作状态并减少不必要的更新。较长任务列表也减少了屏幕外卡片的绘制工作。
|
||||
|
||||
流式活动更新时,只保存变化的记录,并减少连续保存过程中反复读取整份历史的次数。改动针对工具活动较多、运行记录较长的对话,保留原有内容与顺序;实际响应改善取决于历史规模和设备,不以测试中的数据库指标代替整机提速幅度。
|
||||
|
||||
聊天输入和流式回复减少了无关活动面板的刷新;置顶或取消置顶会话时,也不再附带扫描附件引用。笔记启动检查复用已读取的正文信息,减少重复读取,原有内容恢复与清理流程保留。
|
||||
|
||||
### 设置页减少来回查找
|
||||
|
||||
长设置表单的分类标题与相关页签固定在顶部,请求 Header、Body 等低频选项收进高级设置。默认工作目录移到“平台功能 → 通用设置”,Skills 和 MCP 页面移除重复标题,保留导入与添加操作。
|
||||
|
||||
通用设置进一步按用途整理为快捷键、会话与通知、工作区与下载等区域,桌面通知、默认工作目录和模型下载源更容易找到。
|
||||
|
||||
HTTP OCR 高级设置可以直接选择是否保留页眉、页脚、页码等内容,并恢复默认过滤方式。版面与生成参数的分组和间距也重新整理;具体选项效果仍取决于所连接的 OCR 服务。
|
||||
|
||||
成功和提示通知采用更紧凑的卡片,两秒后自动消失;错误提示继续保留,直至手动关闭。删除会话的确认框也去掉了重复警告,永久删除的含义不变。
|
||||
|
||||
## 问题修复
|
||||
|
||||
### 直连文本模型恢复手动压缩上下文
|
||||
|
||||
本地直连文本会话可以从输入区点击“压缩上下文”,即使关闭自动压缩或尚未达到触发阈值,也能手动执行。压缩使用配置的摘要连接,摘要随会话保存并用于后续对话,同时保留最近轮次和完整聊天历史;关闭自动压缩后,已有有效摘要仍可使用。
|
||||
|
||||
会话运行或正在压缩时需等待完成;没有可压缩的较早历史时会提示。这项修复适用于本地直连文本会话,不包含图像生成连接、远程通道会话或 SSH 项目。
|
||||
|
||||
### 长请求持续保留已授权的工具访问
|
||||
|
||||
修复桌面 Agent 请求持续超过十分钟后,工具授权提前失效的问题。请求仍在执行时,已启用并分配的知识库、笔记、浏览器等工具可继续使用;完成、取消或失败清理时仍会撤销该次授权。工具自身的调用超时、读写权限和开关设置保持不变。
|
||||
|
||||
### 取消与失败提示更清楚
|
||||
|
||||
取消和失败信息集中显示在消息状态中,减少与回答正文或工具详情的重复。主动取消使用中性提示,真实失败继续显示错误状态,已经生成的回答保留。
|
||||
|
||||
最后一条失败或取消消息有可恢复的原问题文字时,可以点击“重新编辑”将文字回填输入框,修改后自行发送;不会自动重发,也不承诺恢复附件。
|
||||
|
||||
### 远程回答完成后,可以继续对话
|
||||
|
||||
远程请求现在等待模型交付确认后再结束。回答已经完成时,随后回收空闲 Runtime 失败不会再把结果改成“未知”。确实遇到结果未知的请求,用户显式发送新消息后会建立新的运行绑定并带入已有历史;自动恢复仍只重新连接原请求,不会擅自重复执行结果未知的任务。
|
||||
|
||||
最后一个活动任务结束后,远程空闲 Runtime 会被释放,下一轮对话再恢复历史。仍有任务或待答问题的共享进程会保留;更新后被替换的旧 Agent 会等待已有工作结束再退出,当前 Agent 保持常驻。
|
||||
|
||||
Host 更新还会清理已确认停用的旧 Agent 程序和归属明确的孤儿进程,保留会话历史、活动安装和状态不明的安装。这些完成状态与进程清理修复自 Agent 0.13.4 起提供;本轮建议配套 Agent 0.15.0,仅升级桌面不会直接替换 Host 上已经运行的旧进程。
|
||||
|
||||
### 启动、搜索与回顾结果
|
||||
|
||||
- 修复正常聊天或保存笔记后,重启反复显示历史迁移的问题。普通数据库结构升级也不再因正常空闲页额外整理整库;确需转换的旧数据仍会处理,启动页区分实际操作。
|
||||
- 修复本机直连模型文件搜索参数受限和大结果截断的问题。模型可使用 ripgrep 原生参数,保留原生结果与退出码,并分页续读长输出。Ask 保持工作区只读,Execute 使用当前账号权限;这项变更不属于远程 Agent 或其他 Runtime 的新增工具。
|
||||
- 修复早期监督回顾只取部分会话、消息和正文的问题,改为对入选来源分页、分批处理。事实与来源独立保存,只有必要阶段完成并成功保存结果后才标记完成。
|
||||
- 修复监督回顾中的旧实体引用、摘要合并校验及长摘要报错。非法格式、未知引用和超出响应容量的结果仍会报错,成功保存的批次可以保留供后续处理。
|
||||
- 修复历史回顾入口跳到其他结果、切换后旧响应覆盖当前选择的问题。侧栏、活动记录和图谱按对应结果定位,人工确认与修订的内容保留。
|
||||
|
||||
### 日常界面操作
|
||||
|
||||
- 多个会话同时回复时,侧栏列表不再随流式文本或工具进度反复换位。会话按最新消息的创建时间排序,新消息仍会把会话向前移动,置顶会话继续优先显示。
|
||||
- 输入框的附件、语音与选项按钮统一尺寸、间距和悬停反馈,录音中和选项展开时仍保留对应状态提示。
|
||||
- 切回已查看的会话时,立即显示缓存的累计回复时长,再后台刷新;缓存限本次应用运行期间。
|
||||
- Mermaid 大图放大后,顶部和左侧等边缘仍可通过滚动、拖动到达,窄窗口中的控件可以换行。
|
||||
- Git 分支选择器悬浮在工作区上方,不再把文件列表和提交历史向下挤动;项目选择菜单可以浮出侧栏,长名称与路径有更多显示空间。
|
||||
- 文件差异页将查看文件、刷新和复制路径集中到路径旁,窄面板中可以换行;只有未暂存改动时,省去重复的分区标题。浏览器“前往”按钮改为紧凑图标,保留悬停提示。
|
||||
- 聊天与浏览器、终端工作栏之间的分隔条恢复完整拖动区域;笔记缩略图与内容边缘对齐,键盘焦点轮廓保持可见。
|
||||
- 纯文本排队消息不再显示无效的“查看附件”按钮;浏览器页签关闭失败后重试成功,会清除残留错误。
|
||||
- 监督反馈显示会话或任务名称,固定与刷新按钮在窄侧栏中排列更紧凑。工作回顾和活动页使用可用宽度,运行阶段与已保存批次更醒目。
|
||||
|
||||
### 运行配置与界面修复
|
||||
|
||||
- 修复 Continue 禁用自动更新后仍显示“Checking for updates”的问题,避免空闲终端显示误导性的更新状态。
|
||||
- 补齐 DS Web、远程 Runtime 和模型桥辅助进程启动时的遥测关闭配置;模型、MCP 和用户主动发起的联网请求保持可用。远程遥测配置与 Continue 更新检查修复由 Agent 0.15.0 配套提供,对更新 Host 后新启动的 Runtime 生效,已有进程不会热更新。
|
||||
- 修复知识库不同来源的操作相互阻塞,以及多文档来源中任务范围、筛选计数不一致的问题。
|
||||
- 修复深浅主题中危险操作按钮、禁用状态、控件边框和键盘焦点显示不一致的问题,包括放弃笔记草稿的确认框。
|
||||
- MCP 编辑器和图片预览可以在父弹窗上正常操作;项目弹窗的 Escape 只处理当前弹窗,帮助层覆盖浏览器时不再被原生页面遮挡。
|
||||
- HTML 全屏预览恢复键盘进入与 Escape 返回,继续保持原有沙箱限制。
|
||||
- 窄工作栏的添加按钮不再被滚动箭头遮挡,模型连接协议文字保持可读;DS 入口移除常驻说明,重新打开和停止服务操作继续保留。
|
||||
|
||||
### 回顾运行期间的控制
|
||||
|
||||
回顾运行期间,范围、时间选择和刷新入口继续可用;修改选择不会改变已经启动的回顾。重复点击发起按钮会提示已有运行,避免同时创建重叠回顾。
|
||||
|
||||
活动记录增加取消正在运行回顾的入口,并修复继续回顾后无法再次暂停的问题。暂停保留进度供继续处理;取消会保留已成功保存的批次,但该次回顾不能再继续。取消清理结束前显示“正在取消”,未完成结果不会发布,之后可以新建回顾。
|
||||
|
||||
手动发起、继续与自动回顾共用执行限制;自动回顾在忙碌时等待,手动操作会提示当前已有运行。同一次回顾内部仍可按设置并行处理批次。
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 329 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 149 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 182 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user