@xneog/dsh-client-ui-agent-preset 0.1.0 → 0.1.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-agent-preset/README.md
5
- README.md: f0fdff4b1f2453be9e8b4c1d20f7ca0fee506d55
6
- README.zh.md: 7d78d50c9198363c7a04cc2eb1c9292126feb9e8
5
+ README.md: c933ae67bf0448da33e61a622bbc8d2eeb5f72a2
6
+ README.zh.md: 2edc8aebcb1e6374635a0dbc7bfdafcc3cb53433
package/README.md CHANGED
@@ -1,64 +1,70 @@
1
- # dsh-client-ui-agent-preset
1
+ ---
2
+ description: "Agent-preset surfaces for the Web GUI: the default-preset setting, the new-session chip, the session-header label, and the preset roster management section; for users and maintainers of agent composition."
3
+ kind: "package-reference"
4
+ ---
2
5
 
3
- English | [中文](README.zh.md)
4
-
5
- The agent-preset surfaces: a General-settings row choosing which [preset](../../preset/agent-presets/README.md) new sessions are composed from, a chip on the new-session screen choosing the next session's, a read-only label in the session header, and a settings section that manages the roster — copy, delete, default, and the way into a preset's own files.
6
-
7
- ## Why it is a new-session preference
8
-
9
- A session's preset is fixed when the session is created — the host refuses to adopt an existing session under a different one, because that session's history was produced under the first preset's tools. So this row cannot be a live switch, and it says so: changing it applies to sessions started afterwards while running sessions keep the composition they began with.
6
+ # @xneog/dsh-client-ui-agent-preset
10
7
 
11
- ## The new-session chip
12
-
13
- A second surface, beside the workspace picker on the new-session screen. It sits there rather than in the composer because that is where the choice is still open: a control that spends most of its life disabled belongs on the screen where it still works.
14
-
15
- The chip opens on the deployment default and its pick is *staged* — the screen precedes the session it would apply to. The stage reaches a session when one becomes current and is still blank, which covers both the session the workspace connect created and the blank one it reused; riding along on `sessions.create` would miss the second. It is spent on first use, so the next new session opens on the default again, exactly like the workspace picker beside it.
8
+ English | [中文](README.zh.md)
16
9
 
17
- A session that has started is refused rather than queued: the host answers `agent-preset-locked`, and the stage is dropped instead of waiting for a session that will never accept it.
10
+ ## Summary
18
11
 
19
- ## The session-header label
12
+ This package provides the agent-preset surfaces of the Web GUI: a chip on the new-session screen choosing the next session's preset, a read-only label in the session header, and a settings section that manages the roster — copy, delete, default, and the way into a preset's own files. A session's preset is fixed at creation, so the choice applies to sessions started afterwards while running sessions keep the composition they began with; the default preset is edited in the settings section, where the roster is visible, so General settings carries no duplicate control for the same field. When a deployment composes no presets, all three surfaces render nothing and every session shares the host composition.
20
13
 
21
- A third surface, beside the session title: the preset THIS session runs, as static chrome. A control there would promise a switch the host refuses outright. It reads the preset from the session's own summary and resolves the display name against the same roster the General row reads. Forwarded `agent-preset/selected` owner events fold committed blank-session switches into that shared summary in every tab; the initiating tab may already have applied the RPC echo, and the merge is idempotent.
14
+ ## Table of Contents
22
15
 
23
- ## What it reads and writes
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
24
22
 
25
- Options and the current default both come from one `agentPreset.list` call. The roster already reports which id a session with no explicit choice gets, so the row needs no settings-schema introspection; the write targets the `agent-presets` settings namespace's `default` field, which is what the host resolves at creation.
23
+ -----
26
24
 
27
- A locally authored preset is exactly as privileged as the plugins it names, so the list marks `user` rows rather than presenting every preset as shipped and vetted.
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
28
27
 
29
- Preset files publish one unlocalized `name` and `description`, which Web uses for every `user` row and unknown `system` row. For the four shipped ids (`standard`, `code`, `minimal`, and `cordis`), Web resolves both fields from its active locale only when the roster marks the row `system`; an identically named `user` preset keeps its file metadata.
28
+ Mount this plugin alongside the settings and conversation packages; the preset surfaces then appear where their slots render. The new-session chip opens on the deployment default and stages a pick that lands on the next blank session; the stage is spent on first use, so the following new session opens on the default again.
30
29
 
31
- The row re-reads on `settings/changed` for its own namespace and on `connection/reset`: the roster is a live directory and the default is a settings field, so an external edit or a reconnect can both move it.
30
+ ### Managing the roster
32
31
 
33
- ## The management section
32
+ The settings section shows the roster as cards: a copy dialog is the only way a preset is created — the browser edits no composition text — and every custom card keeps a location action that opens the preset's own files. The default is set from any surface; deleting removes the preset directory while sessions already composed from it keep running. A shipped preset opens in a read-only viewer and offers no location or delete. A roster row carrying `broken` renders as a marked card whose body and duplication are disabled, because a copy of a broken preset is another broken preset; broken custom rows keep their location and delete actions so the files can be fixed and ghost directories cleared. The card face still shows the preset's own description — a chooser cannot act on a package specifier there — and the host's reason rides the badge as a tooltip, plus a visually hidden alert that carries it to assistive technology, which a disabled card body cannot.
34
33
 
35
- A fourth surface, its own settings page (`settings.section` id `agent-presets`, ordered after Models — choosing a model is routine, composing an agent is the deployment-shaping act behind it): the roster as cards, a copy dialog as the only way a preset is created, and a read-only viewer over the shipped compositions.
34
+ ### The conversational entry
36
35
 
37
- The browser edits no composition text. Editing YAML in a web textarea was a weak surface (no completion, no highlighting, no diff), so a new preset is a host-side copy of an existing one — the dialog collects an id (it becomes the directory name, which is why it must be named up front and cannot change later) and an optional display name, and `{ from, id, name? }` is all that crosses the wire. Everything else — description, composition, skills — is edited in the preset's own files, and the page's other job is getting the user TO those files: the copy completes by opening the new directory, and every custom row keeps a location action. Where the host has no desktop opener (`hasDocument: false` on the roster; remote and container deployments), the same actions answer the directory as text on the row instead of offering a button that would spawn into nothing.
36
+ When the roster carries the self-referential `cordis` preset, a dashed add-card stages it and starts a new session — the section closes the settings panel and the new-session chip's own applier composes the blank session the workspace flow produces.
38
37
 
39
- A preset publishes its own description, of any length, and the grid sizes every card row alike — so an unbounded description would set the height of the whole roster. Cards clamp it to four lines and offer the rest in a tooltip, attached only while the text is actually cut off. The clamp is CSS, so the whole description stays in the accessibility tree whatever the card shows.
38
+ -----
40
39
 
41
- A shipped preset opens in the read-only viewer. It is the known-good composition a copy starts from, so reading it is the point; it offers no location and no delete — its install is overwritten by upgrades and is not the user's to manage. The intro carries the guidance a create button used to imply: duplicate an existing preset and make it yours, or let the agent draft one in Creator mode.
40
+ <a id="understand-the-implementation"></a>
41
+ ## Understand the implementation
42
42
 
43
- Beside copying sits the conversational entry: when the roster carries the self-referential `cordis` preset, a dashed add-card (the Models page's affordance) stages it and starts a new session — the section closes the settings panel through the shell's owner-prop `close` and the new-session chip's own applier composes the blank session the workspace flow produces. The seat keeps a late roster load from regressing the display: staged pick first, then the composition the current session already carries, then the deployment default.
43
+ <details>
44
+ <summary>Implementation internals — click to expand</summary>
44
45
 
45
- The dialog mirrors the host's own containment rule (`[a-z0-9][a-z0-9-]*`) and refuses a name already in use — a copy never overwrites. Both checks are conveniences: the host re-applies them and its answer is what the dialog reports on failure.
46
+ The display options come from one `agentPresets/list` call — the roster already reports which id a session with no explicit choice gets, so no surface introspects the settings schema — and the default write, the settings section's make-default action, targets the `agent-presets` settings namespace's `default` field, which is what the host resolves at creation. The settings section queries `settings.canOpenAgentPresetDirectory()` when it first loads and joins that result with the roster; a failed query removes only the native-open affordance. The new-session chip and the header label share one controller, because the staged choice belongs to the flow rather than to any one session; the stage is applied when a session arrives (covering both the session a workspace connect created and the blank one it reused) and dropped on refusal. A refusal announces itself as a transient banner over the composer column, because the chip's label has already reverted and a preset the host refuses to mount is one discovery reported healthy — its roster card carries no reason to go back and read. Only a pick a person just made is announced; the applier that runs when a session becomes current is not. [`dsh-client-connection`](../connection/README.md) authenticates `agentPresets/read`, `agentPresets/copy`, `settings/openAgentPresetDirectory`, `agentPresets/deletePreset`, `agentPresets/list`, and every other Host API method with the same browser session. A composition still names the plugins a session runs, so reading one is reconnaissance, while copy, delete, and the settings-owned directory opener manage the roster and drive the host desktop. The section re-reads on its own actions, `settings/document-updated`, and `connection/reset`, because composition files are edited outside the browser and nothing on the wire announces a file change.
46
47
 
47
- Deleting removes the preset directory. Sessions already composed from it keep running — a composition is mounted once at session creation and nothing re-reads the file.
48
+ </details>
48
49
 
49
- A roster row carrying `broken` (the host's shape check found the composition missing or unloadable) renders as a marked card: red border, a "Failed to load" badge (what discovery observed, not a claim that the files are damaged — the usual cause is a composition the user just edited or deleted), the reason verbatim, the body disabled — it cannot become the default — and duplication disabled, since a copy of a broken preset is another broken preset. A broken custom row keeps its location and delete actions, because the files are where it gets fixed and deleting is how a ghost directory (composition deleted by hand, directory still blocking the id) is cleared; a broken shipped row withholds the viewer too — there is no readable composition to show. The two pickers (the General row and the new-session chip) drop broken presets entirely: they choose the NEXT session's composition, and offering one that cannot compose would only defer the failure to the session start.
50
+ -----
50
51
 
51
- Setting the default writes the `agent-presets` settings namespace, which the host exposes to configuration clients ([`dsh-apiproxy`](../../host/apiproxy/README.md) keeps an explicit allowlist — a namespace outside it makes a picker move and then silently forget).
52
+ <a id="further-exploration"></a>
53
+ ## Further Exploration
52
54
 
53
- `agentPreset.read`, `copy`, `openDocument`, and `remove` are loopback-pinned ([`dsh-client-connection`](../connection/README.md)): a composition names the plugins a session runs, so reading one is reconnaissance, and the rest manage the roster and drive the host desktop. `agentPreset.list` is not — it carries ids, trust, and the two path-free capability flags, and a LAN client's picker needs it.
55
+ Read these pages when the preset surface is not enough. They move from the browser surfaces to the preset domain and the composition model.
54
56
 
55
- ## When the surfaces are absent
57
+ - [dsh-agent-presets](../../preset/agent-presets/README.md) — the host roster and composition the surfaces read and manage.
58
+ - [ui-conversation](../ui-conversation/README.md) — declares the hero and session-header slots the chip and label fill.
59
+ - [ui-settings](../ui-settings/README.md) — the settings shell that hosts the roster section.
60
+ - [Client package map](../README.md) — adjacent browser UI packages.
56
61
 
57
- A deployment that composes no presets answers with an empty roster, and the row, the chip, the label, and the section all render nothing — every session then shares the host composition, and there is nothing to choose between or manage. A deployment that configures no writable root answers `authorable: false`, and the section stays a read-only browser: the shipped compositions still open in the viewer, but every copy action is disabled with the reason as its tooltip rather than offering a dialog whose create always fails.
62
+ -----
58
63
 
64
+ <a id="model-experience"></a>
59
65
  ## Model Experience
60
66
 
61
- Indirectly, through the preset a later session is composed from; [`dsh-agent-presets`](../../preset/agent-presets/README.md) owns what that composition puts in front of the model.
67
+ Indirectly, through the preset a later session is composed from; the preset it selects owns every model-facing effect.
62
68
 
63
69
  #### KV Cache effect
64
70
 
@@ -66,6 +72,23 @@ No direct invalidation. Changing the default never touches a running session's p
66
72
 
67
73
  ## Known Limitations and Deferred Work
68
74
 
69
- - **A preset without metadata is listed by id** — display text is optional, and a copy given no name deliberately falls back to its directory name rather than presenting itself identically to its source.
75
+ <a id="known-limitations-and-deferred-work"></a>
76
+
77
+
78
+ These limits define the current preset surfaces. They are current package constraints, not a general composition comparison or a task backlog.
79
+
80
+ - **A preset without metadata is listed by id** — display text is optional, and a copy given no name deliberately falls back to its directory name rather than presenting itself identically to its source. The resolution itself is the shared `presetDisplayText` fold from [`dsh-agent-presets/display`](../../preset/agent-presets/README.md), which the Settings plugin list inlines over this plugin’s dictionaries to show shipped presets in the active locale without translating user-authored metadata.
70
81
  - **A revealed path is display text, not a link** — where the host has no desktop opener the row shows the directory to copy by hand; the browser cannot open a host filesystem location itself.
71
82
  - **Composition edits are invisible to the page** — the files are edited outside the browser and nothing on the wire announces a file change, so the roster re-reads on its own actions, `settings/changed`, and `connection/reset`, not on every disk edit.
83
+
84
+ <a id="dev-note"></a>
85
+ ### Dev Note
86
+
87
+ <details>
88
+ <summary>Working context for maintainers — click to expand</summary>
89
+
90
+ None.
91
+
92
+ </details>
93
+
94
+ **Runtime invariant:** No companion is published. This is a browser-side surface plugin whose node half owns no event stream or mutable runtime data; the roster and the settings write are host contracts covered there.
package/README.zh.md CHANGED
@@ -1,71 +1,94 @@
1
- # dsh-client-ui-agent-preset
1
+ ---
2
+ description: "Web GUI 的 agent preset 表面:默认 preset 设置、新建会话 chip、会话标题标签与 preset 名单管理分区;供 agent 组装的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
6
+ # @xneog/dsh-client-ui-agent-preset
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- agent preset 的各个表层:General 设置中的一行,用于选择新建会话据以组装的 [preset](../../preset/agent-presets/README.md);新建会话界面上的一枚 chip,用于选择**下一个会话**的 preset;会话标题旁的一个只读标签;以及一个设置页分区,用于管理名单——复制、删除、默认值,以及通往 preset 自身文件的入口。
10
+ ## 概述
6
11
 
7
- ## 为什么它是"新建会话"的偏好设置
12
+ 本包提供 Web GUI 的 agent preset 表面:新建会话界面的一枚 chip,选择下一个会话的 preset;会话标题旁的一个只读标签;以及一个设置分区,用于管理名单——复制、删除、默认值,以及通往 preset 自身文件的入口。会话的 preset 在创建时即固定,因此选择作用于此后开启的会话,运行中的会话保持它们开始时的组装;默认 preset 在能看到名单的设置分区里编辑,通用设置不再为同一字段保留重复控件。当部署未组装任何 preset 时,三个表面都不渲染任何内容,每个会话共用宿主组装。
8
13
 
9
- 会话的 preset 在创建时即固定——宿主拒绝以不同 preset 接管已存在的会话,因为该会话的历史是在最初那份 preset 的工具下产生的。因此本行不可能是实时切换,它也如实说明了这一点:更改只对此后开启的会话生效,而运行中的会话保持它们开始时的组装。
14
+ ## 目录
10
15
 
11
- ## 新建会话 chip
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
12
22
 
13
- 第二个表层,位于新建会话界面上、工作区选择器旁边。它落在这里而非 composer,是因为这里才是选择仍然成立的地方:一个大部分时间处于禁用状态的控件,属于它仍然可用的那个界面。
23
+ -----
14
24
 
15
- chip 以部署默认值打开,其选择是**暂存**的——该界面先于它要应用到的会话存在。暂存值会在某个会话成为当前会话且仍为空白时抵达该会话;这既覆盖工作区连接新建的会话,也覆盖它复用的那个空白会话,而搭 `sessions.create` 的便车会漏掉后者。暂存值一经使用即被清空,因此下一个新会话重新以默认值打开——与它旁边的工作区选择器完全一致。
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
16
27
 
17
- 已经开始的会话会被直接拒绝而非排队:宿主返回 `agent-preset-locked`,暂存值随之丢弃,而不是去等一个永远不会接受它的会话。
28
+ 与设置与对话包一起挂载本插件;preset 表面随即出现在各自槽位渲染之处。新建会话 chip 以部署默认值打开并暂存一个选择,落到下一个空白会话上;暂存一经使用即被清空,因此再下一个新会话重新以默认值打开。
18
29
 
19
- ## 会话标题旁的标签
30
+ ### 管理名单
20
31
 
21
- 第三个表层,位于会话标题旁:**本会话**所运行的 preset,作为静态装饰呈现。在那里放一个控件,等于承诺一次宿主会断然拒绝的切换。它从会话自身的摘要读取 preset,并在 General 行所读的同一份名单上解析显示名称。转发的 owner 事件 `agent-preset/selected` 会在每个标签页中把已经提交的空会话切换折进这份共享摘要;发起方标签页可能已经采用 RPC 回执,而合并是幂等的。
32
+ 设置分区把名单呈现为卡片:复制对话框是创建 preset 的唯一入口——浏览器不编辑任何组装文本——每张自定义卡片都保留一个打开 preset 自身文件的位置动作。默认值可在任一表面设置;删除会移除 preset 目录,而已据其组装的会话继续运行。随附 preset 在只读查看器中打开,不提供位置或删除。名单行携带 `broken` 时渲染为标记卡片,其主体与复制均被禁用,因为损坏 preset 的副本只是另一个损坏 preset;损坏的自定义行保留位置与删除动作,以便修复文件、清掉幽灵目录。卡片正面仍显示 preset 自己的描述——在选择器里,一个包说明符不足以让人采取行动——宿主给出的原因作为提示条挂在徽标上,另有一个视觉隐藏的 alert 把它送达辅助技术,而被禁用的卡片主体做不到这一点。
22
33
 
23
- ## 它读什么、写什么
34
+ ### 对话式入口
24
35
 
25
- 选项与当前默认值都来自同一次 `agentPreset.list` 调用。名单本身已经报告了"未显式选择的会话会得到哪个 id",因此本行无需对 settings schema 做内省;写入目标是 `agent-presets` settings 命名空间的 `default` 字段,也正是宿主在创建时解析的那个字段。
36
+ 名单携带自指的 `cordis` preset 时,一张虚线添加卡会暂存它并开启新会话——分区关闭设置面板,新建会话 chip 自己的应用器负责组装工作区流程产出的空白会话。
26
37
 
27
- 本地创作的 preset 的权限恰好等于它所引用的插件,因此列表会标注 `user` 行,而不是把每个 preset 都呈现为随附且已审核的。
38
+ -----
28
39
 
29
- preset 文件提供一套未国际化的 `name` 与 `description`,Web 将其用于所有 `user` 行和未知的 `system` 行。对于四个随附 id(`standard`、`code`、`minimal` 与 `cordis`),只有名单将该行标记为 `system` 时,Web 才会从当前 locale 解析这两个字段;同名的 `user` preset 仍使用其文件元数据。
40
+ <a id="understand-the-implementation"></a>
41
+ ## 理解实现
30
42
 
31
- 本行在自身命名空间的 `settings/changed` 以及 `connection/reset` 时重新读取:名单是一个活动目录,默认值是一项设置,外部编辑与重新连接都可能改变它。
43
+ <details>
44
+ <summary>实现细节——点击展开</summary>
32
45
 
33
- ## 管理分区
46
+ 展示选项来自同一次 `agentPresets/list` 调用——名单本身已报告未显式选择的会话会得到哪个 id,因此任何表面都无需对 settings schema 做内省——默认值的写入即设置分区的设为默认动作,目标是 `agent-presets` settings 命名空间的 `default` 字段,也正是 Host 在创建时解析的字段。设置分区首次加载时查询 `settings.canOpenAgentPresetDirectory()`,并把结果与名单合并;查询失败只会移除原生打开动作。新建会话 chip 与标题标签共用一个控制器,因为暂存选择属于流程而非任何单个会话;暂存值在会话到达时应用(既覆盖工作区连接新建的会话,也覆盖它复用的空白会话),被拒绝时丢弃。被拒绝会以一条瞬时横幅在 composer 列上方自报,因为 chip 的标签此时已经弹回,而被 Host 拒绝挂载的 preset 正是发现过程报告为健康的那一种——它的名单卡片上没有任何原因可供回头查看。只有人刚做出的选择会被自报;会话成为当前会话时触发的应用器不会。[`dsh-client-connection`](../connection/README.zh.md) 使用同一浏览器会话认证 `agentPresets/read`、`agentPresets/copy`、`settings/openAgentPresetDirectory`、`agentPresets/deletePreset`、`agentPresets/list` 及其他所有 Host API 方法。组装仍会指明一个会话所运行的插件,因此读取属于侦察,而 copy、delete 与 settings 所有的目录打开操作负责管理名单并驱动 Host 桌面。分区在自身操作、`settings/document-updated` 与 `connection/reset` 时重读,因为组装文件在浏览器之外编辑,线上没有任何机制宣布文件变动。
34
47
 
35
- 第四个表层,独立的设置页(`settings.section`,id 为 `agent-presets`,排在「模型」之后——选模型是日常操作,而组装 agent 是它背后那件塑造部署形态的事):名单以卡片呈现,复制对话框是创建 preset 的唯一入口,随附组装则在只读查看器中展示。
48
+ </details>
36
49
 
37
- 浏览器不再编辑任何组装文本。在网页文本域里编 YAML 是弱功能(无补全、无高亮、无 diff),因此新 preset 是宿主端对既有 preset 的一次复制——对话框只收集一个 id(它将成为目录名,所以必须当场取好、事后无法更改)与一个可选显示名,跨越传输层的只有 `{ from, id, name? }`。其余一切——描述、组装、skills——都在 preset 自己的文件里编辑,而本页的另一职责正是把用户送到那些文件面前:复制以打开新目录作为收尾,每张自定义卡片也保有一个位置操作。宿主没有桌面打开器时(名单上的 `hasDocument: false`;远程与容器部署),同样的操作改为把目录以文本显示在卡片上,而不是提供一个点了没反应的按钮。
50
+ -----
38
51
 
39
- preset 自行发布描述,长度不限,而网格让每一行卡片等高——因此不加约束的描述会决定整份名单的高度。卡片把描述截断为四行,其余内容由 tooltip 承载,且仅在文本确实被裁切时才挂载。截断由 CSS 完成,因此无论卡片显示多少,完整描述始终留在无障碍树中。
52
+ <a id="further-exploration"></a>
53
+ ## 进一步探索
40
54
 
41
- 随附 preset 在只读查看器中打开。它是副本据以出发的已知良好组装,因此能读到它正是意义所在;它不提供位置也不提供删除——它的安装目录会被升级覆盖,不归用户管理。开篇引导语承担了从前创建按钮所暗示的信息:复制一份既有预设改成自己的,或用「创造模式」让 Agent 帮你创建。
55
+ 当 preset 面不够用时阅读以下页面。它们从浏览器表面进入 preset 领域与组装模型。
42
56
 
43
- 复制旁边是对话式入口:名单携带自指的 `cordis` preset 时,一张虚线添加卡(模型页的同款样式)会暂存它并开启新会话——分区经外壳的 owner-prop `close` 关闭设置面板,新会话 chip 自己的应用器负责组装工作区流程产出的空白会话。seat 会防止晚到的名单加载回退显示:暂存选择优先,其次是当前会话已携带的组装,最后才是部署默认值。
57
+ - [dsh-agent-presets](../../preset/agent-presets/README.zh.md)——这些表面读取并管理的宿主名单与组装。
58
+ - [ui-conversation](../ui-conversation/README.zh.md)——声明 chip 与标签填充的首屏与会话头部槽位。
59
+ - [ui-settings](../ui-settings/README.zh.md)——承载名单分区的设置外壳。
60
+ - [客户端包映射](../README.zh.md)——相邻的浏览器 UI 包。
44
61
 
45
- 对话框复刻宿主自身的约束规则(`[a-z0-9][a-z0-9-]*`),并拒绝已被占用的名称——复制从不覆写。这两项检查只是便利:宿主会重新校验,失败时对话框报告的正是宿主的答复。
62
+ -----
46
63
 
47
- 删除会移除整个 preset 目录。已据其组装的会话继续运行——组装在会话创建时挂载一次,此后没有任何东西会重新读取该文件。
64
+ <a id="model-experience"></a>
65
+ ## 模型体验
48
66
 
49
- 名单行携带 `broken`(宿主的形状检查发现组装缺失或不可加载)时渲染为标记卡片:红色边框、「加载失败」徽记(discovery 观察到的事实,而非断言文件已损坏——常见起因是用户刚编辑或删除了组装文件)、原样展示的原因、卡片主体禁用——它不能成为默认——复制也禁用,因为损坏 preset 的副本只是又一个损坏的 preset。损坏的自定义行保留位置与删除动作:文件正是修复它的地方,而删除正是清掉幽灵目录(组装文件被手动删除、目录仍占着 id)的方式;损坏的内置行连查看器也不提供——没有可读的组装可展示。两个选择器(通用设置行与新会话 chip)则完全不列出损坏的 preset:它们选的是下一个会话的组装,列出无法组装的选项只会把失败推迟到会话启动。
67
+ 间接影响,经由此后会话据以组装的 preset;它所选择的 preset 拥有所有面向模型的效果。
50
68
 
51
- 设置默认值写入的是 `agent-presets` settings 命名空间,宿主需将其暴露给配置客户端([`dsh-apiproxy`](../../host/apiproxy/README.md) 维护一份显式白名单——不在其中的命名空间会让选择器动一下然后悄悄忘记)。
69
+ #### KV Cache 影响
52
70
 
53
- `agentPreset.read`、`copy`、`openDocument` 与 `remove` 被固定在环回地址(见 [`dsh-client-connection`](../connection/README.md)):组装指明了一个会话所运行的插件,因此读取它是侦察,其余几个则管理名单并驱动宿主桌面。`agentPreset.list` 不在其中——它携带 id、信任级别与两个不含路径的能力标志,而局域网客户端的选择器需要它。
71
+ 没有直接的失效影响。更改默认值绝不触及运行中会话的前缀;此后创建的会话依据它自己的组装建立自己的前缀。
54
72
 
55
- ## 何时不显示这些表层
73
+ ## 已知限制与延期工作
56
74
 
57
- 未组装任何 preset 的部署返回空名单,本行、chip、标签与分区都不渲染任何内容——此时每个会话共用宿主组装,也就无从选择或管理。未配置可写根目录的部署返回 `authorable: false`,分区随之退化为只读浏览:随附组装仍可在查看器中打开,但每个复制操作都被禁用并以原因作提示,而不是给出一个创建必然失败的对话框。
75
+ <a id="known-limitations-and-deferred-work"></a>
58
76
 
59
- ## 模型体验
60
77
 
61
- Indirectly, through the preset a later session is composed from; [`dsh-agent-presets`](../../preset/agent-presets/README.md) owns what that composition puts in front of the model.
78
+ 这些限制界定了当前 preset 表面。它们是当前包约束,不是通用组装对比或任务积压。
62
79
 
63
- #### KV Cache effect
80
+ - **没有元数据的 preset 按 id 列出**——展示文本是可选的,未取名的副本刻意回退到目录名,而不是与其来源呈现得一模一样。解析本身是 [`dsh-agent-presets/display`](../../preset/agent-presets/README.zh.md) 的共享 `presetDisplayText` 纯函数,设置的插件列表把它内联在本插件的字典之上,按当前语言显示内置预设名,同时不翻译用户自建的元数据。
81
+ - **展示的路径是文本,不是链接**——宿主没有桌面打开器时,卡片显示目录供手工复制;浏览器自身无法打开宿主文件系统上的位置。
82
+ - **组装编辑对页面不可见**——文件在浏览器之外编辑,线上不广播文件变动,因此名单只在自身操作、`settings/changed` 与 `connection/reset` 时重读,而非每次磁盘编辑。
64
83
 
65
- 没有直接的失效影响。更改默认值绝不触及运行中会话的前缀;此后创建的会话依据它自己的组装建立自己的前缀。
84
+ <a id="dev-note"></a>
85
+ ### 开发备注
86
+
87
+ <details>
88
+ <summary>维护者的工作上下文——点击展开</summary>
89
+
90
+ 无。
66
91
 
67
- ## 已知限制与暂缓事项
92
+ </details>
68
93
 
69
- - **没有元数据的 preset 按 id 列出** —— 展示文本是可选的,未取名的副本刻意回退到目录名,而不是与其来源呈现得一模一样。
70
- - **展示的路径是文本,不是链接** —— 宿主没有桌面打开器时,卡片显示目录供手工复制;浏览器自身无法打开宿主文件系统上的位置。
71
- - **组装编辑对页面不可见** —— 文件在浏览器之外编辑,传输层不广播文件变动,因此名单只在自身操作、`settings/changed` 与 `connection/reset` 时重读,而非每次磁盘编辑。
94
+ **运行时不变式:** 不发布伴生入口。这是浏览器侧 surface 插件,node half 不拥有事件流或可变运行时数据;roster 与 settings 写入属于 Host 约定。