@deepseek-ai/dsh-client-ui-tool 0.2.0-rc.2 → 0.2.1-alpha.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
@@ -15,23 +15,23 @@
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-client-ui-tool/use-this-package:
18
- en: be2bc859e0d64fe5
19
- zh: d51a35fb36675dd3
18
+ en: 3b9b719ca4e4cc62
19
+ zh: a14b63a16476d684
20
20
  /deepseek-ai-dsh-client-ui-tool/use-this-package/registering-a-business-tool-view:
21
- en: 5332d87e76037f07
22
- zh: db5d06e7e46b8429
21
+ en: f19e077425b8f312
22
+ zh: 24d88794be439302
23
23
  /deepseek-ai-dsh-client-ui-tool/use-this-package/built-in-views:
24
- en: 5bdd3af9df9b2b7c
25
- zh: ff3517e71a2be98a
24
+ en: 2e06c7de0f7f0139
25
+ zh: 9ec0f94c2d7d60bf
26
26
  /deepseek-ai-dsh-client-ui-tool/understand-the-implementation:
27
27
  en: 00bc7b0c84edc603
28
28
  zh: 1cfcf5b435248a91
29
29
  /deepseek-ai-dsh-client-ui-tool/understand-the-implementation/rendering-contract:
30
- en: 2959b10b01e08a7b
31
- zh: 7084ca22650cbb5b
30
+ en: 672e63b2f92e689b
31
+ zh: ba950ecb480325a6
32
32
  /deepseek-ai-dsh-client-ui-tool/understand-the-implementation/cards:
33
- en: 936ae18b0927971f
34
- zh: 170fb021d250fb58
33
+ en: d202f30c846543d2
34
+ zh: a84656956c66a574
35
35
  /deepseek-ai-dsh-client-ui-tool/understand-the-implementation/declared-optional-capabilities:
36
36
  en: c1926deb4e5f3734
37
37
  zh: c5845f465b94a459
@@ -48,5 +48,5 @@
48
48
  en: 7475317a656f1d11
49
49
  zh: 787f10cc0f2c586e
50
50
  /deepseek-ai-dsh-client-ui-tool/known-limitations-and-deferred-work/dev-note:
51
- en: 0fdeab2e4db0261f
52
- zh: 156d2b2952cf112e
51
+ en: e67f633dc6fe7773
52
+ zh: 3bb0c20c93f16f98
package/README.md CHANGED
@@ -29,7 +29,7 @@ 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.
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>`. Read/write/edit show an openable path once `file_path` closes and decodes without errors; write/edit show `NKB` after that path once content arrives, retaining it during execution and after success, before any diff totals. N rounds the decoded input's UTF-16 length up in units of 1024, summing old and new text for edit; it is not file bytes. Error and stopped rows omit the size and diff totals. Command rows show the streamed description. `tool/call` enables the existing call presentation; completing an argument block alone does not start execution.
33
33
 
34
34
  ### Registering a business tool view
35
35
 
@@ -43,11 +43,13 @@ ctx.slots.inject('tool.call.toolview', () =>
43
43
  }, BusinessToolRow))
44
44
  ```
45
45
 
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.
46
+ The owner payload is `ToolCallOwnerProps`: `callId`, `toolName`, the `phase` discriminant and its 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.
47
47
 
48
48
  ### Built-in views
49
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`.
50
+ Every registered view receives the explicit `preparing`, `start`, and `result` props declared in [the Tool slot types](src/client/contract/slots.ts). All blocks expose `name` and a lazy `args` reader; legacy `argsRaw` and result `call` fields remain available. The 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. Write/edit and Bash share their component across stages. Custom renderers may retain separate preparation branches; argument-dependent components accept `StartedToolCallViewProps`.
51
+
52
+ File-tool rows prefer a complete `file_path`; other generic rows, including search and unregistered tools, prefer a non-empty `description` before their variant-specific argument fallback. Read `args` during rendering or view construction: a preparing reader grows in place, and only previously observed answer changes trigger subsequent block publication.
51
53
 
52
54
  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 atomic rows share one left-to-right highlight across their titles, separators, summaries, and suffixes, while settled rows stay static. 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. `ui-skill` demonstrates a business-owned registration for `skill`.
53
55
 
@@ -72,7 +74,7 @@ The package realizes one dispatch rule: atomic Tool views are keyed by wire Tool
72
74
  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.
73
75
 
74
76
 
75
- 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.
77
+ Tool Definitions own the [lazy argument view](../../util/values/README.md). Rows choose their fields and update granularity through its readers, without a separate subscription or registration. Deltas append without scanning; frame-batched publication refreshes observed answers and replaces the block only when an answer changes. Card models that need dispatched arguments continue to read `argsRaw`.
76
78
 
77
79
  ### Cards
78
80
 
@@ -83,7 +85,7 @@ Chat diff cards keep nine rows before folding, enough for a file header, one rem
83
85
 
84
86
  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.
85
87
 
86
- Recorded tool details cover goal and schedule tools, Cordis inspection, workflow and Ralph reports, Session event/search/trace queries, agent and teammate controls, background jobs, persistent terminals, and LSP navigation. These expanded bodies read successful logged results, preserve generic input/output for failures or unsupported data, and keep Inspect available. Dates include the viewer's time zone, and statuses reflect the call result rather than current session state. Session traces preserve descendant indentation. LSP results open filesystem paths through the Host callback and display other URIs as text. The browser adapter consumes recorded producer text and JSON; Host service objects and presenter callbacks do not cross into the Client. [Compact tool details](../../../.agents/notes/implemented/architecture/2026-09-10-compact-tool-details.md) records the presentation trade-offs.
88
+ Recorded tool details cover goal and schedule tools, Cordis inspection, workflow and Ralph reports, Session event/search/trace queries, agent and teammate controls, background jobs, persistent terminals, and LSP navigation. These expanded bodies read successful logged results, preserve generic input/output for failures or unsupported data, and keep Inspect available. Dates include the viewer's time zone, and statuses reflect the call result rather than current session state. Session traces preserve descendant indentation. LSP results open filesystem paths through the Host callback and display other URIs as text. The browser adapter consumes recorded producer text and JSON; Host service objects and presenter callbacks do not cross into the Client.
87
89
 
88
90
  Expanded status dots and labels use static semantic colors. Receipt and job-output headers keep neutral text and omit the status while expanded. An interruption receipt confirms only that interruption was requested.
89
91
 
@@ -142,5 +144,3 @@ These limits define the dispatch depth and the view ownership; they are current
142
144
  None.
143
145
 
144
146
  </details>
145
-
146
- **Runtime invariant:** No companion is published. Tool composition is browser-only and contributes no events or cross-plugin mutable state; slot ownership is checked by ui-slots.
package/README.zh.md CHANGED
@@ -29,7 +29,7 @@ kind: "package-reference"
29
29
 
30
30
  共享工具行和 Bash 行的失败、停止摘要在悬停时仍保留错误色和警告色;只有不处于这两种状态的摘要会在悬停时加深。
31
31
 
32
- 派发前,模型已给出名称的调用显示为不可展开的一行,使用工具自己的图标与标题。通用行显示为`工具调用 · <工具名>`。准备阶段不提供完整参数、文件链接、结果或依赖参数的交互。write/edit 的摘要显示「正在准备内容 NKB」;N 为 `Math.ceil(raw.length / 1024)`,是原始参数字符串长度的整数近似值,不是文件字节数。`tool/call` 才启用既有调用展示;参数块结束本身不代表开始执行。
32
+ 派发前,模型已给出名称的调用显示为不可展开的一行,使用工具自己的图标与标题。通用行显示为 `工具调用 · <工具名>`。read/write/edit 在 `file_path` 闭合且解码无误后显示可打开的路径;write/edit 从内容到达起在该路径后显示 `NKB`,执行中和成功后仍保留,位于差异统计之前。N 按解码后输入的 UTF-16 长度除以 1024 向上取整,edit 合计新旧文本长度;它不是文件字节数。失败和停止的行省略大小与差异统计。命令行显示流入中的描述。`tool/call` 才启用既有调用展示;参数块结束本身不代表开始执行。
33
33
 
34
34
  ### 注册业务工具视图
35
35
 
@@ -43,11 +43,13 @@ ctx.slots.inject('tool.call.toolview', () =>
43
43
  }, BusinessToolRow))
44
44
  ```
45
45
 
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 节点或运行时服务。
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 节点或运行时服务。
47
47
 
48
48
  ### 内置视图
49
49
 
50
- 每个注册视图都接收[工具 slot 类型](src/client/contract/slots.ts)声明的显式 `preparing`、`start` 和 `result` props。通用行在三个阶段使用同一个 `ToolRow`。行模型统一选择标题,并组合通用工具名前缀与已有参数摘要,不按生命周期阶段改变前缀;专用标题不附带英文名。准备阶段的共享参数解析入口直接返回无调用,不解析部分 JSON。write/edit 将准备态和派发后阶段拆成两个组件,只有准备态组件调用 `useToolCallArgumentsPartial`,start 与 result 共用派发后组件。Bash、Skill、Cordis 等自定义 renderer 分别处理准备态,其依赖参数的组件接收 `StartedToolCallViewProps`。
50
+ 每个注册视图都接收[工具 slot 类型](src/client/contract/slots.ts)声明的显式 `preparing`、`start` 和 `result` props。所有块都提供 `name` 和懒计算的 `args` 读器,原有 `argsRaw` 和 result 的 `call` 字段仍可使用。行模型统一选择标题,并组合通用工具名前缀与已有参数摘要,不按生命周期阶段改变前缀;专用标题不附带英文名。write/edit 和 Bash 在各阶段共用组件。自定义 renderer 可保留独立准备态分支;依赖参数的组件接收 `StartedToolCallViewProps`。
51
+
52
+ 文件工具行优先使用完整的 `file_path`;其他通用行(包括搜索和未注册的工具)优先使用非空 `description`,再回退到各自类别的参数摘要。应在渲染或构造视图时读取 `args`:准备态读器原地增长,后续仅在已观察答案变化时重新发布块。
51
53
 
52
54
  本包拥有 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 文案。`ui-skill` 展示了业务包自行拥有的 `skill` 注册项。
53
55
 
@@ -72,7 +74,7 @@ owner 载荷为 `ToolCallOwnerProps`:`callId`、`toolName`、`phase` 判别字
72
74
  Tool 所有者属性将 Chat 注入的稳定 `useDisclosure` 钩子传给根调用及嵌套调用。工具行在拥有展开正文的位置调用它,中间 renderer 不订阅。每次调用拥有独立展开状态,外层轮次收起时重置该状态,不替换 React 身份;展示模式切换保留该状态。
73
75
 
74
76
 
75
- slot 注入的 `useToolCallArgumentsPartial` 钩子按需订阅所属 Step 的 `assistant-step` 来源,并选取当前 callId 的原始参数前缀。来源或调用不存在时返回空字符串。同一步骤中的其他调用可能触发快照检查,但选中的字符串未变时不会刷新使用方。不调用钩子的工具不新增订阅,已派发的调用不再提供参数前缀来源。
77
+ Tool Definition 拥有[懒计算参数视图](../../util/values/README.zh.md)。工具行通过读器选择字段和更新粒度,不另设订阅或注册。delta 追加时不扫描;按帧合批的发布会刷新已观察答案,仅在答案变化时替换块引用。需要完整派发参数的卡片模型继续读取 `argsRaw`。
76
78
 
77
79
  ### 卡片
78
80
 
@@ -83,7 +85,7 @@ Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删
83
85
 
84
86
  Auto 拒绝优先于按工具名选择的专门视图。其通用行保留调用身份、省略原始参数,并且只在显示时归一化存储的理由:去除首尾空白,把行分隔符折叠为空格,结果为空时使用本地化通用理由。Session 与 SDK 错误详情保留原始理由。
85
87
 
86
- 记录结果的工具详情覆盖目标和定时任务工具、Cordis 检查、workflow 与 Ralph 报告、Session 事件/搜索/轨迹查询、Agent 与 teammate 控制、后台作业、持久终端以及 LSP 导航。展开内容读取成功的记录结果,为失败或不支持的数据保留通用输入/输出,并保留 Inspect。日期包含查看者的时区,状态反映调用结果而非当前会话状态。Session 轨迹保留后代的缩进。LSP 结果通过 Host 回调打开文件系统路径,其他 URI 则显示为文本。浏览器适配器消费已记录的 producer 文本与 JSON;Host service 对象和 presenter 回调不会进入 Client。[紧凑工具详情](../../../.agents/notes/implemented/architecture/2026-09-10-compact-tool-details.zh.md)记录了呈现取舍。
88
+ 记录结果的工具详情覆盖目标和定时任务工具、Cordis 检查、workflow 与 Ralph 报告、Session 事件/搜索/轨迹查询、Agent 与 teammate 控制、后台作业、持久终端以及 LSP 导航。展开内容读取成功的记录结果,为失败或不支持的数据保留通用输入/输出,并保留 Inspect。日期包含查看者的时区,状态反映调用结果而非当前会话状态。Session 轨迹保留后代的缩进。LSP 结果通过 Host 回调打开文件系统路径,其他 URI 则显示为文本。浏览器适配器消费已记录的 producer 文本与 JSON;Host service 对象和 presenter 回调不会进入 Client。
87
89
 
88
90
  展开后的状态圆点和文字使用静态语义色。操作回执和任务输出的标题保持中性色,展开时省略标题中的状态。中断回执仅确认已发出中断请求。
89
91
 
@@ -142,5 +144,3 @@ terminal model 使用浏览器安全入口 `@deepseek-ai/dsh-spill-policy/notice
142
144
  无。
143
145
 
144
146
  </details>
145
-
146
- **运行时不变式:** 不发布伴生入口。工具组合只存在于浏览器,不贡献事件或跨插件可变状态;slot 所有权由 ui-slots 校验。
package/lib/client.js CHANGED
@@ -239,6 +239,26 @@ window.__ModuleLoader__.load({
239
239
  "write",
240
240
  "edit"
241
241
  ]);
242
+ /**
243
+ * Summary material read the same way at every stage from the argument view: a
244
+ * complete `file_path` for file tools, otherwise the `description` text so far.
245
+ * Empty when the view carries neither, so the caller falls back to the raw text.
246
+ */
247
+ function argumentSummary(variant, args, cwd, home) {
248
+ if (FILE_PATH_VARIANTS.has(variant)) {
249
+ const path = args.complete("file_path") ? args.text("file_path") : void 0;
250
+ const filePath = path !== void 0 && path !== "" && args.complete("file_path") ? firstLine(path) : void 0;
251
+ return {
252
+ summary: filePath === void 0 ? "" : abbreviateHomePath(relativizeToCwd(filePath, cwd), home),
253
+ filePath
254
+ };
255
+ }
256
+ const description = args.text("description");
257
+ return {
258
+ summary: description === void 0 ? "" : firstLine(description),
259
+ filePath: void 0
260
+ };
261
+ }
242
262
  function deriveFilePath(variant, argsRaw) {
243
263
  if (!FILE_PATH_VARIANTS.has(variant)) return void 0;
244
264
  const parsed = parseArgs(argsRaw);
@@ -276,7 +296,8 @@ window.__ModuleLoader__.load({
276
296
  const done = "kind" in block;
277
297
  const argsRaw = done ? block.call?.argsRaw ?? "" : block.phase === "start" ? block.argsRaw : null;
278
298
  const state = !done ? block.phase === "preparing" ? "preparing" : "running" : block.error?.code === "interrupted" ? "stopped" : block.isError ? "error" : "ok";
279
- const base = argsRaw === null ? "" : argsRaw === "" ? block.callId : abbreviateHomePath(relativizeToCwd(deriveSummary(variant, argsRaw), cwd), home);
299
+ const primary = argumentSummary(variant, block.args, cwd, home);
300
+ const base = primary.summary !== "" || argsRaw === null ? primary.summary : argsRaw === "" ? block.callId : abbreviateHomePath(relativizeToCwd(deriveSummary(variant, argsRaw), cwd), home);
280
301
  const summary = [titleKey === "tool.title.generic" ? toolName : "", base].filter(Boolean).join(" · ");
281
302
  const output = done ? resultText(block) || null : null;
282
303
  const errorSummary = state === "error" && output !== null ? firstLine(output) : null;
@@ -285,7 +306,7 @@ window.__ModuleLoader__.load({
285
306
  variant,
286
307
  titleKey,
287
308
  summary,
288
- filePath: argsRaw === null ? void 0 : deriveFilePath(variant, argsRaw),
309
+ filePath: primary.filePath ?? (argsRaw === null ? void 0 : deriveFilePath(variant, argsRaw)),
289
310
  bodyRaw,
290
311
  output,
291
312
  errorSummary,
@@ -338,19 +359,6 @@ window.__ModuleLoader__.load({
338
359
  const only = block.content[0];
339
360
  return only?.type === "text" ? only.text : void 0;
340
361
  }
341
- /**
342
- * Validate the optional escalation pair shared by first-party shell and file
343
- * mutation tools.
344
- * @param args - parsed open-root Tool arguments.
345
- * @returns whether the declared escalation fields form a valid pair.
346
- */
347
- function validEscalationFields(args) {
348
- const permission = args.sandbox_permissions;
349
- const justification = args.justification;
350
- if (permission === void 0 && justification === void 0) return true;
351
- if (permission !== "workspace-write" && permission !== "danger-full-access") return false;
352
- return typeof justification === "string" && justification.trim() !== "";
353
- }
354
362
  //#endregion
355
363
  //#region lib/types/client/tool/models/read-card-model.js
356
364
  /** Whether a model-supplied argument is a 1-based line position or count: an integer of at least 1. */
@@ -490,7 +498,6 @@ window.__ModuleLoader__.load({
490
498
  }
491
499
  const { file_path: path } = parsed.args;
492
500
  if (typeof path !== "string" || path.trim() === "") return null;
493
- if (!validEscalationFields(parsed.args)) return null;
494
501
  if (parsed.name === "write") {
495
502
  const { content } = parsed.args;
496
503
  return typeof content === "string" ? {
@@ -835,7 +842,6 @@ window.__ModuleLoader__.load({
835
842
  if (timeoutMs !== void 0 && (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0)) return null;
836
843
  if (workdir !== void 0 && typeof workdir !== "string") return null;
837
844
  if (background !== void 0 && typeof background !== "boolean") return null;
838
- if (!validEscalationFields(args)) return null;
839
845
  if (description === void 0) return {
840
846
  kind: "shell",
841
847
  command,
@@ -1529,7 +1535,8 @@ window.__ModuleLoader__.load({
1529
1535
  const summaryText = (state === "error" ? errorSummary ?? normalSummary : null) ?? normalSummary;
1530
1536
  const diffStat = (0, react.useMemo)(() => diffBody === null ? null : (0, _deepseek_ai_dsh_client_ui_primitives.diffTotals)(diffBody.card.diffs), [diffBody]);
1531
1537
  const settledWithCue = state === "error" || state === "stopped";
1532
- const suffix = settledWithCue ? null : summarySuffix ?? diffStat;
1538
+ const suffix = settledWithCue ? null : summarySuffix ?? null;
1539
+ const totals = settledWithCue ? null : diffStat;
1533
1540
  const openFile = (0, react.useMemo)(() => filePath !== void 0 && onOpenFile !== void 0 && !settledWithCue ? (event) => {
1534
1541
  event.stopPropagation();
1535
1542
  if (filePathLine === void 0) onOpenFile(filePath);
@@ -1570,18 +1577,22 @@ window.__ModuleLoader__.load({
1570
1577
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, { children: summaryText })
1571
1578
  }),
1572
1579
  suffix !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1573
- className: clsx(ToolRow_module_css_default.summarySuffix, typeof suffix !== "string" && ToolRow_module_css_default.diffStat),
1574
- children: typeof suffix === "string" ? suffix : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1580
+ className: ToolRow_module_css_default.summarySuffix,
1581
+ children: suffix
1582
+ }),
1583
+ totals !== null && (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1584
+ className: clsx(ToolRow_module_css_default.summarySuffix, ToolRow_module_css_default.diffStat),
1585
+ children: [
1575
1586
  (0, react_jsx_runtime.jsx)("span", {
1576
1587
  className: ToolRow_module_css_default.diffAdded,
1577
- children: `+${suffix.added}`
1588
+ children: `+${totals.added}`
1578
1589
  }),
1579
1590
  " ",
1580
1591
  (0, react_jsx_runtime.jsx)("span", {
1581
1592
  className: ToolRow_module_css_default.diffRemoved,
1582
- children: `-${suffix.removed}`
1593
+ children: `-${totals.removed}`
1583
1594
  })
1584
- ] })
1595
+ ]
1585
1596
  })
1586
1597
  ] }), [
1587
1598
  summaryLinkKeyDown,
@@ -1589,6 +1600,7 @@ window.__ModuleLoader__.load({
1589
1600
  openFile,
1590
1601
  state,
1591
1602
  suffix,
1603
+ totals,
1592
1604
  summaryText
1593
1605
  ]);
1594
1606
  const expandedContent = (0, react.useMemo)(() => open ? (0, react_jsx_runtime.jsxs)("div", {
@@ -1819,16 +1831,7 @@ window.__ModuleLoader__.load({
1819
1831
  return call.phase === "result" ? call.block.call?.name ?? "" : call.block.name;
1820
1832
  }
1821
1833
  /** One atomic call dispatched through the Tool-owned keyed slot. */
1822
- const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, call, assistant, openFile, cwd, home, inspectCall, loadImage, useDisclosure, t, children }) {
1823
- const preparing = call.phase === "preparing";
1824
- const hookContext = (0, react.useMemo)(() => ({
1825
- callId,
1826
- assistant: preparing ? assistant : void 0
1827
- }), [
1828
- assistant,
1829
- callId,
1830
- preparing
1831
- ]);
1834
+ const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, call, openFile, cwd, home, inspectCall, loadImage, useDisclosure, t, children }) {
1832
1835
  const owner = (0, react.useMemo)(() => ({
1833
1836
  callId,
1834
1837
  toolName,
@@ -1862,7 +1865,6 @@ window.__ModuleLoader__.load({
1862
1865
  t
1863
1866
  }) : renderSlot("tool.call.toolview", owner, {
1864
1867
  entryKey: toolName,
1865
- hookContext,
1866
1868
  fallback: (0, react_jsx_runtime.jsx)(GenericToolCard, {
1867
1869
  ...owner,
1868
1870
  t
@@ -1870,14 +1872,13 @@ window.__ModuleLoader__.load({
1870
1872
  }), children]
1871
1873
  });
1872
1874
  });
1873
- const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, assistant, cwd, home, openFile, inspectCall, loadImage, useDisclosure, t }) {
1875
+ const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, cwd, home, openFile, inspectCall, loadImage, useDisclosure, t }) {
1874
1876
  const call = (0, react.useMemo)(() => toolCallPhase(block), [block]);
1875
1877
  return (0, react_jsx_runtime.jsx)(ToolCall, {
1876
1878
  renderSlot,
1877
1879
  callId: call.block.callId,
1878
1880
  toolName: callName(call),
1879
1881
  call,
1880
- assistant,
1881
1882
  openFile,
1882
1883
  cwd,
1883
1884
  home,
@@ -1891,7 +1892,6 @@ window.__ModuleLoader__.load({
1891
1892
  children: call.block.subCalls.map((child) => (0, react_jsx_runtime.jsx)(ToolCallBranch, {
1892
1893
  renderSlot,
1893
1894
  block: child,
1894
- assistant,
1895
1895
  cwd,
1896
1896
  home,
1897
1897
  openFile,
@@ -1911,11 +1911,9 @@ window.__ModuleLoader__.load({
1911
1911
  */
1912
1912
  function ToolCallTree({ renderSlot, node, cwd, openFile, inspectCall, loadImage, useDisclosure, useHostInfo, t }) {
1913
1913
  const home = useHostInfo((info) => info.home);
1914
- const assistant = node.location.kind === "step" ? node.location.step.data.source("assistant-step") : void 0;
1915
1914
  return (0, react_jsx_runtime.jsx)(ToolCallBranch, {
1916
1915
  renderSlot,
1917
1916
  block: node.data.root,
1918
- assistant,
1919
1917
  cwd,
1920
1918
  home,
1921
1919
  openFile,
@@ -1926,27 +1924,6 @@ window.__ModuleLoader__.load({
1926
1924
  });
1927
1925
  }
1928
1926
  //#endregion
1929
- //#region lib/types/client/tool/tool-call-arguments-partial.js
1930
- /** Call-local argument subscription bound by the atomic Tool slot. */
1931
- const subscribeEmpty = () => () => {};
1932
- /**
1933
- * Bind one call without subscribing until its component invokes the Hook.
1934
- * @param _standard - framework-provided scope props.
1935
- * @param context - the preparing call's Step source and identity.
1936
- * @returns a Hook that reads only this call's raw argument prefix.
1937
- */
1938
- const bindToolCallArgumentsPartial = (_standard, context) => {
1939
- const { assistant, callId } = context;
1940
- const subscribe = assistant === void 0 ? subscribeEmpty : (listener) => assistant.subscribe(listener);
1941
- const getSnapshot = () => {
1942
- const block = assistant?.getSnapshot()?.blocks.find((candidate) => candidate.kind === "tool-call" && candidate.callId === callId);
1943
- return block?.kind === "tool-call" ? block.argsRaw : "";
1944
- };
1945
- return function useToolCallArgumentsPartial() {
1946
- return (0, react.useSyncExternalStore)(subscribe, getSnapshot);
1947
- };
1948
- };
1949
- //#endregion
1950
1927
  //#region lib/types/client/locale.js
1951
1928
  /** Locale namespace supplied by the conversation owner to Tool renderers. */
1952
1929
  const CONVERSATION_NS = "conversation";
@@ -2353,25 +2330,6 @@ window.__ModuleLoader__.load({
2353
2330
  }
2354
2331
  };
2355
2332
  //#endregion
2356
- //#region lib/types/client/tool/components/PreparingToolRow.js
2357
- /**
2358
- * Render a non-expandable tool prefix with an optional preparation summary.
2359
- * @param props - tool prefix and locale.
2360
- * @returns the preparation row.
2361
- */
2362
- function PreparingToolRow({ toolName, useDisclosure, icon, title, summary = "", t }) {
2363
- return (0, react_jsx_runtime.jsx)(ToolRow, {
2364
- useDisclosure,
2365
- t,
2366
- variant: classifyTool(toolName),
2367
- toolName,
2368
- icon,
2369
- title,
2370
- summary,
2371
- state: "preparing"
2372
- });
2373
- }
2374
- //#endregion
2375
2333
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css.mjs
2376
2334
  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);border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small);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{border-radius:var(--dsw-radius-sm);background-clip:padding-box;border:2px solid #0000}.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));min-width:0;color:var(--dsw-alias-label-tertiary);align-items:center;transition:color .1s;display:flex}.CY-8Ka_root:hover{color:var(--dsw-alias-label-secondary)}@media (prefers-reduced-motion:reduce){.CY-8Ka_root{transition:none}}.CY-8Ka_leading{width:calc(16px + var(--dsh-content-font-delta,0px));height:calc(16px + var(--dsh-content-font-delta,0px));color:inherit;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:inherit}.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));flex:none}.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));flex:auto;overflow:hidden}.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}";
2377
2335
  const tagId = "@deepseek-ai/dsh-client-ui-tool/bash-sample.module.css";
@@ -2410,6 +2368,7 @@ window.__ModuleLoader__.load({
2410
2368
  /** Visually hidden status for the color-only running sweep and error tone. */
2411
2369
  function stateStatus(state, t) {
2412
2370
  switch (state) {
2371
+ case "preparing": return t("row.preparing");
2413
2372
  case "running": return t("bash.running");
2414
2373
  case "error": return t("bash.failed");
2415
2374
  case "stopped": return t("bash.stopped");
@@ -2417,19 +2376,12 @@ window.__ModuleLoader__.load({
2417
2376
  }
2418
2377
  }
2419
2378
  /**
2420
- * Render expandable Bash output with an accessible lifecycle label.
2379
+ * Render expandable Bash output with an accessible lifecycle label. While the
2380
+ * call is preparing the row shows the description streamed so far and cannot expand.
2421
2381
  * @param props - tool call, Session sources, locale, and inspection callback.
2422
2382
  * @returns the Bash output row.
2423
2383
  */
2424
- const BashRow = (0, react.memo)(function BashRow(props) {
2425
- if (props.phase === "preparing") return (0, react_jsx_runtime.jsx)(PreparingToolRow, {
2426
- ...props,
2427
- icon: BASH_ICON,
2428
- title: props.t(toolTitleKey(props.toolName))
2429
- });
2430
- return (0, react_jsx_runtime.jsx)(StartedBashRow, { ...props });
2431
- });
2432
- const StartedBashRow = (0, react.memo)(function StartedBashRow({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }) {
2384
+ const BashRow = (0, react.memo)(function BashRow({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }) {
2433
2385
  const model = (0, react.useMemo)(() => toolRowModel(toolName, block), [toolName, block]);
2434
2386
  const cwd = useSessions((list) => list.byId[sessionId]?.cwd);
2435
2387
  const terminalModel = (0, react.useMemo)(() => terminalCardModel(block, cwd), [block, cwd]);
@@ -2449,7 +2401,7 @@ window.__ModuleLoader__.load({
2449
2401
  ]);
2450
2402
  const normalSummary = terminal?.description ?? model.summary;
2451
2403
  const settlementLine = state === "error" ? model.errorSummary ?? normalSummary : state === "stopped" ? t("bash.stopped") : null;
2452
- const running = state === "running";
2404
+ const running = state === "running" || state === "preparing";
2453
2405
  const toggleFromKeyboard = (0, react.useCallback)((event) => {
2454
2406
  if (!expandable || event.key !== "Enter" && event.key !== " ") return;
2455
2407
  event.preventDefault();
@@ -2560,26 +2512,33 @@ window.__ModuleLoader__.load({
2560
2512
  //#endregion
2561
2513
  //#region lib/types/client/tool/toolviews/file-mutation-row.js
2562
2514
  const FILE_MUTATION_ICON = (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 });
2515
+ const CONTENT_FIELDS = [
2516
+ "content",
2517
+ "old_string",
2518
+ "new_string"
2519
+ ];
2520
+ const KILOBYTE = 1024;
2521
+ /** Kilobytes of decoded input at every stage; null before any content field arrives. */
2522
+ function contentKilobytes(block) {
2523
+ const { args } = block;
2524
+ const open = CONTENT_FIELDS.find((key) => args.has(key) && !args.complete(key));
2525
+ const completed = CONTENT_FIELDS.reduce((total, key) => key !== open && args.complete(key) ? total + (args.stringLength(key, { step: KILOBYTE }) ?? 0) : total, 0);
2526
+ if (open === void 0) return CONTENT_FIELDS.some((key) => args.has(key)) ? Math.ceil(completed / KILOBYTE) : null;
2527
+ const chars = completed + (args.stringLength(open, {
2528
+ step: KILOBYTE,
2529
+ offset: completed
2530
+ }) ?? 0);
2531
+ return Math.ceil(chars / KILOBYTE);
2532
+ }
2563
2533
  /**
2564
- * Lets users expand an applied file diff and open the reported path.
2534
+ * Shows the path and decoded input size through preparation, execution, and
2535
+ * settlement, with the applied diff available once the call settles.
2565
2536
  */
2566
- function FileMutationRow(props) {
2567
- return props.phase === "preparing" ? (0, react_jsx_runtime.jsx)(PreparingFileMutationRow, { ...props }) : (0, react_jsx_runtime.jsx)(StartedFileMutationRow, { ...props });
2568
- }
2569
- function PreparingFileMutationRow({ toolName, useDisclosure, useToolCallArgumentsPartial, t }) {
2570
- const raw = useToolCallArgumentsPartial();
2571
- return (0, react_jsx_runtime.jsx)(PreparingToolRow, {
2572
- toolName,
2573
- useDisclosure,
2574
- icon: FILE_MUTATION_ICON,
2575
- title: t(toolTitleKey(toolName)),
2576
- t,
2577
- summary: t("tool.preparing.content", { kilobytes: Math.ceil(raw.length / 1024) })
2578
- });
2579
- }
2580
- function StartedFileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
2537
+ function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
2581
2538
  const model = toolRowModel(toolName, block, cwd, home);
2582
2539
  const diff = diffCardModel(block);
2540
+ const kilobytes = contentKilobytes(block);
2541
+ const size = kilobytes === null ? null : t("tool.preparing.content", { kilobytes });
2583
2542
  return (0, react_jsx_runtime.jsx)(ToolRow, {
2584
2543
  useDisclosure,
2585
2544
  t,
@@ -2588,6 +2547,7 @@ window.__ModuleLoader__.load({
2588
2547
  icon: FILE_MUTATION_ICON,
2589
2548
  title: t(model.titleKey),
2590
2549
  summary: model.summary,
2550
+ summarySuffix: size !== null && model.summary !== "" ? size : void 0,
2591
2551
  output: model.output,
2592
2552
  errorSummary: model.errorSummary,
2593
2553
  diff,
@@ -4557,8 +4517,7 @@ window.__ModuleLoader__.load({
4557
4517
  locale: CONVERSATION_NS,
4558
4518
  children: { "tool.call.toolview": {
4559
4519
  kind: "keyed",
4560
- scope: "session",
4561
- inject: { hooks: { toolCallArgumentsPartial: bindToolCallArgumentsPartial } }
4520
+ scope: "session"
4562
4521
  } },
4563
4522
  inject: toolInject
4564
4523
  }, ToolCallTree));
@@ -1,7 +1,7 @@
1
1
  /** Tool UI slot declarations and their composed component props. */
2
- import type { HostObservable, InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime, SessionIdOf, SlotHookFactory } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { HostObservable, InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime, SessionIdOf } from '@deepseek-ai/dsh-client-ui-slots';
3
3
  import type { RemoteHostFacts } from '@deepseek-ai/dsh-api-remotes/client';
4
- import type { AssistantChatData, OpenFileOptions, PreparingToolCall, StartedToolCall, ToolResultNode, UseDisclosure } from '@deepseek-ai/dsh-client-ui-chat/client';
4
+ import type { 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
  import type { AskUserQuestionAnswerItem, AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions/types';
7
7
  declare module '@deepseek-ai/dsh-client-ui-slots' {
@@ -12,16 +12,14 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
12
12
  * `key: '<tool name>'`; a typo never renders.
13
13
  *
14
14
  * Registering an occupied key replaces its view; unclaimed keys use the
15
- * generic row. The owner supplies the call identity and frozen running
16
- * or settled node through explicit phase props. Preparing blocks have no dispatched
17
- * arguments; useToolCallArgumentsPartial optionally subscribes to their raw prefix.
15
+ * generic row. The owner supplies the call identity and running
16
+ * or settled node through explicit phase props. Every stage supplies
17
+ * `name` and a lazy `args` view; preparing arguments may be incomplete.
18
18
  */
19
19
  'tool.call.toolview': {
20
20
  kind: 'keyed';
21
21
  scope: 'session';
22
22
  owner: ToolCallOwnerProps;
23
- hookContext: ToolCallHookContext;
24
- inject: ToolCallInjected;
25
23
  };
26
24
  /**
27
25
  * Durable images of a settled image-bearing Tool call, rendered through
@@ -43,20 +41,6 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
43
41
  };
44
42
  }
45
43
  }
46
- /** Subscribe to this preparing call's raw argument prefix; other phases return an empty string. */
47
- export type UseToolCallArgumentsPartial = () => string;
48
- /** Call-local sources supplied by the Tool tree to the slot's Hook binding. */
49
- export interface ToolCallHookContext {
50
- readonly callId: string;
51
- /** This call's Step source, present only while preparing. */
52
- readonly assistant: HostObservable<Readonly<AssistantChatData> | undefined> | undefined;
53
- }
54
- /** Framework-bound subscriptions available to atomic Tool views on demand. */
55
- export interface ToolCallInjected {
56
- hooks: {
57
- toolCallArgumentsPartial: SlotHookFactory<'tool.call.toolview', UseToolCallArgumentsPartial>;
58
- };
59
- }
60
44
  /** Owner currency of the Tool image gallery slot: references plus the loader. */
61
45
  export interface ToolImagesOwnerProps {
62
46
  /** Durable references or submission-echo previews in result order. */
@@ -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 { StartedToolCallViewProps, ToolCallCommonProps, ToolCallOwnerProps, ToolCallPhaseProps, ToolCallViewProps, ToolCallHookContext, ToolCallInjected, ToolHostInfoInjected, ToolTreeProps, UseToolCallArgumentsPartial, UserQuestionPanels, UserQuestionRecord, } from './contract/slots.ts';
3
+ export type { StartedToolCallViewProps, ToolCallCommonProps, ToolCallOwnerProps, ToolCallPhaseProps, ToolCallViewProps, ToolHostInfoInjected, ToolTreeProps, UserQuestionPanels, UserQuestionRecord, } from './contract/slots.ts';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -23,10 +23,9 @@ export interface ToolRowProps {
23
23
  summary: string;
24
24
  /**
25
25
  * Trailing summary fragment rendered outside the ellipsized summary text, so
26
- * a narrow row clips the summary before this. For a fragment whose whole
27
- * value is surviving that clip — the todo row's parallel-active count.
28
- * null/absent = the summary is the whole collapsed content. Dropped on an
29
- * error row, whose collapsed summary is the failure line instead.
26
+ * a narrow row clips the summary before this. Appears before diff totals
27
+ * when both are present. null/absent omits this fragment. Error and stopped
28
+ * rows omit both the suffix and diff totals.
30
29
  */
31
30
  summarySuffix?: string | null | undefined;
32
31
  /** Original argument JSON formatted only while the row is expanded. */
@@ -18,11 +18,4 @@ export declare function parsedToolCall(block: ToolCallBlock): ParsedToolCall | n
18
18
  * @returns its text, or undefined for any other content layout.
19
19
  */
20
20
  export declare function singleResultText(block: ToolResultNode): string | undefined;
21
- /**
22
- * Validate the optional escalation pair shared by first-party shell and file
23
- * mutation tools.
24
- * @param args - parsed open-root Tool arguments.
25
- * @returns whether the declared escalation fields form a valid pair.
26
- */
27
- export declare function validEscalationFields(args: Record<string, unknown>): boolean;
28
21
  //# sourceMappingURL=raw-tool-call.d.ts.map
@@ -48,8 +48,9 @@ export interface ToolRowModel {
48
48
  summary: string;
49
49
  /**
50
50
  * Filesystem path from args (`path` / `file_path`) when the row is a file
51
- * tool; absent for URL reads and non-file tools. The chat view resolves
52
- * relative values against the session cwd before opening.
51
+ * tool; absent for URL reads and non-file tools. A `file_path` argument
52
+ * supplies it at every stage once its string is complete. The chat view
53
+ * resolves relative values against the session cwd before opening.
53
54
  */
54
55
  filePath: string | undefined;
55
56
  /** Original argument JSON retained for expansion-time body formatting. */
@@ -3,11 +3,12 @@ import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
3
3
  import type { ToolCallViewProps } from '../../contract/slots.ts';
4
4
  type BashRowProps = ToolCallViewProps & PropsLocale<'conversation'>;
5
5
  /**
6
- * Render expandable Bash output with an accessible lifecycle label.
6
+ * Render expandable Bash output with an accessible lifecycle label. While the
7
+ * call is preparing the row shows the description streamed so far and cannot expand.
7
8
  * @param props - tool call, Session sources, locale, and inspection callback.
8
9
  * @returns the Bash output row.
9
10
  */
10
- export declare const BashRow: import("react").MemoExoticComponent<(props: BashRowProps) => import("react").JSX.Element>;
11
+ export declare const BashRow: import("react").MemoExoticComponent<({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }: BashRowProps) => import("react").JSX.Element>;
11
12
  /** Registers the standalone Bash conversation-row sample. */
12
13
  export declare const bashToolviewSample: {
13
14
  name: string;
@@ -3,9 +3,10 @@ import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
3
3
  import type { ToolCallViewProps } from '../../contract/slots.ts';
4
4
  type FileMutationRowProps = ToolCallViewProps & PropsLocale<'conversation'>;
5
5
  /**
6
- * Lets users expand an applied file diff and open the reported path.
6
+ * Shows the path and decoded input size through preparation, execution, and
7
+ * settlement, with the applied diff available once the call settles.
7
8
  */
8
- export declare function FileMutationRow(props: FileMutationRowProps): import("react").JSX.Element;
9
+ export declare function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }: FileMutationRowProps): import("react").JSX.Element;
9
10
  /** Registers the edit and write conversation rows. */
10
11
  export declare const fileMutationToolview: {
11
12
  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.2.0-rc.2",
4
+ "version": "0.2.1-alpha.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.4"
41
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@testing-library/react": "^16.1.0",
@@ -46,33 +46,34 @@
46
46
  "react": "^18.2.0",
47
47
  "react-dom": "^18.2.0",
48
48
  "clsx": "^2.0.0",
49
- "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
50
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
51
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
52
- "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
53
- "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
54
- "@deepseek-ai/dsh-spill-policy": "0.2.0-rc.2",
55
- "@deepseek-ai/dsh-tool-jobs": "0.2.0-rc.2",
56
- "@deepseek-ai/dsh-tool-session-query": "0.2.0-rc.2",
57
- "@deepseek-ai/dsh-tool-terminal": "0.2.0-rc.2",
58
- "@deepseek-ai/dsh-spill": "0.2.0-rc.2",
59
- "@deepseek-ai/cordis": "~4.0.4",
60
- "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
61
- "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
62
- "@deepseek-ai/dsh-client-test-runtime": "0.2.0-rc.2",
63
- "@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
64
- "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
65
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
66
- "@deepseek-ai/dsh-api-workspace-controller": "0.2.0-rc.2",
67
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
68
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
69
- "@deepseek-ai/dsh-client-ui-session": "0.2.0-rc.2",
70
- "@deepseek-ai/dsh-util-workspace-path": "0.2.0-rc.2",
71
- "@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
72
- "@deepseek-ai/dsh-ptc-runtime": "0.2.0-rc.2",
73
- "@deepseek-ai/dsh-token-meter": "0.2.0-rc.2",
74
- "@deepseek-ai/dsh-user-questions": "0.2.0-rc.2",
75
- "@deepseek-ai/dsh-client-ui-chat": "0.2.0-rc.2"
49
+ "@deepseek-ai/dsh-spill-policy": "0.2.1-alpha.1",
50
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
51
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
52
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
53
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
54
+ "@deepseek-ai/dsh-tool-session-query": "0.2.1-alpha.1",
55
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
56
+ "@deepseek-ai/dsh-tool-terminal": "0.2.1-alpha.1",
57
+ "@deepseek-ai/dsh-spill": "0.2.1-alpha.1",
58
+ "@deepseek-ai/dsh-tool-jobs": "0.2.1-alpha.1",
59
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
60
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.1",
61
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.1",
62
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.1",
63
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.1",
64
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.1",
65
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.1",
66
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.1",
67
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-alpha.1",
68
+ "@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.1",
69
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.1",
70
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.1",
71
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.1-alpha.1",
72
+ "@deepseek-ai/dsh-attachment": "0.2.1-alpha.1",
73
+ "@deepseek-ai/dsh-token-meter": "0.2.1-alpha.1",
74
+ "@deepseek-ai/dsh-user-questions": "0.2.1-alpha.1",
75
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.1",
76
+ "@deepseek-ai/dsh-ptc-runtime": "0.2.1-alpha.1"
76
77
  },
77
78
  "files": [
78
79
  "lib/index.js",
@@ -1,19 +0,0 @@
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
@@ -1,9 +0,0 @@
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