diff --git a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.i18n.yaml b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.i18n.yaml index 16a39c6917..68269e8997 100644 --- a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.i18n.yaml @@ -9,14 +9,14 @@ en: 6aa396e12264ee48 zh: 56849a18acaf830a /agent-note-initial-draft-content-and-structured-reference-restoration/decision: - en: 9cf2afd9d5e663e9 - zh: ad59b1bec6ec4666 + en: 1a370f23ee32b6a4 + zh: fb969ec929a6c7c9 /agent-note-initial-draft-content-and-structured-reference-restoration/decision/data-model: en: 7f33895364a9f5cc zh: f1c79ea15f5c151e /agent-note-initial-draft-content-and-structured-reference-restoration/decision/classes-and-methods: - en: ca81423a57f898a0 - zh: 98962cc1c6bce113 + en: e57394545d9d93ff + zh: 5ab142e661750b82 /agent-note-initial-draft-content-and-structured-reference-restoration/decision/data-flow: en: dd57e639e9328f1d zh: 5e16cb2e3a73597c diff --git a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md index 678129340f..cbb15cc56a 100644 --- a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md +++ b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.md @@ -12,7 +12,7 @@ New-task entry points need to place unsent content in the composer. A draft cont Keep the existing `SessionInputShell`, `DraftEditorRuntime`, Conversation store, and Session reference lifetime. Plain text and structured drafts enter through the input model. Initial import finishes before `InputHub.shellFor()` returns, without React effects restoring text. Existing input objects are not restored again. React mounts the same editor and binds the existing persistence callback. -The second parameter of `startSession(workspaceId?, options?)` contains `prompt` and `clearPreviousDraft`. `prompt` accepts only a string; structured drafts remain internal to restoration and Workspace transfer. Omitting options preserves the existing flow. Without clearing, existing content is preserved and only an empty draft adopts the prompt. Explicit clearing replaces the target Session's text document, without deleting attachments or changing other Sessions. Prefilling does not send, execute commands, or change `blank`. +The second parameter of `startSession(workspaceId?, options?)` contains `prompt`, `whenDraftExists`, and `clearPreviousDraft`. `prompt` accepts only a string; structured drafts remain internal to restoration and Workspace transfer. Omitting options preserves the existing flow. An empty draft adopts the prompt. When the target already has text or attachments, `whenDraftExists` decides: `keep` (the default) preserves it, `replace` replaces the target Session's text document with the prompt or clears it without one, and `append` adds the prompt as new paragraphs after the existing text and references. Neither deletes attachments or changes other Sessions. `clearPreviousDraft: true` acts as `replace` only when `whenDraftExists` is omitted. Prefilling does not send, execute commands, or change `blank`. ### Data model @@ -41,7 +41,7 @@ The existing `dsh.conversation.` key remains. Readers accept both leg There is no new draft service, storage key, general task framework, or Session creation entry point. SlotRenderer, Host Session logs, command execution, and file-discovery RPCs are unchanged. `InputActions` remains the shared input-action entry; components receive no separate content-initialization callback. -The call parameters are `startSession(workspaceId?: WorkspaceId, options?: StartSessionOptions)`, `requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions)`, `SessionInputShell.requestDraftInitialization(options)`, and the internal `SessionInputShell.setDraft(input: string | DraftSnapshot)`. `StartSessionOptions` aliases `DraftInitializationOptions`, whose fields are `prompt?: string` and `clearPreviousDraft?: boolean`. A shallow copy captures these values before asynchronous creation, and the result addresses only the retained target binding. Initialization distinguishes applied, preserved, and submission-blocked outcomes. Refusal does not clear first; superseded navigation does not write a draft. +The call parameters are `startSession(workspaceId?: WorkspaceId, options?: StartSessionOptions)`, `requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions)`, `SessionInputShell.requestDraftInitialization(options)`, and the internal `SessionInputShell.setDraft(input: string | DraftSnapshot)`. `StartSessionOptions` extends `DraftInitializationOptions`, whose fields are `prompt?: string`, `whenDraftExists?: 'replace' | 'append' | 'keep'`, and `clearPreviousDraft?: boolean`. A shallow copy captures these values before asynchronous creation, and the result addresses only the retained target binding. Initialization distinguishes applied, preserved, and submission-blocked outcomes. Refusal does not clear first; superseded navigation does not write a draft. ### Data flow diff --git a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md index 07c185a969..12d4e4731a 100644 --- a/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md +++ b/.agents/notes/implemented/architecture/2026-09-30-structured-draft-initialization.zh.md @@ -12,7 +12,7 @@ Status: implemented 保留现有 `SessionInputShell`、`DraftEditorRuntime`、Conversation store 和 Session 引用生命周期。普通文字与结构化草稿统一经过输入模型导入;初始导入在 `InputHub.shellFor()` 返回对象前完成,不由 React effect 恢复文字。已存在的输入对象不重新恢复。React 只挂载同一编辑器,并绑定现有持久化回调。 -`startSession(workspaceId?, options?)` 的第二参数保留 `prompt` 与 `clearPreviousDraft`。`prompt` 仅接受字符串;结构化草稿只用于内部恢复和工作区携带。无选项时维持原流程。不清空时保留已有内容,空稿才采用 prompt;显式清空作用于目标 Session 的文字文档,不删除附件,也不修改其他 Session。预填不自动发送、执行命令或改变 `blank`。 +`startSession(workspaceId?, options?)` 的第二参数包含 `prompt`、`whenDraftExists` 与 `clearPreviousDraft`。`prompt` 仅接受字符串;结构化草稿只用于内部恢复和工作区携带。无选项时维持原流程。空稿直接采用 prompt。目标已有文字或附件时由 `whenDraftExists` 决定:`keep`(默认)保留原稿,`replace` 用 prompt 替换目标 Session 的文字文档、无 prompt 时清空,`append` 在原有文字与引用之后另起段落追加 prompt。三者都不删除附件,也不修改其他 Session。只有未传 `whenDraftExists` 时,`clearPreviousDraft: true` 才等同 `replace`。预填不自动发送、执行命令或改变 `blank`。 ### 数据模型 @@ -41,7 +41,7 @@ Status: implemented 不新增草稿服务、存储 key、通用任务框架或另一套 Session 创建入口;不改 SlotRenderer、Host Session 日志、命令执行和文件发现 RPC。`InputActions` 保留统一输入操作入口,组件不单独注入另一条内容初始化回调。 -调用参数依次为 `startSession(workspaceId?: WorkspaceId, options?: StartSessionOptions)`、`requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions)`、`SessionInputShell.requestDraftInitialization(options)`,以及内部的 `SessionInputShell.setDraft(input: string | DraftSnapshot)`。`StartSessionOptions` 直接引用 `DraftInitializationOptions`,字段为 `prompt?: string` 和 `clearPreviousDraft?: boolean`;进入异步创建前浅拷贝这些值,结果只作用于最终保留的 binding。初始化结果区分已应用、保留原稿和提交期间拒绝;拒绝不先清空,导航被后续操作取消时不写稿。 +调用参数依次为 `startSession(workspaceId?: WorkspaceId, options?: StartSessionOptions)`、`requestDraftInitialization(binding: SessionBinding, options: DraftInitializationOptions)`、`SessionInputShell.requestDraftInitialization(options)`,以及内部的 `SessionInputShell.setDraft(input: string | DraftSnapshot)`。`StartSessionOptions` 扩展 `DraftInitializationOptions`,字段为 `prompt?: string`、`whenDraftExists?: 'replace' | 'append' | 'keep'` 和 `clearPreviousDraft?: boolean`;进入异步创建前浅拷贝这些值,结果只作用于最终保留的 binding。初始化结果区分已应用、保留原稿和提交期间拒绝;拒绝不先清空,导航被后续操作取消时不写稿。 ### 数据流 diff --git a/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.i18n.yaml b/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.i18n.yaml new file mode 100644 index 0000000000..1c14701120 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.i18n.yaml @@ -0,0 +1,37 @@ +# Bilingual-pair consistency record for 2026-10-14-plugin-entry-customization.md (docs/i18n/README.md): per heading +# section, a hash of its English and Chinese blocks outside code blocks and generated regions. +# After editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.md +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus: + en: 2fdf5b95d5603955 + zh: bfdc61e7db5f5f5b +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/problem: + en: 896876f139383cba + zh: 42a4aae7e5885780 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision: + en: a6cfc29cb9caa83c + zh: 21bbeb6a7ab20018 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision/user-visible-behavior: + en: f1456281aa937626 + zh: 6fef46b8d72ddd2b +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision/structure-and-ownership: + en: d6a2816ca55b1c38 + zh: 53217016f1595755 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision/package-changes-relative-to-release-dsh-0-2-1: + en: 18ed81fee1ca7d41 + zh: fc298457e54b6488 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision/actions-slots-and-menu-content: + en: c87e2fdd911714b5 + zh: 074426fdc7abafa9 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/decision/the-three-regions: + en: 770c6150e84742ba + zh: 1d619388c8f38646 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/alternatives-considered: + en: 79355028387c4094 + zh: 5b518166e4803ebe +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/verification: + en: 9c6a9ec155bbbfaa + zh: 8bd6e7afc8c43d21 +/agent-note-plugin-entry-customization-region-owned-pins-and-more-menus/consequences: + en: a2459a3316f3ee60 + zh: 713b51329995fe46 diff --git a/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.md b/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.md new file mode 100644 index 0000000000..58e5929ff5 --- /dev/null +++ b/.agents/notes/implemented/architecture/2026-10-14-plugin-entry-customization.md @@ -0,0 +1,136 @@ +# Agent Note: Plugin entry customization: region-owned pins and More menus + +Status: implemented + +English | [中文](2026-10-14-plugin-entry-customization.zh.md) + +## Problem + +The `release/dsh-0.2.1` Web app shows plugin entries in three regions: the left sidebar's panel buttons (`sidebar.panellist`), the Conversation header's View tabs (`conversation.view`), and the right sidebar guide's tool cards (guide entries from the right-sidebar tab registry). Each region shows every entry in registration order, so users cannot hide entries they rarely use, and every installed plugin makes the regions more crowded. Users also cannot browse more plugins or start creating a plugin from these positions. + +The feature ships in `release/dsh-0.2.1` and is later merged back to master with the release, so it changes as little as possible relative to the release: no changes to the slot framework (`ui-slots`, `ui-renderer`), no new Cordis service, `ui-layout` unchanged, and client plugin packages share only types ([Client package export rules](../../../../packages/client/AGENTS.md)). Persisted data must be readable without migration by a later slot-level store for manual order and pin state. + +## Decision + +Each region keeps and persists its own list of unpinned entries and filters its own entry buttons with it. Each region draws its own More button, opens a menu with the shared `Menu` component, and renders its actions slot inside that menu. The default-loaded plugin package `ui-entry-customization` registers the same menu-content component into the three actions slots: the entry list with pin buttons, Browse other plugins, and Create your plugin. This follows the Plugins page's Add plugin menu, where the page draws the button and menu and `ui-agent-preset` adds Create plugin through `plugins.add.actions`. Entries cannot be reordered. + +### User-visible behavior + +- The left sidebar, the Conversation header, and the right sidebar guide each have a More button. Its menu lists the region's customizable entries. Selecting an entry name opens the entry; its pin button shows or hides the entry in the region; the bottom of the menu has Browse other plugins (opens the Plugins main list) and Create your plugin (opens a new or reused blank Session with the Creator preset and fills in the region's prompt without sending it). +- Entries appear in registration order, as in the release; they cannot be reordered. +- Default entries always show and never appear in the menu: Plugins in the left sidebar, Chat in the Conversation header, and Files in the right sidebar. +- Pin state survives page reloads and is shared by every Session. +- Hiding the selected entry does not navigate away from its content; the left-sidebar row or View tab of the selected entry stays visible, as the current item, until another entry is selected. +- The left-sidebar `