@ckanner/dsh-plugin-flywheel 0.28.0 → 0.28.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/PROTOCOL.md CHANGED
@@ -160,6 +160,33 @@ Go doctor 同时检查 Node 与 Codex 命令。包导入成功不证明账号、
160
160
 
161
161
  config/doctor 的 Go CLI 将 SIGTERM/SIGINT 转为 context 取消,等待 watchdog 收尾后才退出。控制调用取消或超过窗口时,host 先发 SIGTERM,诊断动作再留 20 秒让 Go 完成分阶段清理,仍未退出才 SIGKILL;取消始终报告控制失败,即使迟到结果成功也不覆盖它。start/status/stop 保持原控制进程的 500ms 收尾,后台引擎停止仍走独立 stop 协议。
162
162
 
163
+ ### DSH 命令失败与是否派发
164
+
165
+ `/flywheel` 的 DSH command 结果仍使用 `kind:"success"` 或 `kind:"error"`。成功结果的 `text` 是上述 Go control JSON,包括具有合法诊断报告的 doctor 失败。新的 host 将所有 command 失败包装为以下独立 JSON,放在 `kind:"error"` 的 `text` 中;这不是 Go stdout envelope,也不改变 worker JSONL 或模型工具的异常接口:
166
+
167
+ ```json
168
+ {"protocol":1,"type":"flywheel-control-error","action":"start","dispatch":"not-dispatched","message":"taskDir must be an existing directory"}
169
+ ```
170
+
171
+ | 字段 | 语义 |
172
+ |---|---|
173
+ | `protocol`、`type` | 固定为 `1` 和 `flywheel-control-error`,用于区分命令失败与引擎结果 |
174
+ | `action` | 可读取的请求 action 字符串;解析失败或没有字符串 action 时为 `null`;界面必须与自己的在途请求匹配 |
175
+ | `dispatch` | `not-dispatched` 表示宿主证明本次请求没有启动 Go 控制进程;否则为 `unknown` |
176
+ | `message` | 给用户诊断的错误文本,本身不证明进程是否启动,也不能作为另一个 envelope 递归解析 |
177
+
178
+ 只有参数/目录等派发前校验失败、派发前取消,以及进程创建失败且没有成功启动的证据,才能返回 `not-dispatched`。进入控制进程后出现的非零退出、超时、取消、坏 JSON 或任务身份不符都不能取得这项证明,即使错误文本包含相同 JSON。host 对普通错误同样增加外层 envelope,只把原始错误放入 `message`,避免进程返回的文字冒充宿主确认。
179
+
180
+ 界面只有在版本、类型、action、dispatch 和 message 都符合契约时才使用宿主证明。未知协议、旧 host 的纯文本错误、DSH 传输失败或丢失响应均保持 `unknown`。启动/停止的 `unknown` 结果必须先成功查询原任务状态,再决定后续变更;不得自动重试。已确认未派发的拒绝会显示原因,用户可以修正输入或环境后重新提交。一次未派发的状态查询也不能解除更早启动/停止留下的未确认结果。
181
+
182
+ host 在调用 Go 前把任务和仓库目录规范化为真实路径,并校验引擎返回的任务身份。界面不能把用户输入的符号链接、`..`、尾部斜杠或 Mac `/var` 与 `/private/var` 的文本差异当作引擎身份错误;响应接纳依赖 host 的路径校验和当前请求关联。
183
+
184
+ ### 浏览器查看状态的边界
185
+
186
+ 浏览器端遵循[外部 plain-JS 插件实践](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md),不运行时导入 Harness Client 包。插件自有的 store handle 只通过公开的 `spec`/`create()` 结构交给槽位注册;每个实例提供 `actions`、`getSnapshot()`、`subscribe()` 和 `clearPersisted()`,由宿主负责会话作用域、实例缓存与 hooks 绑定。当前没有持久化配置,`clearPersisted()` 不删除任何任务文件。
187
+
188
+ 异步控制层另有插件自有 observable,快照在未变化时保持同一身份,经 `inject.hooks` 交给宿主绑定;React 组件不自行订阅,不读取 ctx 或原始服务对象。路径草稿与控制快照只是查看缓存,不成为任务账本,也不写入新的 DSH 会话事件。模型可见的命令和工具结果仍由宿主原有记录机制处理。此查看契约不改变 Go control 协议、worker JSONL 或后台任务的停止语义。
189
+
163
190
  ## npm 安装报告与桌面入口
164
191
 
165
192
  以下是 Node 安装器的独立契约,不与 worker JSONL、Go control envelope 或任务 `state.json` 混用。入口为 `npx -y @ckanner/flywheel@latest install` 或已安装包的 `flywheel setup`;二者共用参数与行为。普通 npm 包安装没有修改用户目录的 postinstall,只有显式 install/setup 执行 skills、安装记录和 DSH profile 配置。
package/README.en.md CHANGED
@@ -7,17 +7,21 @@ provides its DSH SDK and Codex Pro workers. The engine owns task state, budgets,
7
7
  verification, Git delivery, and process lifecycles. The desktop is a control and
8
8
  observation interface; it does not need a parent model session to keep a task alive.
9
9
 
10
- This guide describes the **Flywheel 0.28.0** interfaces. Source availability does
10
+ This guide describes the **Flywheel 0.28.1** interfaces. Source availability does
11
11
  not mean that npm `latest` already contains them. Check the registry version and
12
12
  the [release guide](https://github.com/ckanner/flywheel/blob/main/docs/en/releasing.md) before installing. The desktop
13
13
  compatibility baseline is **DSH Mac 0.2.1-rc.5**, not a claim that every DSH build
14
14
  or provider adapter is compatible.
15
15
 
16
+ **Flywheel 0.28.1 introduces the native conversation view.** Version `0.28.0`
17
+ uses the composer popup. Upgrade the CLI and desktop plugin to the same new
18
+ version; merging source does not update an installed plugin.
19
+
16
20
  ## Components
17
21
 
18
22
  | Component | Responsibility |
19
23
  |---|---|
20
- | Flywheel panel | Inspect configuration, run local checks, and start, observe, or stop a task |
24
+ | Flywheel conversation view | A native view alongside Chat and Trajectory for task progress, intervention, configuration, checks, and explicit start/refresh/stop |
21
25
  | `/flywheel` command | Invoke the Go control interface from an explicit desktop command |
22
26
  | `flywheel_control` tool | Expose the same control operations to the host model |
23
27
  | `flywheel-dsh-worker` | Run one native model session through an independent DSH SDK profile |
@@ -27,6 +31,11 @@ The plugin has no separate task database and does not write `state.json`.
27
31
  Kimi CLI, Codex Pro, and the explicit legacy Codex CLI path have separate Go
28
32
  drivers. A DSH LLM provider and an external agent tool are different interfaces.
29
33
 
34
+ The view answers which stage is running, what needs attention, which models are
35
+ configured, and how to stop or recover the task. Requirement discussion, contract
36
+ preparation, and ordinary conversation stay in DSH's chat and skills. Flywheel
37
+ does not replace the host's composer, model selector, trajectory, or right sidebar.
38
+
30
39
  ## Install the complete application
31
40
 
32
41
  You need **Node.js 22.18.0 or later**, npm, and the existing DSH Mac desktop with
@@ -151,10 +160,12 @@ actual inference result. Keep `warn`, `unknown`, and `skipped` distinct from
151
160
 
152
161
  ## Use the desktop controls
153
162
 
154
- Open the **Flywheel** panel below the DSH session input. Select the absolute
155
- task worktree path as the repository directory and the task directory inside
156
- that same worktree. Prepare and review the contracts first; the panel does not
157
- turn an empty directory into a complete task plan.
163
+ Open a DSH session and choose **Flywheel** in the native view bar alongside
164
+ Chat and Trajectory. If the entry is not directly visible, check that bar's
165
+ More menu. Select the absolute task worktree path as the repository directory
166
+ and the task directory inside that same worktree. A blank repository field
167
+ uses the current session's starting directory. Prepare and review the contracts
168
+ first; the view does not turn an empty directory into a complete task plan.
158
169
 
159
170
  The panel, `/flywheel`, and `flywheel_control` share these Go operations:
160
171
 
@@ -171,6 +182,79 @@ engine; closing the panel or desktop is not a stop request. Refresh status to
171
182
  observe it, and use `stop` to request shutdown. `ok: true` describes a successful
172
183
  control operation; task completion is recorded in `state.status`.
173
184
 
185
+ Opening the view starts no task or probe. It reads on explicit actions, without
186
+ automatic polling or task discovery. To observe a task started through another
187
+ entry point, select its task directory and refresh. Effective configuration comes
188
+ from the engine's selected file; installing the plugin or changing DSH's chat
189
+ model does not migrate that configuration.
190
+
191
+ ### View, request, and task lifetimes
192
+
193
+ Task and repository drafts and fetched snapshots are retained separately for
194
+ each DSH session across Chat/Trajectory/Flywheel view switches while the host
195
+ retains that session binding. They are not a task database or durable storage
196
+ across binding release, plugin reload, or desktop restart. Only one control
197
+ request is pending per session. Start/stop locks the directory fields while
198
+ waiting. A read-only request allows path edits, but stays pending until its reply
199
+ settles and rejects late results for the previous selection. Hiding a view does
200
+ not make a pending operation complete.
201
+
202
+ Task state is the last successful snapshot with its refresh time, not a live
203
+ monitor. Failed reads retain valid prior content and show the failure. A lost,
204
+ timed-out, or disconnected start/stop response means the outcome is **unconfirmed**;
205
+ it does not prove that nothing started or that a task stopped. Refresh the same
206
+ task first and inspect its log when needed before deciding how to recover.
207
+ Until a successful status refresh reconciles that task, the view keeps the
208
+ uncertainty visible and disables further starts and stops. It never automatically
209
+ retries a start or stop.
210
+
211
+ A missing directory or a control process that cannot be created is recoverable
212
+ after correcting the input or environment only when the host supplies structured
213
+ evidence that the request was not dispatched. An ordinary error, connection loss,
214
+ or error-message text cannot establish that fact or dismiss an unconfirmed outcome.
215
+ The `/flywheel` command's error `text` uses the JSON discriminator
216
+ `type:"flywheel-control-error"`; its fields and compatibility behavior are defined
217
+ in the [command failure protocol](PROTOCOL.md#dsh-命令失败与是否派发) (Chinese).
218
+
219
+ Switching views, closing the session page, removing the plugin, or exiting DSH
220
+ does not stop the independent Go task. Request an explicit stop and await engine
221
+ confirmation. DSH's trajectory retains its own parent-session command and tool
222
+ events. Complete SDK, Kimi, and Codex Pro worker histories are not automatically
223
+ merged into that trajectory or presented as native DSH background tasks.
224
+
225
+ ### Host UI contract
226
+
227
+ The client uses `ctx.slots.inject()` and a distinct `id: flywheel` in the
228
+ `conversation.view` list. The host owns session scope and view navigation. Chat,
229
+ Trajectory, the composer, and the right sidebar keep their existing entries;
230
+ Flywheel neither shadows them nor draws a separate floating sidebar or composer
231
+ popup. Long paths, model details, and errors wrap or scroll inside the view.
232
+
233
+ As an external plain-JS plugin, the browser module imports only shared React at
234
+ runtime. It does not import `ui-primitives`, `client-store`, or another Harness
235
+ Client package. The plugin owns its buttons, inputs, viewing-state store handle,
236
+ and observable; the host manages registered session instances and binds their
237
+ read hooks. Locale comes through the injected service. Controls follow the
238
+ checked host markup and interactions, consume semantic color aliases, inherit
239
+ the host font, and mount compiled CSS Modules through the React view.
240
+
241
+ The baseline is the exact source snapshot `b830ec950faba0a46dda564be3e2d854afed94f1`,
242
+ which declares version `0.2.1-rc.5`: [external plugin practices](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md),
243
+ [UI guidance](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/.agents/skills/dsh-client-ui-ux/SKILL.md),
244
+ [layout](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/client/ui-layout/README.md),
245
+ [conversation slots](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/client/ui-conversation/src/client/contract/slots.ts),
246
+ and [slot lifecycle](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/docs/subsystems/slots.md).
247
+ The view sits within Conversation's existing header and content geometry; it
248
+ does not change global window-chrome clearance. Source-contract inspection does
249
+ not establish a live Mac desktop pass.
250
+
251
+ Offline UI checks execute the built plugin's own controls, store handle, and
252
+ observable with React and jsdom. Component fixtures adapt slot bindings and
253
+ Remote; a separate check uses the published rc.5 renderer, slots, and Cordis to
254
+ exercise registration, session generations, declaration collapse/restoration,
255
+ and disposal. These checks do not establish real browser geometry or Mac
256
+ window behavior.
257
+
174
258
  Use one task integration worktree for preparation, planning, milestone
175
259
  verification, and the eventual PR. The engine manages packet worktrees for
176
260
  execution, L1, and review. A successful packet is merged into the branch of the
@@ -180,13 +264,33 @@ GitHub PRs, merge remote PRs, or publish packages. See the
180
264
 
181
265
  ## Permissions and lifecycle boundaries
182
266
 
267
+ Desktop integration and worker policy have different scopes. The worker's
268
+ temporary overlay applies only to its independent **SDK process**; it does not
269
+ edit the desktop profile or remove the desktop's plugins, skills, tools, or UI.
270
+ Conversely, desktop installation and sign-in do not prove that the SDK profile
271
+ loads and authorizes the same capabilities. Verify each selected harness through
272
+ its own configuration and supported authorization flow.
273
+
183
274
  The DSH worker requests `read-only` or `workspace-write`, fixes approvals to
184
275
  `never`, and verifies the effective SDK policy before sending the task prompt.
185
- On the checked Mac host, the DSH sandbox uses its Seatbelt runner and filesystem
276
+ In the checked Mac source, the DSH sandbox uses its Seatbelt runner and filesystem
186
277
  fence. Workspace writes include DSH's permitted temporary area; this is not a
187
278
  network-isolation guarantee. Missing or incomplete enforcement is a failure,
188
279
  not a reason to switch to unrestricted access.
189
280
 
281
+ The SDK overlay disables worker-owned delegation, workflow/goal drivers, model
282
+ titles, and automatic model compaction so the Go owner can bound work and
283
+ account for model calls. It also currently disables the whole `tool-web` package,
284
+ including both `web_search` and `web_fetch`. This is a conservative policy,
285
+ not a claim that every DSH web operation requires a model: the official
286
+ [web tool](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/web/tool-web/README.md)
287
+ configures search and fetch independently, while the
288
+ [DeepSeek search backend](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/web/web-search-deepseek/README.md)
289
+ does use an auxiliary model request. This UI fix keeps worker policy unchanged.
290
+ Restoring retrieval or [automatic compaction](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/compaction/compaction-basic/README.md)
291
+ requires a separate check of accounting, budgets, cancellation, and directory
292
+ ownership; the view's location does not establish those guarantees.
293
+
190
294
  Codex Pro uses fresh ephemeral calls and checks the model, directory, approval
191
295
  policy, and sandbox mode before execution. In version 0.8.0, the full
192
296
  `sandboxPolicy` reaches Flywheel only in the returned receipt. Flywheel rejects
package/README.md CHANGED
@@ -6,11 +6,13 @@
6
6
 
7
7
  完整的 npm 安装、SDK 配置到首个任务流程见 [Mac 入门教程](../../docs/getting-started.md),适用于 Flywheel **0.28.0 及以后的完整 npm 发行版**。安装前用 `npm view @ckanner/flywheel version` 确认 registry 的 latest 已更新到所需版本;源码合并或 GitHub Release 不代表 npm 已发行。旧 0.22.1 没有本教程使用的安装与 DSH 接口,当前发行状态见[发行记录](../../docs/releasing.md#3-失败恢复)。
8
8
 
9
+ **Flywheel 0.28.1 引入原生会话视图**;0.28.0 仍使用输入区底部弹层。需要升级 CLI 与桌面插件到同一新版本,源码合并不会自动更新已安装的插件。
10
+
9
11
  ## 提供什么
10
12
 
11
13
  | 部分 | 行为 |
12
14
  |---|---|
13
- | 桌面面板 | 会话输入框底部的 **Flywheel** 按钮;配置查看、环境检查、SDK 无推理探测、启动/刷新/停止;显示全部工作单元、逐项诊断与未知计量 |
15
+ | 桌面会话视图 | 与“对话/轨迹”并列的 **Flywheel** 视图;查看任务进度和待处理事项、检查模型配置与环境、启动/刷新/停止已有任务 |
14
16
  | `/flywheel` | 人工 slash command,通过已有 DSH commands Remote 调用 Go CLI;不会将控制指令交给模型执行 |
15
17
  | `flywheel_control` | 模型工具,复用同一个校验与 CLI 控制路径;后台 start 很快返回,stop 等待引擎确认 |
16
18
  | `flywheel-dsh-worker` | 独立 Node 进程,通过官方 `dsh --profile sdk` stdio JSON-RPC 执行一个原生模型会话 |
@@ -19,6 +21,8 @@
19
21
 
20
22
  插件没有自己的任务数据库,不直接读写 `state.json`。桌面退出不会让后台 Go 任务失去父智能体;Go 拥有 worker 生命周期。原生 SDK 入口只接收已注册的 LLM adapter provider;`subagent_codex_pro`、Kimi ACP、Teams 都不是此接口的 provider。Kimi CLI、Codex Pro machine API 和旧显式 Codex CLI 使用各自 Go driver;Codex Pro 复用同一插件 runner,不经过 DSH 父模型或工具名转发。
21
23
 
24
+ 这个视图用于回答“任务运行到了哪一步、哪里需要处理、使用哪些模型,以及如何停止或恢复”。需求讨论、编写契约和一般对话继续使用 DSH 的对话与 skills;Flywheel 不提供另一套聊天界面,也不接管 DSH 的模型选择器、输入框、轨迹或右侧栏。
25
+
22
26
  ## 一条命令安装到自己的 Mac
23
27
 
24
28
  已有 Node.js 22.18.0 或更高、npm 和 DSH Mac 桌面后,先确认 About、桌面安装的 `dsh --version` 与实际运行入口,再运行:
@@ -117,7 +121,7 @@ node --input-type=module -e 'console.log(JSON.stringify({type:"start",protocol:1
117
121
 
118
122
  ## 桌面使用
119
123
 
120
- 打开一个 DSH 会话,点击输入区底部的 **Flywheel**,填写已准备并审阅契约的任务目录,例如 `/repo/docs/my-task`。仓库目录默认取当前 DSH 会话的起始目录,也可填明确的绝对路径。按钮只执行以下 Go JSON 控制接口:
124
+ 打开一个 DSH 会话,在顶部“对话/轨迹”所在的视图栏选择 **Flywheel**。入口由 DSH 的原生视图栏管理;若未直接显示,检查该栏的更多视图入口。填写已准备并审阅契约的任务目录,例如 `/repo/docs/my-task`。仓库目录默认取当前 DSH 会话的起始目录,也可填明确的绝对路径;生产任务应显式选择任务集成 worktree 及其内部的任务目录。按钮只执行以下 Go JSON 控制接口:
121
125
 
122
126
  ```sh
123
127
  flywheel control status --task-dir /repo/docs/my-task --cwd /repo
@@ -133,11 +137,29 @@ flywheel control doctor --task-dir /repo/docs/my-task --cwd /repo --probe
133
137
  /flywheel {"action":"status","taskDir":"/repo/docs/my-task","cwd":"/repo"}
134
138
  ```
135
139
 
136
- 模型工具 `flywheel_control` 接受 `action`、`taskDir`、`cwd`,以及仅用于 doctor 的可选 `probe` 布尔值。config/doctor 可省 taskDir,cwd 可沿用会话目录;start/status/stop 必须指定任务。输入统一校验,使用 argv 调用,不拼接 shell 命令。面板只在点击时读取状态,不自动轮询,也不重新决定模型路由。
140
+ 模型工具 `flywheel_control` 接受 `action`、`taskDir`、`cwd`,以及仅用于 doctor 的可选 `probe` 布尔值。config/doctor 可省 taskDir,cwd 可沿用会话目录;start/status/stop 必须指定任务。输入统一校验,使用 argv 调用,不拼接 shell 命令。打开视图不会启动任务或探测;视图只在点击时读取状态,不自动轮询,也不自动发现其他入口启动的任务。查看已有任务时,选择同一任务目录再刷新。
137
141
 
138
142
  “查看模型配置”展示配置来源、展开后的阶段绑定及 provider/channel;“检查环境”不启动 SDK,“SDK 无推理检查”显式启用 probe。doctor 的合法退出码 1 会显示逐项诊断,超时、坏协议或不匹配的任务身份仍视为控制错误。`ok:true` 不代表账号、额度和真实推理通过。
139
143
 
140
- 状态区区分未初始化、运行、已完成、暂停、停止、升级和预算停止;全部 packet 可见,不会只展示前几个。未知 usage/cost 明确保留,原始 JSON 默认折叠。改任务/仓库路径会清空旧视图并忽略旧请求的迟到结果。关闭面板、卸载插件或退出桌面,不等于停止任务;重新打开后按“刷新状态”恢复观察,需停止时点“停止”。
144
+ 状态区区分未初始化、运行、已完成、暂停、停止、升级和预算停止;全部 packet 可见,不会只展示前几个。未知 usage/cost 明确保留,原始 JSON 默认折叠。配置显示引擎实际选择的文件及阶段绑定;已有用户配置不会因安装或切换 DSH 对话模型而自动迁移。
145
+
146
+ ### 视图、请求与任务的生命周期
147
+
148
+ 任务/仓库路径草稿和已取得的快照按 DSH 会话分别保留,在宿主仍保留该会话绑定时,切换“对话/轨迹/Flywheel”后可以继续使用;这不是任务数据库,也不保证在会话绑定释放、插件重载或桌面重启后继续保留。每个会话同一时刻只等待一个控制请求。启动/停止等待期间锁定目录输入;只读请求等待期间可以编辑路径,但仍等待已有请求返回,并忽略旧选择的迟到响应。切换视图不会把等待中的请求当成已经完成。
149
+
150
+ 任务状态是最近一次成功读取的快照,带有刷新时间,不能当作实时监控。读取失败时保留已有有效内容并显示失败;启动或停止的响应丢失、超时或断连表示**结果未确认**,不能推断任务没有启动或已经停止。结果未确认时,界面保留提示并禁止继续启动/停止,直到“刷新状态”成功核对该任务;必要时查看任务日志,再决定恢复。界面不会自动重试启动或停止。
151
+
152
+ 目录不存在或控制进程无法创建等情况,只有宿主结构化确认请求尚未执行,界面才允许修正输入或环境后再次提交。普通错误、断连或错误文字本身不构成这项确认,不能据此解除结果未确认状态。`/flywheel` 的失败 `text` 使用 `type:"flywheel-control-error"` 的 JSON 包装,字段和兼容行为见[命令失败协议](PROTOCOL.md#dsh-命令失败与是否派发)。
153
+
154
+ 切换视图、关闭会话页面、卸载插件或退出桌面,都不等于向后台 Go 任务发出停止请求。需要停止时显式点击“停止”并等待引擎确认;重新打开后刷新同一任务。DSH 的原生轨迹继续展示父会话已有的命令与工具记录;独立 SDK、Kimi、Codex Pro worker 的完整执行历史不会自动合并到父会话轨迹,也不会被伪装成 DSH 原生后台任务。
155
+
156
+ ### 宿主 UI 接入
157
+
158
+ 客户端通过 `ctx.slots.inject()` 和独立 `id: flywheel` 注册到 `conversation.view` 列表,使用宿主的会话作用域和视图切换。保留“对话/轨迹”原有条目、输入区和右侧栏;不注册覆盖它们的同名条目,不另外绘制悬浮侧栏或底部大弹层。长路径、模型信息和错误在视图内容区换行或局部滚动,不通过遮挡宿主控件来增加空间。
159
+
160
+ 作为外部 plain-JS 插件,浏览器模块只运行时导入共享 React,不导入 `ui-primitives`、`client-store` 或其他 Harness Client 包。插件自有按钮、输入框、查看状态 store handle 和 observable;宿主根据注册契约管理会话实例并提供读取 hooks,locale 通过注入服务取得。控件参照宿主结构和交互,颜色使用语义别名,字体继承宿主,编译后的 CSS Modules 样式随 React 视图挂载和卸载。这样匹配宿主界面,也避免绑定不稳定的 Client 模块值接口。
161
+
162
+ 依据固定为声明版本 `0.2.1-rc.5` 的源码快照 `b830ec950faba0a46dda564be3e2d854afed94f1`:[外部插件实践](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/preset/agent-preset/skills/cordis-plugin-development/references/practices.md)、[UI 规范](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/.agents/skills/dsh-client-ui-ux/SKILL.md)、[布局说明](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/client/ui-layout/README.md),以及[会话插槽契约](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/packages/client/ui-conversation/src/client/contract/slots.ts)和[插槽生命周期](https://github.com/deepseek-ai/deepseek-harness/blob/b830ec950faba0a46dda564be3e2d854afed94f1/docs/subsystems/slots.md)。视图使用 Conversation 已有标题栏和内容区,遵循其窗口边距,不修改全局窗口留白。源码契约核对不代替目标 Mac 桌面的实机验证。
141
163
 
142
164
  ## 权限、上下文与报告归档
143
165
 
@@ -147,13 +169,17 @@ worker 只支持 `read-only` 与 `workspace-write`。Mac 上由 DSH 的 Seatbelt
147
169
 
148
170
  执行报告先写到 worktree 内的任务报告路径,由 Go 校验后归档到主任务目录。不得为报告写入而把整个任务目录或用户目录设成 full access。
149
171
 
150
- 默认覆盖会关闭 DSH 自主委派、workflow、goal 驱动、模型生成标题、web search 工具及自动模型压缩,避免在一个 Go 工作单元之外再启动辅助模型调用。需要压缩/继续执行时由 Go 显式决定下一次任务;超出上下文或输出 token 限制不会伪装成成功。SDK profile 应只装所需的可信 provider /工具,第三方 Host 插件本身是进程内代码,不能由本包替它提供任意代码隔离。
172
+ 默认覆盖会关闭 DSH 自主委派、workflow、goal 驱动、模型生成标题及自动模型压缩,避免在一个 Go 工作单元之外再启动辅助模型调用。需要压缩/继续执行时由 Go 显式决定下一次任务;超出上下文或输出 token 限制不会伪装成成功。SDK profile 应只装所需的可信 provider /工具,第三方 Host 插件本身是进程内代码,不能由本包替它提供任意代码隔离。
173
+
174
+ 这份临时覆盖只用于每次独立启动的 **SDK worker 进程**,不修改桌面 profile,不卸载或隐藏桌面已有的插件、skills、对话工具及 UI。反过来,桌面已安装插件或已登录账号,也不证明 SDK profile 已加载并授权相同能力;应按对应 harness 的配置和正式授权流程核对。
175
+
176
+ 当前覆盖禁用整个 `tool-web`,因此 SDK worker 的 `web_search` 和 `web_fetch` 都不可用。这是一项保守的运行策略,不是 DSH 所有网页操作必然调用模型:官方 [web 工具](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/web/tool-web/README.md)支持分别配置搜索与抓取,[DeepSeek 搜索后端](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/web/web-search-deepseek/README.md)才明确包含辅助模型调用。此次 UI 修复不变更 worker 策略;恢复检索或[自动压缩](https://github.com/deepseek-ai/deepseek-harness/blob/fcc0ad462172522aaf5c93a7b2e01f6b9f0b0159/packages/compaction/compaction-basic/README.md)等能力,需要另行验证调用计量、预算、取消和工作目录边界。
151
177
 
152
178
  ## 生命周期与可验证范围
153
179
 
154
180
  官方 rc.5 SDK 没有 per-turn cancel,所以使用每调用一个 SDK 进程。worker 请求 `shutdown` 并等待退出;SDK 自己排空其托管命令。Go 继续负责外层 deadline、取消及它拥有的进程组清扫。正常 SDK 关闭未被证明时结果失败,不能进入成功验收。Go 默认 5 秒 kill grace 应保留,以给 worker 清理窗口;不要配置短于桥接清理预算的值。
155
181
 
156
- 测试覆盖离线 worker 全生命周期与事件折叠;桌面 command/tool 入口一致;构建后的浏览器模块经 ModuleLoader/宿主 React/真实 DOM/Remote 的交互;Go 与 Node 的配置、诊断和失败契约;安装记录校验、用户配置优先及损坏入口拒绝。根目录的 npm 安装测试使用实际六包 tarball、隔离目录和 DSH 协议桩,验证完整安装流程。前轮还核对官方 npm rc.5 的真实 Host commands/tools 注册、SDK 初始化/关闭,以及当前 Linux 无可用沙箱时在 prompt 前 fail closed。具体运行结果见[验证记录](../../docs/validation/2026-11-01-results.md)。
182
+ 测试覆盖离线 worker 全生命周期与事件折叠;桌面 command/tool 入口一致;构建后的浏览器模块在 React 与 jsdom 中运行插件自有控件、store handle 和 observable。组件夹具适配槽位桥接和 Remote,另用已发布的 rc.5 renderer、slots 与 Cordis 检验真实注册、会话绑定、声明收起/恢复及卸载;这两类测试都不验证真实宿主几何布局。还覆盖 Go 与 Node 的配置、诊断和失败契约,以及安装记录校验、用户配置优先和损坏入口拒绝。根目录的 npm 安装测试使用实际六包 tarball、隔离目录和 DSH 协议桩,验证完整安装流程。前轮还核对官方 npm rc.5 的真实 Host commands/tools 注册、SDK 初始化/关闭,以及当前 Linux 无可用沙箱时在 prompt 前 fail closed。前轮运行结果见[验证记录](../../docs/validation/2026-11-01-results.md)。
157
183
 
158
184
  尚未在用户 Mac 实测:桌面安装和 UI 渲染、Seatbelt 探针、实际 Flash/GPT 推理、授权可见性及断电恢复。Linux 上的 CLI 加载成功不代替这些验证。不会将协议桩写成付费模型成功的证据。
159
185
 
@@ -0,0 +1,38 @@
1
+ # Third-party notices
2
+
3
+ ## DeepSeek Harness UI patterns
4
+
5
+ Flywheel's plugin-owned Button, Input, and ongoing StateDot treatments are
6
+ adapted from DeepSeek Harness at commit
7
+ `b830ec950faba0a46dda564be3e2d854afed94f1`:
8
+
9
+ - `packages/client/ui-primitives/src/Button.tsx` and its stylesheet
10
+ - `packages/client/ui-primitives/src/Input.tsx` and its stylesheet
11
+ - `packages/client/ui-primitives/src/StateDot.tsx` and its stylesheet
12
+
13
+ [Upstream source](https://github.com/deepseek-ai/deepseek-harness/tree/b830ec950faba0a46dda564be3e2d854afed94f1/packages/client/ui-primitives/src)
14
+
15
+ These adapted portions retain the upstream MIT license below. Other Flywheel
16
+ source remains under the repository's existing license.
17
+
18
+ MIT License
19
+
20
+ Copyright (c) 2026 DeepSeek
21
+
22
+ Permission is hereby granted, free of charge, to any person obtaining a copy
23
+ of this software and associated documentation files (the "Software"), to deal
24
+ in the Software without restriction, including without limitation the rights
25
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26
+ copies of the Software, and to permit persons to whom the Software is
27
+ furnished to do so, subject to the following conditions:
28
+
29
+ The above copyright notice and this permission notice shall be included in all
30
+ copies or substantial portions of the Software.
31
+
32
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38
+ SOFTWARE.