@crazyhappyone/dsh-tui 0.1.0-alpha.47 → 0.1.0-alpha.49
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.md +7 -1
- package/README.zh.md +6 -0
- package/bin/dsh-tui.js +14 -0
- package/cordis.patch.yml +75 -28
- package/dist/index.js +49827 -48802
- package/package.json +2 -1
- package/src/launcher.js +62 -13
- package/src/release-patch.js +23 -0
- package/tui/README.md +14 -0
- package/tui/README.zh.md +14 -0
- package/tui/cordis.patch.yml +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazyhappyone/dsh-tui",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.49",
|
|
4
4
|
"description": "Source-runtime launcher for the DeepSeek Harness terminal interface",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"LICENSE"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
+
"build": "node scripts/build.js",
|
|
22
23
|
"test": "node --test tests/*.test.js",
|
|
23
24
|
"pack:check": "npm pack --dry-run --json"
|
|
24
25
|
},
|
package/src/launcher.js
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* @module @crazyhappyone/dsh-tui/launcher
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { dirname, isAbsolute, join } from 'node:path'
|
|
7
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path'
|
|
8
8
|
|
|
9
9
|
const DEFAULT_SOURCE_URL = 'https://github.com/zhangyang-crazy-one/deepseek-harness.git'
|
|
10
10
|
const DEFAULT_SOURCE_REF = 'feat/deepseek-tui'
|
|
11
|
+
const PROBE_TIMEOUT_MS = 3000
|
|
11
12
|
|
|
12
13
|
/** @typedef {'missing' | 'directory' | 'file' | 'symlink' | 'other'} PathKind */
|
|
13
14
|
|
|
@@ -37,7 +38,10 @@ const DEFAULT_SOURCE_REF = 'feat/deepseek-tui'
|
|
|
37
38
|
* @property {(path: string) => void} makeDirectory
|
|
38
39
|
* @property {(path: string) => string} readText
|
|
39
40
|
* @property {(path: string, content: string) => void} [writeText]
|
|
40
|
-
* @property {
|
|
41
|
+
* @property {string} [nodeExecutable] Node executable for package bin entries without an executable bit.
|
|
42
|
+
* @property {string} [currentDirectory] Working directory for local package resolution.
|
|
43
|
+
* @property {(directory: string) => string | undefined} [resolveDshPackage] Resolve an installed @deepseek-ai/dsh package.json.
|
|
44
|
+
* @property {(command: string, args: string[], options?: {cwd?: string, stdio?: 'inherit', capture?: boolean, timeoutMs?: number}) => CommandResult} run
|
|
41
45
|
* @property {(text: string) => void} writeOut
|
|
42
46
|
* @property {(text: string) => void} writeError
|
|
43
47
|
*/
|
|
@@ -106,15 +110,18 @@ export function resolveLauncherSettings({ env, homeDirectory, packageRoot }) {
|
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
/**
|
|
109
|
-
* Probe
|
|
113
|
+
* Probe DSH_BIN, PATH, npm/pnpm global packages, then local packages, in order.
|
|
114
|
+
* Each subprocess has a timeout. The caller reuses the result for this launch;
|
|
115
|
+
* an explicit DSH_BIN failure never selects a different installation.
|
|
110
116
|
* @param {{env?: Readonly<Record<string, string | undefined>>, settings?: LauncherSettings, adapters: LauncherAdapters}} input
|
|
111
|
-
* @returns {{ok: true, binPath: string, version: string} | {ok: false, reason: string}}
|
|
117
|
+
* @returns {{ok: true, binPath: string, version: string, command?: string, args?: string[]} | {ok: false, reason: string}}
|
|
112
118
|
*/
|
|
113
119
|
export function probeInstalledDsh({ env = {}, settings, adapters }) {
|
|
114
120
|
const explicit = settings?.dshBin ?? env['DSH_BIN']
|
|
115
121
|
if (explicit && explicit.trim() !== '') {
|
|
116
122
|
const trimmed = explicit.trim()
|
|
117
|
-
|
|
123
|
+
if (!isAbsolute(trimmed)) return { ok: false, reason: 'DSH_BIN must be an absolute path' }
|
|
124
|
+
const probe = adapters.run(trimmed, ['--version'], { capture: true, timeoutMs: PROBE_TIMEOUT_MS })
|
|
118
125
|
if (probe.status === 0) {
|
|
119
126
|
return { ok: true, binPath: trimmed, version: probe.stdout.trim() || 'unknown' }
|
|
120
127
|
}
|
|
@@ -122,14 +129,54 @@ export function probeInstalledDsh({ env = {}, settings, adapters }) {
|
|
|
122
129
|
return { ok: false, reason: `DSH_BIN is set to "${trimmed}" but failed to run${err ? `: ${err}` : ` (exit code ${probe.status})`}` }
|
|
123
130
|
}
|
|
124
131
|
|
|
125
|
-
const pathProbe = adapters.run('dsh', ['--version'], { capture: true })
|
|
132
|
+
const pathProbe = adapters.run('dsh', ['--version'], { capture: true, timeoutMs: PROBE_TIMEOUT_MS })
|
|
126
133
|
if (pathProbe.status === 0) {
|
|
127
134
|
return { ok: true, binPath: 'dsh', version: pathProbe.stdout.trim() || 'unknown' }
|
|
128
135
|
}
|
|
129
136
|
|
|
137
|
+
const checked = new Set()
|
|
138
|
+
const failures = []
|
|
139
|
+
function probePackage(manifestPath) {
|
|
140
|
+
if (!manifestPath || checked.has(manifestPath)) return undefined
|
|
141
|
+
checked.add(manifestPath)
|
|
142
|
+
if (adapters.inspectPath(manifestPath) !== 'file') return undefined
|
|
143
|
+
let manifest
|
|
144
|
+
try {
|
|
145
|
+
manifest = JSON.parse(adapters.readText(manifestPath))
|
|
146
|
+
} catch (error) {
|
|
147
|
+
failures.push(`${manifestPath}: ${errorMessage(error)}`)
|
|
148
|
+
return undefined
|
|
149
|
+
}
|
|
150
|
+
const bin = typeof manifest?.bin === 'string' ? manifest.bin : manifest?.bin?.dsh
|
|
151
|
+
if (manifest?.name !== '@deepseek-ai/dsh' || typeof bin !== 'string' || bin.trim() === '') {
|
|
152
|
+
failures.push(`${manifestPath}: missing @deepseek-ai/dsh bin entry`)
|
|
153
|
+
return undefined
|
|
154
|
+
}
|
|
155
|
+
const binPath = resolve(dirname(manifestPath), bin)
|
|
156
|
+
const command = adapters.nodeExecutable ?? binPath
|
|
157
|
+
const args = adapters.nodeExecutable ? [binPath] : []
|
|
158
|
+
const result = adapters.run(command, [...args, '--version'], { capture: true, timeoutMs: PROBE_TIMEOUT_MS })
|
|
159
|
+
if (result.status === 0) {
|
|
160
|
+
return { ok: true, binPath, version: result.stdout.trim() || 'unknown', command, args }
|
|
161
|
+
}
|
|
162
|
+
failures.push(`${binPath}: ${result.stderr.trim() || `exit code ${result.status}`}`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const manager of new Set(['npm', settings?.packageManager ?? 'pnpm'])) {
|
|
166
|
+
const root = adapters.run(manager, ['root', '-g'], { capture: true, timeoutMs: PROBE_TIMEOUT_MS })
|
|
167
|
+
const directory = root.stdout.trim()
|
|
168
|
+
if (root.status !== 0 || !isAbsolute(directory) || /[\r\n]/u.test(directory)) continue
|
|
169
|
+
const result = probePackage(join(directory, '@deepseek-ai', 'dsh', 'package.json'))
|
|
170
|
+
if (result) return result
|
|
171
|
+
}
|
|
172
|
+
for (const directory of new Set([adapters.currentDirectory, settings?.packageRoot])) {
|
|
173
|
+
if (!directory) continue
|
|
174
|
+
const result = probePackage(adapters.resolveDshPackage?.(directory))
|
|
175
|
+
if (result) return result
|
|
176
|
+
}
|
|
130
177
|
return {
|
|
131
178
|
ok: false,
|
|
132
|
-
reason:
|
|
179
|
+
reason: `dsh executable was not found in PATH, DSH_BIN, or global/local packages${failures.length ? ` (${failures.join('; ')})` : ''}`,
|
|
133
180
|
}
|
|
134
181
|
}
|
|
135
182
|
|
|
@@ -152,7 +199,8 @@ export function findBundledPatch(packageRoot, adapters) {
|
|
|
152
199
|
}
|
|
153
200
|
|
|
154
201
|
/**
|
|
155
|
-
* Ensure the tui profile
|
|
202
|
+
* Ensure the custom tui profile uses dsh-base with startup-only patch reload.
|
|
203
|
+
* The release patch supplies TUI plugins; the headless bundle would add a second runner.
|
|
156
204
|
* @param {{homeDirectory?: string, env?: Readonly<Record<string, string | undefined>>, adapters: LauncherAdapters}} input
|
|
157
205
|
*/
|
|
158
206
|
export function ensureTuiProfile({ homeDirectory, env = {}, adapters }) {
|
|
@@ -228,9 +276,10 @@ function launchTui({ args, mode, settings, adapters, env = {} }) {
|
|
|
228
276
|
if (patchPath !== undefined) {
|
|
229
277
|
const probe = probeInstalledDsh({ env, settings, adapters })
|
|
230
278
|
if (probe.ok) {
|
|
231
|
-
return launchLightweightTui({ args,
|
|
279
|
+
return launchLightweightTui({ args, probe, patchPath, adapters, env, settings })
|
|
232
280
|
}
|
|
233
|
-
|
|
281
|
+
const explicit = settings.dshBin ?? env['DSH_BIN']
|
|
282
|
+
if (effectiveMode === 'lightweight' || explicit?.trim()) {
|
|
234
283
|
return reportError(adapters, `lightweight mode requires installed dsh (${probe.reason}); run \`npm i -g @deepseek-ai/dsh\` or use \`dsh-tui --source\``)
|
|
235
284
|
}
|
|
236
285
|
} else if (effectiveMode === 'lightweight') {
|
|
@@ -256,11 +305,11 @@ function launchTui({ args, mode, settings, adapters, env = {} }) {
|
|
|
256
305
|
return launchSourceTui({ args, settings, adapters })
|
|
257
306
|
}
|
|
258
307
|
|
|
259
|
-
function launchLightweightTui({ args,
|
|
308
|
+
function launchLightweightTui({ args, probe, patchPath, adapters, env = {}, settings }) {
|
|
260
309
|
ensureTuiProfile({ homeDirectory: settings?.homeDirectory, env, adapters })
|
|
261
310
|
const result = adapters.run(
|
|
262
|
-
binPath,
|
|
263
|
-
['--profile', 'tui', '--patch', patchPath, ...args],
|
|
311
|
+
probe.command ?? probe.binPath,
|
|
312
|
+
[...(probe.args ?? []), '--profile', 'tui', '--patch', patchPath, ...args],
|
|
264
313
|
{ stdio: 'inherit' },
|
|
265
314
|
)
|
|
266
315
|
return result.status
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Release patch projection from the matching Harness TUI composition. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Point the three bundled plugins at release artifacts, retaining all other rows.
|
|
5
|
+
* @param {string} source - Harness packages/tui/tui/cordis.patch.yml content.
|
|
6
|
+
* @param {string} distDirectory - Relative dist directory from the output patch.
|
|
7
|
+
* @returns {string} Patch text suitable for dsh --patch.
|
|
8
|
+
*/
|
|
9
|
+
export function releasePatch(source, distDirectory) {
|
|
10
|
+
const entries = new Map([
|
|
11
|
+
['@deepseek-ai/dsh-tui/startup', 'startup.js'],
|
|
12
|
+
['./zen-proxy/index.js', 'zen-proxy.js'],
|
|
13
|
+
['@deepseek-ai/dsh-tui', 'index.js'],
|
|
14
|
+
])
|
|
15
|
+
const patch = source.replace(/^(\s+name: )(["'])([^"']+)\2$/gmu, (line, prefix, quote, name) => {
|
|
16
|
+
const file = entries.get(name)
|
|
17
|
+
if (!file) return line
|
|
18
|
+
entries.delete(name)
|
|
19
|
+
return `${prefix}${quote}${distDirectory}/${file}${quote}`
|
|
20
|
+
})
|
|
21
|
+
if (entries.size) throw new Error(`TUI patch is missing plugin entries: ${[...entries.keys()].join(', ')}`)
|
|
22
|
+
return patch
|
|
23
|
+
}
|
package/tui/README.md
CHANGED
|
@@ -42,6 +42,20 @@ Reasoning is hidden by default. Ctrl+O or `/reasoning` shows the complete dim re
|
|
|
42
42
|
|
|
43
43
|
`/tools` opens every recorded call, including generic fallbacks and process failures. Enter opens bounded source pages with the selected action and status kept in the header; n/p move forward/back, d enables raw metadata, y copies the complete original, and e exports a private, non-overwriting `tool-*.txt` file in the launch working directory. Oversized clipboard payloads are explicitly refused with an export hint rather than truncated. Esc returns to the list and then the unchanged conversation. Approval and ask-user dialogs keep input priority.
|
|
44
44
|
|
|
45
|
+
<a id="plugins-and-live-tasks"></a>
|
|
46
|
+
|
|
47
|
+
### Plugins and live tasks
|
|
48
|
+
|
|
49
|
+
`/plugins` or `g p` opens the Plugins page with installation-supplied and profile-owned bundles. Read-only reasons remain visible; non-removable bundles can still be toggled when the service permits it. Changes affect every session using the profile. Without Plugin Manager, the page reports that the service is unavailable and remains closable.
|
|
50
|
+
|
|
51
|
+
The page separates saved selection, running state and operation outcome. A successfully saved `restart-required` result offers `R` or `/reload`; `failed`, `cancelled` and `overridden` retain their service-reported meaning without a successful-restart notice. Inventory refreshes on open, after operations and on manager notifications. External patch edits are reread when the page reopens.
|
|
52
|
+
|
|
53
|
+
Installation starts with an inspection; refusal preserves the entered spec and starts no package operation. Esc closes the page while the controller continues tracking an installation; reopening shows its latest progress or result. Only `c` explicitly requests cancellation during installation: `cancelled` confirms cancellation, `too-late` keeps waiting, and `not-running` does not claim cancellation. Build-script retry requires confirmation of the exact pending package names; approval persists by package name in the profile and runs scripts with the host user's permissions. Removal also requires confirmation naming the bundle.
|
|
54
|
+
|
|
55
|
+
The live HUD separates task plans from background execution. It prioritizes in-progress todos and shows only running or stopping jobs; finished jobs disappear on the next state refresh without deleting their records or marking output read. Existing `job_list` and `job_output` access remains valid within the job/Agent lifetime, without a cross-restart guarantee. Process completion does not imply exit-code success. Todo, Workflow and Jobs keep independent state; finishing a bash job does not complete a todo.
|
|
56
|
+
|
|
57
|
+
`renderPolicy.normalHudRows`, `compactHudRows` and `compactHeightThreshold` default to 8, 4 and 24. Below 24 terminal rows the HUD uses the compact limit; available space can reduce either limit further. All three values must be positive integers and the compact limit cannot exceed the normal limit. Titles, Workflow summaries and hidden-item counts share the budget; empty sections collapse. The renderer reserves space for input, dialogs and the transcript before allocating HUD rows.
|
|
58
|
+
|
|
45
59
|
### Contract
|
|
46
60
|
|
|
47
61
|
- The runtime owns the live Agent handle, session projection and session-directory state; the render package receives only the controller interface. The top-bar title is a folded `session/title` except a `fallback` title that coexists with a human user message; before a provider or rename title the loop shows the compact mount name `DeepSeek · deepseek-tui`. Directory rows still use the first-human-message fallback. An empty idle window paints the generated official FishLogo, `DeepSeek`, and `有什么可以帮忙的` in the conversation column. The environment selects half-block, full-block, ASCII, or plain output independently of color; `brandAnimation` stores `auto | on | off`, and every input, history, overlay, resize, completion, or unmount stop clears the one-shot reveal timer. The runtime answers `approval/request` for that live agent and calls `next()` for every other agent: `y`/`a` resolve `'allowed-once'`, `n`/`d`/Esc resolve `'rejected'`, and abort (including Ctrl+C cancelling generation) resolves `'cancelled'` via the request signal. Policy `'never'` is decided by the host before this listener runs, so no ApprovalPane appears. Ctrl+E flips the current window's tool-card fold (`toolCardsExpanded`; no session event). Empty `/permission` opens the preset overlay; parameterized `/permission <name>` runs `ctx.commands.execute`. Empty `/settings` opens the settings overlay on every top-level `describe()` field (`llm-deepseek · models`; `llm-pi-ai · providers` opens a structured form — a directory name, template index 1–4, single-line `名称 端点 [模型[,模型…]]`, or multi-line `name= baseURL= models= api=`; existing routes expand into child rows for `api` / `baseURL` / `apiKeyEnv` / `displayName` / `models`); Enter apply writes the selected field through `ctx.settings.update`. An empty `models=` line, the literal `auto` in either form, the two-token `名称 端点` form, and an existing route's `providers.<route>.models` row typed as `auto` all defer model assembly to `ctx.llm.discoverModels`; the overlay shows `正在获取模型列表…` while the request is in flight, and any refusal or empty reply is painted on the ✗ pair without writing settings — a 401/403 without a stored credential appends `请先使用 /key 配置 API key`. Browse `e` reports `prepareDocument()` and `r` rereads rows (`✓ 已重载设置`). Empty `/resume` opens the session list. `/reload` is a local command: it flushes the live session, unmounts, disposes that session, then spawns a replacement Node with the same launcher flags plus `--resume <id>`, dropping the original task positional so the first message is not sent again. Overlay `r` only rereads settings rows. Idle boot with no configured `DEEPSEEK_API_KEY` opens `首次设置`; Enter saves through `ctx.credentials.set` and then opens the model pane. Esc skips without opening it. The `tui` section owns `colorTier`, `submitOnEnter` (Enter inserts a newline when false), `notify` (`off | attention | every-turn`, default `attention`), `notifyQuietInputSeconds` (non-negative integer, default 10), `brandAnimation` (shown as `自动 / 开启 / 关闭`), `scrollbar` (boolean, default `true`), `reasoning` and `statusDetails` (booleans, default `false`), `locale` (`zh-CN | en-US`, default `zh-CN`), and the validated `renderPolicy` described above. A `user-questions/request` waterfall listener is registered in the current runtime-root Agent scope; it delegates foreign and child requests with `next()`, while accepted requests paint `AskUserPane`, bind abort/replacement/disposal to one cleanup, and notify exactly once at admission. ↑↓/jk move the highlight, and digit then Enter returns the original option label. The slash directory includes each command's `description`.
|
package/tui/README.zh.md
CHANGED
|
@@ -42,6 +42,20 @@ bundle patch 从 `tuiStartup` 读取可选的 `task` 首条消息种子、可选
|
|
|
42
42
|
|
|
43
43
|
`/tools` 打开全部已记录调用,包括通用回退卡和进程失败。Enter 打开有界原文分页,页首保留所选操作与状态;n/p 前后翻页,d 开启原始元数据,y 复制完整原文,e 在启动工作目录中导出私有且不覆盖已有文件的 `tool-*.txt`。超大剪贴板载荷会被明确拒绝并提示导出,不会截断。Esc 先返回列表,再回到原对话。批准与用户提问对话始终保留输入优先级。
|
|
44
44
|
|
|
45
|
+
<a id="plugins-and-live-tasks"></a>
|
|
46
|
+
|
|
47
|
+
### 插件与实时任务
|
|
48
|
+
|
|
49
|
+
`/plugins` 或 `g p` 打开 Plugins 页面,按安装供给与 profile 自有分组列出 bundle。只读原因保持可见;不可移除的 bundle 在服务允许时仍可启停。变更影响使用该 profile 的所有会话。未组合 Plugin Manager 时,页面明确提示服务不可用,并仍可关闭。
|
|
50
|
+
|
|
51
|
+
页面区分已保存的选择、运行状态与操作结果。成功保存且结果为 `restart-required` 时提供 `R` 或 `/reload`;`failed`、`cancelled` 与 `overridden` 保留服务报告的含义,不显示成功重启提示。清单在打开、操作结束和收到管理器通知时刷新。外部 patch 编辑在页面重新打开时重读。
|
|
52
|
+
|
|
53
|
+
安装先进行预检;拒绝时保留输入的 spec,不启动包操作。Esc 关闭页面后,控制器继续跟踪安装;重开显示最新进度或结果。安装期间只有 `c` 显式请求取消:`cancelled` 确认取消,`too-late` 继续等待,`not-running` 不声称取消成功。构建脚本重试要求确认准确的待审批包名;审批按包名持久化到 profile,并以宿主用户权限运行脚本。移除同样需要确认具名 bundle。
|
|
54
|
+
|
|
55
|
+
实时 HUD 将任务计划与后台执行分区呈现。它优先显示进行中待办,作业只显示运行中或停止中项;结束作业在下次状态刷新时撤出,不删除记录或把输出标为已读。既有 `job_list` 与 `job_output` 访问在 job/Agent 生命周期内仍有效,不保证跨重启保留。进程结束不代表退出码成功。Todo、Workflow 与 Jobs 保持独立状态;bash 结束不会完成待办。
|
|
56
|
+
|
|
57
|
+
`renderPolicy.normalHudRows`、`compactHudRows` 与 `compactHeightThreshold` 默认分别为 8、4 和 24。终端不足 24 行时 HUD 使用紧凑上限;可用空间还可进一步收缩任一上限。三个值必须为正整数,紧凑上限不能大于普通上限。标题、Workflow 摘要与隐藏项计数共享预算;空分区自动收起。渲染器先为输入、对话框与正文预留空间,再分配 HUD 行数。
|
|
58
|
+
|
|
45
59
|
### 约定
|
|
46
60
|
|
|
47
61
|
- 运行时拥有 live Agent 句柄、会话投影和会话目录状态;渲染包只接收 controller 接口。顶栏标题是已折叠的 `session/title`,但与人类用户消息并存的 `fallback` 标题除外;在出现 provider 或重命名标题之前循环显示紧凑挂载名 `DeepSeek · deepseek-tui`。目录行仍使用第一条人类消息作为回退。空闲无消息时,对话列绘制生成的官方 FishLogo、`DeepSeek` 与 `有什么可以帮忙的`。环境独立于颜色选择 half-block、full-block、ASCII 或纯字标输出;`brandAnimation` 保存 `auto | on | off`,任何输入、历史、覆盖层、resize、播放完成或卸载 stop 都会清除一次性 reveal timer。运行时只为已绑定的 live agent 回答 `approval/request`,其他 agent 调用 `next()`。`y`/`a` 得到 `'allowed-once'`,`n`/`d`/Esc 得到 `'rejected'`,中止(含 Ctrl+C 停止生成)经请求 signal 得到 `'cancelled'`。策略 `'never'` 由 host 在该 listener 之前决定,因此不会出现 ApprovalPane。Ctrl+E 翻转当前窗口的工具卡折叠(`toolCardsExpanded`;不写 session 事件)。空 `/permission` 打开预设覆盖层;带参 `/permission <name>` 走 `ctx.commands.execute`。空 `/settings` 打开设置覆盖层,列出 `describe()` 的每个顶层字段(`llm-deepseek · models`;`llm-pi-ai · providers` 打开一个结构化表单——目录名、模板序号 1–4、单行 `名称 端点 [模型[,模型…]]`,或多行 `name= baseURL= models= api=`;已有路由展开为 `api` / `baseURL` / `apiKeyEnv` / `displayName` / `models` 的子行);Enter 应用经 `ctx.settings.update` 写入所选字段。`models=` 留空、任一表单中的字面量 `auto`、两 token 的 `名称 端点` 形式,以及已有路由 `providers.<route>.models` 行被填成 `auto` 时,都把模型列表组装交给 `ctx.llm.discoverModels`;面板在请求进行中显示 `正在获取模型列表…`,任何拒绝或空响应都画在 ✗ 行上且不写任何设置——未存凭据时的 401/403 会追加 `请先使用 /key 配置 API key`。浏览态 `e` 报告 `prepareDocument()`,`r` 重读行(`✓ 已重载设置`)。空 `/resume` 打开会话列表。`/reload` 是本地命令:flush 当前会话、卸载终端、dispose 该会话,再以相同启动器标志加上 `--resume <id>` 拉起新的 Node,并丢掉原来的任务位置参数,以免首条消息再发一次。覆盖层上的 `r` 只重读设置行。空闲启动且未配置 `DEEPSEEK_API_KEY` 时打开 `首次设置`;Enter 经 `ctx.credentials.set` 保存后打开模型面板,Esc 跳过且不打开。`tui` 分节拥有 `colorTier`、`submitOnEnter`(为 false 时 Enter 插入换行)、`notify`(`off | attention | every-turn`,默认 `attention`)、`notifyQuietInputSeconds`(非负整数,默认 10)、`brandAnimation`(显示为 `自动 / 开启 / 关闭`)、`scrollbar`(布尔值,默认 `true`)、`reasoning` 与 `statusDetails`(布尔值,默认 `false`)、`locale`(`zh-CN | en-US`,默认 `zh-CN`)以及上文所述已验证的 `renderPolicy`。当前 runtime root Agent 的 scope 注册 `user-questions/request` waterfall listener;它用 `next()` 委托外部 root 与 child 请求,被接纳的请求则绘制 `AskUserPane`,把中止、Agent 替换与释放归并到同一清理,并只在准入时通知一次。↑↓/jk 移动高亮,数字键再 Enter 返回选项的原始 label。斜杠目录包含每条命令的 `description`。
|
package/tui/cordis.patch.yml
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
You are interacting with the user through the deepseek-tui
|
|
18
18
|
terminal interface.
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
#
|
|
20
|
+
# HMR stays disabled. Profile and home patch edits apply on the next
|
|
21
|
+
# process start; /reload restarts the terminal with the current session.
|
|
22
22
|
- id: hmr
|
|
23
23
|
disabled: true
|
|
24
24
|
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
name: "@deepseek-ai/dsh-tool-ask-user"
|
|
87
87
|
|
|
88
88
|
- id: tui-startup
|
|
89
|
-
name: "
|
|
89
|
+
name: "../dist/startup.js"
|
|
90
90
|
|
|
91
91
|
# Zero-config official OpenAI/Anthropic routes. They register
|
|
92
92
|
# openai-official / anthropic-official so they do not collide with the
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
# http://127.0.0.1:4097/v1 to reach the Zen free tier.
|
|
105
105
|
# Remove this row to disable the listener.
|
|
106
106
|
- id: zen-proxy
|
|
107
|
-
name: "
|
|
107
|
+
name: "../dist/zen-proxy.js"
|
|
108
108
|
config:
|
|
109
109
|
host: 127.0.0.1
|
|
110
110
|
port: 4097
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
# Reads its task from the ordinary tuiStartup provider.
|
|
125
125
|
- id: tui-runtime
|
|
126
126
|
# pi-lens-ignore: YAML:0
|
|
127
|
-
name: "
|
|
127
|
+
name: "../dist/index.js"
|
|
128
128
|
inject: [tuiStartup]
|
|
129
129
|
# pi-lens-ignore: YAML:0
|
|
130
130
|
config:
|