@crazyhappyone/dsh-tui 0.1.0-alpha.5 → 0.1.0-alpha.50

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/CHANGELOG.md ADDED
@@ -0,0 +1,49 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0-alpha.50 — 2026-10-21
4
+
5
+ Prerelease for DSH `0.2.1-rc.2`; npm channel: `next`. The changes below include the unreleased work since `0.1.0-alpha.49`.
6
+
7
+ ### Fixed
8
+
9
+ - **Shared official model configuration:** lightweight and source launch modes now both default to `deepseek-tui`. `--profile NAME` / `--profile=NAME` controls both bundle installation and boot; duplicate or missing profile arguments fail before installation. Previously, installing the official `dsh` executable could silently switch lightweight mode to the empty `tui` profile and hide providers configured by Magpie in `deepseek-tui`.
10
+ - `/model` continues to read DSH's `ctx.llm` registry and persists selections through `agentDefaultModel`. No parallel configuration reader, cross-profile copy, or provider credentials are added. Large catalogs now use the actual terminal height, keeping the heading, selected row, filter and navigation visible.
11
+ - Backend-started turns, including Goal continuation and scheduled wakeups, enter the running interaction state. Ctrl+C cancels the active turn. The Goal footer distinguishes durable `active` state from armed/disarmed continuation and explains `/goal resume`.
12
+ - Mouse selection preserves Chinese text, margins and copy order without repainting the entire screen. Repeated coordinates produce no extra output; a clipboard helper closing stdin no longer crashes the TUI with EPIPE.
13
+ - Approval, question and plan-review content uses physical row budgets so decisions stay visible. Custom answers, batch/multiple selections, pasted text, cancellation and chat drafts retain their separate ownership.
14
+ - Credential editors and secret `/key`/`/login` arguments are masked, including caret movement and selection; secret selections cannot be copied.
15
+ - Plugin-market registry selection is preserved through both inspection and installation, and cleared when switching to an official catalog target.
16
+
17
+ ### Added
18
+
19
+ - `/timeline` event/tool/usage/timing details and full JSON; `/todos` complete task browsing; `/deliveries`, `/attachments` and `/review` for delivered files, typed references and exact per-file diffs.
20
+ - Official time context, `present`, and persistent schedule tools; `/schedules` lists, inspects, opens the owning Session and confirms cancellation. Pending reminders recover on restart; a closed process runs no timers.
21
+ - Subagent live output, continuation (`c`, queue or steer), Stop requests (`s`) and wide-terminal side-by-side viewing (`v`), preserving the main Session and draft.
22
+ - Light/dark themes across truecolor/256/16/plain terminals, grouped settings, `/keys`, conflict-checked composer `/bind` and `/unbind`, grapheme input selection and plain-stream screen-reader mode.
23
+ - File-tree coalesced automatic watching, manual refresh, preserved selection, recoverable errors and watcher disposal.
24
+ - `/preset` with isolated standard/PTC/minimal/cordis compositions, selected before the first turn; `/market` search and approved install preview; `/inspect` official Host contracts; `/focus` rendering.
25
+ - BCP47 locale registration, bounded language-specific lexical code highlighting and read-only Alt+H help during blocking dialogs.
26
+ - macOS image-paste adapter using `pngpaste`, explicit missing-helper errors and cancellation/timeout handling.
27
+ - Official-source runtime initialization, bundle linking, generated-contract preparation and standalone source/test type-check setup.
28
+
29
+ ### Upgrade and boundaries
30
+
31
+ - Update with `npm install --global @crazyhappyone/dsh-tui@next`. Run `dsh-tui probe` to check the engine and default profile. Source mode also uses the same profile.
32
+ - Existing `tui` and `deepseek-tui` directories are retained. To keep the old lightweight configuration, use `dsh-tui --profile tui`. DSH profiles remain independent; a provider configured only in `web` is not automatically global. Refresh Magpie's DSH connection/catalog after creating a new profile.
33
+ - `/reload` refreshes code in a running source-linked installation while retaining its existing profile; quit and relaunch to change the default profile. Resumed Goals require explicit `/goal resume`.
34
+ - Images and PDF/Office documents use metadata/text or the system opener. IME preedit remains native to the terminal; Ink exposes no composition events. Physical macOS/IME/screen-reader devices, remote market downloads, live model replies and external Stop convergence are not established by offline tests.
35
+
36
+ ### 中文变更说明
37
+
38
+ - **修复模型配置入口分裂:**轻量模式与源码模式统一默认使用官方 `deepseek-tui` profile;`--profile` 同时决定安装和启动目标。旧版在探测到官方 `dsh` 后会改用缺少配置的 `tui`,导致 Magpie 已写入的模型不出现在列表中。继续使用官方 `ctx.llm` / `agentDefaultModel`,不另建配置加载器、不复制其他 profile;模型列表按实际终端高度显示。
39
+ - **修复运行与输入状态:**后台 Goal/定时回合正确进入生成中,Ctrl+C 取消回合;页脚区分目标 active 和自动续跑是否启用。修复鼠标复制、EPIPE、窄屏决策按钮、自定义/多选问答和秘密输入遮罩。
40
+ - **新增会话与文件能力:**事件轨迹/JSON、完整 TODO、定时提醒、时间上下文、交付物、附件目录、逐文件 diff,以及子代理实时输出、排队/引导续聊、停止请求与宽屏并排。
41
+ - **新增操作与扩展能力:**明暗主题、设置分组、快捷键查看/重绑定、文件树监控、四种隔离 preset、市场预览、Host 自检、focus、语言包注册、有界词法高亮、字素选区、普通流无障碍和阻塞对话只读帮助。
42
+ - **升级:**`npm install --global @crazyhappyone/dsh-tui@next`。旧 profile 均保留;需要旧轻量配置时用 `--profile tui`。`/reload` 保留当前 profile,切换默认 profile 需退出后重新启动;Goal 恢复后执行 `/goal resume`。创建新 profile 后刷新 Magpie 的 DSH 接入/目录。
43
+ - **边界:**关闭进程期间提醒不计时;图片及 PDF/Office 使用文本/元数据或系统程序。未将离线测试等同于联网模型、远程安装、真实外部 Stop 收敛或 macOS/IME/屏幕阅读器实机验证。
44
+
45
+ [Full comparison](https://github.com/zhangyang-crazy-one/dsh-tui/compare/v0.1.0-alpha.49...v0.1.0-alpha.50)
46
+
47
+ ## Earlier releases
48
+
49
+ See [GitHub Releases](https://github.com/zhangyang-crazy-one/dsh-tui/releases) for `0.1.0-alpha.49` and earlier release notes.
package/README.i18n.yaml CHANGED
@@ -1,5 +1,5 @@
1
1
  # Bilingual-pair consistency record: both languages carry equal authority.
2
2
  # This source-only mirror has no DSH pairing runner. Recompute with:
3
3
  # git hash-object README.md README.zh.md
4
- README.md: 496d812168deb2af7d4a933f961b58c1cfd814cd
5
- README.zh.md: 8474c7be4cf16c0d5123222bab95b5231f34e185
4
+ README.md: 85d9293b354853b972f28f7b85d1823395178530
5
+ README.zh.md: 249948d86146a20736141157efd01ce0c2e80768
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Installable source-runtime launcher and public source mirror for the DeepSeek Harness terminal interface."
2
+ description: "DeepSeek Harness terminal interface: a dsh plugin bundle plus its launcher."
3
3
  kind: "package-group"
4
4
  ---
5
5
 
@@ -13,10 +13,29 @@ English | [中文](README.zh.md)
13
13
 
14
14
  ## Summary
15
15
 
16
- `@crazyhappyone/dsh-tui` provides the `dsh-tui` command for running and safely updating the DeepSeek Harness terminal interface. The launcher manages a dedicated DSH source checkout, so it never pulls, resets, stashes, or cleans a contributor's development checkout. This public repository also mirrors the `packages/tui/` bundle and renderer sources for review. DSH continues to own agents, sessions, tools, persistence, providers, permissions, and profile assembly.
16
+ `@crazyhappyone/dsh-tui` is a terminal interface for DeepSeek Harness (dsh), shipped as a dsh **plugin bundle** plus a `dsh-tui` launcher. The package declares `dsh.bundle`, so dsh installs it into a profile like any other plugin; the launcher only automates that install and boots the profile. This repository owns the plugin sources (`tui/`, `tui-render/`). DSH continues to own agents, sessions, tools, persistence, providers, permissions, and profile assembly.
17
+
18
+ ## Release 0.1.0-alpha.50
19
+
20
+ This prerelease targets DSH `0.2.1-rc.2`. It adds terminal navigation and Session tools, fixes background Goal status and input handling, and makes both launcher modes use the same official model configuration. See the [changelog](CHANGELOG.md#010-alpha50--2026-10-21) for the full changes and verification boundaries.
21
+
22
+ ```sh
23
+ npm install --global @crazyhappyone/dsh-tui@next
24
+ dsh-tui probe
25
+ dsh-tui
26
+ ```
27
+
28
+ Both lightweight and source modes now default to the official `deepseek-tui` profile under `$DSH_HOME/profiles/` (normally `~/.dsh/profiles/`). `/model` reads `ctx.llm`, and model selection uses DSH's `agentDefaultModel`; this bundle does not read a private model configuration or copy another profile's providers. Magpie writes existing `profiles/*/cordis.patch.yml` files. If Magpie is connected before a new profile is created, refresh its DSH connection/catalog after the profile exists and restart the TUI.
29
+
30
+ Earlier lightweight versions used `tui`, while source mode used `deepseek-tui`. Neither directory is deleted or migrated automatically. To retain an older lightweight profile, run `dsh-tui --profile tui`. To use another TUI-enabled official profile, pass `--profile NAME`: installation and boot use that exact same target in either mode. Profiles remain independently configured by DSH; a provider configured only in `web` is not automatically global.
31
+
32
+ For a running source-linked installation, `/reload` loads the rebuilt bundle but preserves that process's selected profile. To change from `tui` to `deepseek-tui`, quit and launch again (or pass the desired profile explicitly). Resumed Goals require `/goal resume` to enable automatic continuation.
17
33
 
18
34
  ## Table of Contents
19
35
 
36
+ - [Release and upgrade](#release-010-alpha50)
37
+ - [Changelog](CHANGELOG.md)
38
+ - [Terminal capabilities](#terminal-capabilities)
20
39
  - [Screenshots](#screenshots)
21
40
  - [Install the launcher](#install-the-launcher)
22
41
  - [Run and update](#run-and-update)
@@ -33,9 +52,9 @@ English | [中文](README.zh.md)
33
52
  <a id="screenshots"></a>
34
53
  ## Screenshots
35
54
 
36
- Idle home:
55
+ Interactive settings pane (`/settings`):
37
56
 
38
- ![dsh-tui idle home](assets/screenshots/dsh-tui-home.png)
57
+ ![dsh-tui settings pane](assets/screenshots/dsh-tui-settings.png)
39
58
 
40
59
  After sending `你好`:
41
60
 
@@ -51,7 +70,7 @@ The unscoped `dsh-tui` package belongs to another maintainer. This project publi
51
70
  `dsh-tui` supports two runtime modes:
52
71
 
53
72
  ### Mode A: Lightweight Mode (Recommended, Zero-Clone)
54
- Install the official core engine and the TUI launcher globally (dozens of MB):
73
+ Install the official engine and the TUI launcher globally:
55
74
 
56
75
  ```text
57
76
  npm install --global @deepseek-ai/dsh
@@ -60,7 +79,18 @@ dsh-tui probe
60
79
  dsh-tui
61
80
  ```
62
81
 
63
- In this mode, the launcher automatically detects the installed `dsh` executable and mounts the bundled prebuilt TUI extension without cloning the 2GB monorepo.
82
+ The first launch runs `dsh plugin --profile deepseek-tui add <package directory>`, which links this package into the `deepseek-tui` profile after `@deepseek-ai/dsh-base`; later launches find it there and run `dsh --profile deepseek-tui` directly. Without the launcher, the same two dsh commands work by hand:
83
+
84
+ ```text
85
+ dsh plugin --profile deepseek-tui add @crazyhappyone/dsh-tui@next
86
+ dsh --profile deepseek-tui
87
+ ```
88
+
89
+ Installing as a bundle matters in dsh 0.2: `/settings` edits are written to the profile's own patch layer, which applies after bundle layers. A `--patch` overlay would apply after the profile layer and dsh refuses settings writes to rows such an overlay owns.
90
+
91
+ Detection checks an absolute `DSH_BIN` override, PATH, npm and pnpm global packages, then packages resolvable from the working directory and launcher directory. Each probe subprocess has a ten-second timeout, which covers a cold first start. A broken explicit `DSH_BIN` is reported without selecting another installation. Package bin entries run through the launcher's Node executable.
92
+
93
+ The bundle targets the dsh `0.2` release line (built against `0.2.1-rc.2`, also verified on `0.2.1-alpha.2`). The package declares `@deepseek-ai/dsh` `>=0.2.0-rc.2 <0.3.0` as an optional peer, so dsh's own plugin compatibility check covers manual installs, and the launcher refuses another engine line with the exact install command; `DSH_TUI_SKIP_ENGINE_CHECK=1` bypasses the launcher check.
64
94
 
65
95
  ### Mode B: Source Mode (Developer / Debugging)
66
96
  To debug or hack on TUI or DSH source directly:
@@ -86,7 +116,7 @@ dsh-tui
86
116
 
87
117
  Run `dsh-tui update` when you want to refresh the dedicated runtime before launching it again.
88
118
 
89
- Ordinary arguments pass to the `deepseek-tui` profile unchanged:
119
+ Ordinary arguments pass unchanged to the selected official profile (`deepseek-tui` by default) in both modes:
90
120
 
91
121
  ```text
92
122
  dsh-tui "review this repository"
@@ -110,13 +140,13 @@ dsh-tui update
110
140
  <a id="configure-the-source-runtime"></a>
111
141
  ## Configure the source runtime
112
142
 
113
- The defaults track the owner's private `feat/deepseek-tui` branch. Git authorization for that repository is required. Other users can select a compatible accessible repository and ref.
143
+ The defaults use the official public repository at tag `dsh-v0.2.1-rc.2`. Source mode links this bundle into the existing `deepseek-tui` profile and preserves its user patch. Missing Typert runtime artifacts are generated with the upstream generator before boot. The source CLI runs through `pnpm exec node`, avoiding the `predsh` hook that reinstalls the entire workspace on every launch.
114
144
 
115
145
  | Environment variable | Default | Purpose |
116
146
  |---|---|---|
117
147
  | `DSH_TUI_RUNTIME_DIR` | `~/.local/share/dsh-tui/runtime` | Dedicated clone used only by the launcher |
118
- | `DSH_TUI_SOURCE_URL` | `https://github.com/zhangyang-crazy-one/deepseek-harness.git` | Git remote cloned and fetched by `update` |
119
- | `DSH_TUI_SOURCE_REF` | `feat/deepseek-tui` | Branch or ref fetched by `update` |
148
+ | `DSH_TUI_SOURCE_URL` | `https://github.com/deepseek-ai/deepseek-harness.git` | Git remote cloned and fetched by `update` |
149
+ | `DSH_TUI_SOURCE_REF` | `dsh-v0.2.1-rc.2` | Branch or ref fetched by `update` |
120
150
  | `DSH_TUI_PNPM` | `pnpm` | pnpm executable used for install and launch |
121
151
 
122
152
  Values must be non-empty, and the runtime directory must be absolute. The launcher refuses a symbolic-link runtime path and an existing directory that is not a Git checkout. Child commands receive argument arrays without shell interpolation.
@@ -128,15 +158,69 @@ If dependency refresh fails after a fast-forward, the runtime stays at the repor
128
158
  <a id="relationship-to-dsh"></a>
129
159
  ## Relationship to DSH
130
160
 
131
- The TUI is a DSH profile layer, not a separate agent runtime:
161
+ The TUI is a dsh plugin bundle, not a fork or a separate agent runtime:
132
162
 
133
163
  ```text
134
- @deepseek-ai/dsh-base
135
- └─ @deepseek-ai/dsh-tui profile patch, terminal lifecycle, controller
136
- └─ @deepseek-ai/dsh-tui-render Ink projection and terminal I/O
164
+ @deepseek-ai/dsh-base dsh core bundle (agents, sessions, tools)
165
+ └─ @crazyhappyone/dsh-tui this bundle: cordis.patch.yml + dist/*
166
+ ├─ tui-startup (./startup) command-line provider (task, --resume, --cwd)
167
+ ├─ tui (./settings) volatile TUI preferences shown in /settings
168
+ ├─ tui-runtime (./runtime) terminal lifecycle and controller
169
+ ├─ schedule (./schedule) official scheduler with shared Session activation
170
+ └─ zen-proxy (./zen-proxy) optional OpenCode Zen header proxy
137
171
  ```
138
172
 
139
- The integration source lives on the private [`feat/deepseek-tui` DSH branch](https://github.com/zhangyang-crazy-one/deepseek-harness/tree/feat/deepseek-tui/packages/tui). Changes that affect DSH services, profile composition, assembled CLI snapshots, or Agent Notes belong in that monorepo and follow its architecture, testing, and documentation rules.
173
+ Rows name plugins through the package's `exports`, so a settings edit records a portable row name in the profile patch. The bundle also inserts the published dsh plugins `session-stats`, `message-feedback`, `tool-ask-user`, `workspace-changes`, `tool-schedule`, `time-context`, `tool-present`, and a loopback `webserver` for the account sign-in callback, and overrides `system-prompt`, `tools`, `session-query-sqlite`, and `session-title-llm`.
174
+
175
+ ### Reminders and user questions
176
+
177
+ The model can use the official `schedule_create`, `schedule_list`, `schedule_update`, and `schedule_delete` tools. `/schedules` lists reminders across Sessions: ↑↓ or PgUp/PgDn selects, Enter shows the full prompt, a second Enter opens the owning Session, `r` refreshes, and `d` asks for cancellation confirmation (`y` confirms; `n` or Esc keeps it). Delivery resumes the original Session even after navigating elsewhere. Tasks persist across restart; timers run only while this process is open, and overdue tasks are handled on the next launch. A delivery receipt confirms durable inbox admission, not a completed model response. The adapter bundles the official scheduler and Session activation helpers from the pinned DSH build; upstream upgrades require integration checks.
178
+
179
+ User questions support all questions in a batch, multiple selections, and custom text. Space toggles a multi-select choice; `c` opens the custom editor; Enter saves text and submits choices. Questions without choices open the editor directly. Tab opens the complete question and answer for scrolling; Tab or Esc returns to editing. Esc in the editor discards that edit (or cancels a text-only question), while Esc on the choices cancels the request. Pasted multiline answers retain their original text and do not change the chat draft.
180
+
181
+ Credential editors and secret arguments in `/key` and `/login` display bullets while keeping credential reference names visible. Masking affects display only: editing and submission retain the original value, and cancelling restores the chat draft.
182
+
183
+ ### Time context, delivered files, and image paste
184
+
185
+ The official `time-context` plugin supplies the current time and process time zone to the model when preparing a step, refreshing after ten minutes. This model context does not create an extra human transcript message.
186
+
187
+ The model can explicitly deliver existing files with the official `present` tool (up to eight files per call). `/deliveries` lists this Session's recorded deliveries: ↑↓ selects, Enter previews UTF-8 text, `o` requests opening the selected file in the local system application, and Esc returns. PDF, Office, images, and other binary formats show file details and use the system application. Text reads are limited to 1 MiB by default. Completed turns also show the delivered paths and descriptions; their records survive Session replay, but the files must still exist and remain accessible.
188
+
189
+ Clipboard image paste uses `pngpaste -` on macOS ([installation: `brew install pngpaste`](https://github.com/jcsalterego/pngpaste)), `wl-paste` on Wayland, or `xclip` on X11. A missing helper gives a visible error. Reads time out after five seconds by default and are cancelled when the TUI closes; existing image limits and validation still apply. The macOS command and subprocess behavior have automated coverage on Linux; macOS hardware validation remains pending.
190
+
191
+ ### DeepSeek account, models, and working directory
192
+
193
+ - `/login` opens the DeepSeek account page when dsh mounts the `deepseek-account` service: Enter starts browser sign-in, `o` reopens the authorization link, `c` cancels, and the page shows the profile and balance once signed in. The browser returns to the bundle's `webserver` row on `127.0.0.1` with an OS-assigned port. Over SSH the page prints the `ssh -L` forward instead of opening a browser; pin `port` on the `webserver` row so the forward stays stable. Without the account service, `/login` and `/key` open the API-key editor.
194
+ - `/logout` signs out after confirmation; stored API keys remain.
195
+ - `/model` lists `deepseek-account` and `deepseek-official` with the step that makes their models available (`/login` or `/key`) while their catalogs are empty, and refuses to select such a row.
196
+ - `/cd [path]` shows or changes the Session working directory on dsh 0.2.1 and later. The header, `@` mentions, and `/files` follow it, and the model receives the change notice; existing shells keep their own directories.
197
+ - `/plugins` lists official bundles in their own group. An official catalog entry whose files are not installed is marked installable, and Space opens the install preview for its exact target.
198
+
199
+ ### OpenCode Zen free models
200
+
201
+ The bundled patch mounts `zen-proxy` (vendored from
202
+ [zhangyang-crazy-one/dsh-zen-proxy](https://github.com/zhangyang-crazy-one/dsh-zen-proxy),
203
+ fork of [Yee-h/dsh-zen-proxy](https://github.com/Yee-h/dsh-zen-proxy)): an in-process
204
+ localhost proxy that injects the official OpenCode client headers Zen requires
205
+ (`User-Agent`, `x-opencode-client/session/request/project`). Without it Zen answers
206
+ `400 MissingSessionID` / `429 FreeUsageLimitError` because dsh always sends its
207
+ own attribution `User-Agent`.
208
+
209
+ To use it, add a provider through the TUI `/settings` provider form (or the
210
+ profile's `cordis.patch.yml`) pointing at the proxy, and keep the key in credentials:
211
+
212
+ ```yaml
213
+ - id: llm-pi-ai
214
+ config:
215
+ providers:
216
+ opencode:
217
+ api: openai-completions
218
+ baseURL: http://127.0.0.1:4097/v1
219
+ apiKeyEnv: OPENCODE_API_KEY
220
+ ```
221
+
222
+ The proxy listens on `127.0.0.1:4097` only; add `- id: zen-proxy` with
223
+ `disabled: true` to the profile's `cordis.patch.yml` to turn it off.
140
224
 
141
225
  -----
142
226
 
@@ -145,7 +229,8 @@ The integration source lives on the private [`feat/deepseek-tui` DSH branch](htt
145
229
 
146
230
  | Package | DSH shape | Responsibility |
147
231
  |---|---|---|
148
- | [`tui/`](tui/README.md) | Profile bundle plus runtime plugin | Composes the terminal layer over `dsh-base`, owns the live terminal session, and maps user actions to DSH services |
232
+ | [`tui/`](tui/README.md) | Runtime, startup, and settings plugins | Composes the terminal layer over `dsh-base`, owns the live terminal session, and maps user actions to DSH services |
233
+ | [`plugins/zen-proxy/`](https://github.com/zhangyang-crazy-one/dsh-zen-proxy) | Vendored plugin (bundled as `dist/zen-proxy.js`) | In-process OpenAI-compatible proxy injecting OpenCode Zen client headers; mounted in `cordis.patch.yml` |
149
234
  | [`tui-render/`](tui-render/README.md) | Library | Projects controller state through Ink without owning agents, persistence, or model requests |
150
235
 
151
236
  -----
@@ -153,9 +238,20 @@ The integration source lives on the private [`feat/deepseek-tui` DSH branch](htt
153
238
  <a id="development-workflow"></a>
154
239
  ## Development workflow
155
240
 
156
- Implement TUI behavior in the complete DSH checkout, run the checks selected by the changed behavior, and export the confirmed `packages/tui/` tree here. Develop the launcher in this repository with `npm test`; test installation through a packed tarball rather than a workspace link.
241
+ `tui/` and `tui-render/` compile against an upstream dsh checkout at the tag named by `COMPATIBLE_DSH_VERSION` in `src/launcher.js`:
242
+
243
+ ```text
244
+ git clone --branch dsh-v0.2.1-rc.2 https://github.com/deepseek-ai/deepseek-harness ../deepseek-harness
245
+ (cd ../deepseek-harness && pnpm install)
246
+ npm run build # or DSH_SOURCE=/path/to/checkout npm run build
247
+ (cd ../deepseek-harness && pnpm install) # link the mounted plugin's dev dependencies
248
+ npm run dev:setup # same DSH_SOURCE override; build types and link editor dependencies
249
+ npm run typecheck # strict checks for sources and tests
250
+ ```
251
+
252
+ `npm run build` copies the plugin packages and `cordis.patch.yml` into the checkout's `packages/tui/` workspace, bundles `dist/index.js`, `dist/startup.js`, `dist/settings.js`, `dist/schedule.js`, and `dist/zen-proxy.js` with esbuild, and import-checks each output. Run the plugin tests from the checkout with `npx vitest run packages/tui`, and the launcher tests here with `npm test`; run `npm run pack:check` before release. Test installation through a packed tarball or `dsh plugin --profile <name> add <this directory>`.
157
253
 
158
- The launcher runtime must remain separate from the development checkout. To test against another source safely, point `DSH_TUI_RUNTIME_DIR` at a temporary absolute directory and configure `DSH_TUI_SOURCE_URL` and `DSH_TUI_SOURCE_REF`.
254
+ Local `tsconfig.json` files support editors in this standalone repository. The build mounts `tsconfig.workspace.json` as the checkout's package config to preserve upstream project references. `dev:setup` builds dependency declarations and links whole `node_modules` directories, preserving pnpm's relative links. Re-run build and setup after upstream or public type changes; restart the editor's TypeScript project if it still displays old missing-module diagnostics.
159
255
 
160
256
  -----
161
257
 
@@ -178,21 +274,42 @@ The equivalent npm website settings are organization or user `zhangyang-crazy-on
178
274
  For each release, bump `package.json`, merge the change after CI passes, then create a GitHub Release whose tag matches the package version:
179
275
 
180
276
  ```text
181
- gh release create v0.1.0-alpha.4 --prerelease --generate-notes
277
+ gh release create v0.1.0-alpha.50 --prerelease --notes-file docs/releases/v0.1.0-alpha.50.md
182
278
  ```
183
279
 
184
280
  The `Publish npm` workflow runs tests and packed-package verification again before publishing. Do not rerun an old release tag: npm versions are immutable. Promotion to stable is a new version and a non-prerelease GitHub Release.
185
281
 
186
282
  -----
187
283
 
284
+ ## Terminal capabilities
285
+
286
+ `/timeline` reads individual Session events, actual tool/token/timing data and full JSON; `/attachments` lists typed image/file references and opens local copies; `/review` reads each changed file's official diff. `/files` watches expanded directories with coalesced refresh and retains manual `r` refresh.
287
+
288
+ `/settings` uses Tab/Shift+Tab section navigation and persists `tui.theme=dark|light`. `/keys` lists context-specific bindings; `/bind ACTION Ctrl+X`, `/bind ACTION default` and `/unbind ACTION` edit composer shortcuts with conflict checks. Shift+arrows/Home/End selects input by grapheme, typing/paste replaces the selection, and Ctrl+Y copies ordinary selections; credential selections cannot be copied. Alt+H opens read-only help during approvals, questions and plan review.
289
+
290
+ `/agents` supports `c` continuation (Enter queues, Ctrl+Enter steers), `s` request Stop, and `v` side-by-side viewing at 100+ columns. Narrow terminals use the single-pane view. Human controls preserve the catalog's exact direct-parent address; Stop acknowledgement does not claim execution has already stopped.
291
+
292
+ `/preset` browses standard/PTC/minimal/cordis declarations; `/preset ID` selects an isolated composition before the first turn. Started Sessions remain locked. `/market QUERY` searches configured indexes and routes `i` through plugin-manager inspection and confirmation; `n/p` pages results. `/inspect` browses official Host providers; `/inspect host PROVIDER METHOD JSON` reads an exact contract. `/focus` hides intermediate tool cards without changing model tools or the Session log. External language packs can call `registerTuiLocale`; fenced code uses bounded language-specific lexical highlighting.
293
+
294
+ The Goal footer distinguishes armed automatic continuation from a stopped continuation requiring `/goal resume`. Backend-started turns update the running state and Ctrl+C cancellation path. After updating a running source installation, use `/reload`; a resumed Goal requires explicit `/goal resume` to rearm.
295
+
296
+ Verification and platform boundaries: [P1/P2 evidence](docs/p1-p2-verification-2026-10-20.md).
297
+
298
+ -----
299
+
188
300
  <a id="known-limitations"></a>
189
301
  ## Known limitations
190
302
 
191
- - **Private default source** — npm installation is public, but the default DSH runtime remote requires repository authorization; anonymous users must configure an accessible compatible source.
303
+ - **Third-party plugins must match the engine** — dsh 0.2 rejects older authentication plugins that only declare dsh 0.1.x support; the launcher never grants version exemptions automatically.
192
304
  - **Source toolchain required** — runtime initialization requires Git, pnpm, and a DSH-supported Node version.
193
305
  - **No automatic conflict resolution** — dirty or non-fast-forward runtime history requires explicit human action or a new runtime directory.
194
306
  - **Runtime update is not launcher update** — `dsh-tui update` refreshes DSH source and dependencies; npm updates the launcher package.
195
307
  - **Integration owns release readiness** — launcher success does not replace the DSH branch's behavior, snapshot, build, or hygiene checks.
308
+ - **Source mode also uses this plugin** — the configured checkout must be compatible with this bundle's dsh version. Replace a historical profile's `@deepseek-ai/dsh-tui` bundle with `@crazyhappyone/dsh-tui`; back up the profile and preserve user settings during migration.
309
+ - **Reminders need a running process** — `/schedules` uses the official service and persistent origin Sessions. Restart can recover pending reminders; a closed process runs no timers.
310
+ - **Terminal capability limits** — images and PDF/Office files use metadata/text or the system opener. Ink exposes no IME composition events; native terminal preedit remains authoritative. `INK_SCREEN_READER=true` enables plain-stream rendering, without mouse capture, alternate screen or animation; physical IME/screen-reader devices and macOS clipboard have not been verified.
311
+ - **Account sign-in needs a reachable Platform** — sign-in reports `no-response` when the host cannot reach `platform.deepseek.com`; use `/key` in that case.
312
+ - **No physical session deletion on dsh 0.2** — 0.2 session persistence archives instead of deleting, and the TUI composition mounts no workspace archive service, so the session list reports deletion as unavailable.
196
313
 
197
314
  <a id="dev-note"></a>
198
315
  ## Dev Note
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "DeepSeek Harness 终端界面的可安装源码运行时 launcher 与公开源码镜像。"
2
+ description: "DeepSeek Harness 终端界面:一个 dsh 插件 bundle 及其 launcher。"
3
3
  kind: "package-group"
4
4
  ---
5
5
 
@@ -13,10 +13,29 @@ kind: "package-group"
13
13
 
14
14
  ## 概述
15
15
 
16
- `@crazyhappyone/dsh-tui` 提供 `dsh-tui` 命令,用于运行和安全更新 DeepSeek Harness 终端界面。Launcher 管理专用 DSH 源码 checkout,因此不会 pull、reset、stash 或 clean 贡献者的开发 checkout。本公开仓库还镜像 `packages/tui/` bundle 与 renderer 源码以供审查。Agent、会话、工具、持久化、provider、权限与 profile 组装仍由 DSH 拥有。
16
+ `@crazyhappyone/dsh-tui` 是 DeepSeek Harness(dsh)的终端界面,以 dsh **插件 bundle** 加 `dsh-tui` launcher 的形式发布。包声明了 `dsh.bundle`,因此 dsh 会像安装其他插件一样把它装进 profile;launcher 只负责自动完成这一安装并启动 profile。本仓库拥有插件源码(`tui/`、`tui-render/`)。Agent、会话、工具、持久化、provider、权限与 profile 组装仍由 DSH 拥有。
17
+
18
+ ## 0.1.0-alpha.50 版本
19
+
20
+ 本预发布版面向 DSH `0.2.1-rc.2`,新增终端导航和会话能力,修复 Goal 后台状态与输入交互,并让两种启动模式使用同一份官方模型配置。完整变更与验证边界见 [changelog](CHANGELOG.md#010-alpha50--2026-10-21)。
21
+
22
+ ```sh
23
+ npm install --global @crazyhappyone/dsh-tui@next
24
+ dsh-tui probe
25
+ dsh-tui
26
+ ```
27
+
28
+ 轻量模式和源码模式现在默认使用 `$DSH_HOME/profiles/`(通常为 `~/.dsh/profiles/`)下的官方 `deepseek-tui` profile。`/model` 读取 `ctx.llm`,模型选择调用 DSH 的 `agentDefaultModel`;本 bundle 不读取私有模型配置,也不复制其他 profile 的 provider。Magpie 会写入已有的 `profiles/*/cordis.patch.yml`;若在新 profile 创建前已接入 Magpie,创建后刷新其 DSH 接入/模型目录,再重启 TUI。
29
+
30
+ 旧版轻量模式使用 `tui`,源码模式使用 `deepseek-tui`。两个目录均保留,不自动删除或迁移。继续使用原轻量 profile 可运行 `dsh-tui --profile tui`。使用其他已挂载 TUI 的官方 profile 时传入 `--profile NAME`;两种模式的安装和启动都会使用同一个指定目标。各 profile 仍由 DSH 独立配置;只写入 `web` 的 provider 不会自动变成全局配置。
31
+
32
+ 正在运行的源码链接安装可通过 `/reload` 加载新构建,但会保留进程原先选中的 profile。若从 `tui` 切换到 `deepseek-tui`,需退出后重新启动,或显式指定 profile。恢复的 Goal 需执行 `/goal resume` 才会自动续跑。
17
33
 
18
34
  ## 目录
19
35
 
36
+ - [版本与升级](#010-alpha50-版本)
37
+ - [Changelog](CHANGELOG.md)
38
+ - [终端能力](#终端能力)
20
39
  - [截图](#screenshots)
21
40
  - [安装 launcher](#install-the-launcher)
22
41
  - [运行与更新](#run-and-update)
@@ -33,9 +52,9 @@ kind: "package-group"
33
52
  <a id="screenshots"></a>
34
53
  ## 截图
35
54
 
36
- 空闲首页:
55
+ 交互式设置面板(`/settings`):
37
56
 
38
- ![dsh-tui 空闲首页](assets/screenshots/dsh-tui-home.png)
57
+ ![dsh-tui 设置面板](assets/screenshots/dsh-tui-settings.png)
39
58
 
40
59
  发送 `你好` 后:
41
60
 
@@ -51,7 +70,7 @@ kind: "package-group"
51
70
  `dsh-tui` 支持两种运行模式:
52
71
 
53
72
  ### 模式 A:轻量模式(推荐,零 Clone 秒开)
54
- 只需通过 npm 全局安装官方核心引擎与 TUI launcher(仅数十 MB),即可直接运行:
73
+ 全局安装官方引擎与 TUI launcher:
55
74
 
56
75
  ```text
57
76
  npm install --global @deepseek-ai/dsh
@@ -60,7 +79,18 @@ dsh-tui probe
60
79
  dsh-tui
61
80
  ```
62
81
 
63
- 在此模式下,launcher 会自动探测全局 `dsh`,并挂载预构建的 TUI 扩展,无需克隆 2GB 的 monorepo 仓库。
82
+ 首次启动会执行 `dsh plugin --profile deepseek-tui add <包目录>`,把本包链接进 `deepseek-tui` profile,排在 `@deepseek-ai/dsh-base` 之后;之后的启动检测到已安装,直接执行 `dsh --profile deepseek-tui`。不使用 launcher 时,也可以手动执行同样的两条 dsh 命令:
83
+
84
+ ```text
85
+ dsh plugin --profile deepseek-tui add @crazyhappyone/dsh-tui@next
86
+ dsh --profile deepseek-tui
87
+ ```
88
+
89
+ 在 dsh 0.2 中以 bundle 方式安装是必需的:`/settings` 的修改写入 profile 自己的 patch 层,该层在 bundle 层之后生效;而 `--patch` overlay 位于 profile 层之后,dsh 会拒绝对此类 overlay 所拥有的行写入设置。
90
+
91
+ 探测顺序为绝对路径 `DSH_BIN`、PATH、npm/pnpm 全局包、工作目录和 launcher 目录可解析的本地包;每个探测子进程限时十秒,以覆盖冷启动。显式 `DSH_BIN` 失败时不会选择其他安装。包内 bin 使用 launcher 的 Node 执行。
92
+
93
+ 本 bundle 面向 dsh `0.2` 发布线(基于 `0.2.1-rc.2` 构建,并在 `0.2.1-alpha.2` 上验证)。包把 `@deepseek-ai/dsh` `>=0.2.0-rc.2 <0.3.0` 声明为可选 peer,因此手动安装时由 dsh 自身的插件兼容性检查把关;launcher 会拒绝其他引擎发布线并给出确切的安装命令,设置 `DSH_TUI_SKIP_ENGINE_CHECK=1` 可跳过 launcher 的检查。
64
94
 
65
95
  ### 模式 B:源码模式(开发者调试)
66
96
  若需对 TUI 或 DSH 底层代码进行修改与调试:
@@ -110,13 +140,13 @@ dsh-tui update
110
140
  <a id="configure-the-source-runtime"></a>
111
141
  ## 配置源码运行时
112
142
 
113
- 默认值跟踪所有者的 private `feat/deepseek-tui` 分支。该仓库需要 Git authorization。其他用户可以选择一个兼容且可访问的仓库与 ref。
143
+ 默认使用官方公开仓库的 `dsh-v0.2.1-rc.2` tag。源码模式会将本插件链接到现有 `deepseek-tui` profile,保留用户 patch;缺少 Typert 运行时产物时先调用上游生成器。随后通过 `pnpm exec node` 启动源码 CLI,不运行每次都会安装整个工作区的 `predsh` 钩子。
114
144
 
115
145
  | 环境变量 | 默认值 | 用途 |
116
146
  |---|---|---|
117
147
  | `DSH_TUI_RUNTIME_DIR` | `~/.local/share/dsh-tui/runtime` | 仅供 launcher 使用的专用 clone |
118
- | `DSH_TUI_SOURCE_URL` | `https://github.com/zhangyang-crazy-one/deepseek-harness.git` | `update` clone 和 fetch 的 Git remote |
119
- | `DSH_TUI_SOURCE_REF` | `feat/deepseek-tui` | `update` fetch 的 branch 或 ref |
148
+ | `DSH_TUI_SOURCE_URL` | `https://github.com/deepseek-ai/deepseek-harness.git` | `update` clone 和 fetch 的 Git remote |
149
+ | `DSH_TUI_SOURCE_REF` | `dsh-v0.2.1-rc.2` | `update` fetch 的 branch 或 ref |
120
150
  | `DSH_TUI_PNPM` | `pnpm` | 安装和启动所用的 pnpm executable |
121
151
 
122
152
  所有值都不得为空,运行时目录必须是绝对路径。Launcher 会拒绝 symbolic-link runtime path,也会拒绝不是 Git checkout 的现有目录。Child command 接收参数数组,不使用 shell interpolation。
@@ -128,15 +158,68 @@ dsh-tui update
128
158
  <a id="relationship-to-dsh"></a>
129
159
  ## 与 DSH 的关系
130
160
 
131
- TUI 是 DSH profile 层,而不是独立的 agent 运行时:
161
+ TUI 是 dsh 插件 bundle,不是 fork,也不是独立的 agent 运行时:
132
162
 
133
163
  ```text
134
- @deepseek-ai/dsh-base
135
- └─ @deepseek-ai/dsh-tui profile patch, terminal lifecycle, controller
136
- └─ @deepseek-ai/dsh-tui-render Ink projection and terminal I/O
164
+ @deepseek-ai/dsh-base dsh 核心 bundle(agent、会话、工具)
165
+ └─ @crazyhappyone/dsh-tui 本 bundle:cordis.patch.yml + dist/*
166
+ ├─ tui-startup (./startup) 命令行 provider(任务、--resume、--cwd)
167
+ ├─ tui (./settings) /settings 中可编辑的 TUI 偏好(volatile)
168
+ ├─ tui-runtime (./runtime) 终端生命周期与控制器
169
+ ├─ schedule (./schedule) 官方定时服务与共享会话激活
170
+ └─ zen-proxy (./zen-proxy) 可选的 OpenCode Zen 请求头代理
137
171
  ```
138
172
 
139
- 集成源码位于 private [`feat/deepseek-tui` DSH 分支](https://github.com/zhangyang-crazy-one/deepseek-harness/tree/feat/deepseek-tui/packages/tui)。影响 DSH 服务、profile 组合、组装后 CLI snapshot 或 Agent Note 的变更归该 monorepo 所有,并遵循其中的架构、测试与文档规则。
173
+ 各行通过包的 `exports` 引用插件,因此设置修改会在 profile patch 中记录可移植的行名。本 bundle 还插入已发布的 dsh 插件 `session-stats`、`message-feedback`、`tool-ask-user`、`workspace-changes`、`tool-schedule`、`time-context`、`tool-present`,以及用于账号登录回调的回环 `webserver`,并覆盖 `system-prompt`、`tools`、`session-query-sqlite` 与 `session-title-llm`。
174
+
175
+ ### 定时提醒与用户提问
176
+
177
+ 模型可使用官方 `schedule_create`、`schedule_list`、`schedule_update`、`schedule_delete` 工具。`/schedules` 跨会话列出提醒:↑↓ 或 PgUp/PgDn 选择、Enter 查看完整提示词、再次 Enter 打开所属会话、`r` 刷新、`d` 请求取消确认(`y` 确认,`n` 或 Esc 保留)。切换到其他会话后,投递仍恢复原会话。任务跨重启持久化;计时器仅在当前进程运行时工作,关闭期间到期的任务在下次启动时处理。投递回执表示已持久写入 inbox,不表示模型已完成回答。适配层打包固定 DSH 构建版本的官方定时服务和会话激活助手;升级上游后需重跑集成检查。
178
+
179
+ 用户提问支持整批逐题作答、多选和自定义文本。Space 切换多选项;`c` 打开自定义编辑器;Enter 保存文本、提交选项。无选项的问题直接进入编辑器。Tab 打开完整问题与回答供滚动阅读,Tab 或 Esc 返回编辑。编辑器内 Esc 丢弃本次编辑(纯文本问题则取消提问);选项页 Esc 取消整次请求。粘贴的多行回答保留原文,不改变聊天草稿。
180
+
181
+ 凭据编辑器及 `/key`、`/login` 的密钥参数显示圆点遮罩,凭据引用名保持可见。遮罩只影响显示:编辑和提交保留原值,取消后恢复聊天草稿。
182
+
183
+ ### 时间上下文、交付文件与图片粘贴
184
+
185
+ 官方 `time-context` 插件在准备模型步骤时提供当前时间和进程所在时区,十分钟后刷新。这类模型上下文不会增加人类对话中的消息行。
186
+
187
+ 模型可用官方 `present` 工具显式交付现有文件,每次最多八个。`/deliveries` 列出当前会话已记录的交付文件:↑↓ 选择、Enter 预览 UTF-8 文本、`o` 请求本机系统应用打开所选文件、Esc 返回。PDF、Office、图片等二进制格式显示文件信息,并通过系统应用查看。文本读取默认限制为 1 MiB。已完成回合也会显示交付路径与说明;记录可随会话恢复,但文件必须仍存在且可访问。
188
+
189
+ 剪贴板图片粘贴在 macOS 使用 `pngpaste -`([安装:`brew install pngpaste`](https://github.com/jcsalterego/pngpaste)),Wayland 使用 `wl-paste`,X11 使用 `xclip`。缺少助手时显示明确错误;读取默认五秒超时,关闭 TUI 时取消,并保留既有图片大小限制与校验。macOS 命令和子进程行为已在 Linux 上自动验证,macOS 实机验证仍待完成。
190
+
191
+ ### DeepSeek 账号、模型与工作目录
192
+
193
+ - 当 dsh 挂载 `deepseek-account` 服务时,`/login` 打开 DeepSeek 账号页:Enter 发起浏览器登录,`o` 重新打开授权链接,`c` 取消;登录后页面显示账号资料与余额。浏览器回调到本 bundle 的 `webserver` 行,监听 `127.0.0.1` 上由系统分配的端口。通过 SSH 使用时,页面显示 `ssh -L` 端口转发命令而不打开浏览器;在 `webserver` 行固定 `port` 可让转发保持稳定。未挂载账号服务时,`/login` 与 `/key` 打开 API 密钥编辑器。
194
+ - `/logout` 确认后退出登录,已保存的 API 密钥保留。
195
+ - `/model` 在 `deepseek-account` 与 `deepseek-official` 目录为空时列出它们,并注明使模型可用的步骤(`/login` 或 `/key`),且拒绝选中此类行。
196
+ - `/cd [路径]` 在 dsh 0.2.1 及以后版本查看或切换会话工作目录。顶栏、`@` 提及与 `/files` 随之切换,模型会收到变更通知;已有 shell 保留各自的目录。
197
+ - `/plugins` 将官方 bundle 单独分组。文件尚未安装的官方目录条目标记为可安装,按 Space 打开其精确安装目标的安装预览。
198
+
199
+ ### OpenCode Zen 免费模型
200
+
201
+ 打包后的 patch 挂载了 `zen-proxy`(vendored 自
202
+ [zhangyang-crazy-one/dsh-zen-proxy](https://github.com/zhangyang-crazy-one/dsh-zen-proxy),
203
+ fork 自 [Yee-h/dsh-zen-proxy](https://github.com/Yee-h/dsh-zen-proxy)):进程内 localhost
204
+ 代理,注入 Zen 要求的 OpenCode 官方客户端头(`User-Agent`、
205
+ `x-opencode-client/session/request/project`)。没有它,Zen 会返回
206
+ `400 MissingSessionID` / `429 FreeUsageLimitError`,因为 dsh 始终发送自己的
207
+ attribution `User-Agent`。
208
+
209
+ 使用方法:通过 TUI `/settings` provider 表单(或 profile 的 `cordis.patch.yml`)
210
+ 添加一个指向该代理的 provider,并把密钥放在 credentials 中:
211
+
212
+ ```yaml
213
+ - id: llm-pi-ai
214
+ config:
215
+ providers:
216
+ opencode:
217
+ api: openai-completions
218
+ baseURL: http://127.0.0.1:4097/v1
219
+ apiKeyEnv: OPENCODE_API_KEY
220
+ ```
221
+
222
+ 代理只监听 `127.0.0.1:4097`;在 profile 的 `cordis.patch.yml` 中加入 `- id: zen-proxy` 并设置 `disabled: true` 即可关闭。
140
223
 
141
224
  -----
142
225
 
@@ -145,7 +228,8 @@ TUI 是 DSH profile 层,而不是独立的 agent 运行时:
145
228
 
146
229
  | 包 | DSH 形态 | 职责 |
147
230
  |---|---|---|
148
- | [`tui/`](tui/README.zh.md) | Profile bundle 与运行时插件 | 在 `dsh-base` 上组合终端层、拥有 live 终端会话,并将用户动作映射到 DSH 服务 |
231
+ | [`tui/`](tui/README.zh.md) | 运行时、启动与设置插件 | 在 `dsh-base` 上组合终端层、拥有 live 终端会话,并将用户动作映射到 DSH 服务 |
232
+ | [`plugins/zen-proxy/`](https://github.com/zhangyang-crazy-one/dsh-zen-proxy) | Vendored 插件(打包为 `dist/zen-proxy.js`) | 进程内 OpenAI 兼容代理,注入 OpenCode Zen 客户端头;在 `cordis.patch.yml` 中挂载 |
149
233
  | [`tui-render/`](tui-render/README.zh.md) | Library | 通过 Ink 投影控制器状态,但不拥有 agent、持久化或模型请求 |
150
234
 
151
235
  -----
@@ -153,9 +237,20 @@ TUI 是 DSH profile 层,而不是独立的 agent 运行时:
153
237
  <a id="development-workflow"></a>
154
238
  ## 开发工作流
155
239
 
156
- 在完整 DSH checkout 中实现 TUI 行为,运行受变更行为影响的检查,并将确认后的 `packages/tui/` tree 导出到这里。在本仓库中使用 `npm test` 开发 launcher;通过 packed tarball 测试安装,不使用 workspace link。
240
+ `tui/` 与 `tui-render/` 基于上游 dsh checkout 编译,版本为 `src/launcher.js` 中 `COMPATIBLE_DSH_VERSION` 指定的 tag:
241
+
242
+ ```text
243
+ git clone --branch dsh-v0.2.1-rc.2 https://github.com/deepseek-ai/deepseek-harness ../deepseek-harness
244
+ (cd ../deepseek-harness && pnpm install)
245
+ npm run build # 或 DSH_SOURCE=/path/to/checkout npm run build
246
+ (cd ../deepseek-harness && pnpm install) # 链接挂载后的插件开发依赖
247
+ npm run dev:setup # 同样支持 DSH_SOURCE;生成类型声明并链接编辑器依赖
248
+ npm run typecheck # 严格检查源码和测试
249
+ ```
250
+
251
+ `npm run build` 把插件包与 `cordis.patch.yml` 复制进 checkout 的 `packages/tui/` workspace,用 esbuild 打包 `dist/index.js`、`dist/startup.js`、`dist/settings.js`、`dist/schedule.js` 与 `dist/zen-proxy.js`,并逐个检查导入。插件测试在 checkout 中运行 `npx vitest run packages/tui`,launcher 测试在本仓库运行 `npm test`;发布前运行 `npm run pack:check`。通过 packed tarball 或 `dsh plugin --profile <name> add <本目录>` 测试安装。
157
252
 
158
- Launcher runtime 必须与开发 checkout 分离。要安全测试其他源码,请将 `DSH_TUI_RUNTIME_DIR` 指向临时绝对目录,并配置 `DSH_TUI_SOURCE_URL` 与 `DSH_TUI_SOURCE_REF`。
253
+ 本地 `tsconfig.json` 用于独立插件仓库的编辑器检查;构建时使用 `tsconfig.workspace.json` 作为 checkout 中的包配置,保留上游项目引用。`dev:setup` 构建依赖类型声明并链接整个 `node_modules` 目录,保留 pnpm 的相对链接。更新上游或公开类型后重新执行 build 和 setup;编辑器若仍显示旧的缺失模块错误,需要重载 TypeScript 项目。
159
254
 
160
255
  -----
161
256
 
@@ -178,21 +273,42 @@ npx --yes npm@11 trust github @crazyhappyone/dsh-tui \
178
273
  每次发布时,先提升 `package.json` 版本,等待 CI 通过并合并,然后创建 tag 与 package version 一致的 GitHub Release:
179
274
 
180
275
  ```text
181
- gh release create v0.1.0-alpha.4 --prerelease --generate-notes
276
+ gh release create v0.1.0-alpha.50 --prerelease --notes-file docs/releases/v0.1.0-alpha.50.md
182
277
  ```
183
278
 
184
279
  `Publish npm` workflow 会在发布前再次运行测试与 packed-package 验证。不要重新运行旧的 release tag:npm version 不可覆盖。提升到 stable 必须使用新版本并发布 non-prerelease GitHub Release。
185
280
 
186
281
  -----
187
282
 
283
+ ## 终端能力
284
+
285
+ `/timeline` 浏览逐条 Session 事件、真实工具/token/时长与完整 JSON;`/attachments` 列出类型化图片/文件引用并打开本地副本;`/review` 读取逐文件官方 diff。`/files` 对已展开目录合并自动刷新,并保留手工 `r` 刷新。
286
+
287
+ `/settings` 使用 Tab/Shift+Tab 切换分组,持久化 `tui.theme=dark|light`。`/keys` 列出各场景按键;`/bind ACTION Ctrl+X`、`/bind ACTION default`、`/unbind ACTION` 修改输入区快捷键并检查冲突。Shift+方向键/Home/End 按字素选择,输入/粘贴替换选区,Ctrl+Y 复制普通选区;凭据选区禁止复制。审批、提问及计划评审中可用 Alt+H 打开只读帮助。
288
+
289
+ `/agents` 支持 `c` 续聊(Enter 排队、Ctrl+Enter 引导)、`s` 请求停止、`v` 在 100 列以上并排查看。窄终端保留单面板。人工控制保留目录给出的准确直接父会话地址;Stop 回执不表示执行已经停止。
290
+
291
+ `/preset` 浏览 standard/PTC/minimal/cordis 声明,`/preset ID` 在首轮前选择隔离组合;开始对话后保持锁定。`/market QUERY` 检索已配置索引,`i` 进入插件管理器预览及确认,`n/p` 翻页。`/inspect` 浏览官方 Host provider,`/inspect host PROVIDER METHOD JSON` 查询具体契约。`/focus` 隐藏中间工具卡片,不修改模型工具或会话日志。外部语言包可调用 `registerTuiLocale`;围栏代码采用有界的按语言词法高亮。
292
+
293
+ Goal 页脚区分自动续跑和需要 `/goal resume` 恢复的停止状态。后台开启的回合会更新运行状态及 Ctrl+C 取消路径。更新正在运行的源码安装后使用 `/reload`;恢复的 Goal 需显式 `/goal resume` 重新授权续跑。
294
+
295
+ 验证及平台边界见 [P1/P2 验收记录](docs/p1-p2-verification-2026-10-20.md)。
296
+
297
+ -----
298
+
188
299
  <a id="known-limitations"></a>
189
300
  ## 已知限制
190
301
 
191
- - **Private 默认源码** — npm 安装是 public,但默认 DSH runtime remote 需要仓库授权;匿名用户必须配置一个可访问的兼容源码。
302
+ - **第三方插件需匹配引擎版本** — 旧认证插件如果只声明兼容 dsh 0.1.x,会被 dsh 0.2 拒绝加载;launcher 不自动授予版本豁免。
192
303
  - **需要源码工具链** — 初始化运行时需要 Git、pnpm 与 DSH 支持的 Node 版本。
193
304
  - **不自动解决冲突** — dirty 或 non-fast-forward runtime history 需要显式人工操作或新的运行时目录。
194
305
  - **运行时更新不是 launcher 更新** — `dsh-tui update` 刷新 DSH 源码与依赖;npm 更新 launcher package。
195
306
  - **集成分支拥有发布就绪状态** — launcher 成功不能替代 DSH 分支的行为、snapshot、build 或 hygiene 检查。
307
+ - **源码模式也使用本插件** — 配置的 checkout 必须与本 bundle 的 dsh 版本兼容。历史 profile 中的 `@deepseek-ai/dsh-tui` 旧 bundle 应替换为 `@crazyhappyone/dsh-tui`;迁移前备份 profile,并保留用户设置。
308
+ - **提醒需要进程运行** — `/schedules` 使用官方服务及持久化原会话;重启可恢复待投递提醒,关闭进程期间不运行计时器。
309
+ - **终端能力边界** — 图片及 PDF/Office 文档使用元数据/文本或系统打开。Ink 没有 IME composition 事件,预编辑由终端原生处理。`INK_SCREEN_READER=true` 使用普通输出流,关闭鼠标捕获、备用屏幕及动画;真实 IME/屏幕阅读器设备和 macOS 剪贴板尚未验证。
310
+ - **账号登录需要可访问的 Platform** — 主机无法访问 `platform.deepseek.com` 时登录报告 `no-response`(服务无响应),此时请使用 `/key`。
311
+ - **dsh 0.2 不支持物理删除会话** — 0.2 的会话持久化以归档代替删除,而 TUI 组合未挂载 workspace 归档服务,因此会话列表会提示无法删除。
196
312
 
197
313
  <a id="dev-note"></a>
198
314
  ## 开发备注