@deepseek-harness-tui/dsh-tui 0.8.6 → 0.8.7

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 (105) hide show
  1. package/README.md +13 -3
  2. package/bin/dsh-tui.js +269 -218
  3. package/cordis.patch.yml +48 -22
  4. package/lib/types/cc/figures.d.ts.map +1 -1
  5. package/lib/types/cc/figures.js +14 -13
  6. package/lib/types/cc/syntaxRuns.d.ts +16 -0
  7. package/lib/types/cc/syntaxRuns.d.ts.map +1 -0
  8. package/lib/types/cc/syntaxRuns.js +79 -0
  9. package/lib/types/commands.d.ts +14 -0
  10. package/lib/types/commands.d.ts.map +1 -1
  11. package/lib/types/commands.js +20 -1
  12. package/lib/types/components/Chat/SubagentMessage.d.ts +19 -0
  13. package/lib/types/components/Chat/SubagentMessage.d.ts.map +1 -0
  14. package/lib/types/components/Chat/SubagentMessage.js +75 -0
  15. package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
  16. package/lib/types/components/EffortInputBorder.js +2 -2
  17. package/lib/types/components/EffortTierBadge.js +1 -1
  18. package/lib/types/components/HelpMenu.d.ts +8 -1
  19. package/lib/types/components/HelpMenu.d.ts.map +1 -1
  20. package/lib/types/components/HelpMenu.js +15 -4
  21. package/lib/types/components/LogoV2.d.ts +3 -1
  22. package/lib/types/components/LogoV2.d.ts.map +1 -1
  23. package/lib/types/components/LogoV2.js +2 -2
  24. package/lib/types/components/MessageList.d.ts +6 -2
  25. package/lib/types/components/MessageList.d.ts.map +1 -1
  26. package/lib/types/components/MessageList.js +17 -6
  27. package/lib/types/components/ModelPicker.js +2 -2
  28. package/lib/types/components/PromptInput.d.ts +1 -1
  29. package/lib/types/components/PromptInput.d.ts.map +1 -1
  30. package/lib/types/components/PromptInput.js +75 -15
  31. package/lib/types/components/SkillsPicker.js +2 -2
  32. package/lib/types/components/SplitDiffView.d.ts +1 -13
  33. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  34. package/lib/types/components/SplitDiffView.js +6 -105
  35. package/lib/types/components/SubagentCard.d.ts +9 -0
  36. package/lib/types/components/SubagentCard.d.ts.map +1 -0
  37. package/lib/types/components/SubagentCard.js +26 -0
  38. package/lib/types/components/SubagentDashboard.d.ts +13 -0
  39. package/lib/types/components/SubagentDashboard.d.ts.map +1 -0
  40. package/lib/types/components/SubagentDashboard.js +50 -0
  41. package/lib/types/components/SubagentDetailScene.d.ts +16 -0
  42. package/lib/types/components/SubagentDetailScene.d.ts.map +1 -0
  43. package/lib/types/components/SubagentDetailScene.js +141 -0
  44. package/lib/types/components/SyntaxText.d.ts +15 -0
  45. package/lib/types/components/SyntaxText.d.ts.map +1 -0
  46. package/lib/types/components/SyntaxText.js +34 -0
  47. package/lib/types/components/ThinkingToggle.d.ts +3 -10
  48. package/lib/types/components/ThinkingToggle.d.ts.map +1 -1
  49. package/lib/types/components/ThinkingToggle.js +4 -9
  50. package/lib/types/components/design-system/ListItem.d.ts.map +1 -1
  51. package/lib/types/components/design-system/ListItem.js +1 -1
  52. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  53. package/lib/types/components/messages/AssistantThinkingMessage.js +18 -7
  54. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -0
  55. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  56. package/lib/types/components/messages/AssistantToolUseMessage.js +42 -6
  57. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  58. package/lib/types/components/messages/UserPromptMessage.js +15 -2
  59. package/lib/types/dsh-adapter/channel.d.ts +53 -2
  60. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  61. package/lib/types/dsh-adapter/channel.js +294 -7
  62. package/lib/types/dsh-adapter/contract.d.ts +27 -4
  63. package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
  64. package/lib/types/dsh-adapter/contract.js +56 -10
  65. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  66. package/lib/types/dsh-adapter/index.js +9 -3
  67. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  68. package/lib/types/dsh-adapter/plugin.js +38 -0
  69. package/lib/types/dsh-adapter/shortcuts.js +3 -3
  70. package/lib/types/dsh-adapter/subagents.d.ts +87 -0
  71. package/lib/types/dsh-adapter/subagents.d.ts.map +1 -0
  72. package/lib/types/dsh-adapter/subagents.js +204 -0
  73. package/lib/types/herdr.d.ts +28 -0
  74. package/lib/types/herdr.d.ts.map +1 -0
  75. package/lib/types/herdr.js +133 -0
  76. package/lib/types/i18n.d.ts +215 -31
  77. package/lib/types/i18n.d.ts.map +1 -1
  78. package/lib/types/i18n.js +65 -14
  79. package/lib/types/ink/ink.d.ts +4 -0
  80. package/lib/types/ink/ink.d.ts.map +1 -1
  81. package/lib/types/ink/ink.js +46 -15
  82. package/lib/types/minimalMode.d.ts +13 -0
  83. package/lib/types/minimalMode.d.ts.map +1 -0
  84. package/lib/types/minimalMode.js +17 -0
  85. package/lib/types/screens/Chat.d.ts +1 -1
  86. package/lib/types/screens/Chat.d.ts.map +1 -1
  87. package/lib/types/screens/Chat.js +94 -43
  88. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  89. package/lib/types/screens/StatusLine.js +6 -2
  90. package/lib/types/screens/TrajectoryScene.d.ts.map +1 -1
  91. package/lib/types/screens/TrajectoryScene.js +4 -2
  92. package/lib/types/theme.d.ts +8 -0
  93. package/lib/types/theme.d.ts.map +1 -1
  94. package/lib/types/theme.js +38 -14
  95. package/lib/types/tips.js +3 -3
  96. package/lib/types/update.d.ts +18 -0
  97. package/lib/types/update.d.ts.map +1 -1
  98. package/lib/types/update.js +73 -2
  99. package/lib/types/utils/execFileNoThrow.d.ts +3 -20
  100. package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
  101. package/lib/types/utils/execFileNoThrow.js +53 -32
  102. package/lib/types/utils/externalEditor.d.ts +12 -11
  103. package/lib/types/utils/externalEditor.d.ts.map +1 -1
  104. package/lib/types/utils/externalEditor.js +11 -11
  105. package/package.json +64 -58
package/cordis.patch.yml CHANGED
@@ -41,14 +41,17 @@
41
41
  #
42
42
  # The model-facing plugin set moves INTO the agent-presets roster: every
43
43
  # session composes its tools/prompt sections from one preset directory
44
- # (standard/code/minimal/cordis) instead of the host rows below. The dsh CLI's
45
- # profile-boot sees this composition's `agent-presets` row and overlays the
46
- # shipped `config/agent-presets/` root onto it automatically, so the row here
47
- # carries no roots; `$DSH_HOME/.agent-presets` (user-authored presets) is
48
- # appended by the roster itself (`includeUserRoot` default). Mirroring the
49
- # official dsh-web-app patch: every dsh-base row a preset now owns is
50
- # disabled here, so a minimal agent does not leak host-layer tools (an agent's
51
- # registry view resolves agent → preset → global).
44
+ # (standard/code/minimal/cordis) instead of the host rows below. The TUI's
45
+ # roster row uses the scoped `dsh-tui-agent-presets` id and carries the
46
+ # shipped `config/agent-presets/` system root itself (derived from the dsh
47
+ # CLI installation through the launcher-maintained `profiles/node_modules`
48
+ # fallback link), because the official profile-boot root overlay only targets
49
+ # the unscoped `agent-presets` id that surface bundles own. The roster itself
50
+ # appends `$DSH_HOME/.agent-presets` (user-authored presets,
51
+ # `includeUserRoot` default). Mirroring the official dsh-web-app patch: every
52
+ # dsh-base row a preset now owns is disabled here, so a minimal agent does not
53
+ # leak host-layer tools (an agent's registry view resolves agent → preset →
54
+ # global).
52
55
 
53
56
  - id: agent-instructions
54
57
  disabled: true
@@ -162,21 +165,32 @@
162
165
  # Workspace grouping is a separate durable ledger, not a cwd-derived
163
166
  # projection. Mount the same domain stack and storage root as dsh-web-app
164
167
  # so TUI-created sessions can attach to the exact registry Web reads.
165
- - id: storage
168
+ #
169
+ # The six rows below own host-plane services that the official web-app
170
+ # bundle may already mount. Loader entry ids are process-global, so these
171
+ # rows use dsh-tui-* scoped ids and self-disable when an enabled row with
172
+ # the official id/name is already present in the tree. The disabled check
173
+ # is evaluated during the same include update that inserts every row, so
174
+ # it sees the web-app rows regardless of their activation state.
175
+ - id: dsh-tui-storage
166
176
  name: '@deepseek-ai/dsh-storage'
177
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage' && entry.options.name === '@deepseek-ai/dsh-storage' && !entry.disabled)"
167
178
 
168
- - id: storage-json
179
+ - id: dsh-tui-storage-json
169
180
  name: '@deepseek-ai/dsh-storage-json'
181
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage-json' && entry.options.name === '@deepseek-ai/dsh-storage-json' && !entry.disabled)"
170
182
  config:
171
183
  root: !!js dshHomePath('storages')
172
184
 
173
- - id: storage-domain
185
+ - id: dsh-tui-storage-domain
174
186
  name: '@deepseek-ai/dsh-storage-domain'
187
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'storage-domain' && entry.options.name === '@deepseek-ai/dsh-storage-domain' && !entry.disabled)"
175
188
  config:
176
189
  backend: json
177
190
 
178
- - id: workspace
191
+ - id: dsh-tui-workspace
179
192
  name: '@deepseek-ai/dsh-workspace'
193
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'workspace' && entry.options.name === '@deepseek-ai/dsh-workspace' && !entry.disabled)"
180
194
 
181
195
  # Generic terminal workspace registry. Optional plugins add providers;
182
196
  # the TUI itself always supplies LOCAL and has no provider-specific code.
@@ -217,23 +231,35 @@
217
231
  name: '@deepseek-harness-tui/dsh-tui/extensions'
218
232
 
219
233
  # The agent-preset roster (issue #8): `ctx.agentPresets`, the service the
220
- # TUI composes every session's model-facing world from. No `roots` here —
221
- # the dsh CLI's profile-boot overlays its shipped `config/agent-presets/`
222
- # directory (standard/code/minimal/cordis, system trust) onto this row
223
- # whenever a composition carries it, and the roster itself appends the
224
- # user-authored `$DSH_HOME/.agent-presets` root. A boot that never reached
225
- # profile-boot (bare `dsh --config cordis.yml`) leaves the roster empty;
226
- # the TUI then keeps its pre-presets behavior (see presets.ts).
227
- - id: agent-presets
234
+ # TUI composes every session's model-facing world from. The scoped row
235
+ # carries the official CLI's shipped `config/agent-presets/` directory
236
+ # (standard/code/minimal/cordis, system trust) through the
237
+ # launcher-maintained profiles/node_modules fallback link; the roster
238
+ # itself appends `$DSH_HOME/.agent-presets` (user-authored presets,
239
+ # `includeUserRoot` default). A boot that never reached profile-boot
240
+ # leaves the system root empty and the roster finds only user presets.
241
+ - id: dsh-tui-agent-presets
228
242
  name: '@deepseek-ai/dsh-agent-presets'
243
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'agent-presets' && entry.options.name === '@deepseek-ai/dsh-agent-presets' && !entry.disabled)"
229
244
  config:
230
245
  default: standard
246
+ roots: !!js >-
247
+ (() => {
248
+ const base = ctx.baseUrl
249
+ if (!base) return undefined
250
+ const root = new URL('../node_modules/@deepseek-ai/dsh/config/agent-presets/', base)
251
+ let path = decodeURIComponent(root.pathname)
252
+ if (/^\/[A-Za-z]:/.test(path)) path = path.slice(1)
253
+ return [{ path, trust: 'system' }]
254
+ })()
231
255
 
232
256
  # Host-plane services the `cordis` preset's plugin-experimentation tool
233
257
  # waits on (dynamicCordisRunner/cordisInspect); dsh-base carries no such
234
- # row — the official web app inserts it the same way.
235
- - id: cordis-host-runner
258
+ # row — the official web app inserts it the same way, so this copy yields
259
+ # to it when it is already present.
260
+ - id: dsh-tui-cordis-host-runner
236
261
  name: '@deepseek-ai/dsh-cordis-host-runner'
262
+ disabled: !!js "[...ctx.loader.entries()].some(entry => entry.options.id === 'cordis-host-runner' && entry.options.name === '@deepseek-ai/dsh-cordis-host-runner' && !entry.disabled)"
237
263
 
238
264
  # The interactive front door. The plugin creates/resumes its agent at
239
265
  # runtime, seeds the startup status line, and disposes the whole app tree
@@ -1 +1 @@
1
- {"version":3,"file":"figures.d.ts","sourceRoot":"","sources":["../../../src/cc/figures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,eAAO,MAAM,YAAY,QAA4C,CAAA;AAGrE,kDAAkD;AAClD,eAAO,MAAM,OAAO,WAAW,CAAA;AAC/B,+BAA+B;AAC/B,eAAO,MAAM,IAAI,WAAW,CAAA;AAC5B,gDAAgD;AAChD,eAAO,MAAM,eAAe,WAAW,CAAA;AACvC,qEAAqE;AACrE,eAAO,MAAM,MAAM,WAAW,CAAA;AAC9B,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,WAAW,CAAA;AACxC,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,WAAW,CAAA;AACzC,iDAAiD;AACjD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,sBAAsB;AACtB,eAAO,MAAM,QAAQ,WAAW,CAAA;AAChC,wBAAwB;AACxB,eAAO,MAAM,UAAU,WAAW,CAAA;AAClC,2CAA2C;AAC3C,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,qCAAqC;AACrC,eAAO,MAAM,UAAU,WAAW,CAAA;AAClC,+CAA+C;AAC/C,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,wCAAwC;AACxC,eAAO,MAAM,WAAW,WAAW,CAAA;AACnC,sCAAsC;AACtC,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,0BAA0B;AAC1B,eAAO,MAAM,SAAS,WAAW,CAAA;AACjC,2BAA2B;AAC3B,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,uDAAuD;AACvD,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,wCAAwC;AACxC,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,mDAAmD;AACnD,eAAO,MAAM,YAAY,WAAW,CAAA;AACpC,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAA;AACtC,iDAAiD;AACjD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,wCAAwC;AACxC,eAAO,MAAM,SAAS,WAAW,CAAA;AACjC,oDAAoD;AACpD,eAAO,MAAM,cAAc,WAAW,CAAA;AACtC,mCAAmC;AACnC,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAGxC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,UAKjC,CAAA;AACD,uCAAuC;AACvC,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAChE,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,WAAW,CAAA;AAO/C,eAAO,MAAM,uBAAuB,UAWnC,CAAA;AACD,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAC9C;;;uEAGuE;AACvE,eAAO,MAAM,uBAAuB,WAAW,CAAA"}
1
+ {"version":3,"file":"figures.d.ts","sourceRoot":"","sources":["../../../src/cc/figures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uEAAuE;AACvE,eAAO,MAAM,YAAY,QAA4C,CAAA;AAGrE,kDAAkD;AAClD,eAAO,MAAM,OAAO,WAAW,CAAA;AAC/B,+BAA+B;AAC/B,eAAO,MAAM,IAAI,WAAW,CAAA;AAC5B,gDAAgD;AAChD,eAAO,MAAM,eAAe,WAAW,CAAA;AACvC,qEAAqE;AACrE,eAAO,MAAM,MAAM,WAAW,CAAA;AAC9B,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,WAAW,CAAA;AACxC,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,WAAW,CAAA;AACzC,iDAAiD;AACjD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,sBAAsB;AACtB,eAAO,MAAM,QAAQ,WAAW,CAAA;AAChC,wBAAwB;AACxB,eAAO,MAAM,UAAU,WAAW,CAAA;AAClC,2CAA2C;AAC3C,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,qCAAqC;AACrC,eAAO,MAAM,UAAU,WAAW,CAAA;AAClC,+CAA+C;AAC/C,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,wCAAwC;AACxC,eAAO,MAAM,WAAW,WAAW,CAAA;AACnC,sCAAsC;AACtC,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,0BAA0B;AAC1B,eAAO,MAAM,SAAS,WAAW,CAAA;AACjC,2BAA2B;AAC3B,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,uDAAuD;AACvD,eAAO,MAAM,aAAa,WAAW,CAAA;AACrC,wCAAwC;AACxC,eAAO,MAAM,UAAU,WAAW,CAAA;AAGlC,mDAAmD;AACnD,eAAO,MAAM,YAAY,WAAW,CAAA;AACpC,qDAAqD;AACrD,eAAO,MAAM,cAAc,WAAW,CAAA;AACtC,iDAAiD;AACjD,eAAO,MAAM,cAAc,WAAW,CAAA;AAGtC,wCAAwC;AACxC,eAAO,MAAM,SAAS,WAAW,CAAA;AACjC,oDAAoD;AACpD,eAAO,MAAM,cAAc,WAAW,CAAA;AACtC,mCAAmC;AACnC,eAAO,MAAM,gBAAgB,WAAW,CAAA;AAGxC,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,UAKjC,CAAA;AACD,uCAAuC;AACvC,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAChE,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,WAAW,CAAA;AAQ/C,eAAO,MAAM,uBAAuB,UAWnC,CAAA;AACD,eAAO,MAAM,4BAA4B,KAAK,CAAA;AAC9C;;;uEAGuE;AACvE,eAAO,MAAM,uBAAuB,WAAW,CAAA"}
@@ -82,20 +82,21 @@ export const BRIDGE_READY_INDICATOR = '\u00b7\u2714\ufe0e\u00b7';
82
82
  export const BRIDGE_FAILED_INDICATOR = '\u00d7';
83
83
  // Thinking spinner (Kimi Code style braille cycle, shown while reasoning
84
84
  // streams; the static anchor takes over once the step settles). Each frame
85
- // is padded to 2 columns so it matches the settled ⚓ anchor exactly — a
86
- // 1-col frame would shift the whole label right by one column the moment
87
- // the step settles.
85
+ // is padded to 2 columns (space BEFORE the braille glyph) so it matches the
86
+ // settled ⚓ anchor exactly — the spinner sits one column right, hugging the
87
+ // label like the anchor does, and a 1-col frame would shift the whole label
88
+ // right by one column the moment the step settles.
88
89
  export const THINKING_SPINNER_FRAMES = [
89
- '\u280b ', // ⠋
90
- '\u2819 ', // ⠙
91
- '\u2839 ', // ⠹
92
- '\u2838 ', // ⠸
93
- '\u283c ', // ⠼
94
- '\u2834 ', // ⠴
95
- '\u2826 ', // ⠦
96
- '\u2827 ', // ⠧
97
- '\u2807 ', // ⠇
98
- '\u280f ', // ⠏
90
+ ' \u280b', // ⠋
91
+ ' \u2819', // ⠙
92
+ ' \u2839', // ⠹
93
+ ' \u2838', // ⠸
94
+ ' \u283c', // ⠼
95
+ ' \u2834', // ⠴
96
+ ' \u2826', // ⠦
97
+ ' \u2827', // ⠧
98
+ ' \u2807', // ⠇
99
+ ' \u280f', // ⠏
99
100
  ];
100
101
  export const THINKING_SPINNER_INTERVAL_MS = 80;
101
102
  /** Thinking settled marker: anchor (`⚓`) — the static end-state glyph after
@@ -0,0 +1,16 @@
1
+ import type { CliHighlight } from './cliHighlight.js';
2
+ import type { Theme } from '../theme.js';
3
+ export type SyntaxRun = {
4
+ readonly text: string;
5
+ readonly color?: string;
6
+ };
7
+ export type SyntaxLines = readonly (readonly SyntaxRun[])[];
8
+ type SyntaxTheme = Theme | Record<string, (text: string) => string>;
9
+ /** Parse ANSI once, preserving active syntax colors over embedded newlines. */
10
+ export declare function parseAnsiRuns(text: string): SyntaxRun[];
11
+ export declare function splitRunsToLines(runs: readonly SyntaxRun[]): SyntaxLines;
12
+ /** Highlight complete text, then split it; unsupported or failed languages are plain. */
13
+ export declare function highlightLines(text: string, language: string | undefined, highlighter: CliHighlight | null, theme: SyntaxTheme | undefined, themeSig: string): SyntaxLines | undefined;
14
+ export declare function syntaxThemeSignature(theme: Theme): string;
15
+ export {};
16
+ //# sourceMappingURL=syntaxRuns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntaxRuns.d.ts","sourceRoot":"","sources":["../../../src/cc/syntaxRuns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC1E,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,CAAA;AAC3D,KAAK,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;AASnE,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAmBvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,WAAW,CAUxE;AAKD,yFAAyF;AACzF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,WAAW,EAAE,YAAY,GAAG,IAAI,EAChC,KAAK,EAAE,WAAW,GAAG,SAAS,EAC9B,QAAQ,EAAE,MAAM,GACf,WAAW,GAAG,SAAS,CAoBzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAGzD"}
@@ -0,0 +1,79 @@
1
+ import { SYNTAX_CLASS_TO_TOKEN, buildSyntaxTheme } from './syntaxTheme.js';
2
+ const ANSI16 = {
3
+ 30: 'rgb(0,0,0)', 31: 'rgb(128,0,0)', 32: 'rgb(0,128,0)', 33: 'rgb(128,128,0)',
4
+ 34: 'rgb(0,0,128)', 35: 'rgb(128,0,128)', 36: 'rgb(0,128,128)', 37: 'rgb(192,192,192)',
5
+ 90: 'rgb(128,128,128)', 91: 'rgb(255,0,0)', 92: 'rgb(0,255,0)', 93: 'rgb(255,255,0)',
6
+ 94: 'rgb(0,0,255)', 95: 'rgb(255,0,255)', 96: 'rgb(0,255,255)', 97: 'rgb(255,255,255)',
7
+ };
8
+ /** Parse ANSI once, preserving active syntax colors over embedded newlines. */
9
+ export function parseAnsiRuns(text) {
10
+ const runs = [];
11
+ let color;
12
+ let rest = text;
13
+ // eslint-disable-next-line no-control-regex -- parsing SGR is intentional
14
+ const sgr = /\x1b\[([0-9;]+)m/;
15
+ while (rest.length > 0) {
16
+ const match = sgr.exec(rest);
17
+ const chunk = match === null ? rest : rest.slice(0, match.index);
18
+ if (chunk !== '')
19
+ runs.push(color === undefined ? { text: chunk } : { text: chunk, color });
20
+ if (match === null)
21
+ break;
22
+ const codes = match[1].split(';').map(Number);
23
+ if (codes.includes(0) || codes.includes(39))
24
+ color = undefined;
25
+ else if (codes[0] === 38 && codes[1] === 2 && codes.length >= 5)
26
+ color = `rgb(${codes[2]},${codes[3]},${codes[4]})`;
27
+ else if (codes[0] === 38 && codes[1] === 5 && codes.length >= 3)
28
+ color = `ansi256(${codes[2]})`;
29
+ else if (codes.length === 1 && ANSI16[codes[0]] !== undefined)
30
+ color = ANSI16[codes[0]];
31
+ rest = rest.slice(match.index + match[0].length);
32
+ }
33
+ return runs;
34
+ }
35
+ export function splitRunsToLines(runs) {
36
+ const lines = [[]];
37
+ for (const run of runs) {
38
+ const parts = run.text.split('\n');
39
+ for (let i = 0; i < parts.length; i++) {
40
+ if (i > 0)
41
+ lines.push([]);
42
+ if (parts[i] !== '')
43
+ lines[lines.length - 1].push(run.color === undefined ? { text: parts[i] } : { text: parts[i], color: run.color });
44
+ }
45
+ }
46
+ return lines;
47
+ }
48
+ const syntaxCache = new Map();
49
+ const SYNTAX_CACHE_MAX = 64;
50
+ /** Highlight complete text, then split it; unsupported or failed languages are plain. */
51
+ export function highlightLines(text, language, highlighter, theme, themeSig) {
52
+ if (highlighter === null || theme === undefined || language === undefined || text === '' || !highlighter.supportsLanguage(language))
53
+ return undefined;
54
+ const key = `${themeSig}\u0000${language}\u0000${text}`;
55
+ const cached = syntaxCache.get(key);
56
+ if (cached !== undefined)
57
+ return cached;
58
+ try {
59
+ const themeOption = 'syntaxKeyword' in theme
60
+ ? buildSyntaxTheme(theme)
61
+ : theme;
62
+ const highlighted = highlighter.highlight(text, { language, theme: themeOption });
63
+ const lines = splitRunsToLines(parseAnsiRuns(highlighted));
64
+ if (syntaxCache.size >= SYNTAX_CACHE_MAX) {
65
+ const first = syntaxCache.keys().next().value;
66
+ if (first !== undefined)
67
+ syntaxCache.delete(first);
68
+ }
69
+ syntaxCache.set(key, lines);
70
+ return lines;
71
+ }
72
+ catch {
73
+ return undefined;
74
+ }
75
+ }
76
+ export function syntaxThemeSignature(theme) {
77
+ const palette = theme;
78
+ return Object.values(SYNTAX_CLASS_TO_TOKEN).map(key => palette[key] ?? '').join('|');
79
+ }
@@ -53,6 +53,20 @@ export type CommandChildren = (canonicalPath: readonly string[]) => readonly Com
53
53
  * commands merge in at runtime; locals win on name collisions.
54
54
  */
55
55
  export declare const LOCAL_COMMANDS: LocalCommand[];
56
+ /**
57
+ * Hidden slash commands: intentionally not exposed in the `/` suggestion
58
+ * menu or Help, but still recognized as local commands when typed. They are
59
+ * kept out of `LOCAL_COMMANDS` so `filterCommands`/`completeCommands` never
60
+ * surface them; dispatch recognizes them via {@link HIDDEN_COMMAND_NAMES}.
61
+ */
62
+ export declare const HIDDEN_COMMANDS: readonly LocalCommand[];
63
+ /** Names of hidden commands, for fast dispatch/lookup. */
64
+ export declare const HIDDEN_COMMAND_NAMES: ReadonlySet<string>;
65
+ /**
66
+ * Whether the input names a hidden command (same slash-optional trimming
67
+ * rules as {@link isLocalCommandName}).
68
+ */
69
+ export declare function isHiddenCommandName(input: string): boolean;
56
70
  /**
57
71
  * Resolve a command's description in the active UI language. The en text in
58
72
  * `LOCAL_COMMANDS` (and the registry's own text for external commands) is
@@ -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,EA2DxC,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,EA2DxC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAElD,CAAA;AAED,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAEpD,CAAA;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG1D;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"}
@@ -71,6 +71,25 @@ export const LOCAL_COMMANDS = [
71
71
  { name: 'quit', description: 'Exit dsh-tui', tag: 'alias of /exit' },
72
72
  { name: 'q', description: 'Exit dsh-tui', tag: 'alias of /exit' },
73
73
  ];
74
+ /**
75
+ * Hidden slash commands: intentionally not exposed in the `/` suggestion
76
+ * menu or Help, but still recognized as local commands when typed. They are
77
+ * kept out of `LOCAL_COMMANDS` so `filterCommands`/`completeCommands` never
78
+ * surface them; dispatch recognizes them via {@link HIDDEN_COMMAND_NAMES}.
79
+ */
80
+ export const HIDDEN_COMMANDS = [
81
+ { name: 'deepseek', description: 'Hidden DeepSeek easter egg' },
82
+ ];
83
+ /** Names of hidden commands, for fast dispatch/lookup. */
84
+ export const HIDDEN_COMMAND_NAMES = new Set(HIDDEN_COMMANDS.map(command => command.name));
85
+ /**
86
+ * Whether the input names a hidden command (same slash-optional trimming
87
+ * rules as {@link isLocalCommandName}).
88
+ */
89
+ export function isHiddenCommandName(input) {
90
+ const name = input.replace(/^\//, '').trim();
91
+ return HIDDEN_COMMAND_NAMES.has(name);
92
+ }
74
93
  /**
75
94
  * Resolve a command's description in the active UI language. The en text in
76
95
  * `LOCAL_COMMANDS` (and the registry's own text for external commands) is
@@ -111,7 +130,7 @@ export function isLocalCommandName(input, list = LOCAL_COMMANDS) {
111
130
  // Trailing whitespace is legal (Tab completion leaves a space after the
112
131
  // name so the user can type arguments).
113
132
  const name = input.replace(/^\//, '').trim();
114
- return list.some(command => command.name === name);
133
+ return HIDDEN_COMMAND_NAMES.has(name) || list.some(command => command.name === name);
115
134
  }
116
135
  /**
117
136
  * Filter commands by a `/…` input prefix (matches the CC overlay behavior).
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { SubagentRow } from '../../dsh-adapter/channel.js';
3
+ /**
4
+ * Borderless, fixed-height activity card embedded directly in the transcript
5
+ * (Kimi Code visual language). Running: header + one-line current tool + a
6
+ * constant 3-row waterfall (each row hard-clipped to one terminal line so
7
+ * the card height never changes). Settled: folds to the header line alone
8
+ * (failure keeps one error line). The running glyph reuses the user's
9
+ * working-activity preset (`/activity`), so the indicator follows the same
10
+ * setting as the main spinner.
11
+ */
12
+ export declare function SubagentMessage({ subagent, addMargin, activityFrames, onClick }: {
13
+ subagent: SubagentRow;
14
+ addMargin: boolean;
15
+ activityFrames?: string;
16
+ isExpanded: boolean;
17
+ onClick: () => void;
18
+ }): React.ReactNode;
19
+ //# sourceMappingURL=SubagentMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubagentMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/Chat/SubagentMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AA+C/D;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;IAChF,QAAQ,EAAE,WAAW,CAAA;IACrB,SAAS,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CAqElB"}
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { Box, Text, useAnimationFrame, useTerminalSize } from '../../ui.js';
4
+ import { t } from '../../i18n.js';
5
+ import { resolvePreset } from '../activityFrames.js';
6
+ import { toolNameColor } from '../messages/AssistantToolUseMessage.js';
7
+ import { stringWidth } from '../../ink/stringWidth.js';
8
+ import { isMinimalMode } from '../../minimalMode.js';
9
+ /** The waterfall window is a Kimi Code style constant-height region. */
10
+ const WATERFALL_ROWS = 3;
11
+ /** Card left padding + the `│ ` gutter prefix. */
12
+ const WATERFALL_GUTTER = 4;
13
+ function duration(ms = 0) {
14
+ const seconds = Math.floor(ms / 1000);
15
+ return seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m${seconds % 60}s`;
16
+ }
17
+ function tokens(row) {
18
+ const total = row.tokens?.total ?? ((row.tokens?.input ?? 0) + (row.tokens?.output ?? 0) || 0);
19
+ return total > 0 ? `${total} tok` : '- tok';
20
+ }
21
+ function status(row) {
22
+ const minimal = isMinimalMode();
23
+ if (row.status === 'completed')
24
+ return { glyph: minimal ? '✓' : '🟢', label: t('subagent-status-completed'), color: minimal ? undefined : 'success' };
25
+ if (row.status === 'failed')
26
+ return { glyph: minimal ? '×' : '🔴', label: t('subagent-status-failed'), color: minimal ? undefined : 'error' };
27
+ if (row.status === 'cancelled')
28
+ return { glyph: minimal ? '×' : '🔴', label: t('subagent-status-cancelled'), color: minimal ? undefined : 'error' };
29
+ return { glyph: minimal ? '·' : '🟡', label: t('subagent-status-running'), color: minimal ? undefined : 'warning' };
30
+ }
31
+ /** Hard single-line clip by display width — a wrapped waterfall row would
32
+ * break the constant-height window. */
33
+ function clipLine(text, maxWidth) {
34
+ if (maxWidth <= 1)
35
+ return '';
36
+ let width = 0;
37
+ let index = 0;
38
+ while (index < text.length) {
39
+ // Advance by the next full code point so wide glyphs (CJK, emoji) are
40
+ // never split in half.
41
+ const next = text.codePointAt(index);
42
+ const char = String.fromCodePoint(next);
43
+ const charWidth = stringWidth(char);
44
+ if (width + charWidth > maxWidth - 1)
45
+ break;
46
+ width += charWidth;
47
+ index += char.length;
48
+ }
49
+ return index < text.length ? `${text.slice(0, index)}…` : text;
50
+ }
51
+ /**
52
+ * Borderless, fixed-height activity card embedded directly in the transcript
53
+ * (Kimi Code visual language). Running: header + one-line current tool + a
54
+ * constant 3-row waterfall (each row hard-clipped to one terminal line so
55
+ * the card height never changes). Settled: folds to the header line alone
56
+ * (failure keeps one error line). The running glyph reuses the user's
57
+ * working-activity preset (`/activity`), so the indicator follows the same
58
+ * setting as the main spinner.
59
+ */
60
+ export function SubagentMessage({ subagent, addMargin, activityFrames, onClick }) {
61
+ const [, time] = useAnimationFrame(120);
62
+ const { columns } = useTerminalSize();
63
+ const info = status(subagent);
64
+ const settled = subagent.status === 'completed' || subagent.status === 'failed' || subagent.status === 'cancelled';
65
+ const elapsed = subagent.completedAt ? subagent.durationMs : Date.now() - subagent.startedAt;
66
+ const lastRunning = [...subagent.toolCalls].reverse().find(tool => tool.status === 'running');
67
+ const previousDone = lastRunning
68
+ ? subagent.toolCalls[subagent.toolCalls.indexOf(lastRunning) - 1]
69
+ : subagent.toolCalls[subagent.toolCalls.length - 1];
70
+ const preset = React.useMemo(() => resolvePreset(activityFrames), [activityFrames]);
71
+ const activity = settled ? [] : subagent.outputLines.slice(-WATERFALL_ROWS);
72
+ const runningGlyph = preset.frames[Math.floor(time / preset.intervalMs) % preset.frames.length] ?? '·';
73
+ const rowWidth = Math.max(20, (columns ?? 80) - WATERFALL_GUTTER);
74
+ return _jsxs(Box, { flexDirection: "column", marginTop: addMargin ? 1 : 0, paddingLeft: 2, onClick: onClick, children: [_jsxs(Box, { flexDirection: "row", gap: 1, children: [_jsx(Text, { color: info.color, children: settled ? info.glyph : ` ${runningGlyph}` }), _jsx(Text, { bold: true, children: `${t('subagent-card-prefix')}${subagent.description}` }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { children: subagent.model ?? subagent.provider ?? 'default' }), subagent.effort && _jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { dimColor: true, children: subagent.effort })] }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { dimColor: true, children: duration(elapsed) }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { dimColor: true, children: tokens(subagent) }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsxs(Text, { dimColor: true, children: [subagent.toolCalls.length, " tools"] }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { color: info.color, children: info.label })] }), !settled && (lastRunning ?? previousDone) !== undefined && (_jsx(Text, { wrap: "truncate", children: lastRunning !== undefined ? (_jsxs(_Fragment, { children: [previousDone !== undefined && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { color: "success", children: "\u2713" }), _jsx(Text, { color: toolNameColor(previousDone.name), children: previousDone.name }), _jsx(Text, { dimColor: true, children: ' · ' })] })), lastRunning.argsPreview === undefined && (_jsx(Text, { color: toolNameColor(lastRunning.name), children: lastRunning.name })), lastRunning.argsPreview !== undefined && (_jsxs(_Fragment, { children: [_jsx(Text, { color: toolNameColor(lastRunning.name), children: lastRunning.name }), _jsx(Text, { dimColor: true, children: ` (${clipLine(lastRunning.argsPreview.replace(/\s+/g, ' ').trim(), Math.max(10, rowWidth - lastRunning.name.length - 6))})` })] }))] })) : (previousDone !== undefined && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: ' · ' }), _jsx(Text, { color: "success", children: "\u2713" }), _jsx(Text, { color: toolNameColor(previousDone.name), children: previousDone.name }), previousDone.argsPreview !== undefined && (_jsx(Text, { dimColor: true, children: ` (${clipLine(previousDone.argsPreview.replace(/\s+/g, ' ').trim(), Math.max(10, rowWidth - previousDone.name.length - 6))})` }))] }))) })), !settled && Array.from({ length: WATERFALL_ROWS }, (_, index) => (_jsx(Text, { dimColor: true, wrap: "truncate", children: ` │ ${clipLine(activity[index] ?? '', rowWidth)}` }, `${subagent.agentId}-wf-${index}-${time}`))), settled && subagent.status === 'failed' && subagent.error && (_jsx(Text, { color: "error", wrap: "truncate", children: ` └ ${clipLine(subagent.error, rowWidth)}` }))] });
75
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"EffortInputBorder.d.ts","sourceRoot":"","sources":["../../../src/components/EffortInputBorder.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAA8D,MAAM,OAAO,CAAA;AAGlF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AA8BxC,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,GACT,EAAE;IACD,sCAAsC;IACtC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,6CAA6C;IAC7C,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,SAAS,EAAE,MAAM,KAAK,GAAG,KAAK,CAAA;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,GAAG,KAAK,CAAC,SAAS,CA0DlB"}
1
+ {"version":3,"file":"EffortInputBorder.d.ts","sourceRoot":"","sources":["../../../src/components/EffortInputBorder.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAA8D,MAAM,OAAO,CAAA;AAGlF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAgCxC,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,GACT,EAAE;IACD,sCAAsC;IACtC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,6CAA6C;IAC7C,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,SAAS,EAAE,MAAM,KAAK,GAAG,KAAK,CAAA;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,GAAG,KAAK,CAAC,SAAS,CA0DlB"}
@@ -26,7 +26,7 @@ import { ClockContext } from '../ink/components/ClockContext.js';
26
26
  import { IGNITION_TIMELINE, ignitionLineColors } from '../trajectory/effortIgnition.js';
27
27
  /** 边框行(顶/底共用同一色段序列——同步变色)。 */
28
28
  function BorderRow({ left, right, runs, idleColor, }) {
29
- return (_jsxs(Text, { children: [_jsx(Text, { color: idleColor, children: left }), runs.map((run, i) => (_jsx(Text, { color: run.color, children: run.glyph }, i))), _jsx(Text, { color: idleColor, children: right })] }));
29
+ return (_jsx(Box, { width: "100%", height: 1, flexShrink: 0, overflow: "hidden", children: _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { color: idleColor, children: left }), runs.map((run, i) => (_jsx(Text, { color: run.color, children: run.glyph }, i))), _jsx(Text, { color: idleColor, children: right })] }) }));
30
30
  }
31
31
  export function EffortInputBorder({ effort, levels, columns, onLight, idleColor, children, }) {
32
32
  const clock = useContext(ClockContext);
@@ -69,5 +69,5 @@ export function EffortInputBorder({ effort, levels, columns, onLight, idleColor,
69
69
  else
70
70
  runs.push({ glyph: '─', color });
71
71
  }
72
- return (_jsxs(Box, { flexDirection: "column", alignItems: "flex-start", justifyContent: "flex-start", width: "100%", flexShrink: 0, children: [_jsx(BorderRow, { left: "\u256D", right: "\u256E", runs: runs, idleColor: idleColor }), children, _jsx(BorderRow, { left: "\u2570", right: "\u256F", runs: runs, idleColor: idleColor })] }));
72
+ return (_jsxs(Box, { flexDirection: "column", alignItems: "flex-start", justifyContent: "flex-start", width: "100%", flexShrink: 0, children: [_jsx(BorderRow, { left: "\u256D", right: "\u256E", runs: runs, idleColor: idleColor }), _jsx(Box, { flexShrink: 0, children: children }), _jsx(BorderRow, { left: "\u2570", right: "\u256F", runs: runs, idleColor: idleColor })] }));
73
73
  }
@@ -93,5 +93,5 @@ export function EffortTierBadge({ effort, levels, onLight, columns, leadingColum
93
93
  spaced += ' '.repeat(Math.max(0, at - column)) + overlay.label[i];
94
94
  column = at + 1;
95
95
  }
96
- return (_jsx(Text, { bold: true, color: color, children: spaced }));
96
+ return (_jsx(Text, { bold: true, color: color, wrap: "truncate-end", children: spaced }));
97
97
  }
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { type ScrollBoxHandle } from '../ui.js';
2
3
  import type { LocalCommand } from '../commands.js';
3
4
  /**
4
5
  * The `?` help menu, mirroring Claude Code's `PromptInputHelpMenu.tsx`
@@ -10,7 +11,13 @@ import type { LocalCommand } from '../commands.js';
10
11
  * menu is for chrome commands. Modifier labels follow the platform
11
12
  * convention: ⌘ on macOS, ctrl elsewhere.
12
13
  */
13
- export declare function HelpMenu({ commands, }: {
14
+ export declare function HelpMenu({ commands, viewportHeight, viewportWidth, scrollRef, }: {
14
15
  commands: readonly LocalCommand[];
16
+ /** Fixed viewport supplied by the prompt overlay; unset for standalone renders. */
17
+ viewportHeight?: number;
18
+ /** Terminal width used to collapse the three-column layout when necessary. */
19
+ viewportWidth?: number;
20
+ /** PromptInput owns keyboard routing and drives this scroll viewport. */
21
+ scrollRef?: React.Ref<ScrollBoxHandle>;
15
22
  }): React.ReactNode;
16
23
  //# sourceMappingURL=HelpMenu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HelpMenu.d.ts","sourceRoot":"","sources":["../../../src/components/HelpMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAKlD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAA;CAClC,GAAG,KAAK,CAAC,SAAS,CAiElB"}
1
+ {"version":3,"file":"HelpMenu.d.ts","sourceRoot":"","sources":["../../../src/components/HelpMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAKlD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,EACvB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAA;IACjC,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,yEAAyE;IACzE,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;CACvC,GAAG,KAAK,CAAC,SAAS,CAyHlB"}
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import Box from '../ink/components/Box.js';
3
- import Text from '../ink/components/Text.js';
2
+ import { Box, ScrollBox, Text } from '../ui.js';
4
3
  import { localizedDescription } from '../commands.js';
5
4
  import { t } from '../i18n.js';
6
5
  import { modLabel } from '../utils/modifiers.js';
@@ -14,7 +13,19 @@ import { modLabel } from '../utils/modifiers.js';
14
13
  * menu is for chrome commands. Modifier labels follow the platform
15
14
  * convention: ⌘ on macOS, ctrl elsewhere.
16
15
  */
17
- export function HelpMenu({ commands, }) {
16
+ export function HelpMenu({ commands, viewportHeight, viewportWidth, scrollRef, }) {
18
17
  const chrome = commands.filter(command => !command.skill);
19
- return (_jsxs(Box, { paddingX: 2, flexDirection: "row", gap: 4, children: [_jsxs(Box, { flexDirection: "column", width: 26, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-for-commands') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-this-help') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-verbose-output', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-trajectory', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-search-history', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-interrupt') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-exit') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-redraw', { mod: modLabel }) }) })] }), _jsxs(Box, { flexDirection: "column", width: 24, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-clear-input') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-history-nav') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-move-cursor') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-word-jumps', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-complete-command') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-cycle-mode') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-editor') }) })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 1, children: [_jsx(Text, { dimColor: true, children: t('help-commands-title') }), chrome.map(command => (_jsx(Box, { children: _jsxs(Text, { dimColor: true, wrap: "truncate-end", children: ["/", command.name, " \u2014 ", localizedDescription(command)] }) }, command.name)))] })] }));
18
+ const primaryShortcuts = (_jsxs(Box, { flexDirection: "column", width: 26, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-for-commands') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-this-help') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-verbose-output', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-trajectory', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-search-history', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-interrupt') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-exit') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-redraw', { mod: modLabel }) }) })] }));
19
+ const secondaryShortcuts = (_jsxs(Box, { flexDirection: "column", width: 24, flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-clear-input') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-history-nav') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-move-cursor') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-word-jumps', { mod: modLabel }) }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-complete-command') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-cycle-mode') }) }), _jsx(Box, { children: _jsx(Text, { dimColor: true, children: t('help-open-editor') }) })] }));
20
+ const commandRows = chrome.map(command => (_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate-end", children: ["/", command.name, " \u2014 ", localizedDescription(command)] }) }, command.name)));
21
+ const compactCommandRows = chrome.map(command => (_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate-end", children: ["/", command.name, " \u2014 ", localizedDescription(command)] }) }, command.name)));
22
+ const commandList = (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Text, { dimColor: true, children: t('help-commands-title') }), commandRows] }));
23
+ const content = (_jsxs(Box, { paddingX: 2, flexDirection: "row", gap: 4, children: [primaryShortcuts, secondaryShortcuts, _jsx(Box, { flexDirection: "column", flexShrink: 1, children: commandList })] }));
24
+ // Standalone renders (notably the i18n verifier) keep the historical
25
+ // intrinsic-height layout. The real prompt overlay supplies an explicit
26
+ // height so a growing command registry cannot escape the terminal.
27
+ if (viewportHeight === undefined)
28
+ return content;
29
+ const compact = viewportWidth !== undefined && viewportWidth < 72;
30
+ return (_jsxs(Box, { height: viewportHeight, flexDirection: "column", children: [compact ? (_jsxs(ScrollBox, { ref: scrollRef, flexDirection: "column", flexGrow: 1, flexShrink: 1, paddingX: 2, children: [primaryShortcuts, secondaryShortcuts, _jsx(Text, { dimColor: true, children: t('help-commands-title') }), compactCommandRows] })) : (_jsxs(Box, { paddingX: 2, flexDirection: "row", gap: 4, flexGrow: 1, children: [primaryShortcuts, secondaryShortcuts, _jsx(ScrollBox, { ref: scrollRef, flexDirection: "column", flexGrow: 1, flexShrink: 1, children: commandList })] })), _jsx(Box, { paddingX: 2, flexShrink: 0, children: _jsx(Text, { dimColor: true, wrap: "truncate-end", children: t('help-scroll-hint') }) })] }));
20
31
  }
@@ -14,7 +14,7 @@ import { type Tip } from '../tips.js';
14
14
  * the whale the welcome tagline, centered under the art, in ice
15
15
  * blue. Narrow terminals drop the whale and keep the text column.
16
16
  */
17
- export declare function LogoV2({ model, effort, cwd, skipIntro, tip, }: {
17
+ export declare function LogoV2({ model, effort, cwd, skipIntro, tip, whale, }: {
18
18
  model: string;
19
19
  effort?: string | undefined;
20
20
  cwd: string;
@@ -22,5 +22,7 @@ export declare function LogoV2({ model, effort, cwd, skipIntro, tip, }: {
22
22
  skipIntro?: boolean;
23
23
  /** Test seam: pin the startup tip line (probes need a deterministic tip). */
24
24
  tip?: Tip;
25
+ /** Show the pixel whale art (settings `dsh-tui.whale`); off → text-only header. */
26
+ whale?: boolean;
25
27
  }): React.ReactNode;
26
28
  //# sourceMappingURL=LogoV2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,YAAY,CAAA;AAuDpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,EACjB,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,GAAG,CAAA;CACV,GAAG,KAAK,CAAC,SAAS,CAqFlB"}
1
+ {"version":3,"file":"LogoV2.d.ts","sourceRoot":"","sources":["../../../src/components/LogoV2.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,YAAY,CAAA;AAuDpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,EACrB,KAAK,EACL,MAAM,EACN,GAAG,EACH,SAAiB,EACjB,GAAG,EACH,KAAY,GACb,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,GAAG,KAAK,CAAC,SAAS,CAqFlB"}
@@ -65,7 +65,7 @@ function capitalize(text) {
65
65
  * the whale the welcome tagline, centered under the art, in ice
66
66
  * blue. Narrow terminals drop the whale and keep the text column.
67
67
  */
68
- export function LogoV2({ model, effort, cwd, skipIntro = false, tip, }) {
68
+ export function LogoV2({ model, effort, cwd, skipIntro = false, tip, whale = true, }) {
69
69
  const [step, setStep] = React.useState(skipIntro ? OPENING_SEQUENCE.length : 0);
70
70
  const settled = step >= OPENING_SEQUENCE.length;
71
71
  // Opening clock: drives the shimmer sweep and big-text highlight only
@@ -89,7 +89,7 @@ export function LogoV2({ model, effort, cwd, skipIntro = false, tip, }) {
89
89
  const wordmarkRGB = parseRGB(theme.claude) ?? BRAND;
90
90
  const wordmarkShimmerRGB = parseRGB(theme.claudeShimmer) ?? ICE;
91
91
  const taglineRGB = parseRGB(theme.claudeBlue_FOR_SYSTEM_SPINNER) ?? ICE;
92
- const showWhale = columns >= WHALE_MIN_COLUMNS;
92
+ const showWhale = whale && columns >= WHALE_MIN_COLUMNS;
93
93
  const frameIndex = settled ? STANDARD_FRAME_INDEX : OPENING_SEQUENCE[step].frame;
94
94
  // Frozen clock for the settled header: t=0 parks every sweep highlight
95
95
  // off-screen, leaving the static gradient behind.
@@ -3,7 +3,7 @@ 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
5
  import type { ToolBackground } from '../tuiDisplayPrefs.js';
6
- export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout, thinkingFold, toolBackground, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
6
+ export declare function MessageList({ rows, expanded, expandedRows, selectedId, onToggleRow, model, diffLayout, thinkingFold, toolBackground, activityFrames, showAll, onToggleAll, onLoadOlder, thinkingVisible, registerRowRef, scrollHandle, forceMountRowId, newSinceRowId, onUnseenCount, failureHintRowId, failureHint, }: {
7
7
  rows: readonly ChatRow[];
8
8
  expanded: boolean;
9
9
  expandedRows: ReadonlySet<number>;
@@ -16,6 +16,9 @@ export declare function MessageList({ rows, expanded, expandedRows, selectedId,
16
16
  thinkingFold?: 'preview' | 'full';
17
17
  /** Tool-card background treatment from the live channel settings. */
18
18
  toolBackground?: ToolBackground;
19
+ /** Working-activity preset name from the channel; drives the subagent
20
+ * card's running glyph so both indicators follow one setting. */
21
+ activityFrames?: string;
19
22
  showAll: boolean;
20
23
  onToggleAll: () => void;
21
24
  /** Restore folded-away older rows from the session log (CC-style "load
@@ -48,9 +51,10 @@ export declare function MessageList({ rows, expanded, expandedRows, selectedId,
48
51
  * welcome line. It scrolls away with the transcript once the conversation
49
52
  * fills the viewport (Claude Code shows its ✦ logo in the same slot).
50
53
  */
51
- export declare function LogoHeader({ model, effort, cwd, }: {
54
+ export declare function LogoHeader({ model, effort, cwd, whale, }: {
52
55
  model: string;
53
56
  effort?: string | undefined;
54
57
  cwd: string;
58
+ whale?: boolean;
55
59
  }): React.ReactNode;
56
60
  //# sourceMappingURL=MessageList.d.ts.map