@deepseek-ai/dsh-client-ui-tool 0.1.7-alpha.1 → 0.1.7-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-tool/README.md
5
- README.md: e26a277028d41420c4796b4678a2d6897d592872
6
- README.zh.md: 63d34c640571b0b3e363f6968221d15eea70ad49
5
+ README.md: b4a529fbcb1ed33976d71baf043e625fcca4c89c
6
+ README.zh.md: 406dc884f3529af79d675e6fbe1586e7485c3780
package/README.md CHANGED
@@ -29,6 +29,8 @@ Tool calls appear in the conversation as cards: a root call tree with its nested
29
29
 
30
30
  Shared Tool rows and Bash rows retain error and warning colors for failed and stopped summaries, including on hover. Hover darkens only summaries without those states.
31
31
 
32
+ Before dispatch, a named model call appears as one non-expandable row with its tool-owned icon and title. A generic row shows `Tool call · <tool name>`. Preparation exposes no complete arguments, file link, result, or parameter-dependent interaction. Write/edit show `Preparing content NKB` in the summary; N is `Math.ceil(raw.length / 1024)`, an integer estimate of the raw argument string length, not the file's byte size. `tool/call` enables the existing call presentation; completing an argument block alone does not start execution.
33
+
32
34
  ### Registering a business tool view
33
35
 
34
36
  An owning business package registers its wire Tool name into `tool.call.toolview`:
@@ -41,10 +43,12 @@ ctx.slots.inject('tool.call.toolview', () =>
41
43
  }, BusinessToolRow))
42
44
  ```
43
45
 
44
- The owner payload is `ToolCallOwnerProps`: `callId`, `toolName`, the frozen `block`, optional `cwd` and `home`, the session-authorized `loadImage` loader (for a view whose result carries durable images), and plain `openFile`/`inspect` callbacks. A PTC dispatch block retains its event's `parentCallId`; a root Session call has no such field, so descendants route through the same keyed dispatch — a registered view such as `read_image` renders its card there, and unregistered descendants keep the generic flattened form. Path summaries relativize to the Session cwd first, then replace a leftover POSIX Host home with `~`; `filePath` and Host open keep the authored filesystem path. The registration receives the normal Session slot runtime share but no React node or Runtime service.
46
+ The owner payload is `ToolCallOwnerProps`: `callId`, `toolName`, the `phase` discriminant and its frozen stage-specific `block`, optional `cwd` and `home`, the session-authorized `loadImage` loader (for a view whose result carries durable images), and plain `openFile`/`inspect` callbacks. A PTC dispatch block retains its event's `parentCallId`; a root Session call has no such field, so descendants route through the same keyed dispatch — a registered view such as `read_image` renders its card there, and unregistered descendants keep the generic flattened form. Path summaries relativize to the Session cwd first, then replace a leftover POSIX Host home with `~`; `filePath` and Host open keep the authored filesystem path. The registration receives the normal Session slot runtime share but no React node or Runtime service.
45
47
 
46
48
  ### Built-in views
47
49
 
50
+ Every registered view receives the explicit `preparing`, `start`, and `result` props declared in [the Tool slot types](src/client/contract/slots.ts). Shared rows use the same `ToolRow` in all stages. Their row model selects the title and combines any generic tool-name prefix with the available argument summary independently of lifecycle state. Tool-owned titles omit the English name. The shared argument parser returns no call during preparation and does not parse partial JSON. Write/edit use separate preparing and dispatched components, so only the preparing component invokes `useToolCallArgumentsPartial`; start and result share the dispatched component. Custom renderers such as Bash, Skill, and Cordis handle preparation separately; their argument-dependent components accept `StartedToolCallViewProps`.
51
+
48
52
  This package owns the generic fallback and the built-in shell/pwsh, read, read_image, write/edit, running `str_replace_editor` `create`/`str_replace`, grep/glob, web, todo, question, and PTC dispatch presentations. Structured cards derive directly from first-party raw event fields; Host `presentCall` and `presentResult` values never enter the Client. Running and settled foreground standard `bash`/`pwsh` and `terminal_send` calls use terminal cards at the root and in PTC dispatch children, subject to the same argument, result, and error checks. Persistent `bash`/`pwsh` calls use terminal cards only while running. Shell output ending in a recognized spill-policy notice uses expandable generic output in shell rows and generic output in Details; a displaced or omitted exit marker cannot establish success. Settled persistent-shell results stay generic because reset and partial-output diagnostics do not always describe one process exit status; root persistent results are expandable, while background acknowledgements remain collapsed. A native or PTC dispatch failure carrying `AUTO_REVIEW_DENIED` shows the Auto review verdict in its collapsed row and one normalized not-executed reason when expanded; a missing or whitespace-only reason uses localized fallback text. A successful question row pairs call questions with result answers by their stable ids and shows readable question/answer lines when expanded. A cancelled or interrupted row shows its verdict and original questions without inventing answers. Unsupported, malformed, or ambiguous inputs fall back to flattened Tool input/result text. `ui-skill` demonstrates a business-owned registration for `skill`.
49
53
 
50
54
  -----
@@ -59,16 +63,19 @@ The package realizes one dispatch rule: atomic Tool views are keyed by wire Tool
59
63
 
60
64
  ### Rendering contract
61
65
 
62
- `ToolCallTree` receives one root `ToolCallBlock` that already contains recursive `subCalls`, the session `cwd`, and the owner's callbacks for opening files and inspecting calls. It recursively walks the standard call blocks and sends the root and children at every depth through the same atomic dispatch path, without subscribing to a separate parent-to-children map. Each root and child wrapper preserves the `data-chat-anchor-key="call:<id>"` and `data-chat-call-id` DOM contract used for paging and selection.
66
+ `ToolCallTree` receives one Tool node, Session `cwd`, and navigation callbacks. Each branch receives a stable block and memoizes its explicit phase props, so changing one subcall leaves unchanged sibling branches unrendered. It dispatches each tool by name through `tool.call.toolview`. Dispatched roots retain their recursive `subCalls`; preparation has no children. Each root and child wrapper preserves the `data-chat-anchor-key="call:<id>"` and `data-chat-call-id` DOM contract used for paging and selection. The Tool node keeps the same callId across all three stages.
63
67
 
64
68
  Tool owner props forward Chat's stable `useDisclosure` Hook through root and nested calls. Rows invoke it where they own their expanded bodies; intermediate renderers do not subscribe. Each invocation has independent open state that resets when the enclosing Turn collapses, without replacing React identity. Presentation-mode switches preserve it.
65
69
 
70
+
71
+ The slot-injected `useToolCallArgumentsPartial` Hook lazily subscribes to the owning Step's `assistant-step` source and selects this callId's raw argument prefix. Missing sources or calls return an empty string. Other calls in the same Step may trigger a snapshot check, but an unchanged selected string does not refresh the consumer. Tools that do not invoke the Hook add no subscription; dispatched calls have no argument-prefix source.
72
+
66
73
  ### Cards
67
74
 
68
75
 
69
76
  Every card is read in place in the call tree; there is no second, full-height presentation of a selected call. Row renderers share one pure card model for each terminal, read, diff, search, and web card, and the image card's gallery renders through the tool-owned `tool.call.images` slot. These models validate raw call arguments, result content, failure state, persisted metadata, PTC dispatch `parentCallId`, and Session path facts. Unsupported or malformed inputs use flattened Tool result text. A file-path summary opens the file through the owner's `openFile`, which the chat view routes to the right Sidebar's text preview; `inspect` opens the trajectory view and is absent when that View is unavailable; cards then omit Inspect. Card-specific limits and fallback rules for the terminal, diff, read, search, and web cards remain in [the ui-primitives README](../ui-primitives/README.md); the image card's model in this package carries its own fallback rules.
70
77
 
71
- Chat diff cards keep nine rows before folding, enough for a file header, one removed/added pair, and three context lines on either side. The collapsed row and expanded footer share the primitive's exact or coarse-replacement counts.
78
+ Chat diff cards keep nine rows before folding, enough for a file header, one removed/added pair, and three context lines on either side. The tool row shows the primitive's exact or coarse-replacement counts; the expanded card contains the diff body without a totals footer.
72
79
 
73
80
  An Auto denial takes precedence over keyed specialized views. Its generic row preserves the call identity, omits raw arguments, and normalizes the stored reason only for display: trim surrounding whitespace and collapse line separators to spaces, with localized fallback for an empty result. Session and SDK error details keep the original reason.
74
81
 
@@ -98,7 +105,7 @@ These pages cover the conversation host, the view slots, and the card models.
98
105
  <a id="model-experience"></a>
99
106
  ## Model Experience
100
107
 
101
- None, as the package is a browser-side tool presentation layer that renders logged calls without changing model context.
108
+ None, as the package renders streamed tool identities and logged calls without changing model context.
102
109
 
103
110
  #### KV Cache effect
104
111
 
package/README.zh.md CHANGED
@@ -29,6 +29,8 @@ kind: "package-reference"
29
29
 
30
30
  共享工具行和 Bash 行的失败、停止摘要在悬停时仍保留错误色和警告色;只有不处于这两种状态的摘要会在悬停时加深。
31
31
 
32
+ 派发前,模型已给出名称的调用显示为不可展开的一行,使用工具自己的图标与标题。通用行显示为`工具调用 · <工具名>`。准备阶段不提供完整参数、文件链接、结果或依赖参数的交互。write/edit 的摘要显示「正在准备内容 NKB」;N 为 `Math.ceil(raw.length / 1024)`,是原始参数字符串长度的整数近似值,不是文件字节数。`tool/call` 才启用既有调用展示;参数块结束本身不代表开始执行。
33
+
32
34
  ### 注册业务工具视图
33
35
 
34
36
  拥有该视图的业务包将其 wire 工具名称注册进 `tool.call.toolview`:
@@ -41,10 +43,12 @@ ctx.slots.inject('tool.call.toolview', () =>
41
43
  }, BusinessToolRow))
42
44
  ```
43
45
 
44
- owner 载荷为 `ToolCallOwnerProps`:`callId`、`toolName`、冻结的 `block`、可选 `cwd` 与 `home`、会话授权的 `loadImage` loader(供结果携带持久图像的视图使用),以及普通的 `openFile`/`inspect` 回调。PTC dispatch 块保留事件的 `parentCallId`;根会话调用没有该字段,因此后代调用都走同一条按 key 分发路径:已注册视图的调用(如 `read_image`)也会在嵌套处渲染对应卡片,未注册的后代调用则保持通用压平形式。路径摘要先相对会话 cwd 缩短,再把剩余的 POSIX Host home 写成 `~`;`filePath` 与 Host 打开仍使用作者给出的文件系统路径。注册项会收到常规的会话 slot 运行时共享数据,但不会收到 React 节点或运行时服务。
46
+ owner 载荷为 `ToolCallOwnerProps`:`callId`、`toolName`、`phase` 判别字段及对应阶段的冻结 `block`、可选 `cwd` 与 `home`、会话授权的 `loadImage` loader(供结果携带持久图像的视图使用),以及普通的 `openFile`/`inspect` 回调。PTC dispatch 块保留事件的 `parentCallId`;根会话调用没有该字段,因此后代调用都走同一条按 key 分发路径:已注册视图的调用(如 `read_image`)也会在嵌套处渲染对应卡片,未注册的后代调用则保持通用压平形式。路径摘要先相对会话 cwd 缩短,再把剩余的 POSIX Host home 写成 `~`;`filePath` 与 Host 打开仍使用作者给出的文件系统路径。注册项会收到常规的会话 slot 运行时共享数据,但不会收到 React 节点或运行时服务。
45
47
 
46
48
  ### 内置视图
47
49
 
50
+ 每个注册视图都接收[工具 slot 类型](src/client/contract/slots.ts)声明的显式 `preparing`、`start` 和 `result` props。通用行在三个阶段使用同一个 `ToolRow`。行模型统一选择标题,并组合通用工具名前缀与已有参数摘要,不按生命周期阶段改变前缀;专用标题不附带英文名。准备阶段的共享参数解析入口直接返回无调用,不解析部分 JSON。write/edit 将准备态和派发后阶段拆成两个组件,只有准备态组件调用 `useToolCallArgumentsPartial`,start 与 result 共用派发后组件。Bash、Skill、Cordis 等自定义 renderer 分别处理准备态,其依赖参数的组件接收 `StartedToolCallViewProps`。
51
+
48
52
  本包拥有 generic fallback,以及 shell/pwsh、read、read_image、write/edit、运行中的 `str_replace_editor` `create`/`str_replace`、grep/glob、web、todo、question 与 PTC dispatch 的内置展示。结构化卡片直接从第一方原始 event 字段派生;Host `presentCall` 与 `presentResult` 值不会进入 Client。运行中与已完成的前台标准 `bash`/`pwsh` 和 `terminal_send` 调用,无论位于根还是 PTC dispatch 子调用中,都在通过相同的参数、结果和错误检查后使用 terminal 卡片。持久 `bash`/`pwsh` 调用仅在运行中使用 terminal 卡片。以已识别的 spill 策略提示结尾的 shell 输出,在 shell 行中使用可展开的 generic 输出,在 Details 中使用 generic 输出;位置被改变或被省略的退出标记无法证明成功。已完成的持久 shell 结果保持 generic 展示,因为 reset 与部分输出诊断不一定描述单个进程的退出状态;根调用的持久 shell 结果可展开,后台启动回执则保持折叠。带有 `AUTO_REVIEW_DENIED` 的原生或 PTC dispatch 失败会在折叠行显示 Auto review 裁决,展开时显示一行归一化后的“未执行”原因;原因缺失或只有空白时使用本地化 fallback 文案。成功的问题行按稳定 id 配对调用中的问题与结果中的回答,展开后显示可读的问答行。已取消或已中断的问题行显示其裁决与原始问题,不虚构回答。不受支持、格式错误或含糊的输入回退为压平的工具输入/结果文本。`ui-skill` 展示了业务包自行拥有的 `skill` 注册项。
49
53
 
50
54
  -----
@@ -59,16 +63,19 @@ owner 载荷为 `ToolCallOwnerProps`:`callId`、`toolName`、冻结的 `block`
59
63
 
60
64
  ### 渲染约定
61
65
 
62
- `ToolCallTree` 接收一个已经包含递归 `subCalls` 的 root `ToolCallBlock`、会话 `cwd`,以及属主用于打开文件和检查调用的回调。它递归遍历标准调用块,让 root 与任意深度的 child 经过同一条原子分发路径,不订阅独立的 parent-to-children map。每个 root 和 child 包装层都保留 `data-chat-anchor-key="call:<id>"` 与 `data-chat-call-id` DOM 约定,供分页和 selection 使用。
66
+ `ToolCallTree` 接收一个 Tool 节点、会话 `cwd` 和导航回调。每个分支接收稳定的 block,并缓存显式阶段 props,因此一个子调用变化不会重渲染未变化的兄弟分支。它通过 `tool.call.toolview` 按工具名分发。已派发的根调用保留递归 `subCalls`,准备阶段没有子调用。每个根调用和子调用包装层都保留 `data-chat-anchor-key="call:<id>"` 与 `data-chat-call-id` DOM 约定,供分页和选择使用。Tool 节点在三个阶段保持同一个 callId。
63
67
 
64
68
  Tool 所有者属性将 Chat 注入的稳定 `useDisclosure` 钩子传给根调用及嵌套调用。工具行在拥有展开正文的位置调用它,中间 renderer 不订阅。每次调用拥有独立展开状态,外层轮次收起时重置该状态,不替换 React 身份;展示模式切换保留该状态。
65
69
 
70
+
71
+ slot 注入的 `useToolCallArgumentsPartial` 钩子按需订阅所属 Step 的 `assistant-step` 来源,并选取当前 callId 的原始参数前缀。来源或调用不存在时返回空字符串。同一步骤中的其他调用可能触发快照检查,但选中的字符串未变时不会刷新使用方。不调用钩子的工具不新增订阅,已派发的调用不再提供参数前缀来源。
72
+
66
73
  ### 卡片
67
74
 
68
75
 
69
76
  每张卡片都直接在调用树中查看;选中调用后不会再显示第二个全高视图。行 renderer 为 terminal、read、diff、search 和 web 卡片各复用同一个纯 card model,image 卡片的图库经由工具自有 `tool.call.images` slot 渲染。这些 model 校验原始调用参数、结果内容、失败状态、持久 metadata、PTC dispatch 的 `parentCallId` 与会话路径信息。不受支持或格式错误的输入使用压平的工具结果文本。文件路径摘要经属主的 `openFile` 打开文件,chat 视图把它路由到右侧 Sidebar 的文本预览;`inspect` 打开轨迹视图;该视图不可用时不提供此回调,卡片随之隐藏 Inspect。terminal、diff、read、search 与 web 卡片的上限与 fallback 规则仍由 [ui-primitives README](../ui-primitives/README.zh.md) 负责;image 卡片的 fallback 规则由本包内的 card model 自行承载。
70
77
 
71
- Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删除与新增行及两侧各三行上下文。折叠工具行与展开卡片底部采用原语一致的精确或粗粒度替换统计。
78
+ Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删除与新增行及两侧各三行上下文。工具行显示原语提供的精确或粗粒度替换统计;展开卡片包含差异正文,不显示底部统计。
72
79
 
73
80
  Auto 拒绝优先于按工具名选择的专门视图。其通用行保留调用身份、省略原始参数,并且只在显示时归一化存储的理由:去除首尾空白,把行分隔符折叠为空格,结果为空时使用本地化通用理由。Session 与 SDK 错误详情保留原始理由。
74
81
 
@@ -98,7 +105,7 @@ terminal model 使用浏览器安全入口 `@deepseek-ai/dsh-spill-policy/notice
98
105
  <a id="model-experience"></a>
99
106
  ## 模型体验
100
107
 
101
- 无。该包是浏览器端工具展示层,只渲染已记录的工具调用,不改变模型上下文。
108
+ 无。该包渲染流式工具身份与已记录调用,不改变模型上下文。
102
109
 
103
110
  #### KV Cache 影响
104
111
 
package/lib/client.js CHANGED
@@ -106,7 +106,45 @@ window.__ModuleLoader__.load({
106
106
  cordis_stop: "tool.title.stopCordis",
107
107
  cordis_undefine: "tool.title.removeCordis",
108
108
  pwsh: "tool.title.pwsh",
109
- read_image: "tool.title.readImage"
109
+ read_image: "tool.title.readImage",
110
+ todo_write: "todo.rowTitle",
111
+ ask_user_question: "ask.rowTitle",
112
+ create_goal: "tool.title.createGoal",
113
+ get_goal: "tool.title.getGoal",
114
+ update_goal: "tool.title.updateGoal",
115
+ schedule_create: "tool.title.createSchedule",
116
+ schedule_list: "tool.title.listSchedules",
117
+ schedule_delete: "tool.title.deleteSchedule",
118
+ cordis_inspect_list: "tool.title.inspectProviders",
119
+ cordis_inspect_query: "tool.title.queryRuntime",
120
+ cordis_inspect_self: "tool.title.inspectPlugins",
121
+ workflow: "tool.title.workflow",
122
+ ralph: "tool.title.ralph",
123
+ session_event_read: "tool.title.readEvent",
124
+ session_event_search: "tool.title.searchEvents",
125
+ session_event_trace: "tool.title.traceEvent",
126
+ session_search: "tool.title.searchSessions",
127
+ session_trace: "tool.title.traceSession",
128
+ list_subagent_models: "tool.title.listModels",
129
+ subagent: "tool.title.subagent",
130
+ list_agents: "tool.title.listAgents",
131
+ send_message: "tool.title.sendMessage",
132
+ interrupt_agent: "tool.title.interruptAgent",
133
+ job_list: "tool.title.listJobs",
134
+ job_output: "tool.title.readJob",
135
+ job_kill: "tool.title.killJob",
136
+ terminal_open: "tool.title.openTerminal",
137
+ terminal_read: "tool.title.readTerminal",
138
+ terminal_list: "tool.title.listTerminals",
139
+ terminal_signal: "tool.title.signalTerminal",
140
+ terminal_close: "tool.title.closeTerminal",
141
+ lsp: "tool.title.lsp",
142
+ spawn_teammate: "tool.title.spawnTeammate",
143
+ team_task_create: "tool.title.createTeamTask",
144
+ team_task_get: "tool.title.getTeamTask",
145
+ team_task_update: "tool.title.updateTeamTask",
146
+ team_task_list: "tool.title.listTeamTasks",
147
+ wait_agent: "tool.title.waitAgent"
110
148
  };
111
149
  /**
112
150
  * Classify a tool name into its row variant.
@@ -116,6 +154,14 @@ window.__ModuleLoader__.load({
116
154
  function classifyTool(toolName) {
117
155
  return TOOL_VARIANTS[toolName] ?? "others";
118
156
  }
157
+ /**
158
+ * Select a tool-owned or generic title without reading arguments.
159
+ * @param toolName - wire tool name.
160
+ * @returns the localized title key.
161
+ */
162
+ function toolTitleKey(toolName) {
163
+ return TOOL_TITLE_KEYS[toolName] ?? VARIANT_TITLE_KEYS[classifyTool(toolName)];
164
+ }
119
165
  function deriveAutoReviewDenial(block) {
120
166
  if (!("kind" in block) || !block.isError) return null;
121
167
  const error = block.error;
@@ -218,27 +264,27 @@ window.__ModuleLoader__.load({
218
264
  /**
219
265
  * Derive the full row model from a frozen call slice.
220
266
  * @param toolName - wire tool name (dispatch-supplied; survives windowless results).
221
- * @param block - RunningToolCall or ToolResultNode off the snapshot caches.
267
+ * @param block - preparing call, dispatched call, or result from the snapshot.
222
268
  * @param cwd - session workspace root; workspace-rooted path summaries display relative to it.
223
269
  * @param home - host account home; a leftover POSIX home path displays as `~`.
224
270
  * @returns the row model.
225
271
  */
226
272
  function toolRowModel(toolName, block, cwd, home) {
227
273
  const variant = classifyTool(toolName);
274
+ const titleKey = toolTitleKey(toolName);
228
275
  const done = "kind" in block;
229
- const argsRaw = (done ? block.call?.argsRaw : block.argsRaw) ?? "";
230
- const state = !done ? "running" : block.error?.code === "interrupted" ? "stopped" : block.isError ? "error" : "ok";
231
- const base = argsRaw === "" ? block.callId : abbreviateHomePath(relativizeToCwd(deriveSummary(variant, argsRaw), cwd), home);
232
- const toolTitleKey = TOOL_TITLE_KEYS[toolName];
233
- const summary = variant === "others" && toolName !== "" && toolTitleKey === void 0 ? `${toolName} · ${base}` : base;
276
+ const argsRaw = done ? block.call?.argsRaw ?? "" : block.phase === "start" ? block.argsRaw : null;
277
+ const state = !done ? block.phase === "preparing" ? "preparing" : "running" : block.error?.code === "interrupted" ? "stopped" : block.isError ? "error" : "ok";
278
+ const base = argsRaw === null ? "" : argsRaw === "" ? block.callId : abbreviateHomePath(relativizeToCwd(deriveSummary(variant, argsRaw), cwd), home);
279
+ const summary = [titleKey === "tool.title.generic" ? toolName : "", base].filter(Boolean).join(" · ");
234
280
  const output = done ? resultText(block) || null : null;
235
281
  const errorSummary = state === "error" && output !== null ? firstLine(output) : null;
236
282
  const bodyRaw = argsRaw === "" ? null : argsRaw;
237
283
  return {
238
284
  variant,
239
- titleKey: toolTitleKey ?? VARIANT_TITLE_KEYS[variant],
285
+ titleKey,
240
286
  summary,
241
- filePath: deriveFilePath(variant, argsRaw),
287
+ filePath: argsRaw === null ? void 0 : deriveFilePath(variant, argsRaw),
242
288
  bodyRaw,
243
289
  output,
244
290
  errorSummary,
@@ -251,10 +297,11 @@ window.__ModuleLoader__.load({
251
297
  const parsedCalls = /* @__PURE__ */ new WeakMap();
252
298
  /**
253
299
  * Parse the call head paired with one immutable Tool block.
254
- * @param block - running or settled Tool block.
255
- * @returns the Tool name and object arguments, or null when the call head or valid JSON object is unavailable.
300
+ * @param block - preparing, dispatched, or settled Tool block.
301
+ * @returns the Tool name and object arguments, or null during preparation or when valid arguments are unavailable.
256
302
  */
257
303
  function parsedToolCall(block) {
304
+ if (!("kind" in block) && block.phase === "preparing") return null;
258
305
  const cached = parsedCalls.get(block);
259
306
  if (cached !== void 0 || parsedCalls.has(block)) return cached ?? null;
260
307
  const call = "kind" in block ? block.call : block;
@@ -623,6 +670,11 @@ window.__ModuleLoader__.load({
623
670
  const COUNT_OFFSET = EXACT_OMISSION.indexOf("0");
624
671
  const COUNT_SUFFIX = EXACT_OMISSION.slice(COUNT_OFFSET + 1);
625
672
  function isOmission(text) {
673
+ const imageNotice = / Omitted ([1-9][0-9]*) images\.$/.exec(text);
674
+ if (imageNotice !== null) {
675
+ if (!Number.isSafeInteger(Number(imageNotice[1]))) return false;
676
+ text = text.slice(0, imageNotice.index);
677
+ }
626
678
  if (text === describeOmitted({ kind: "none" }, "bytes") || text === describeOmitted({ kind: "unknown" }, "bytes")) return true;
627
679
  const count = Number(text.slice(COUNT_OFFSET, text.length - COUNT_SUFFIX.length));
628
680
  return Number.isSafeInteger(count) && count >= 0 && text === describeOmitted({
@@ -1022,6 +1074,18 @@ window.__ModuleLoader__.load({
1022
1074
  //#region lib/types/client/tool/models/primitive-labels.js
1023
1075
  /** Localized copy adapters for Cordis-free UI primitives used by Tool cards. */
1024
1076
  /**
1077
+ * Localize the shared code-card toolbar.
1078
+ * @param t - Conversation locale seat.
1079
+ * @returns Language fallback and wrapping actions.
1080
+ */
1081
+ function codeToolbarLabels(t) {
1082
+ return {
1083
+ codeLabel: t("codeBlock.title"),
1084
+ wrapLabel: t("codeBlock.wrap"),
1085
+ unwrapLabel: t("codeBlock.unwrap")
1086
+ };
1087
+ }
1088
+ /**
1025
1089
  * Build localized Markdown chrome labels.
1026
1090
  * @param t - Conversation locale seat.
1027
1091
  * @returns Markdown chrome labels.
@@ -1030,7 +1094,8 @@ window.__ModuleLoader__.load({
1030
1094
  return {
1031
1095
  code: {
1032
1096
  copyLabel: t("copy"),
1033
- copiedLabel: t("copied")
1097
+ copiedLabel: t("copied"),
1098
+ toolbarLabels: codeToolbarLabels(t)
1034
1099
  },
1035
1100
  footnotes: t("markdown.footnotes")
1036
1101
  };
@@ -1042,13 +1107,13 @@ window.__ModuleLoader__.load({
1042
1107
  */
1043
1108
  function diffBlockLabels(t) {
1044
1109
  return {
1110
+ ...codeToolbarLabels(t),
1045
1111
  copy: t("copy"),
1046
1112
  copied: t("copied"),
1047
1113
  collapseAria: t("diff.collapseAria"),
1048
1114
  expandAria: (count) => t("diff.expandAria", { count }),
1049
1115
  collapse: t("collapse"),
1050
- expand: (count) => t("diff.expandRest", { count }),
1051
- files: (count) => t(count === 1 ? "diff.files.one" : "diff.files.other", { count })
1116
+ expand: (count) => t("diff.expandRest", { count })
1052
1117
  };
1053
1118
  }
1054
1119
  /**
@@ -1058,6 +1123,7 @@ window.__ModuleLoader__.load({
1058
1123
  */
1059
1124
  function readBlockLabels(t) {
1060
1125
  return {
1126
+ ...codeToolbarLabels(t),
1061
1127
  window: (shown, total) => t("read.window", {
1062
1128
  shown,
1063
1129
  total
@@ -1174,7 +1240,7 @@ window.__ModuleLoader__.load({
1174
1240
  }
1175
1241
  //#endregion
1176
1242
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/components/ToolDetails.module.css.mjs
1177
- const css$3 = ".DXqwVW_root{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-markdown-code-block);color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xs-13);border-radius:12px;margin:4px 0 4px 4px;overflow:hidden}.DXqwVW_list{max-height:320px;margin:0;padding:0;list-style:none;overflow-y:auto}.DXqwVW_item,.DXqwVW_empty{margin:0;padding:10px 14px}.DXqwVW_item+.DXqwVW_item{border-top:.5px solid var(--dsw-alias-border-l2)}.DXqwVW_root[data-inspect]:not([data-caption])>.DXqwVW_list>.DXqwVW_item,.DXqwVW_root[data-inspect]:not([data-caption]) .DXqwVW_empty,.DXqwVW_root[data-inspect] .DXqwVW_caption{padding-inline-end:88px}.DXqwVW_caption{color:var(--dsw-alias-label-caption);padding:10px 14px 6px;font-size:12px}.DXqwVW_heading{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.DXqwVW_text{white-space:pre-wrap;overflow-wrap:anywhere;flex:1;min-width:0}.DXqwVW_status{flex:none;justify-content:center;align-self:flex-start;align-items:center;width:14px;height:18px;font-size:16px;line-height:18px;display:inline-flex}.DXqwVW_pending{box-sizing:border-box;border:1px solid var(--dsw-alias-label-tertiary);border-radius:2px;width:10px;height:10px}.DXqwVW_heading:has(.DXqwVW_statusText) .DXqwVW_text{flex-basis:12em}.DXqwVW_statusText{color:var(--dsw-alias-label-caption);white-space:nowrap;margin-inline-start:auto;font-size:12px}.DXqwVW_previous,.DXqwVW_unchanged{color:var(--dsw-alias-label-tertiary)}.DXqwVW_item[data-change=added] .DXqwVW_status{color:var(--dsw-alias-state-success-primary)}.DXqwVW_item[data-change=removed] .DXqwVW_status{color:var(--dsw-alias-state-error-primary)}.DXqwVW_item[data-change=removed] .DXqwVW_text{color:var(--dsw-alias-label-tertiary);text-decoration:line-through}.DXqwVW_unchanged{border-top:.5px solid var(--dsw-alias-border-l2)}.DXqwVW_unchanged summary{cursor:pointer;align-items:center;gap:6px;padding:9px 14px;list-style:none;display:flex}.DXqwVW_unchanged summary::-webkit-details-marker{display:none}.DXqwVW_unchanged[open] summary svg{transform:rotate(90deg)}.DXqwVW_fields{margin:0}.DXqwVW_heading+.DXqwVW_fields{margin-top:6px}.DXqwVW_field{grid-template-columns:5.5em minmax(0,1fr);gap:12px;display:grid}.DXqwVW_field+.DXqwVW_field{margin-top:4px}.DXqwVW_field dt{color:var(--dsw-alias-label-caption)}.DXqwVW_field dd{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.DXqwVW_badge{color:var(--dsw-alias-label-caption);flex:none;align-items:center;gap:5px;font-size:12px;display:inline-flex}.DXqwVW_badge:before{content:\"\";corner-shape:round;background:currentColor;border-radius:50%;width:5px;height:5px}.DXqwVW_badge[data-tone=info]{color:var(--dsw-alias-state-business-primary)}.DXqwVW_badge[data-tone=success]{color:var(--dsw-alias-state-success-primary)}.DXqwVW_badge[data-tone=warning]{color:var(--dsw-alias-state-warn-primary)}.DXqwVW_badge[data-tone=error]{color:var(--dsw-alias-state-error-primary)}.DXqwVW_subtitle{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin-top:3px;font-size:12px}.DXqwVW_description{color:var(--dsw-alias-label-caption);white-space:pre-wrap;overflow-wrap:anywhere;margin:6px 0}.DXqwVW_lines{white-space:pre-wrap;overflow-wrap:anywhere;margin:6px 0 0;padding-inline-start:18px}.DXqwVW_lines li+li{margin-top:4px}.DXqwVW_group{border-top:.5px solid var(--dsw-alias-border-l2);margin-top:8px}.DXqwVW_group>summary{color:var(--dsw-alias-label-caption);cursor:pointer;overflow-wrap:anywhere;align-items:center;gap:6px;padding:8px 0 0;list-style:none;display:flex}.DXqwVW_group>summary::-webkit-details-marker{display:none}.DXqwVW_group[open]>summary svg{transform:rotate(90deg)}.DXqwVW_group>summary svg{flex:none}.DXqwVW_group .DXqwVW_list{max-height:none;overflow:visible}.DXqwVW_group .DXqwVW_item{padding:9px 0 2px 20px}.DXqwVW_prose,.DXqwVW_code{max-width:100%;font-size:13px}.DXqwVW_prose{margin-top:8px}.DXqwVW_root .DXqwVW_item>.DXqwVW_code{max-height:240px;margin:8px 0 0;overflow:auto}.DXqwVW_root .DXqwVW_group .DXqwVW_item:has(>.DXqwVW_code:only-child){padding:4px 0 0 20px}.DXqwVW_root .DXqwVW_group .DXqwVW_item>.DXqwVW_code:only-child{margin:0}.DXqwVW_root .DXqwVW_code [data-code-block-banner]{padding:4px 10px}.DXqwVW_root .DXqwVW_code pre{padding:6px 10px 8px}.DXqwVW_path{min-width:0;color:inherit;font:inherit;text-align:start;overflow-wrap:anywhere;cursor:pointer;background:0 0;border:none;flex:1;padding:0}.DXqwVW_path:hover{text-decoration:underline}.DXqwVW_path:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}";
1243
+ const css$3 = ".DXqwVW_root{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-markdown-code-block);color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xs-13);border-radius:12px;margin:4px 0 4px 4px;overflow:hidden}.DXqwVW_list{max-height:320px;margin:0;padding:0;list-style:none;overflow-y:auto}.DXqwVW_item,.DXqwVW_empty{margin:0;padding:10px 14px}.DXqwVW_item+.DXqwVW_item{border-top:.5px solid var(--dsw-alias-border-l2)}.DXqwVW_root[data-inspect]:not([data-caption])>.DXqwVW_list>.DXqwVW_item,.DXqwVW_root[data-inspect]:not([data-caption]) .DXqwVW_empty,.DXqwVW_root[data-inspect] .DXqwVW_caption{padding-inline-end:88px}.DXqwVW_caption{color:var(--dsw-alias-label-caption);padding:10px 14px 6px;font-size:12px}.DXqwVW_heading{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.DXqwVW_text{white-space:pre-wrap;overflow-wrap:anywhere;flex:1;min-width:0}.DXqwVW_status{flex:none;justify-content:center;align-self:flex-start;align-items:center;width:14px;height:18px;font-size:16px;line-height:18px;display:inline-flex}.DXqwVW_pending{box-sizing:border-box;border:1px solid var(--dsw-alias-label-tertiary);border-radius:2px;width:10px;height:10px}.DXqwVW_heading:has(.DXqwVW_statusText) .DXqwVW_text{flex-basis:12em}.DXqwVW_statusText{color:var(--dsw-alias-label-caption);white-space:nowrap;margin-inline-start:auto;font-size:12px}.DXqwVW_previous,.DXqwVW_unchanged{color:var(--dsw-alias-label-tertiary)}.DXqwVW_item[data-change=added] .DXqwVW_status{color:var(--dsw-alias-state-success-primary)}.DXqwVW_item[data-change=removed] .DXqwVW_status{color:var(--dsw-alias-state-error-primary)}.DXqwVW_item[data-change=removed] .DXqwVW_text{color:var(--dsw-alias-label-tertiary);text-decoration:line-through}.DXqwVW_unchanged{border-top:.5px solid var(--dsw-alias-border-l2)}.DXqwVW_unchanged summary{cursor:pointer;align-items:center;gap:6px;padding:9px 14px;list-style:none;display:flex}.DXqwVW_unchanged summary::-webkit-details-marker{display:none}.DXqwVW_unchanged[open] summary svg{transform:rotate(90deg)}.DXqwVW_fields{margin:0}.DXqwVW_heading+.DXqwVW_fields{margin-top:6px}.DXqwVW_field{grid-template-columns:5.5em minmax(0,1fr);gap:12px;display:grid}.DXqwVW_field+.DXqwVW_field{margin-top:4px}.DXqwVW_field dt{color:var(--dsw-alias-label-caption)}.DXqwVW_field dd{white-space:pre-wrap;overflow-wrap:anywhere;margin:0}.DXqwVW_badge{color:var(--dsw-alias-label-caption);flex:none;align-items:center;gap:5px;font-size:12px;display:inline-flex}.DXqwVW_badge:before{content:\"\";corner-shape:round;background:currentColor;border-radius:50%;width:5px;height:5px}.DXqwVW_badge[data-tone=info]{color:var(--dsw-alias-state-business-primary)}.DXqwVW_badge[data-tone=success]{color:var(--dsw-alias-state-success-primary)}.DXqwVW_badge[data-tone=warning]{color:var(--dsw-alias-state-warn-primary)}.DXqwVW_badge[data-tone=error]{color:var(--dsw-alias-state-error-primary)}.DXqwVW_subtitle{color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;margin-top:3px;font-size:12px}.DXqwVW_description{color:var(--dsw-alias-label-caption);white-space:pre-wrap;overflow-wrap:anywhere;margin:6px 0}.DXqwVW_lines{white-space:pre-wrap;overflow-wrap:anywhere;margin:6px 0 0;padding-inline-start:18px}.DXqwVW_lines li+li{margin-top:4px}.DXqwVW_group{border-top:.5px solid var(--dsw-alias-border-l2);margin-top:8px}.DXqwVW_group>summary{color:var(--dsw-alias-label-caption);cursor:pointer;overflow-wrap:anywhere;align-items:center;gap:6px;padding:8px 0 0;list-style:none;display:flex}.DXqwVW_group>summary::-webkit-details-marker{display:none}.DXqwVW_group[open]>summary svg{transform:rotate(90deg)}.DXqwVW_group>summary svg{flex:none}.DXqwVW_group .DXqwVW_list{max-height:none;overflow:visible}.DXqwVW_group .DXqwVW_item{padding:9px 0 2px 20px}.DXqwVW_prose,.DXqwVW_code{max-width:100%;font-size:13px}.DXqwVW_prose{margin-top:8px}.DXqwVW_root .DXqwVW_item>.DXqwVW_code{max-height:240px;margin:8px 0 0;overflow:auto}.DXqwVW_root .DXqwVW_item:has(>.DXqwVW_code:only-child){padding:0}.DXqwVW_root .DXqwVW_item>.DXqwVW_code:only-child{margin:0}.DXqwVW_root .DXqwVW_group .DXqwVW_item:has(>.DXqwVW_code:only-child){padding:4px 0 0 20px}.DXqwVW_path{min-width:0;color:inherit;font:inherit;text-align:start;overflow-wrap:anywhere;cursor:pointer;background:0 0;border:none;flex:1;padding:0}.DXqwVW_path:hover{text-decoration:underline}.DXqwVW_path:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:3px}";
1178
1244
  const tagId$3 = "@deepseek-ai/dsh-client-ui-tool/ToolDetails.module.css";
1179
1245
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1180
1246
  const tag = document.createElement("style");
@@ -1282,6 +1348,7 @@ window.__ModuleLoader__.load({
1282
1348
  })
1283
1349
  }),
1284
1350
  item.code !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.CodeBlock, {
1351
+ toolbarLabels: codeToolbarLabels(t),
1285
1352
  className: ToolDetails_module_css_default.code,
1286
1353
  code: item.code.text,
1287
1354
  lang: item.code.language,
@@ -1347,7 +1414,7 @@ window.__ModuleLoader__.load({
1347
1414
  }
1348
1415
  //#endregion
1349
1416
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css.mjs
1350
- const css$2 = ".o3BgMG_root{flex-direction:column;display:flex}.o3BgMG_leading{flex-shrink:0}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_leading,.o3BgMG_root[data-tool^=cordis_] .o3BgMG_title{color:var(--dsw-alias-state-business-primary)}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_title{font-weight:500}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_sep{background:var(--dsw-alias-state-business-primary)}.o3BgMG_chevron{color:var(--dsw-alias-label-secondary)}.o3BgMG_title{font-weight:400;transition:color .1s}.o3BgMG_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.o3BgMG_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:auto;transition:color .1s;overflow:hidden}.o3BgMG_summarySuffix{white-space:nowrap;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:none;margin-left:4px;transition:color .1s}.o3BgMG_row:hover .o3BgMG_title,.o3BgMG_row:hover .o3BgMG_summary:not(.o3BgMG_errorSummary):not(.o3BgMG_stoppedSummary),.o3BgMG_row:hover .o3BgMG_summarySuffix{color:var(--dsw-alias-label-primary)}.o3BgMG_diffStat{font-family:var(--ds-font-family-code);font-size:calc(var(--dsh-content-font-size-secondary,13px) - 2px);color:var(--dsw-alias-label-caption);margin-left:10px;transform:translateY(.5px)}.o3BgMG_fileLink{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:inherit;text-align:left;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);text-decoration:underline dotted;text-decoration-color:var(--dsw-alias-label-tertiary);text-underline-offset:3px;cursor:pointer;background:0 0;border:none;flex:0 auto;margin:0;padding:0;text-decoration-thickness:1px;transition:color .1s;overflow:hidden}.o3BgMG_row:hover .o3BgMG_fileLink,.o3BgMG_fileLink:hover{color:var(--dsw-alias-label-primary);text-decoration-color:currentColor}.o3BgMG_errorSummary{color:var(--dsw-alias-state-error-primary)}.o3BgMG_stoppedSummary{color:var(--dsw-alias-state-warn-label)}.o3BgMG_bodyWrap{flex-direction:column;display:flex}.o3BgMG_inspectButton{border:.5px solid var(--dsw-alias-border-l3);corner-shape:round;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);cursor:pointer;opacity:0;border-radius:999px;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;font-size:11px;line-height:16px;transition:opacity .1s;display:inline-flex}.o3BgMG_root:hover .o3BgMG_inspectButton,.o3BgMG_inspectButton:focus-visible{opacity:1}.o3BgMG_detailsBodyWrap{position:relative}.o3BgMG_detailsBodyWrap .o3BgMG_inspectButton{margin:0;position:absolute;top:12px;right:12px}.o3BgMG_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}.o3BgMG_bodyScroll{max-height:260px;overflow-y:auto}.o3BgMG_ioCard{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small);border-radius:12px;flex-direction:column;margin:4px 0 4px 4px;display:flex}.o3BgMG_ioSection{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:14px;max-height:150px;padding:12px 16px;display:grid;overflow-y:auto}.o3BgMG_ioSection::-webkit-scrollbar-thumb{background-clip:padding-box;border:2px solid #0000;border-radius:6px}.o3BgMG_ioSection::-webkit-scrollbar-track{margin:6px 0}.o3BgMG_ioLabel{color:var(--dsw-alias-label-caption);align-self:start;position:sticky;top:0}.o3BgMG_ioDivider{background:var(--dsw-alias-border-l2);flex:none;height:.5px}.o3BgMG_ioText{white-space:pre-wrap;word-break:break-word;min-width:0;color:var(--dsw-alias-label-secondary)}.o3BgMG_ioText[data-error]{color:var(--dsw-alias-state-error-primary)}.o3BgMG_codeBody,.o3BgMG_terminalBody,.o3BgMG_diffBody,.o3BgMG_readBody,.o3BgMG_imageBody,.o3BgMG_searchBody,.o3BgMG_webBody{margin:4px 0 4px 4px}.o3BgMG_searchRecovery{white-space:pre-wrap;overflow-wrap:anywhere;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary);margin:4px 0 4px 4px}.o3BgMG_imageLabel{overflow-wrap:anywhere;font:var(--dsw-font-sm-13);color:var(--dsw-alias-label-secondary);margin-bottom:4px}.o3BgMG_imageMeta{white-space:pre-wrap;overflow-wrap:anywhere;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary)}.o3BgMG_codeBody{--dsl-code-block-content-font:var(--dsw-font-markdown-code-block-small)}.o3BgMG_terminalBody{--dsl-terminal-font:var(--dsw-font-markdown-code-block-small);--dsl-terminal-line-height:18px;--dsl-terminal-output-max-height:224px;border:.5px solid var(--dsw-alias-border-l1)}.o3BgMG_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
1417
+ const css$2 = ".o3BgMG_root{flex-direction:column;display:flex}.o3BgMG_leading{flex-shrink:0}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_leading,.o3BgMG_root[data-tool^=cordis_] .o3BgMG_title{color:var(--dsw-alias-state-business-primary)}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_title{font-weight:500}.o3BgMG_root[data-tool^=cordis_] .o3BgMG_sep{background:var(--dsw-alias-state-business-primary)}.o3BgMG_chevron{color:var(--dsw-alias-label-secondary)}.o3BgMG_title{font-weight:400;transition:color .1s}.o3BgMG_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.o3BgMG_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:auto;transition:color .1s;overflow:hidden}.o3BgMG_summarySuffix{white-space:nowrap;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:none;margin-left:4px;transition:color .1s}.o3BgMG_row:hover .o3BgMG_title,.o3BgMG_row:hover .o3BgMG_summary:not(.o3BgMG_errorSummary):not(.o3BgMG_stoppedSummary),.o3BgMG_row:hover .o3BgMG_summarySuffix{color:var(--dsw-alias-label-primary)}.o3BgMG_diffStat{font-family:var(--ds-font-family-code);font-size:calc(var(--dsh-content-font-size-secondary,13px) - 2px);color:var(--dsw-alias-label-caption);margin-left:10px;transform:translateY(.5px)}.o3BgMG_fileLink{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:inherit;text-align:left;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);text-decoration:underline dotted;text-decoration-color:var(--dsw-alias-label-tertiary);text-underline-offset:3px;cursor:pointer;background:0 0;border:none;flex:0 auto;margin:0;padding:0;text-decoration-thickness:1px;transition:color .1s;overflow:hidden}.o3BgMG_row:hover .o3BgMG_fileLink,.o3BgMG_fileLink:hover{color:var(--dsw-alias-label-primary);text-decoration-color:currentColor}.o3BgMG_errorSummary{color:var(--dsw-alias-state-error-primary)}.o3BgMG_stoppedSummary{color:var(--dsw-alias-state-warn-label)}.o3BgMG_bodyWrap{flex-direction:column;display:flex}.o3BgMG_inspectButton{border:.5px solid var(--dsw-alias-border-l3);corner-shape:round;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);cursor:pointer;opacity:0;border-radius:999px;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;font-size:11px;line-height:16px;transition:opacity .1s;display:inline-flex}.o3BgMG_root:hover .o3BgMG_inspectButton,.o3BgMG_inspectButton:focus-visible{opacity:1}.o3BgMG_detailsBodyWrap{position:relative}.o3BgMG_detailsBodyWrap .o3BgMG_inspectButton{margin:0;position:absolute;top:12px;right:12px}.o3BgMG_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}.o3BgMG_bodyScroll{max-height:260px;overflow-y:auto}.o3BgMG_ioCard{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small);border-radius:12px;flex-direction:column;margin:4px 0 4px 4px;display:flex}.o3BgMG_ioSection{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:14px;max-height:150px;padding:12px 16px;display:grid;overflow-y:auto}.o3BgMG_ioSection::-webkit-scrollbar-thumb{background-clip:padding-box;border:2px solid #0000;border-radius:6px}.o3BgMG_ioSection::-webkit-scrollbar-track{margin:6px 0}.o3BgMG_ioLabel{color:var(--dsw-alias-label-caption);align-self:start;position:sticky;top:0}.o3BgMG_ioDivider{background:var(--dsw-alias-border-l2);flex:none;height:.5px}.o3BgMG_ioText{white-space:pre-wrap;word-break:break-word;min-width:0;color:var(--dsw-alias-label-secondary)}.o3BgMG_ioText[data-error]{color:var(--dsw-alias-state-error-primary)}.o3BgMG_codeBody,.o3BgMG_terminalBody,.o3BgMG_diffBody,.o3BgMG_readBody,.o3BgMG_imageBody,.o3BgMG_searchBody,.o3BgMG_webBody{margin:4px 0 4px 4px}.o3BgMG_searchRecovery{white-space:pre-wrap;overflow-wrap:anywhere;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary);margin:4px 0 4px 4px}.o3BgMG_imageLabel{overflow-wrap:anywhere;font:var(--dsw-font-sm-13);color:var(--dsw-alias-label-secondary);margin-bottom:4px}.o3BgMG_imageMeta{white-space:pre-wrap;overflow-wrap:anywhere;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary)}.o3BgMG_terminalBody{--dsl-terminal-font:var(--dsw-font-markdown-code-block-small);--dsl-terminal-line-height:18px;--dsl-terminal-output-max-height:224px;border:.5px solid var(--dsw-alias-border-l1)}.o3BgMG_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
1351
1418
  const tagId$2 = "@deepseek-ai/dsh-client-ui-tool/ToolRow.module.css";
1352
1419
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
1353
1420
  const tag = document.createElement("style");
@@ -1395,6 +1462,7 @@ window.__ModuleLoader__.load({
1395
1462
  /** Visually hidden run-state label for color-only running and settlement cues. */
1396
1463
  function stateStatus$1(state, t) {
1397
1464
  switch (state) {
1465
+ case "preparing": return t("row.preparing");
1398
1466
  case "running": return t("row.running");
1399
1467
  case "error": return t("row.failed");
1400
1468
  case "stopped": return t("row.stopped");
@@ -1403,6 +1471,7 @@ window.__ModuleLoader__.load({
1403
1471
  }
1404
1472
  /**
1405
1473
  * Render one localized tool summary and lazily mounted result card.
1474
+ * Preparation retains the icon, title, and optional tool-name summary without disclosure.
1406
1475
  * @param props - tool state, summary, output, and navigation callbacks.
1407
1476
  * @returns the tool disclosure.
1408
1477
  */
@@ -1424,7 +1493,7 @@ window.__ModuleLoader__.load({
1424
1493
  const inputRaw = bodyRaw ?? null;
1425
1494
  const outputText = output ?? null;
1426
1495
  const card = askQuestionBody ?? terminalBody ?? diffBody ?? readBody ?? imageBody ?? searchBody ?? webBody ?? detailsBody;
1427
- const expandable = inputRaw !== null || outputText !== null || card !== null;
1496
+ const expandable = state !== "preparing" && (inputRaw !== null || outputText !== null || card !== null);
1428
1497
  const open = expanded && expandable;
1429
1498
  const bodyText = (0, react.useMemo)(() => open && card === null && inputRaw !== null ? formatToolBody(variant, inputRaw) : null, [
1430
1499
  card,
@@ -1433,7 +1502,7 @@ window.__ModuleLoader__.load({
1433
1502
  variant
1434
1503
  ]);
1435
1504
  const status = stateStatus$1(state, t);
1436
- const running = state === "running";
1505
+ const running = state === "running" || state === "preparing";
1437
1506
  const normalSummary = terminalBody?.description ?? (open ? detailsBody?.expandedSummary ?? summary : summary);
1438
1507
  const summaryText = (state === "error" ? errorSummary ?? normalSummary : null) ?? normalSummary;
1439
1508
  const diffStat = (0, react.useMemo)(() => {
@@ -1550,6 +1619,7 @@ window.__ModuleLoader__.load({
1550
1619
  lang: "typescript",
1551
1620
  copyLabel: t("copy"),
1552
1621
  copiedLabel: t("copied"),
1622
+ toolbarLabels: codeToolbarLabels(t),
1553
1623
  className: ToolRow_module_css_default.codeBody
1554
1624
  })
1555
1625
  }), (cardBody !== null || outputText !== null) && (0, react_jsx_runtime.jsxs)("div", {
@@ -1651,6 +1721,7 @@ window.__ModuleLoader__.load({
1651
1721
  code: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutlineRegular, { size: 14 }),
1652
1722
  others: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkleRegular, { size: 14 })
1653
1723
  };
1724
+ /** @param props - current tool stage and locale. @returns its preparation or dispatched card. */
1654
1725
  function GenericToolCard({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
1655
1726
  const model = toolRowModel(toolName, block, cwd, home);
1656
1727
  const autoReview = model.autoReviewDenial === null ? null : localizeAutoReviewDenial(model.autoReviewDenial, t);
@@ -1701,16 +1772,38 @@ window.__ModuleLoader__.load({
1701
1772
  //#endregion
1702
1773
  //#region lib/types/client/tool/ToolCallTree.js
1703
1774
  /** Root/subcall Tool composition with one keyed atomic dispatch path. */
1704
- /** Resolve a Tool call's wire name from either lifecycle form. */
1705
- function callName(node) {
1706
- return "kind" in node ? node.call?.name ?? "" : node.name;
1775
+ function toolCallPhase(block) {
1776
+ if ("kind" in block) return {
1777
+ phase: "result",
1778
+ block
1779
+ };
1780
+ return block.phase === "preparing" ? {
1781
+ phase: "preparing",
1782
+ block
1783
+ } : {
1784
+ phase: "start",
1785
+ block
1786
+ };
1787
+ }
1788
+ /** Resolve a Tool call's wire name from its current stage. */
1789
+ function callName(call) {
1790
+ return call.phase === "result" ? call.block.call?.name ?? "" : call.block.name;
1707
1791
  }
1708
1792
  /** One atomic call dispatched through the Tool-owned keyed slot. */
1709
- const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, block, openFile, cwd, home, inspectCall, loadImage, useDisclosure, t, children }) {
1793
+ const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, call, assistant, openFile, cwd, home, inspectCall, loadImage, useDisclosure, t, children }) {
1794
+ const preparing = call.phase === "preparing";
1795
+ const hookContext = (0, react.useMemo)(() => ({
1796
+ callId,
1797
+ assistant: preparing ? assistant : void 0
1798
+ }), [
1799
+ assistant,
1800
+ callId,
1801
+ preparing
1802
+ ]);
1710
1803
  const owner = (0, react.useMemo)(() => ({
1711
1804
  callId,
1712
1805
  toolName,
1713
- block,
1806
+ ...call,
1714
1807
  openFile,
1715
1808
  cwd,
1716
1809
  home,
@@ -1722,7 +1815,7 @@ window.__ModuleLoader__.load({
1722
1815
  }), [
1723
1816
  callId,
1724
1817
  toolName,
1725
- block,
1818
+ call,
1726
1819
  openFile,
1727
1820
  cwd,
1728
1821
  home,
@@ -1730,7 +1823,7 @@ window.__ModuleLoader__.load({
1730
1823
  inspectCall,
1731
1824
  useDisclosure
1732
1825
  ]);
1733
- const autoReviewDenied = (0, react.useMemo)(() => toolRowModel(toolName, block).autoReviewDenial !== null, [toolName, block]);
1826
+ const autoReviewDenied = (0, react.useMemo)(() => call.phase === "result" && toolRowModel(toolName, call.block).autoReviewDenial !== null, [toolName, call]);
1734
1827
  return (0, react_jsx_runtime.jsxs)("div", {
1735
1828
  className: ToolCallTree_module_css_default.callRow,
1736
1829
  "data-chat-anchor-key": `call:${callId}`,
@@ -1740,6 +1833,7 @@ window.__ModuleLoader__.load({
1740
1833
  t
1741
1834
  }) : renderSlot("tool.call.toolview", owner, {
1742
1835
  entryKey: toolName,
1836
+ hookContext,
1743
1837
  fallback: (0, react_jsx_runtime.jsx)(GenericToolCard, {
1744
1838
  ...owner,
1745
1839
  t
@@ -1747,12 +1841,14 @@ window.__ModuleLoader__.load({
1747
1841
  }), children]
1748
1842
  });
1749
1843
  });
1750
- const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, cwd, home, openFile, inspectCall, loadImage, useDisclosure, t }) {
1844
+ const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, assistant, cwd, home, openFile, inspectCall, loadImage, useDisclosure, t }) {
1845
+ const call = (0, react.useMemo)(() => toolCallPhase(block), [block]);
1751
1846
  return (0, react_jsx_runtime.jsx)(ToolCall, {
1752
1847
  renderSlot,
1753
- callId: block.callId,
1754
- toolName: callName(block),
1755
- block,
1848
+ callId: call.block.callId,
1849
+ toolName: callName(call),
1850
+ call,
1851
+ assistant,
1756
1852
  openFile,
1757
1853
  cwd,
1758
1854
  home,
@@ -1760,12 +1856,13 @@ window.__ModuleLoader__.load({
1760
1856
  useDisclosure,
1761
1857
  loadImage,
1762
1858
  t,
1763
- children: block.subCalls.length > 0 ? (0, react_jsx_runtime.jsx)("div", {
1859
+ children: call.phase !== "preparing" && call.block.subCalls.length > 0 ? (0, react_jsx_runtime.jsx)("div", {
1764
1860
  className: ToolCallTree_module_css_default.subCalls,
1765
1861
  "data-subcalls": true,
1766
- children: block.subCalls.map((child) => (0, react_jsx_runtime.jsx)(ToolCallBranch, {
1862
+ children: call.block.subCalls.map((child) => (0, react_jsx_runtime.jsx)(ToolCallBranch, {
1767
1863
  renderSlot,
1768
1864
  block: child,
1865
+ assistant,
1769
1866
  cwd,
1770
1867
  home,
1771
1868
  openFile,
@@ -1785,10 +1882,11 @@ window.__ModuleLoader__.load({
1785
1882
  */
1786
1883
  function ToolCallTree({ renderSlot, node, cwd, openFile, inspectCall, loadImage, useDisclosure, useHostInfo, t }) {
1787
1884
  const home = useHostInfo((info) => info.home);
1788
- const block = node.data.root;
1885
+ const assistant = node.location.kind === "step" ? node.location.step.data.source("assistant-step") : void 0;
1789
1886
  return (0, react_jsx_runtime.jsx)(ToolCallBranch, {
1790
1887
  renderSlot,
1791
- block,
1888
+ block: node.data.root,
1889
+ assistant,
1792
1890
  cwd,
1793
1891
  home,
1794
1892
  openFile,
@@ -1799,6 +1897,27 @@ window.__ModuleLoader__.load({
1799
1897
  });
1800
1898
  }
1801
1899
  //#endregion
1900
+ //#region lib/types/client/tool/tool-call-arguments-partial.js
1901
+ /** Call-local argument subscription bound by the atomic Tool slot. */
1902
+ const subscribeEmpty = () => () => {};
1903
+ /**
1904
+ * Bind one call without subscribing until its component invokes the Hook.
1905
+ * @param _standard - framework-provided scope props.
1906
+ * @param context - the preparing call's Step source and identity.
1907
+ * @returns a Hook that reads only this call's raw argument prefix.
1908
+ */
1909
+ const bindToolCallArgumentsPartial = (_standard, context) => {
1910
+ const { assistant, callId } = context;
1911
+ const subscribe = assistant === void 0 ? subscribeEmpty : (listener) => assistant.subscribe(listener);
1912
+ const getSnapshot = () => {
1913
+ const block = assistant?.getSnapshot()?.blocks.find((candidate) => candidate.kind === "tool-call" && candidate.callId === callId);
1914
+ return block?.kind === "tool-call" ? block.argsRaw : "";
1915
+ };
1916
+ return function useToolCallArgumentsPartial() {
1917
+ return (0, react.useSyncExternalStore)(subscribe, getSnapshot);
1918
+ };
1919
+ };
1920
+ //#endregion
1802
1921
  //#region lib/types/client/locale.js
1803
1922
  /** Locale namespace supplied by the conversation owner to Tool renderers. */
1804
1923
  const CONVERSATION_NS = "conversation";
@@ -1896,7 +2015,7 @@ window.__ModuleLoader__.load({
1896
2015
  function AskQuestionRow({ toolName, block, inspect, useDisclosure, t }) {
1897
2016
  const model = toolRowModel(toolName, block);
1898
2017
  const code = "kind" in block ? block.error?.code : void 0;
1899
- const argsRaw = ("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "";
2018
+ const argsRaw = model.bodyRaw ?? "";
1900
2019
  let summary = model.summary;
1901
2020
  let state = model.state;
1902
2021
  let transcript = null;
@@ -1937,7 +2056,7 @@ window.__ModuleLoader__.load({
1937
2056
  variant: model.variant,
1938
2057
  toolName,
1939
2058
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutlineRegular, {}),
1940
- title: t("ask.rowTitle"),
2059
+ title: t(model.titleKey),
1941
2060
  summary,
1942
2061
  bodyRaw: transcript === null ? model.bodyRaw : null,
1943
2062
  output: transcript === null ? model.output : null,
@@ -1959,6 +2078,25 @@ window.__ModuleLoader__.load({
1959
2078
  }
1960
2079
  };
1961
2080
  //#endregion
2081
+ //#region lib/types/client/tool/components/PreparingToolRow.js
2082
+ /**
2083
+ * Render a non-expandable tool prefix with an optional preparation summary.
2084
+ * @param props - tool prefix and locale.
2085
+ * @returns the preparation row.
2086
+ */
2087
+ function PreparingToolRow({ toolName, useDisclosure, icon, title, summary = "", t }) {
2088
+ return (0, react_jsx_runtime.jsx)(ToolRow, {
2089
+ useDisclosure,
2090
+ t,
2091
+ variant: classifyTool(toolName),
2092
+ toolName,
2093
+ icon,
2094
+ title,
2095
+ summary,
2096
+ state: "preparing"
2097
+ });
2098
+ }
2099
+ //#endregion
1962
2100
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css.mjs
1963
2101
  const css = ".CY-8Ka_card{flex-direction:column;display:flex}.CY-8Ka_terminal{--dsl-terminal-font:var(--dsw-font-markdown-code-block-small);--dsl-terminal-line-height:18px;--dsl-terminal-output-max-height:224px;border:.5px solid var(--dsw-alias-border-l1);margin:4px 0 4px 4px}.CY-8Ka_ioCard{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small);border-radius:12px;flex-direction:column;margin:4px 0 4px 4px;display:flex}.CY-8Ka_ioSection{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:14px;max-height:150px;padding:12px 16px;display:grid;overflow-y:auto}.CY-8Ka_ioSection::-webkit-scrollbar-thumb{background-clip:padding-box;border:2px solid #0000;border-radius:6px}.CY-8Ka_ioSection::-webkit-scrollbar-track{margin:6px 0}.CY-8Ka_ioLabel{color:var(--dsw-alias-label-caption);align-self:start;position:sticky;top:0}.CY-8Ka_ioDivider{background:var(--dsw-alias-border-l2);flex:none;height:.5px}.CY-8Ka_ioText{white-space:pre-wrap;word-break:break-word;min-width:0;color:var(--dsw-alias-label-secondary)}.CY-8Ka_ioText[data-error]{color:var(--dsw-alias-state-error-primary)}.CY-8Ka_root[data-expandable]{cursor:pointer}.CY-8Ka_root{height:calc(24px + var(--dsh-content-font-delta,0px));align-items:center;min-width:0;display:flex}.CY-8Ka_leading{width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;margin-right:6px;display:inline-flex;position:relative}.CY-8Ka_leading svg:not([data-state]){width:calc(14px + var(--dsh-content-font-delta,0px));height:calc(14px + var(--dsh-content-font-delta,0px))}.CY-8Ka_chevron{color:var(--dsw-alias-label-secondary)}.CY-8Ka_iconIdle{opacity:1;transition:opacity .1s;display:inline-flex}.CY-8Ka_chevronHover{opacity:0;margin:auto;transition:opacity .1s;position:absolute;inset:0}.CY-8Ka_root:hover .CY-8Ka_iconIdle{opacity:0}.CY-8Ka_root:hover .CY-8Ka_chevronHover{opacity:1}.CY-8Ka_title{font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-secondary);flex:none;transition:color .1s}.CY-8Ka_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.CY-8Ka_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:var(--dsh-content-font-size-secondary,13px);line-height:calc(24px + var(--dsh-content-font-delta,0px));color:var(--dsw-alias-label-tertiary);flex:auto;transition:color .1s;overflow:hidden}.CY-8Ka_root:hover .CY-8Ka_title,.CY-8Ka_root:hover .CY-8Ka_summary:not(.CY-8Ka_errorSummary):not(.CY-8Ka_stoppedSummary){color:var(--dsw-alias-label-primary)}.CY-8Ka_errorSummary{color:var(--dsw-alias-state-error-primary)}.CY-8Ka_stoppedSummary{color:var(--dsw-alias-state-warn-label)}.CY-8Ka_bodyWrap{flex-direction:column;display:flex}.CY-8Ka_inspectButton{border:.5px solid var(--dsw-alias-border-l4);corner-shape:round;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-secondary);cursor:pointer;opacity:0;border-radius:999px;align-self:flex-start;align-items:center;gap:4px;margin:4px 0 2px 4px;padding:2px 8px;font-size:11px;line-height:16px;transition:opacity .1s;display:inline-flex}.CY-8Ka_card:hover .CY-8Ka_inspectButton,.CY-8Ka_inspectButton:focus-visible{opacity:1}.CY-8Ka_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}.CY-8Ka_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
1964
2102
  const tagId = "@deepseek-ai/dsh-client-ui-tool/bash-sample.module.css";
@@ -2008,7 +2146,15 @@ window.__ModuleLoader__.load({
2008
2146
  * @param props - tool call, Session sources, locale, and inspection callback.
2009
2147
  * @returns the Bash output row.
2010
2148
  */
2011
- const BashRow = (0, react.memo)(function BashRow({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }) {
2149
+ const BashRow = (0, react.memo)(function BashRow(props) {
2150
+ if (props.phase === "preparing") return (0, react_jsx_runtime.jsx)(PreparingToolRow, {
2151
+ ...props,
2152
+ icon: BASH_ICON,
2153
+ title: props.t(toolTitleKey(props.toolName))
2154
+ });
2155
+ return (0, react_jsx_runtime.jsx)(StartedBashRow, { ...props });
2156
+ });
2157
+ const StartedBashRow = (0, react.memo)(function StartedBashRow({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }) {
2012
2158
  const model = (0, react.useMemo)(() => toolRowModel(toolName, block), [toolName, block]);
2013
2159
  const cwd = useSessions((list) => list.byId[sessionId]?.cwd);
2014
2160
  const terminalModel = (0, react.useMemo)(() => terminalCardModel(block, cwd), [block, cwd]);
@@ -2136,10 +2282,25 @@ window.__ModuleLoader__.load({
2136
2282
  };
2137
2283
  //#endregion
2138
2284
  //#region lib/types/client/tool/toolviews/file-mutation-row.js
2285
+ const FILE_MUTATION_ICON = (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 });
2139
2286
  /**
2140
2287
  * Lets users expand an applied file diff and open the reported path.
2141
2288
  */
2142
- function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
2289
+ function FileMutationRow(props) {
2290
+ return props.phase === "preparing" ? (0, react_jsx_runtime.jsx)(PreparingFileMutationRow, { ...props }) : (0, react_jsx_runtime.jsx)(StartedFileMutationRow, { ...props });
2291
+ }
2292
+ function PreparingFileMutationRow({ toolName, useDisclosure, useToolCallArgumentsPartial, t }) {
2293
+ const raw = useToolCallArgumentsPartial();
2294
+ return (0, react_jsx_runtime.jsx)(PreparingToolRow, {
2295
+ toolName,
2296
+ useDisclosure,
2297
+ icon: FILE_MUTATION_ICON,
2298
+ title: t(toolTitleKey(toolName)),
2299
+ t,
2300
+ summary: t("tool.preparing.content", { kilobytes: Math.ceil(raw.length / 1024) })
2301
+ });
2302
+ }
2303
+ function StartedFileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
2143
2304
  const model = toolRowModel(toolName, block, cwd, home);
2144
2305
  const diff = diffCardModel(block);
2145
2306
  return (0, react_jsx_runtime.jsx)(ToolRow, {
@@ -2147,7 +2308,7 @@ window.__ModuleLoader__.load({
2147
2308
  t,
2148
2309
  variant: model.variant,
2149
2310
  toolName,
2150
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 }),
2311
+ icon: FILE_MUTATION_ICON,
2151
2312
  title: t(model.titleKey),
2152
2313
  summary: model.summary,
2153
2314
  output: model.output,
@@ -3485,51 +3646,22 @@ window.__ModuleLoader__.load({
3485
3646
  //#endregion
3486
3647
  //#region lib/types/client/tool/toolviews/details-row.js
3487
3648
  /** Keyed recorded-result rows sharing the compact detail body. */
3488
- const TITLE_KEYS = {
3489
- create_goal: "tool.title.createGoal",
3490
- get_goal: "tool.title.getGoal",
3491
- update_goal: "tool.title.updateGoal",
3492
- schedule_create: "tool.title.createSchedule",
3493
- schedule_list: "tool.title.listSchedules",
3494
- schedule_delete: "tool.title.deleteSchedule",
3495
- cordis_inspect_list: "tool.title.inspectProviders",
3496
- cordis_inspect_query: "tool.title.queryRuntime",
3497
- cordis_inspect_self: "tool.title.inspectPlugins",
3498
- workflow: "tool.title.workflow",
3499
- ralph: "tool.title.ralph",
3500
- session_event_read: "tool.title.readEvent",
3501
- session_event_search: "tool.title.searchEvents",
3502
- session_event_trace: "tool.title.traceEvent",
3503
- session_search: "tool.title.searchSessions",
3504
- session_trace: "tool.title.traceSession",
3505
- list_subagent_models: "tool.title.listModels",
3506
- subagent: "tool.title.subagent",
3507
- list_agents: "tool.title.listAgents",
3508
- send_message: "tool.title.sendMessage",
3509
- interrupt_agent: "tool.title.interruptAgent",
3510
- job_list: "tool.title.listJobs",
3511
- job_output: "tool.title.readJob",
3512
- job_kill: "tool.title.killJob",
3513
- terminal_open: "tool.title.openTerminal",
3514
- terminal_read: "tool.title.readTerminal",
3515
- terminal_list: "tool.title.listTerminals",
3516
- terminal_signal: "tool.title.signalTerminal",
3517
- terminal_close: "tool.title.closeTerminal",
3518
- lsp: "tool.title.lsp",
3519
- spawn_teammate: "tool.title.spawnTeammate",
3520
- team_task_create: "tool.title.createTeamTask",
3521
- team_task_get: "tool.title.getTeamTask",
3522
- team_task_update: "tool.title.updateTeamTask",
3523
- team_task_list: "tool.title.listTeamTasks",
3524
- wait_agent: "tool.title.waitAgent"
3525
- };
3526
3649
  const LSP_TITLE_KEYS = {
3527
3650
  goToDefinition: "tool.title.findDefinition",
3528
3651
  findReferences: "tool.title.findReferences",
3529
3652
  goToImplementation: "tool.title.findImplementation",
3530
3653
  hover: "tool.title.hoverSymbol"
3531
3654
  };
3655
+ /** Teammate-coordination tools presented with the two-person team icon. */
3656
+ const TEAMMATE_TOOLS = new Set([
3657
+ "spawn_teammate",
3658
+ "list_agents",
3659
+ "send_message",
3660
+ "interrupt_agent",
3661
+ "wait_agent"
3662
+ ]);
3532
3663
  function detailIcon(toolName) {
3664
+ if (TEAMMATE_TOOLS.has(toolName)) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconUsersOutlineRegular, { size: 14 });
3533
3665
  if (toolName.startsWith("schedule_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconClockOutlineRegular, { size: 14 });
3534
3666
  if (toolName.endsWith("_goal")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGoalOutlineRegular, { size: 14 });
3535
3667
  if (toolName.startsWith("cordis_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCordisPluginOutlineRegular, {});
@@ -3553,7 +3685,7 @@ window.__ModuleLoader__.load({
3553
3685
  locale
3554
3686
  ]);
3555
3687
  const operation = toolName === "lsp" ? parsedToolCall(block)?.args.operation : void 0;
3556
- const titleKey = typeof operation === "string" && Object.hasOwn(LSP_TITLE_KEYS, operation) ? LSP_TITLE_KEYS[operation] : Object.hasOwn(TITLE_KEYS, toolName) ? TITLE_KEYS[toolName] : model.titleKey;
3688
+ const titleKey = typeof operation === "string" && Object.hasOwn(LSP_TITLE_KEYS, operation) ? LSP_TITLE_KEYS[operation] : model.titleKey;
3557
3689
  return (0, react_jsx_runtime.jsx)(ToolRow, {
3558
3690
  useDisclosure,
3559
3691
  t,
@@ -3960,6 +4092,7 @@ window.__ModuleLoader__.load({
3960
4092
  return typeof value === "object" && value !== null;
3961
4093
  }
3962
4094
  function summarize(argsRaw, t) {
4095
+ if (argsRaw === null) return null;
3963
4096
  let parsed;
3964
4097
  try {
3965
4098
  parsed = JSON.parse(argsRaw);
@@ -3990,7 +4123,7 @@ window.__ModuleLoader__.load({
3990
4123
  t
3991
4124
  ]);
3992
4125
  const model = toolRowModel(toolName, block);
3993
- const summary = summarize(("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "", t) ?? {
4126
+ const summary = summarize(model.bodyRaw, t) ?? {
3994
4127
  text: model.summary,
3995
4128
  extra: 0
3996
4129
  };
@@ -4000,7 +4133,7 @@ window.__ModuleLoader__.load({
4000
4133
  variant: model.variant,
4001
4134
  toolName,
4002
4135
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutlineRegular, {}),
4003
- title: t("todo.rowTitle"),
4136
+ title: t(model.titleKey),
4004
4137
  summary: summary.text,
4005
4138
  summarySuffix: [diff?.summary, summary.extra > 0 ? `+${summary.extra}` : null].filter((part) => part !== null && part !== void 0).join(" · ") || null,
4006
4139
  bodyRaw: model.bodyRaw,
@@ -4090,7 +4223,8 @@ window.__ModuleLoader__.load({
4090
4223
  locale: CONVERSATION_NS,
4091
4224
  children: { "tool.call.toolview": {
4092
4225
  kind: "keyed",
4093
- scope: "session"
4226
+ scope: "session",
4227
+ inject: { hooks: { toolCallArgumentsPartial: bindToolCallArgumentsPartial } }
4094
4228
  } },
4095
4229
  inject: toolInject
4096
4230
  }, ToolCallTree));
@@ -1,7 +1,7 @@
1
1
  /** Tool UI slot declarations and their composed component props. */
2
- import type { HostObservable, InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { HostObservable, InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime, SlotHookFactory } from '@deepseek-ai/dsh-client-ui-slots';
3
3
  import type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client';
4
- import type { OpenFileOptions, ToolCallBlock, UseDisclosure } from '@deepseek-ai/dsh-client-ui-chat/client';
4
+ import type { AssistantChatData, OpenFileOptions, PreparingToolCall, StartedToolCall, ToolResultNode, UseDisclosure } from '@deepseek-ai/dsh-client-ui-chat/client';
5
5
  import type { MessageImageLoader, MessageImageSource } from '@deepseek-ai/dsh-client-ui-conversation/client';
6
6
  declare module '@deepseek-ai/dsh-client-ui-slots' {
7
7
  interface SlotMap {
@@ -12,12 +12,15 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
12
12
  *
13
13
  * Registering an occupied key replaces its view; unclaimed keys use the
14
14
  * generic row. The owner supplies the call identity and frozen running
15
- * or settled node through ToolCallOwnerProps.
15
+ * or settled node through explicit phase props. Preparing blocks have no dispatched
16
+ * arguments; useToolCallArgumentsPartial optionally subscribes to their raw prefix.
16
17
  */
17
18
  'tool.call.toolview': {
18
19
  kind: 'keyed';
19
20
  scope: 'session';
20
21
  owner: ToolCallOwnerProps;
22
+ hookContext: ToolCallHookContext;
23
+ inject: ToolCallInjected;
21
24
  };
22
25
  /**
23
26
  * Durable images of a settled image-bearing Tool call, rendered through
@@ -39,6 +42,20 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
39
42
  };
40
43
  }
41
44
  }
45
+ /** Subscribe to this preparing call's raw argument prefix; other phases return an empty string. */
46
+ export type UseToolCallArgumentsPartial = () => string;
47
+ /** Call-local sources supplied by the Tool tree to the slot's Hook binding. */
48
+ export interface ToolCallHookContext {
49
+ readonly callId: string;
50
+ /** This call's Step source, present only while preparing. */
51
+ readonly assistant: HostObservable<Readonly<AssistantChatData> | undefined> | undefined;
52
+ }
53
+ /** Framework-bound subscriptions available to atomic Tool views on demand. */
54
+ export interface ToolCallInjected {
55
+ hooks: {
56
+ toolCallArgumentsPartial: SlotHookFactory<'tool.call.toolview', UseToolCallArgumentsPartial>;
57
+ };
58
+ }
42
59
  /** Owner currency of the Tool image gallery slot: references plus the loader. */
43
60
  export interface ToolImagesOwnerProps {
44
61
  /** Durable references or submission-echo previews in result order. */
@@ -49,37 +66,43 @@ export interface ToolImagesOwnerProps {
49
66
  align: 'start' | 'end';
50
67
  }
51
68
  /** Standard owner currency supplied to every atomic Tool view. */
52
- export interface ToolCallOwnerProps {
53
- /** Stable injected Hook; each invocation owns its open state and subscribes to enclosing-Turn resets. */
69
+ export interface ToolCallCommonProps {
70
+ /** Stable Hook; each invocation owns its open state and subscribes to enclosing-Turn resets. */
54
71
  useDisclosure: UseDisclosure;
55
- /** Tool call identity, stable across running and settled forms. */
72
+ /** Call identity, stable across all stages. */
56
73
  callId: string;
57
74
  /** Wire Tool name and keyed dispatch value. */
58
75
  toolName: string;
59
- /** Frozen running call or settled result node. */
60
- block: ToolCallBlock;
61
76
  /** Session workspace root for relative summaries. */
62
77
  cwd?: string | undefined;
63
78
  /** Host account home; POSIX home-rooted summaries display as `~`. */
64
79
  home?: string | undefined;
65
- /**
66
- * Open a Tool argument path. A view that knows which line the call was about
67
- * passes it, and the opened surface lands there.
68
- */
80
+ /** Open an argument path at its optional requested line. */
69
81
  openFile: (path: string, options?: OpenFileOptions) => void;
70
- /**
71
- * Session-authorized image loader for the `tool.call.images` slot, supplied
72
- * by the chat node that owns this call. A composed chat node always
73
- * supplies it (`ChatNodeOwnerProps.loadImage` is required), so the tool
74
- * layer never imports an attachment implementation nor handles URL
75
- * authorization.
76
- */
82
+ /** Chat-supplied, session-authorized loader for durable images; Tool views do not manage attachment URLs. */
77
83
  loadImage: MessageImageLoader;
78
84
  /** Inspect this call in the trajectory view when available. */
79
85
  inspect?: (() => void) | undefined;
80
86
  }
87
+ /** Stage-specific tool data; only start/result expose the dispatched call material. */
88
+ export type ToolCallPhaseProps = {
89
+ readonly phase: 'preparing';
90
+ readonly block: PreparingToolCall;
91
+ } | {
92
+ readonly phase: 'start';
93
+ readonly block: StartedToolCall;
94
+ } | {
95
+ readonly phase: 'result';
96
+ readonly block: ToolResultNode;
97
+ };
98
+ /** Common owner callbacks and the data admitted at the current tool stage. */
99
+ export type ToolCallOwnerProps = ToolCallCommonProps & ToolCallPhaseProps;
81
100
  /** Full props of a registered atomic Tool view. */
82
101
  export type ToolCallViewProps = PropsRuntime<'tool.call.toolview'>;
102
+ /** Existing argument/result business components exclude the preparation stage. */
103
+ export type StartedToolCallViewProps = Exclude<ToolCallViewProps, {
104
+ readonly phase: 'preparing';
105
+ }>;
83
106
  /** Injected Host description for POSIX home-path display. */
84
107
  export type ToolHostInfoInjected = {
85
108
  hooks: {
@@ -92,6 +115,6 @@ export type ToolHostInfoInjected = {
92
115
  hostInfo: HostObservable<RemoteHostFacts>;
93
116
  };
94
117
  };
95
- /** Full props of the Tool call-tree renderer registered as a `tool-call` Chat Node. */
118
+ /** Full props of the Tool call-tree renderer registered as a tool-call Chat Node. */
96
119
  export type ToolTreeProps = PropsRuntime<'conversation.chat.node', 'tool-call'> & PropsRenderSlots<'tool.call.toolview'> & PropsLocale<'conversation'> & InjectFace<ToolHostInfoInjected>;
97
120
  //# sourceMappingURL=slots.d.ts.map
@@ -1,4 +1,4 @@
1
1
  /** Browser Tool plugin: whole-call composition and keyed atomic Tool views. */
2
2
  export { apply, inject } from './apply.ts';
3
- export type { ToolCallOwnerProps, ToolCallViewProps, ToolHostInfoInjected, ToolTreeProps, } from './contract/slots.ts';
3
+ export type { StartedToolCallViewProps, ToolCallCommonProps, ToolCallOwnerProps, ToolCallPhaseProps, ToolCallViewProps, ToolCallHookContext, ToolCallInjected, ToolHostInfoInjected, ToolTreeProps, UseToolCallArgumentsPartial, } from './contract/slots.ts';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,19 @@
1
+ /** Tool-owned non-expandable chrome without dispatched argument material. */
2
+ import type { ReactNode } from 'react';
3
+ import type { ToolCallViewProps } from '../../contract/slots.ts';
4
+ import { type ToolRowProps } from './ToolRow.tsx';
5
+ /** Inputs contain a tool-owned icon/title and no expandable body. */
6
+ type PreparingToolRowProps = Pick<ToolCallViewProps, 'toolName' | 'useDisclosure'> & {
7
+ readonly icon: ReactNode;
8
+ readonly title: string;
9
+ readonly summary?: string;
10
+ readonly t: ToolRowProps['t'];
11
+ };
12
+ /**
13
+ * Render a non-expandable tool prefix with an optional preparation summary.
14
+ * @param props - tool prefix and locale.
15
+ * @returns the preparation row.
16
+ */
17
+ export declare function PreparingToolRow({ toolName, useDisclosure, icon, title, summary, t }: PreparingToolRowProps): import("react").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=PreparingToolRow.d.ts.map
@@ -78,6 +78,7 @@ export interface ToolRowProps {
78
78
  }
79
79
  /**
80
80
  * Render one localized tool summary and lazily mounted result card.
81
+ * Preparation retains the icon, title, and optional tool-name summary without disclosure.
81
82
  * @param props - tool state, summary, output, and navigation callbacks.
82
83
  * @returns the tool disclosure.
83
84
  */
@@ -1,7 +1,13 @@
1
1
  /** Localized copy adapters for Cordis-free UI primitives used by Tool cards. */
2
- import type { DiffBlockLabels, MarkdownLabels, ReadBlockLabels, SearchBlockLabels, WebBlockLabels } from '@deepseek-ai/dsh-client-ui-primitives';
2
+ import type { CodeToolbarLabels, DiffBlockLabels, MarkdownLabels, ReadBlockLabels, SearchBlockLabels, WebBlockLabels } from '@deepseek-ai/dsh-client-ui-primitives';
3
3
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
4
4
  type T = TranslateNS<'conversation'>;
5
+ /**
6
+ * Localize the shared code-card toolbar.
7
+ * @param t - Conversation locale seat.
8
+ * @returns Language fallback and wrapping actions.
9
+ */
10
+ export declare function codeToolbarLabels(t: T): CodeToolbarLabels;
5
11
  /**
6
12
  * Build localized Markdown chrome labels.
7
13
  * @param t - Conversation locale seat.
@@ -1,5 +1,6 @@
1
1
  /** Shared narrowing for raw Tool call and result fields consumed by card models. */
2
- import type { ToolCallBlock, ToolResultNode } from '@deepseek-ai/dsh-client-ui-chat/client';
2
+ import type { ToolResultNode } from '@deepseek-ai/dsh-client-ui-chat/client';
3
+ import type { ToolCallBlock } from './tool-call-model.ts';
3
4
  /** A parsed, in-window Tool call whose arguments are a JSON object. */
4
5
  export interface ParsedToolCall {
5
6
  name: string;
@@ -7,8 +8,8 @@ export interface ParsedToolCall {
7
8
  }
8
9
  /**
9
10
  * Parse the call head paired with one immutable Tool block.
10
- * @param block - running or settled Tool block.
11
- * @returns the Tool name and object arguments, or null when the call head or valid JSON object is unavailable.
11
+ * @param block - preparing, dispatched, or settled Tool block.
12
+ * @returns the Tool name and object arguments, or null during preparation or when valid arguments are unavailable.
12
13
  */
13
14
  export declare function parsedToolCall(block: ToolCallBlock): ParsedToolCall | null;
14
15
  /**
@@ -1,5 +1,5 @@
1
1
  /** Todo changes relative to the preceding recorded write. */
2
- import type { ToolCallBlock } from '@deepseek-ai/dsh-client-ui-chat/client';
2
+ import type { ToolCallBlock } from './tool-call-model.ts';
3
3
  import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
4
4
  import type { ToolDetailsModel } from '../components/ToolDetails.tsx';
5
5
  import type { TodoBaseline } from './todo-history.ts';
@@ -11,13 +11,13 @@ export type { ToolCallBlock } from '@deepseek-ai/dsh-client-ui-chat/client';
11
11
  /** Tool-call row variants selected by the generic atomic renderer. */
12
12
  export type ToolRowVariant = 'search' | 'read' | 'bash' | 'write' | 'edit' | 'code' | 'others';
13
13
  /** Row lifecycle state used by summary styling and accessible status text. */
14
- export type ToolRowState = 'running' | 'ok' | 'error' | 'stopped';
14
+ export type ToolRowState = 'preparing' | 'running' | 'ok' | 'error' | 'stopped';
15
15
  /** Locale-neutral structured fact consumed only by the user-facing Tool row. */
16
16
  export interface AutoReviewDenial {
17
17
  /** Raw persisted reviewer reason; display normalization happens at render time. */
18
18
  reason: string | null;
19
19
  }
20
- type ToolTitleKey = Extract<LocaleKeysOf<'conversation'>, `tool.title.${string}`>;
20
+ type ToolTitleKey = Extract<LocaleKeysOf<'conversation'>, `tool.title.${string}` | 'ask.rowTitle' | 'todo.rowTitle'>;
21
21
  /** Locale key per generic row variant. */
22
22
  export declare const VARIANT_TITLE_KEYS: {
23
23
  readonly search: "tool.title.search";
@@ -34,10 +34,17 @@ export declare const VARIANT_TITLE_KEYS: {
34
34
  * @returns matching variant, others when unknown.
35
35
  */
36
36
  export declare function classifyTool(toolName: string): ToolRowVariant;
37
+ /**
38
+ * Select a tool-owned or generic title without reading arguments.
39
+ * @param toolName - wire tool name.
40
+ * @returns the localized title key.
41
+ */
42
+ export declare function toolTitleKey(toolName: string): ToolTitleKey;
37
43
  /** Everything ToolRow needs, derived once from the frozen slice. */
38
44
  export interface ToolRowModel {
39
45
  variant: ToolRowVariant;
40
46
  titleKey: ToolTitleKey;
47
+ /** Generic rows retain the wire tool name; available arguments append their summary. */
41
48
  summary: string;
42
49
  /**
43
50
  * Filesystem path from args (`path` / `file_path`) when the row is a file
@@ -73,7 +80,7 @@ export declare function formatToolBody(variant: ToolRowVariant, argsRaw: string)
73
80
  /**
74
81
  * Derive the full row model from a frozen call slice.
75
82
  * @param toolName - wire tool name (dispatch-supplied; survives windowless results).
76
- * @param block - RunningToolCall or ToolResultNode off the snapshot caches.
83
+ * @param block - preparing call, dispatched call, or result from the snapshot.
77
84
  * @param cwd - session workspace root; workspace-rooted path summaries display relative to it.
78
85
  * @param home - host account home; a leftover POSIX home path displays as `~`.
79
86
  * @returns the row model.
@@ -0,0 +1,9 @@
1
+ import type { ToolCallInjected } from '../contract/slots.ts';
2
+ /**
3
+ * Bind one call without subscribing until its component invokes the Hook.
4
+ * @param _standard - framework-provided scope props.
5
+ * @param context - the preparing call's Step source and identity.
6
+ * @returns a Hook that reads only this call's raw argument prefix.
7
+ */
8
+ export declare const bindToolCallArgumentsPartial: ToolCallInjected['hooks']['toolCallArgumentsPartial'];
9
+ //# sourceMappingURL=tool-call-arguments-partial.d.ts.map
@@ -1,7 +1,8 @@
1
1
  import type { ToolCallOwnerProps, ToolTreeProps } from '../../contract/slots.ts';
2
2
  /** Card props: the owner payload plus the render site's locale seat (plain prop). */
3
- export interface GenericToolCardProps extends ToolCallOwnerProps {
3
+ export type GenericToolCardProps = ToolCallOwnerProps & {
4
4
  t: ToolTreeProps['t'];
5
- }
5
+ };
6
+ /** @param props - current tool stage and locale. @returns its preparation or dispatched card. */
6
7
  export declare function GenericToolCard({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }: GenericToolCardProps): import("react").JSX.Element;
7
8
  //# sourceMappingURL=GenericToolCard.d.ts.map
@@ -7,7 +7,7 @@ type BashRowProps = ToolCallViewProps & PropsLocale<'conversation'>;
7
7
  * @param props - tool call, Session sources, locale, and inspection callback.
8
8
  * @returns the Bash output row.
9
9
  */
10
- export declare const BashRow: import("react").MemoExoticComponent<({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }: BashRowProps) => import("react").JSX.Element>;
10
+ export declare const BashRow: import("react").MemoExoticComponent<(props: BashRowProps) => import("react").JSX.Element>;
11
11
  /** Registers the standalone Bash conversation-row sample. */
12
12
  export declare const bashToolviewSample: {
13
13
  name: string;
@@ -1,16 +1,18 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
2
  import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
3
3
  import type { ToolCallViewProps } from '../../contract/slots.ts';
4
+ type DetailsRowProps = ToolCallViewProps & PropsLocale<'conversation'>;
4
5
  /**
5
6
  * Present recorded entities, receipts, and report fields in the existing expandable row.
6
7
  * @param props - Tool call, row actions, and locale supplied by the keyed slot.
7
8
  * @returns A Tool row with structured details or generic input/output.
8
9
  */
9
- export declare function DetailsRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }: ToolCallViewProps & PropsLocale<'conversation'>): import("react").JSX.Element;
10
+ export declare function DetailsRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }: DetailsRowProps): import("react").JSX.Element;
10
11
  /** Register recorded-result details through the standard atomic Tool slot. */
11
12
  export declare const detailsToolview: {
12
13
  name: string;
13
14
  inject: string[];
14
15
  apply(ctx: Context): void;
15
16
  };
17
+ export {};
16
18
  //# sourceMappingURL=details-row.d.ts.map
@@ -5,7 +5,7 @@ type FileMutationRowProps = ToolCallViewProps & PropsLocale<'conversation'>;
5
5
  /**
6
6
  * Lets users expand an applied file diff and open the reported path.
7
7
  */
8
- export declare function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }: FileMutationRowProps): import("react").JSX.Element;
8
+ export declare function FileMutationRow(props: FileMutationRowProps): import("react").JSX.Element;
9
9
  /** Registers the edit and write conversation rows. */
10
10
  export declare const fileMutationToolview: {
11
11
  name: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-tool",
3
3
  "description": "Client Tool call-tree renderer and keyed per-tool presentation slot",
4
- "version": "0.1.7-alpha.1",
4
+ "version": "0.1.7-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "license": "MIT",
40
40
  "peerDependencies": {
41
- "@deepseek-ai/cordis": "^4.0.3"
41
+ "@deepseek-ai/cordis": "~4.0.4"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@testing-library/react": "^16.1.0",
@@ -46,31 +46,32 @@
46
46
  "react": "^18.2.0",
47
47
  "react-dom": "^18.2.0",
48
48
  "clsx": "^2.0.0",
49
- "@deepseek-ai/dsh-spill-policy": "^0.1.7-alpha.1",
50
- "@deepseek-ai/dsh-agent": "^0.1.7-alpha.1",
51
- "@deepseek-ai/dsh-llm": "^0.1.7-alpha.1",
52
- "@deepseek-ai/dsh-session": "^0.1.7-alpha.1",
53
- "@deepseek-ai/dsh-system-prompt": "^0.1.7-alpha.1",
54
- "@deepseek-ai/dsh-tools": "^0.1.7-alpha.1",
55
- "@deepseek-ai/dsh-tool-jobs": "^0.1.7-alpha.1",
56
- "@deepseek-ai/dsh-tool-session-query": "^0.1.7-alpha.1",
57
- "@deepseek-ai/dsh-spill": "^0.1.7-alpha.1",
58
- "@deepseek-ai/cordis": "^4.0.3",
59
- "@deepseek-ai/dsh-api-remotes": "^0.1.7-alpha.1",
60
- "@deepseek-ai/dsh-client-connection": "^0.1.7-alpha.1",
61
- "@deepseek-ai/dsh-client-locale": "^0.1.7-alpha.1",
62
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.7-alpha.1",
63
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-alpha.1",
64
- "@deepseek-ai/dsh-tool-terminal": "^0.1.7-alpha.1",
65
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-alpha.1",
66
- "@deepseek-ai/dsh-client-ui-chat": "^0.1.7-alpha.1",
67
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-alpha.1",
68
- "@deepseek-ai/dsh-client-ui-session": "^0.1.7-alpha.1",
69
- "@deepseek-ai/dsh-util-workspace-path": "^0.1.7-alpha.1",
70
- "@deepseek-ai/dsh-attachment": "^0.1.7-alpha.1",
71
- "@deepseek-ai/dsh-ptc-runtime": "^0.1.7-alpha.1",
72
- "@deepseek-ai/dsh-api-workspace-controller": "^0.1.7-alpha.1",
73
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-alpha.1"
49
+ "@deepseek-ai/dsh-llm": "0.1.7-rc.1",
50
+ "@deepseek-ai/dsh-agent": "0.1.7-rc.1",
51
+ "@deepseek-ai/dsh-spill-policy": "0.1.7-rc.1",
52
+ "@deepseek-ai/dsh-system-prompt": "0.1.7-rc.1",
53
+ "@deepseek-ai/dsh-tools": "0.1.7-rc.1",
54
+ "@deepseek-ai/dsh-session": "0.1.7-rc.1",
55
+ "@deepseek-ai/dsh-tool-terminal": "0.1.7-rc.1",
56
+ "@deepseek-ai/dsh-spill": "0.1.7-rc.1",
57
+ "@deepseek-ai/cordis": "~4.0.4",
58
+ "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.1",
59
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.1",
60
+ "@deepseek-ai/dsh-client-locale": "0.1.7-rc.1",
61
+ "@deepseek-ai/dsh-client-test-runtime": "0.1.7-rc.1",
62
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.1",
63
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.1",
64
+ "@deepseek-ai/dsh-api-workspace-controller": "0.1.7-rc.1",
65
+ "@deepseek-ai/dsh-tool-jobs": "0.1.7-rc.1",
66
+ "@deepseek-ai/dsh-tool-session-query": "0.1.7-rc.1",
67
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.1",
68
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
69
+ "@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.1",
70
+ "@deepseek-ai/dsh-attachment": "0.1.7-rc.1",
71
+ "@deepseek-ai/dsh-ptc-runtime": "0.1.7-rc.1",
72
+ "@deepseek-ai/dsh-util-workspace-path": "0.1.7-rc.1",
73
+ "@deepseek-ai/dsh-client-ui-chat": "0.1.7-rc.1",
74
+ "@deepseek-ai/dsh-token-meter": "0.1.7-rc.1"
74
75
  },
75
76
  "files": [
76
77
  "lib/index.js",