@deepseek-harness-tui/dsh-tui 0.7.2 → 0.8.0

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.
Files changed (119) hide show
  1. package/README.md +3 -3
  2. package/bin/dsh-tui.js +24 -3
  3. package/cordis.patch.yml +24 -11
  4. package/cordis.yml +9 -1
  5. package/lib/types/commands.d.ts.map +1 -1
  6. package/lib/types/commands.js +2 -1
  7. package/lib/types/components/GoalTodoPanel.d.ts.map +1 -1
  8. package/lib/types/components/GoalTodoPanel.js +6 -1
  9. package/lib/types/components/HistorySearchDialog.d.ts.map +1 -1
  10. package/lib/types/components/HistorySearchDialog.js +5 -1
  11. package/lib/types/components/MessageList.d.ts +3 -1
  12. package/lib/types/components/MessageList.d.ts.map +1 -1
  13. package/lib/types/components/MessageList.js +9 -5
  14. package/lib/types/components/PluginSceneBoundary.d.ts +31 -0
  15. package/lib/types/components/PluginSceneBoundary.d.ts.map +1 -0
  16. package/lib/types/components/PluginSceneBoundary.js +29 -0
  17. package/lib/types/components/PromptInput.d.ts.map +1 -1
  18. package/lib/types/components/PromptInput.js +52 -74
  19. package/lib/types/components/SearchBox.d.ts +4 -0
  20. package/lib/types/components/SearchBox.d.ts.map +1 -1
  21. package/lib/types/components/SearchBox.js +101 -2
  22. package/lib/types/components/SkillsPicker.d.ts +18 -0
  23. package/lib/types/components/SkillsPicker.d.ts.map +1 -0
  24. package/lib/types/components/SkillsPicker.js +50 -0
  25. package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts +4 -1
  26. package/lib/types/components/Spinner/SpinnerAnimationRow.d.ts.map +1 -1
  27. package/lib/types/components/Spinner/SpinnerAnimationRow.js +10 -5
  28. package/lib/types/components/SplitDiffView.d.ts +28 -0
  29. package/lib/types/components/SplitDiffView.d.ts.map +1 -0
  30. package/lib/types/components/SplitDiffView.js +417 -0
  31. package/lib/types/components/WorkingSpinner.d.ts +3 -1
  32. package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
  33. package/lib/types/components/WorkingSpinner.js +2 -2
  34. package/lib/types/components/design-system/ThemedText.d.ts +7 -1
  35. package/lib/types/components/design-system/ThemedText.d.ts.map +1 -1
  36. package/lib/types/components/design-system/ThemedText.js +2 -2
  37. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +3 -1
  38. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  39. package/lib/types/components/messages/AssistantToolUseMessage.js +17 -7
  40. package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
  41. package/lib/types/components/questions/AskUserQuestionPanel.js +52 -8
  42. package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
  43. package/lib/types/components/questions/PlanReviewPanel.js +12 -3
  44. package/lib/types/dsh-adapter/channel.d.ts +78 -0
  45. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  46. package/lib/types/dsh-adapter/channel.js +165 -14
  47. package/lib/types/dsh-adapter/contract.d.ts +1 -1
  48. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  49. package/lib/types/dsh-adapter/contract.js +1 -0
  50. package/lib/types/dsh-adapter/index.d.ts +4 -0
  51. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  52. package/lib/types/dsh-adapter/index.js +1 -0
  53. package/lib/types/dsh-adapter/packaged-presets.d.ts.map +1 -1
  54. package/lib/types/dsh-adapter/packaged-presets.js +5 -2
  55. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  56. package/lib/types/dsh-adapter/plugin.js +66 -3
  57. package/lib/types/dsh-adapter/promptDebug.d.ts +10 -0
  58. package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -0
  59. package/lib/types/dsh-adapter/promptDebug.js +148 -0
  60. package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
  61. package/lib/types/dsh-adapter/providerWizard.js +3 -1
  62. package/lib/types/dsh-adapter/scenes.d.ts +75 -0
  63. package/lib/types/dsh-adapter/scenes.d.ts.map +1 -0
  64. package/lib/types/dsh-adapter/scenes.js +78 -0
  65. package/lib/types/dsh-adapter/settings-sections.d.ts +116 -0
  66. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -0
  67. package/lib/types/dsh-adapter/settings-sections.js +63 -0
  68. package/lib/types/dsh-adapter/settingsEditor.d.ts +128 -0
  69. package/lib/types/dsh-adapter/settingsEditor.d.ts.map +1 -0
  70. package/lib/types/dsh-adapter/settingsEditor.js +244 -0
  71. package/lib/types/i18n.d.ts +169 -18
  72. package/lib/types/i18n.d.ts.map +1 -1
  73. package/lib/types/i18n.js +45 -6
  74. package/lib/types/ink/components/Text.d.ts +9 -1
  75. package/lib/types/ink/components/Text.d.ts.map +1 -1
  76. package/lib/types/ink/components/Text.js +7 -6
  77. package/lib/types/ink/ink.d.ts.map +1 -1
  78. package/lib/types/ink/ink.js +4 -2
  79. package/lib/types/ink/log-update.d.ts.map +1 -1
  80. package/lib/types/ink/log-update.js +76 -9
  81. package/lib/types/ink/parse-keypress.d.ts.map +1 -1
  82. package/lib/types/ink/parse-keypress.js +4 -1
  83. package/lib/types/ink/terminal.d.ts +40 -4
  84. package/lib/types/ink/terminal.d.ts.map +1 -1
  85. package/lib/types/ink/terminal.js +57 -5
  86. package/lib/types/ink/termio/tokenize.d.ts +6 -0
  87. package/lib/types/ink/termio/tokenize.d.ts.map +1 -1
  88. package/lib/types/ink/termio/tokenize.js +18 -4
  89. package/lib/types/jsx-runtime.d.ts +2 -0
  90. package/lib/types/jsx-runtime.d.ts.map +1 -0
  91. package/lib/types/jsx-runtime.js +13 -0
  92. package/lib/types/modelRoute.d.ts +10 -2
  93. package/lib/types/modelRoute.d.ts.map +1 -1
  94. package/lib/types/modelRoute.js +33 -4
  95. package/lib/types/scenes.d.ts +3 -0
  96. package/lib/types/scenes.d.ts.map +1 -0
  97. package/lib/types/scenes.js +4 -0
  98. package/lib/types/screens/Chat.d.ts.map +1 -1
  99. package/lib/types/screens/Chat.js +182 -26
  100. package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
  101. package/lib/types/screens/SessionBrowser.js +30 -15
  102. package/lib/types/screens/Settings.d.ts +20 -0
  103. package/lib/types/screens/Settings.d.ts.map +1 -0
  104. package/lib/types/screens/Settings.js +333 -0
  105. package/lib/types/screens/StatusLine.js +1 -1
  106. package/lib/types/sessions/view.d.ts.map +1 -1
  107. package/lib/types/sessions/view.js +13 -1
  108. package/lib/types/settings-sections.d.ts +3 -0
  109. package/lib/types/settings-sections.d.ts.map +1 -0
  110. package/lib/types/settings-sections.js +4 -0
  111. package/lib/types/theme.d.ts +12 -0
  112. package/lib/types/theme.d.ts.map +1 -1
  113. package/lib/types/theme.js +36 -0
  114. package/lib/types/update.d.ts +21 -7
  115. package/lib/types/update.d.ts.map +1 -1
  116. package/lib/types/update.js +66 -16
  117. package/lib/types/utils/paths.d.ts.map +1 -1
  118. package/lib/types/utils/paths.js +4 -1
  119. package/package.json +49 -9
package/README.md CHANGED
@@ -138,7 +138,7 @@ macOS 自带 Terminal.app 会自行消费 `⌘` 快捷键,请继续使用 `Ctr
138
138
  | 会话 | `/new` 新会话 · `/resume` 会话浏览器(搜索、预览、跨项目、折叠子 agent 运行) · `/rename` 重命名会话 · `/workspace resume|rename|open` 管理工作区 · `/clear` 清屏 · `/compact` 压缩 · `/export` 导出 Markdown · `/trace` 轨迹场景(亦可 `Ctrl+T`) |
139
139
  | 状态 | `/status` 会话信息 · `/cost` token 用量 · `/doctor` 环境自检 · `/config` 配置来源 · `/init` 创建 AGENTS.md |
140
140
  | 模型 | `/model` 选择器 · `/thinking` 思考显示 · `/tokens` token 明细 · `/theme` 主题选择器 · `/lang` 中英界面切换 |
141
- | 账号/策略 | `/provider` 添加模型提供方 · `/login` 凭证状态 · `/logout` 登出说明 · `/permissions` 权限说明 · `/add-dir` 文件策略范围 · `/hooks` · `/mcp` · `/memory` |
141
+ | 账号/策略 | `/provider` 添加模型提供方 · `/login` 凭证状态 · `/logout` 登出说明 · `/permissions` 权限说明 · `/add-dir` 文件策略范围 · `/hooks` · `/mcp` |
142
142
  | 技能 | `/audit` 代码审计 · `/bug` bug 报告 · `/review` 代码评审 · `/practice` 编程练习 · `/pr_comments` PR 评论 · `/release-notes` 发布说明 · `/vuln-check` 漏洞检查 |
143
143
  | 其它 | `/agents` 子代理列表 · `/update` 自动更新并重启 · `/vim` · `/terminal-setup` · `/connect` · `/help` · `/exit` |
144
144
  | 注册表 | `/plan` `/goal`(DSH 命令注册表插件,随插件自动并入 `/` 菜单) |
@@ -207,7 +207,7 @@ compaction 和持久化继续由 DSH 服务拥有。更详细的模块边界与
207
207
  - **TPS 仪表**:参考 pi-tps-meter——流式 1/8 格 gauge、历史 min-max sparkline、
208
208
  速度语义色(≥50 绿 / ≥20 黄 / <20 红)。
209
209
  - **working-activity 生态**:工作状态行复用
210
- [dsh-working-activity](https://github.com/ccch1mneyyy/dsh-working-activity)
210
+ [dsh-working-activity](https://github.com/ccch1mneyyy/working-activity)
211
211
  的纯状态机,在进程内从基础会话事件派生,不向共享日志写入 UI 状态。
212
212
  - **终端粘贴**:raw 模式下 Ctrl+V 由应用接管,按平台读取系统剪贴板——Windows
213
213
  走 PowerShell `Get-Clipboard`,macOS 走 `osascript`/`pbpaste`,Linux 自动探测
@@ -231,7 +231,7 @@ compaction 和持久化继续由 DSH 服务拥有。更详细的模块边界与
231
231
  权限提升命令会弹出审批条。`/permission` 预设切换由 dsh-base 的
232
232
  `permission-presets` 插件提供,profile 组合默认可用;裸组合 `cordis.yml`
233
233
  未挂载该插件(无 `/permission` 命令)。
234
- - `/vim` `/connect` `/hooks` `/memory` 为 CC 同名占位:对应能力在 DSH 侧无等价
234
+ - `/vim` `/connect` `/hooks` 为 CC 同名占位:对应能力在 DSH 侧无等价
235
235
  机制,命令会给出明确说明而非静默。
236
236
 
237
237
  完整已知限制与安全边界见[架构与限制](docs/architecture.md)。
package/bin/dsh-tui.js CHANGED
@@ -55,9 +55,13 @@ const MSG = {
55
55
  en: `[dsh-tui] First run — initializing the ${PROFILE} profile (${PACKAGE}@${ownVersion})…`,
56
56
  zh: `[dsh-tui] 首次运行,正在初始化 ${PROFILE} profile(${PACKAGE}@${ownVersion})…`,
57
57
  },
58
+ bootstrapRetryW: {
59
+ en: '[dsh-tui] pnpm refused to add to the workspace root (ERR_PNPM_ADDING_TO_ROOT) — retrying with -w…',
60
+ zh: '[dsh-tui] pnpm 拒绝写入 workspace 根(ERR_PNPM_ADDING_TO_ROOT)——带 -w 重试…',
61
+ },
58
62
  installFailed: {
59
- en: `[dsh-tui] Plugin install failed. Retry manually later:\n dsh plugin --profile ${PROFILE} add ${PACKAGE}@${ownVersion}`,
60
- zh: `[dsh-tui] 插件安装失败。可稍后手工重试:\n dsh plugin --profile ${PROFILE} add ${PACKAGE}@${ownVersion}`,
63
+ en: `[dsh-tui] Plugin install failed. Retry manually later:\n dsh plugin --profile ${PROFILE} add -w ${PACKAGE}@${ownVersion}`,
64
+ zh: `[dsh-tui] 插件安装失败。可稍后手工重试:\n dsh plugin --profile ${PROFILE} add -w ${PACKAGE}@${ownVersion}`,
61
65
  },
62
66
  versionMismatch: {
63
67
  en: (installed, own) =>
@@ -96,6 +100,10 @@ const MSG = {
96
100
  en: err => `[dsh-tui] Failed to launch: ${err.message}`,
97
101
  zh: err => `[dsh-tui] 启动失败:${err.message}`,
98
102
  },
103
+ profileExited: {
104
+ en: code => `[dsh-tui] dsh profile exited with code ${code}. Run it directly for diagnostics:\n dsh --profile ${PROFILE}`,
105
+ zh: code => `[dsh-tui] dsh profile 已退出(退出码 ${code})。可直接运行以下命令查看诊断:\n dsh --profile ${PROFILE}`,
106
+ },
99
107
  legacyEnv: {
100
108
  en: (oldName, newName) => `[dsh-tui] note: env ${oldName} was renamed to ${newName}; the old name no longer takes effect.`,
101
109
  zh: (oldName, newName) => `[dsh-tui] 提示:环境变量 ${oldName} 已更名为 ${newName},旧名不再生效。`,
@@ -147,7 +155,19 @@ if (installedVersion === undefined) {
147
155
  process.exit(1)
148
156
  }
149
157
  console.log(msg('bootstrapStart'))
150
- const add = spawnSync(...cmd('dsh', ['plugin', '--profile', PROFILE, 'add', `${PACKAGE}@${ownVersion}`]), { stdio: 'inherit', ...shellOpt })
158
+ // pnpm ≥11 在带 pnpm-workspace.yaml 的 profile 目录里可能拒绝向
159
+ // workspace root 写依赖(ERR_PNPM_ADDING_TO_ROOT,issue #239):识别该
160
+ // 错误时带 -w 重试一次。stderr 走 pipe 捕获供识别,stdout 保持
161
+ // inherit 让用户实时看到安装进度;手工重试提示同步带 -w。
162
+ const runAdd = extraArgs => spawnSync(
163
+ ...cmd('dsh', ['plugin', '--profile', PROFILE, 'add', ...extraArgs, `${PACKAGE}@${ownVersion}`]),
164
+ { stdio: ['inherit', 'inherit', 'pipe'], ...shellOpt },
165
+ )
166
+ let add = runAdd([])
167
+ if (add.status !== 0 && String(add.stderr).includes('ERR_PNPM_ADDING_TO_ROOT')) {
168
+ console.log(msg('bootstrapRetryW'))
169
+ add = runAdd(['-w'])
170
+ }
151
171
  if (add.status !== 0) {
152
172
  console.error(msg('installFailed'))
153
173
  process.exit(add.status ?? 1)
@@ -233,6 +253,7 @@ child.on('exit', (code, signal) => {
233
253
  if (signal) {
234
254
  process.kill(process.pid, signal)
235
255
  } else {
256
+ if (code !== null && code !== 0) console.error(MSG.profileExited[lang](code))
236
257
  process.exit(code ?? 0)
237
258
  }
238
259
  })
package/cordis.patch.yml CHANGED
@@ -187,6 +187,16 @@
187
187
  # execution and durable command events remain owned by dsh-commands.
188
188
  - id: dsh-tui-command-trees
189
189
  name: '@deepseek-harness-tui/dsh-tui/command-trees'
190
+ # Optional plugins declare editable settings sections here (issue #165);
191
+ # storage, validation and writes remain owned by the dsh settings service.
192
+ - id: dsh-tui-settings-sections
193
+ name: '@deepseek-harness-tui/dsh-tui/settings-sections'
194
+
195
+ # Optional plugins register full-screen scenes (trajectory-style whole-
196
+ # terminal views) here and open them from their own command handlers;
197
+ # rendering and input ownership remain owned by the TUI's Chat screen.
198
+ - id: dsh-tui-scenes
199
+ name: '@deepseek-harness-tui/dsh-tui/scenes'
190
200
 
191
201
  # The agent-preset roster (issue #8): `ctx.agentPresets`, the service the
192
202
  # TUI composes every session's model-facing world from. No `roots` here —
@@ -217,17 +227,17 @@
217
227
  name: '@deepseek-harness-tui/dsh-tui'
218
228
  # The entry-level dependency augments the plugin's `agents` inject and
219
229
  # prevents startup Session creation from racing WorkspaceRegistry init.
220
- inject: [workspaceRegistry, agents, tuiWorkspaces]
221
- # `tuiWorkspaces` lives in the entry-level inject ONLY as an ordering
222
- # guarantee alongside the dsh-tui-workspaces row above — it is
223
- # deliberately absent from the plugin's code-level inject (issue
224
- # #183): the dsh CLI may read this patch from an older copy of the
225
- # package than the plugin module it loads, and a hard code-level
226
- # inject then deadlocks the tree at boot ("pending (waiting for
227
- # service: tuiWorkspaces)"). Without the row the TUI degrades to a
228
- # local-only workspace runtime instead. (The comment sits below the
229
- # inject line: verify-workspace-attachment.mjs asserts the
230
- # name→inject distance.)
230
+ inject: [workspaceRegistry, agents, tuiWorkspaces, tuiScenes]
231
+ # `tuiWorkspaces`/`tuiScenes` live in the entry-level inject ONLY as an
232
+ # ordering (and reload-rebind) guarantee alongside their service rows
233
+ # above — they are deliberately absent from the plugin's code-level
234
+ # inject (issue #183): the dsh CLI may read this patch from an older
235
+ # copy of the package than the plugin module it loads, and a hard
236
+ # code-level inject then deadlocks the tree at boot ("pending (waiting
237
+ # for service: tuiWorkspaces)"). Without the rows the TUI degrades:
238
+ # /workspace falls back to the local-only runtime, plugin scenes never
239
+ # open. (The comment sits below the inject line:
240
+ # verify-workspace-attachment.mjs asserts the name→inject distance.)
231
241
  config:
232
242
  provider: deepseek-official
233
243
  # Alt-screen fullscreen(CC 同款):应用内鼠标选区(选择即复制, OSC 52 +
@@ -235,6 +245,9 @@
235
245
  # inline 模式下由终端原生选择/复制/scrollback 接管;想用 fullscreen 在
236
246
  # profile 用户层 cordis.patch.yml 同 id 覆盖整行 config(fullscreen: true)。
237
247
  fullscreen: false
248
+ # Edit/Write diff 呈现:auto(≥110 列双栏对照,窄屏统一式)/
249
+ # split(强制双栏)/ unified(强制统一式)。/settings 屏可实时改。
250
+ # diffLayout: auto
238
251
  # 每个请求实际生效的推理强度,按当前路由的 adapter 档位校验
239
252
  # (deepseek: off/high/max)——不在档位表里的值被忽略,回落 adapter
240
253
  # 默认值。优先于持久化的 Shift+Tab 选择(~/.dsh-tui/effort.json);
package/cordis.yml CHANGED
@@ -29,9 +29,17 @@
29
29
  - id: dsh-tui-command-trees
30
30
  name: '@deepseek-harness-tui/dsh-tui/command-trees'
31
31
 
32
+ # Optional plugins declare editable settings sections here (issue #165);
33
+ # storage, validation and writes remain owned by the dsh settings service.
34
+ - id: dsh-tui-settings-sections
35
+ name: '@deepseek-harness-tui/dsh-tui/settings-sections'
36
+
37
+ - id: dsh-tui-scenes
38
+ name: '@deepseek-harness-tui/dsh-tui/scenes'
39
+
32
40
  - id: dsh-tui
33
41
  name: '@deepseek-harness-tui/dsh-tui'
34
- inject: [agents, tuiWorkspaces]
42
+ inject: [agents, tuiWorkspaces, tuiScenes]
35
43
  config:
36
44
  provider: deepseek-official
37
45
  # Alt-screen fullscreen (CC 同款): 应用内鼠标选区(选择即复制, OSC 52 +
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;AAElF,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,KAAK,SAAS,qBAAqB,EAAE,CAAA;AAEpG;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,YAAY,EAuDxC,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAIhG;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAIhD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,YAAY,EAAmB,GAC7C,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,YAAY,EAAmB,GAC7C,YAAY,EAAE,CAKhB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,SAAS,YAAY,EAAmB,EAC/C,QAAQ,GAAE,eAA0B,GACnC,iBAAiB,EAAE,CAoCrB"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;AAElF,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,+EAA+E;AAC/E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,2EAA2E;AAC3E,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,KAAK,SAAS,qBAAqB,EAAE,CAAA;AAEpG;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,YAAY,EAwDxC,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAIhG;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAIhD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,YAAY,EAAmB,GAC7C,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,YAAY,EAAmB,GAC7C,YAAY,EAAE,CAKhB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,SAAS,YAAY,EAAmB,EAC/C,QAAQ,GAAE,eAA0B,GACnC,iBAAiB,EAAE,CAoCrB"}
@@ -26,6 +26,7 @@ export const LOCAL_COMMANDS = [
26
26
  { name: 'status', description: 'Show session status' },
27
27
  { name: 'cost', description: 'Show session token usage' },
28
28
  { name: 'config', description: 'Show the dsh-tui configuration source' },
29
+ { name: 'settings', description: 'View and edit plugin settings' },
29
30
  { name: 'doctor', description: 'Run environment checks' },
30
31
  { name: 'init', description: 'Create AGENTS.md in the working directory' },
31
32
  { name: 'agents', description: 'Show subagents of this session' },
@@ -46,7 +47,7 @@ export const LOCAL_COMMANDS = [
46
47
  { name: 'add-dir', description: 'Show the filesystem policy scope' },
47
48
  { name: 'hooks', description: 'Show hooks status' },
48
49
  { name: 'mcp', description: 'Show MCP status' },
49
- { name: 'memory', description: 'Show memory status' },
50
+ { name: 'skills', description: 'List available skills' },
50
51
  { name: 'update', description: 'Update dsh-tui and restart' },
51
52
  // Built-in skills (CC's skill commands, driven through DSH skills)
52
53
  { name: 'audit', description: 'Run a comprehensive code audit on this project' },
@@ -1 +1 @@
1
- {"version":3,"file":"GoalTodoPanel.d.ts","sourceRoot":"","sources":["../../../src/components/GoalTodoPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,OAAO,EAA8B,MAAM,2BAA2B,CAAA;AAwDpF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CA2DhF"}
1
+ {"version":3,"file":"GoalTodoPanel.d.ts","sourceRoot":"","sources":["../../../src/components/GoalTodoPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,OAAO,EAA8B,MAAM,2BAA2B,CAAA;AAwDpF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,CAAC,SAAS,CAgEhF"}
@@ -45,7 +45,12 @@ function BranchPrefix({ last }) {
45
45
  */
46
46
  export function GoalTodoPanel({ channel }) {
47
47
  const goal = channel.goal;
48
- const todos = channel.todos ?? [];
48
+ const allTodos = channel.todos ?? [];
49
+ // Completed rows are useful progress while a turn is running, but become
50
+ // stale footer noise once the agent is idle. Keep unfinished work visible.
51
+ const todos = channel.working
52
+ ? allTodos
53
+ : allTodos.filter(todo => todo.status !== 'completed');
49
54
  if (goal === undefined && todos.length === 0)
50
55
  return null;
51
56
  const visible = todos.slice(0, MAX_TODOS);
@@ -1 +1 @@
1
- {"version":3,"file":"HistorySearchDialog.d.ts","sourceRoot":"","sources":["../../../src/components/HistorySearchDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IAChC,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CAmDlB"}
1
+ {"version":3,"file":"HistorySearchDialog.d.ts","sourceRoot":"","sources":["../../../src/components/HistorySearchDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IAChC,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,KAAK,CAAC,SAAS,CAuDlB"}
@@ -26,7 +26,11 @@ export function HistorySearchDialog({ query, cursorOffset, matches, focusIndex,
26
26
  const { start, end } = listWindow(matches.map(() => 2), focusIndex, Math.max(terminalRows - 18, 2), 1);
27
27
  return (_jsx(Pane, { color: "permission", children: _jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Text, { bold: true, color: "permission", children: t('history-search-title') }), _jsx(SearchBox, { query: query, cursorOffset: cursorOffset, isFocused: true, isTerminalFocused: isTerminalFocused, placeholder: t('history-search-placeholder') }), matches.length === 0 ? (_jsx(Text, { dimColor: true, children: t('history-search-empty') })) : (matches.slice(start, end).map((entry, index) => {
28
28
  const absoluteIndex = start + index;
29
- return (_jsx(ListItem, { isFocused: absoluteIndex === focusIndex, description: formatRelativeAge(entry.ts), showScrollUp: absoluteIndex === start && start > 0, showScrollDown: absoluteIndex === end - 1 && end < matches.length, children: entry.text }, historyEntryId(entry)));
29
+ return (_jsx(ListItem, { isFocused: absoluteIndex === focusIndex,
30
+ // The SearchBox owns the native-cursor declaration while this
31
+ // dialog is open — result rows must not park the cursor on
32
+ // themselves, or IME preedit lands on a list row.
33
+ declareCursor: false, description: formatRelativeAge(entry.ts), showScrollUp: absoluteIndex === start && start > 0, showScrollDown: absoluteIndex === end - 1 && end < matches.length, children: entry.text }, historyEntryId(entry)));
30
34
  })), _jsx(Text, { dimColor: true, italic: true, children: _jsx(HintLine, { text: t('hint-history-search') }) })] }) }));
31
35
  }
32
36
  /** Relative age like CC's formatRelativeTimeAgo ("now" / "5m ago" / …), localized. */
@@ -2,13 +2,15 @@ import React from 'react';
2
2
  import { type ScrollBoxHandle } from '../ui.js';
3
3
  import type { ChatRow } from '../dsh-adapter/channel.js';
4
4
  import type { DOMElement } from '../ink/dom.js';
5
- export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
5
+ export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
6
6
  rows: readonly ChatRow[];
7
7
  expanded: boolean;
8
8
  expandedRows: ReadonlySet<number>;
9
9
  selectedId: number | null;
10
10
  onToggleRow: (rowId: number) => void;
11
11
  model: string;
12
+ /** Edit/Write diff presentation preference (forwarded to tool cards). */
13
+ diffLayout?: 'auto' | 'split' | 'unified';
12
14
  showAll: boolean;
13
15
  onToggleAll: () => void;
14
16
  /** Restore folded-away older rows from the session log (CC-style "load
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAyC,MAAM,2BAA2B,CAAA;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAuC/C,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAsB,EACtB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB;2EACuE;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/D,oDAAoD;IACpD,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACrC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;8EAC0E;IAC1E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,qBAoPA;AAuQD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,MAAM,EACN,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,KAAK,CAAC,SAAS,CAMlB"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/MessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAyC,MAAM,2BAA2B,CAAA;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAuC/C,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,UAAmB,EACnB,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAsB,EACtB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,SAAS,OAAO,EAAE,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACzC,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB;2EACuE;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/D,oDAAoD;IACpD,YAAY,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IACrC,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B;8EAC0E;IAC1E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,qBAyPA;AA2QD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,MAAM,EACN,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,KAAK,CAAC,SAAS,CAMlB"}
@@ -37,7 +37,7 @@ const DEFAULT_ROW_HEIGHT = 2;
37
37
  /** Cold-start estimate of the header block above the rows; corrected by the
38
38
  * first layout measurement. */
39
39
  const DEFAULT_HEADER_LINES = 14;
40
- export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, showAll, onToggleAll, onLoadOlder, thinkingVisible = true, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }) {
40
+ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout = 'auto', showAll, onToggleAll, onLoadOlder, thinkingVisible = true, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }) {
41
41
  const hiddenCount = rows.length - MAX_RENDERED_ROWS;
42
42
  // The thinking filter runs BEFORE virtualization so window indices line up.
43
43
  const visibleRows = (showAll || hiddenCount <= 0
@@ -158,8 +158,12 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
158
158
  }
159
159
  }
160
160
  }
161
+ const lastUnseenReportRef = React.useRef(-1);
161
162
  React.useEffect(() => {
162
- onUnseenCount?.(unseenCount);
163
+ if (unseenCount !== lastUnseenReportRef.current) {
164
+ lastUnseenReportRef.current = unseenCount;
165
+ onUnseenCount?.(unseenCount);
166
+ }
163
167
  });
164
168
  // Post-commit: measure mounted rows, derive the content-space base from
165
169
  // the first mounted row's Yoga top, and clamp render-time scrollTop to the
@@ -228,10 +232,10 @@ export function MessageList({ rows, expanded, expandedRows, selectedId, onToggle
228
232
  // spacing; only the very first row of the whole list has none.
229
233
  const addMargin = margins.get(row.id) === true;
230
234
  const tool = row.tool;
231
- return (_jsx(MemoRow, { rowId: row.id, kind: row.kind, text: row.text, executionTarget: row.executionTarget, streaming: row.streaming === true, durationMs: row.durationMs, time: row.time, addMargin: addMargin, isSelected: selectedId === row.id, isExpanded: expandedRows.has(row.id), expanded: expanded, model: model, background: rowBackground(row.id), toolCallId: tool?.callId, toolName: tool?.name, toolArgsText: tool?.argsText, toolArgsFull: tool?.argsFull, toolStatus: tool?.status, toolResultText: tool?.resultText, toolResultFull: tool?.resultFull, toolErrorText: tool?.errorText, toolFootnote: failureHintRowId === row.id ? failureHint : undefined, toolCallView: tool?.callView, toolResultView: tool?.resultView, toolStartedAt: tool?.startedAt, toolDurationMs: tool?.durationMs, nowSec: tool?.status === 'running' ? nowSec : undefined, onToggleRow: onToggleRow, setRowRef: setRowRef }, row.id));
235
+ return (_jsx(MemoRow, { rowId: row.id, kind: row.kind, text: row.text, executionTarget: row.executionTarget, streaming: row.streaming === true, durationMs: row.durationMs, time: row.time, addMargin: addMargin, isSelected: selectedId === row.id, isExpanded: expandedRows.has(row.id), expanded: expanded, model: model, diffLayout: diffLayout, background: rowBackground(row.id), toolCallId: tool?.callId, toolName: tool?.name, toolArgsText: tool?.argsText, toolArgsFull: tool?.argsFull, toolStatus: tool?.status, toolResultText: tool?.resultText, toolResultFull: tool?.resultFull, toolErrorText: tool?.errorText, toolFootnote: failureHintRowId === row.id ? failureHint : undefined, toolCallView: tool?.callView, toolResultView: tool?.resultView, toolStartedAt: tool?.startedAt, toolDurationMs: tool?.durationMs, nowSec: tool?.status === 'running' ? nowSec : undefined, onToggleRow: onToggleRow, setRowRef: setRowRef }, row.id));
232
236
  }), bottomPad > 0 && _jsx(Box, { height: bottomPad, flexShrink: 0 })] }));
233
237
  }
234
- function TranscriptRow({ rowId, kind, text, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, onToggleRow, setRowRef, }) {
238
+ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, durationMs, time, addMargin, isSelected, isExpanded, expanded, model, diffLayout, background, toolCallId, toolName, toolArgsText, toolArgsFull, toolStatus, toolResultText, toolResultFull, toolErrorText, toolFootnote, toolCallView, toolResultView, toolStartedAt, toolDurationMs, onToggleRow, setRowRef, }) {
235
239
  const ref = React.useCallback((el) => {
236
240
  setRowRef(rowId, el);
237
241
  }, [setRowRef, rowId]);
@@ -273,7 +277,7 @@ function TranscriptRow({ rowId, kind, text, executionTarget, streaming, duration
273
277
  startedAt: toolStartedAt,
274
278
  durationMs: toolDurationMs,
275
279
  };
276
- return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote }) }));
280
+ return (_jsx(Box, { flexDirection: "column", ref: ref, children: _jsx(AssistantToolUseMessage, { tool: tool, addMargin: addMargin, verbose: isExpanded || expanded, isSelected: isSelected, isExpanded: isExpanded, footnote: toolFootnote, diffLayout: diffLayout }) }));
277
281
  }
278
282
  case 'notice':
279
283
  return (_jsx(Box, { marginTop: 1, ref: ref, children: _jsx(Divider, { title: ` ${text} ` }) }));
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Error boundary for plugin scenes (dsh-tui-scenes). A scene component is
3
+ * third-party code rendered inside Chat's tree: without a boundary a render
4
+ * error propagates to ink's app-level boundary (src/ink/components/App.tsx)
5
+ * and takes the whole TUI down with it. Catching here collapses the blast
6
+ * radius to the scene itself — the host reports the error to the transcript
7
+ * and closes the scene, landing the user back on the conversation.
8
+ *
9
+ * Boundaries catch render/lifecycle errors only; errors thrown from async
10
+ * handlers and effects remain the scene's own responsibility (see the
11
+ * 场景红线 section in docs/plugins.md).
12
+ */
13
+ import React from 'react';
14
+ type PluginSceneBoundaryProps = {
15
+ /** Scene id, echoed into the error report. */
16
+ readonly id: string;
17
+ /** Called once per caught error; the host reports it and closes the scene. */
18
+ readonly onError: (id: string, error: Error) => void;
19
+ readonly children: React.ReactNode;
20
+ };
21
+ type PluginSceneBoundaryState = {
22
+ readonly crashed: boolean;
23
+ };
24
+ export declare class PluginSceneBoundary extends React.Component<PluginSceneBoundaryProps, PluginSceneBoundaryState> {
25
+ state: PluginSceneBoundaryState;
26
+ static getDerivedStateFromError(): PluginSceneBoundaryState;
27
+ componentDidCatch(error: Error): void;
28
+ render(): React.ReactNode;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=PluginSceneBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginSceneBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/PluginSceneBoundary.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,KAAK,wBAAwB,GAAG;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IACpD,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CACnC,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK,CAAC,SAAS,CACtD,wBAAwB,EACxB,wBAAwB,CACzB;IACU,KAAK,EAAE,wBAAwB,CAAqB;IAE7D,MAAM,CAAC,wBAAwB,IAAI,wBAAwB;IAQlD,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIrC,MAAM,IAAI,KAAK,CAAC,SAAS;CAGnC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Error boundary for plugin scenes (dsh-tui-scenes). A scene component is
3
+ * third-party code rendered inside Chat's tree: without a boundary a render
4
+ * error propagates to ink's app-level boundary (src/ink/components/App.tsx)
5
+ * and takes the whole TUI down with it. Catching here collapses the blast
6
+ * radius to the scene itself — the host reports the error to the transcript
7
+ * and closes the scene, landing the user back on the conversation.
8
+ *
9
+ * Boundaries catch render/lifecycle errors only; errors thrown from async
10
+ * handlers and effects remain the scene's own responsibility (see the
11
+ * 场景红线 section in docs/plugins.md).
12
+ */
13
+ import React from 'react';
14
+ export class PluginSceneBoundary extends React.Component {
15
+ state = { crashed: false };
16
+ static getDerivedStateFromError() {
17
+ // Suppress the scene's next render. The host's onError closes the scene
18
+ // in the same commit turn, so this null fallback normally never paints;
19
+ // it exists only to keep a closed-nowhere crash from remounting the
20
+ // throwing component in a loop.
21
+ return { crashed: true };
22
+ }
23
+ componentDidCatch(error) {
24
+ this.props.onError(this.props.id, error);
25
+ }
26
+ render() {
27
+ return this.state.crashed ? null : this.props.children;
28
+ }
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAkDxD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,IAAI,OAAO,CAAA;IAClB,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,IAAI,IAAI,CAAA;IACpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACrD,6EAA6E;IAC7E,eAAe,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,IAAI,IAAI,CAAA;IACvB,8EAA8E;IAC9E,eAAe,CAAC,IAAI,IAAI,CAAA;IACxB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,cAAc,EACd,eAAe,EACf,aAAa,GACd,EAAE,gBAAgB,qBAq6BlB"}
1
+ {"version":3,"file":"PromptInput.d.ts","sourceRoot":"","sources":["../../../src/components/PromptInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAkDxD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,IAAI,OAAO,CAAA;IAClB,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB,0EAA0E;IAC1E,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,IAAI,IAAI,CAAA;IACpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACrD,6EAA6E;IAC7E,eAAe,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,IAAI,IAAI,CAAA;IACvB,8EAA8E;IAC9E,eAAe,CAAC,IAAI,IAAI,CAAA;IACxB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,cAAc,EACd,eAAe,EACf,aAAa,GACd,EAAE,gBAAgB,qBAg5BlB"}