@deepseek-ai/dsh-client-ui-tool 0.1.6-alpha.2 → 0.1.7-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/lib/client.js CHANGED
@@ -1111,13 +1111,13 @@ window.__ModuleLoader__.load({
1111
1111
  }
1112
1112
  //#endregion
1113
1113
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/components/AskQuestionCard.module.css.mjs
1114
- const css$3 = ".fsXYAq_card{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);border-radius:12px;flex-direction:column;gap:16px;max-height:360px;margin:4px 0 4px 4px;padding:16px 20px;display:flex;overflow-y:auto}.fsXYAq_item{flex-direction:column;gap:2px;min-width:0;display:flex}.fsXYAq_question,.fsXYAq_answer{white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px));margin:0}.fsXYAq_question{color:var(--dsw-alias-label-tertiary)}.fsXYAq_answer{color:var(--dsw-alias-label-primary)}.fsXYAq_answerLine{display:block}.fsXYAq_skipped{color:var(--dsw-alias-label-tertiary)}.fsXYAq_verdict{color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px));margin:0}.fsXYAq_questionList{flex-direction:column;gap:8px;margin:0;padding-left:20px;display:flex}.fsXYAq_unansweredQuestion{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}";
1115
- const tagId$3 = "@deepseek-ai/dsh-client-ui-tool/AskQuestionCard.module.css";
1116
- if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1114
+ const css$4 = ".fsXYAq_card{border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);border-radius:12px;flex-direction:column;gap:16px;max-height:360px;margin:4px 0 4px 4px;padding:16px 20px;display:flex;overflow-y:auto}.fsXYAq_item{flex-direction:column;gap:2px;min-width:0;display:flex}.fsXYAq_question,.fsXYAq_answer{white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px));margin:0}.fsXYAq_question{color:var(--dsw-alias-label-tertiary)}.fsXYAq_answer{color:var(--dsw-alias-label-primary)}.fsXYAq_answerLine{display:block}.fsXYAq_skipped{color:var(--dsw-alias-label-tertiary)}.fsXYAq_verdict{color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px));margin:0}.fsXYAq_questionList{flex-direction:column;gap:8px;margin:0;padding-left:20px;display:flex}.fsXYAq_unansweredQuestion{color:var(--dsw-alias-label-tertiary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--dsh-content-font-size,14px);line-height:calc(24px + var(--dsh-content-font-delta,0px))}";
1115
+ const tagId$4 = "@deepseek-ai/dsh-client-ui-tool/AskQuestionCard.module.css";
1116
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
1117
1117
  const tag = document.createElement("style");
1118
1118
  tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
1119
- tag.dataset.pluginCss = tagId$3;
1120
- tag.textContent = css$3;
1119
+ tag.dataset.pluginCss = tagId$4;
1120
+ tag.textContent = css$4;
1121
1121
  document.head.appendChild(tag);
1122
1122
  }
1123
1123
  var AskQuestionCard_module_css_default = {
@@ -1173,8 +1173,181 @@ window.__ModuleLoader__.load({
1173
1173
  });
1174
1174
  }
1175
1175
  //#endregion
1176
+ //#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}";
1178
+ const tagId$3 = "@deepseek-ai/dsh-client-ui-tool/ToolDetails.module.css";
1179
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1180
+ const tag = document.createElement("style");
1181
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
1182
+ tag.dataset.pluginCss = tagId$3;
1183
+ tag.textContent = css$3;
1184
+ document.head.appendChild(tag);
1185
+ }
1186
+ var ToolDetails_module_css_default = {
1187
+ "badge": "DXqwVW_badge",
1188
+ "caption": "DXqwVW_caption",
1189
+ "code": "DXqwVW_code",
1190
+ "description": "DXqwVW_description",
1191
+ "empty": "DXqwVW_empty",
1192
+ "field": "DXqwVW_field",
1193
+ "fields": "DXqwVW_fields",
1194
+ "group": "DXqwVW_group",
1195
+ "heading": "DXqwVW_heading",
1196
+ "item": "DXqwVW_item",
1197
+ "lines": "DXqwVW_lines",
1198
+ "list": "DXqwVW_list",
1199
+ "path": "DXqwVW_path",
1200
+ "pending": "DXqwVW_pending",
1201
+ "previous": "DXqwVW_previous",
1202
+ "prose": "DXqwVW_prose",
1203
+ "root": "DXqwVW_root",
1204
+ "status": "DXqwVW_status",
1205
+ "statusText": "DXqwVW_statusText",
1206
+ "subtitle": "DXqwVW_subtitle",
1207
+ "text": "DXqwVW_text",
1208
+ "unchanged": "DXqwVW_unchanged"
1209
+ };
1210
+ //#endregion
1211
+ //#region lib/types/client/tool/components/ToolDetails.js
1212
+ /** Compact, read-only fields and lists for recorded Tool results. */
1213
+ function DetailItem({ item, t, onOpenFile }) {
1214
+ const status = item.status;
1215
+ return (0, react_jsx_runtime.jsxs)("li", {
1216
+ className: ToolDetails_module_css_default.item,
1217
+ "data-change": item.change?.value,
1218
+ children: [
1219
+ item.title !== void 0 && (0, react_jsx_runtime.jsxs)("div", {
1220
+ className: ToolDetails_module_css_default.heading,
1221
+ children: [
1222
+ status !== void 0 && (0, react_jsx_runtime.jsx)("span", {
1223
+ className: ToolDetails_module_css_default.status,
1224
+ role: "img",
1225
+ "aria-label": item.change?.label ?? status.label,
1226
+ children: item.change?.value === "added" ? "+" : item.change?.value === "removed" ? "−" : status.value === "completed" ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { size: 14 }) : status.value === "in_progress" ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlayOutlineRegular, { size: 14 }) : (0, react_jsx_runtime.jsx)("span", { className: ToolDetails_module_css_default.pending })
1227
+ }),
1228
+ item.location !== void 0 && onOpenFile !== void 0 ? (0, react_jsx_runtime.jsx)("button", {
1229
+ className: ToolDetails_module_css_default.path,
1230
+ type: "button",
1231
+ onClick: () => {
1232
+ const location = item.location;
1233
+ if (location !== void 0) onOpenFile(location.path, location.line === void 0 ? void 0 : { line: location.line });
1234
+ },
1235
+ children: item.title
1236
+ }) : (0, react_jsx_runtime.jsx)("span", {
1237
+ className: ToolDetails_module_css_default.text,
1238
+ children: item.title
1239
+ }),
1240
+ item.badge !== void 0 && (0, react_jsx_runtime.jsx)("span", {
1241
+ className: ToolDetails_module_css_default.badge,
1242
+ "data-tone": item.badge.tone,
1243
+ children: item.badge.label
1244
+ }),
1245
+ status !== void 0 && (0, react_jsx_runtime.jsxs)("span", {
1246
+ className: ToolDetails_module_css_default.statusText,
1247
+ children: [
1248
+ item.previousStatus !== void 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
1249
+ className: ToolDetails_module_css_default.previous,
1250
+ children: item.previousStatus
1251
+ }), (0, react_jsx_runtime.jsx)("span", { children: " → " })] }),
1252
+ (0, react_jsx_runtime.jsx)("span", { children: status.label }),
1253
+ item.change?.value === "updated" && item.previousStatus === void 0 && (0, react_jsx_runtime.jsxs)("span", { children: [" · ", item.change.label] })
1254
+ ]
1255
+ })
1256
+ ]
1257
+ }),
1258
+ item.subtitle !== void 0 && (0, react_jsx_runtime.jsx)("div", {
1259
+ className: ToolDetails_module_css_default.subtitle,
1260
+ children: item.subtitle
1261
+ }),
1262
+ item.description !== void 0 && (0, react_jsx_runtime.jsx)("p", {
1263
+ className: ToolDetails_module_css_default.description,
1264
+ children: item.description
1265
+ }),
1266
+ item.fields.length > 0 && (0, react_jsx_runtime.jsx)("dl", {
1267
+ className: ToolDetails_module_css_default.fields,
1268
+ children: item.fields.map((field) => (0, react_jsx_runtime.jsxs)("div", {
1269
+ className: ToolDetails_module_css_default.field,
1270
+ children: [(0, react_jsx_runtime.jsx)("dt", { children: field.label }), (0, react_jsx_runtime.jsx)("dd", { children: field.value })]
1271
+ }, field.label))
1272
+ }),
1273
+ item.lines !== void 0 && (0, react_jsx_runtime.jsx)("ul", {
1274
+ className: ToolDetails_module_css_default.lines,
1275
+ children: item.lines.map((line, index) => (0, react_jsx_runtime.jsx)("li", { children: line }, index))
1276
+ }),
1277
+ item.markdown !== void 0 && (0, react_jsx_runtime.jsx)("div", {
1278
+ className: ToolDetails_module_css_default.prose,
1279
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
1280
+ text: item.markdown,
1281
+ labels: markdownLabels(t)
1282
+ })
1283
+ }),
1284
+ item.code !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.CodeBlock, {
1285
+ className: ToolDetails_module_css_default.code,
1286
+ code: item.code.text,
1287
+ lang: item.code.language,
1288
+ copyLabel: t("copy"),
1289
+ copiedLabel: t("copied")
1290
+ }),
1291
+ item.groups?.map((group, index) => (0, react_jsx_runtime.jsxs)("details", {
1292
+ className: ToolDetails_module_css_default.group,
1293
+ children: [(0, react_jsx_runtime.jsxs)("summary", { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {}), (0, react_jsx_runtime.jsx)("span", { children: group.label })] }), (0, react_jsx_runtime.jsx)("ul", {
1294
+ className: ToolDetails_module_css_default.list,
1295
+ children: group.items.map((child, childIndex) => (0, react_jsx_runtime.jsx)(DetailItem, {
1296
+ item: child,
1297
+ t,
1298
+ onOpenFile
1299
+ }, childIndex))
1300
+ })]
1301
+ }, index))
1302
+ ]
1303
+ });
1304
+ }
1305
+ /**
1306
+ * Render recorded values with local disclosures, copy controls, and file navigation.
1307
+ * @param props.model - Localized fields or list items; an empty list uses its empty label.
1308
+ * @param props.hasInspect - Reserve space for the row's upper-right Inspect button.
1309
+ * @param props.t - Conversation dictionary for shared Markdown and code controls.
1310
+ * @param props.onOpenFile - Open a recorded file location in the session workspace.
1311
+ * @returns The expanded detail body.
1312
+ */
1313
+ function ToolDetails({ model, hasInspect = false, t, onOpenFile }) {
1314
+ return (0, react_jsx_runtime.jsxs)("div", {
1315
+ className: ToolDetails_module_css_default.root,
1316
+ "data-inspect": hasInspect || void 0,
1317
+ "data-caption": model.caption !== void 0 || void 0,
1318
+ children: [
1319
+ model.caption !== void 0 && (0, react_jsx_runtime.jsx)("div", {
1320
+ className: ToolDetails_module_css_default.caption,
1321
+ children: model.caption
1322
+ }),
1323
+ model.items.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
1324
+ className: ToolDetails_module_css_default.empty,
1325
+ children: model.empty
1326
+ }) : (0, react_jsx_runtime.jsx)("ul", {
1327
+ className: ToolDetails_module_css_default.list,
1328
+ children: model.items.map((item, index) => (0, react_jsx_runtime.jsx)(DetailItem, {
1329
+ item,
1330
+ t,
1331
+ onOpenFile
1332
+ }, index))
1333
+ }),
1334
+ model.unchanged !== void 0 && (0, react_jsx_runtime.jsxs)("details", {
1335
+ className: ToolDetails_module_css_default.unchanged,
1336
+ children: [(0, react_jsx_runtime.jsxs)("summary", { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, {}), model.unchanged.label] }), (0, react_jsx_runtime.jsx)("ul", {
1337
+ className: ToolDetails_module_css_default.list,
1338
+ children: model.unchanged.items.map((item, index) => (0, react_jsx_runtime.jsx)(DetailItem, {
1339
+ item,
1340
+ t,
1341
+ onOpenFile
1342
+ }, index))
1343
+ })]
1344
+ })
1345
+ ]
1346
+ });
1347
+ }
1348
+ //#endregion
1176
1349
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css.mjs
1177
- const css$2 = ".o3BgMG_root{flex-direction:column;display:flex}.o3BgMG_row{position:relative;overflow:hidden}.o3BgMG_root[data-state=running] .o3BgMG_row:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite o3BgMG_dsh-tool-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes o3BgMG_dsh-tool-row-sweep{0%{left:-300px}90%,to{left:100%}}.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}.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;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}.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;overflow:hidden}.o3BgMG_fileLink:hover{color:var(--dsw-alias-label-primary);text-decoration-color:currentColor}.o3BgMG_errorSummary{color:var(--dsw-alias-state-error-primary)}.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_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}";
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}";
1178
1351
  const tagId$2 = "@deepseek-ai/dsh-client-ui-tool/ToolRow.module.css";
1179
1352
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
1180
1353
  const tag = document.createElement("style");
@@ -1188,9 +1361,9 @@ window.__ModuleLoader__.load({
1188
1361
  "bodyWrap": "o3BgMG_bodyWrap",
1189
1362
  "chevron": "o3BgMG_chevron",
1190
1363
  "codeBody": "o3BgMG_codeBody",
1364
+ "detailsBodyWrap": "o3BgMG_detailsBodyWrap",
1191
1365
  "diffBody": "o3BgMG_diffBody",
1192
1366
  "diffStat": "o3BgMG_diffStat",
1193
- "dsh-tool-row-sweep": "o3BgMG_dsh-tool-row-sweep",
1194
1367
  "errorSummary": "o3BgMG_errorSummary",
1195
1368
  "fileLink": "o3BgMG_fileLink",
1196
1369
  "imageBody": "o3BgMG_imageBody",
@@ -1209,6 +1382,7 @@ window.__ModuleLoader__.load({
1209
1382
  "searchBody": "o3BgMG_searchBody",
1210
1383
  "searchRecovery": "o3BgMG_searchRecovery",
1211
1384
  "sep": "o3BgMG_sep",
1385
+ "stoppedSummary": "o3BgMG_stoppedSummary",
1212
1386
  "summary": "o3BgMG_summary",
1213
1387
  "summarySuffix": "o3BgMG_summarySuffix",
1214
1388
  "terminalBody": "o3BgMG_terminalBody",
@@ -1218,17 +1392,7 @@ window.__ModuleLoader__.load({
1218
1392
  };
1219
1393
  //#endregion
1220
1394
  //#region lib/types/client/tool/components/ToolRow.js
1221
- function leadingFor$1(state, icon) {
1222
- switch (state) {
1223
- case "error": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" });
1224
- case "stopped": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
1225
- default: return icon;
1226
- }
1227
- }
1228
- /** Visually hidden run-state label: the StateDot and the CSS sweep are both
1229
- * aria-hidden / colour-only, so assistive technology needs this text to know a
1230
- * row is running, failed, or interrupted. null in the ok state (the icon and
1231
- * summary already describe a settled row). */
1395
+ /** Visually hidden run-state label for color-only running and settlement cues. */
1232
1396
  function stateStatus$1(state, t) {
1233
1397
  switch (state) {
1234
1398
  case "running": return t("row.running");
@@ -1237,23 +1401,29 @@ window.__ModuleLoader__.load({
1237
1401
  default: return null;
1238
1402
  }
1239
1403
  }
1240
- function ToolRow({ t, variant, toolName, icon, title, summary, summarySuffix, bodyRaw, output, askQuestion, errorSummary, terminal, diff, read, image, renderSlot, loadImage, search, web, state, filePath, filePathLine, onOpenFile, inspect }) {
1241
- const [expanded, setExpanded] = (0, react.useState)(false);
1404
+ /**
1405
+ * Render one localized tool summary and lazily mounted result card.
1406
+ * @param props - tool state, summary, output, and navigation callbacks.
1407
+ * @returns the tool disclosure.
1408
+ */
1409
+ const ToolRow = (0, react.memo)(function ToolRow({ t, variant, toolName, icon, title, summary, summarySuffix, bodyRaw, output, askQuestion, errorSummary, terminal, diff, read, image, renderSlot, loadImage, search, web, details, state, filePath, filePathLine, onOpenFile, inspect, useDisclosure }) {
1410
+ const { expanded, toggle: toggleExpand } = useDisclosure();
1242
1411
  const terminalLabels = (0, react.useMemo)(() => terminalBlockLabels(t), [t]);
1243
1412
  const diffLabels = (0, react.useMemo)(() => diffBlockLabels(t), [t]);
1244
1413
  const readLabels = (0, react.useMemo)(() => readBlockLabels(t), [t]);
1245
1414
  const searchLabels = (0, react.useMemo)(() => searchBlockLabels(t), [t]);
1246
1415
  const webLabels = (0, react.useMemo)(() => webBlockLabels(t), [t]);
1247
- const terminalBody = terminal === void 0 || terminal === null ? null : localizeTerminalCardModel(terminal, t);
1416
+ const terminalBody = (0, react.useMemo)(() => terminal === void 0 || terminal === null ? null : localizeTerminalCardModel(terminal, t), [terminal, t]);
1248
1417
  const diffBody = diff ?? null;
1249
1418
  const readBody = read ?? null;
1250
1419
  const imageBody = image !== void 0 && image !== null && renderSlot !== void 0 && loadImage !== void 0 ? image : null;
1251
1420
  const searchBody = search ?? null;
1252
1421
  const webBody = web ?? null;
1253
1422
  const askQuestionBody = askQuestion ?? null;
1423
+ const detailsBody = details ?? null;
1254
1424
  const inputRaw = bodyRaw ?? null;
1255
1425
  const outputText = output ?? null;
1256
- const card = askQuestionBody ?? terminalBody ?? diffBody ?? readBody ?? imageBody ?? searchBody ?? webBody;
1426
+ const card = askQuestionBody ?? terminalBody ?? diffBody ?? readBody ?? imageBody ?? searchBody ?? webBody ?? detailsBody;
1257
1427
  const expandable = inputRaw !== null || outputText !== null || card !== null;
1258
1428
  const open = expanded && expandable;
1259
1429
  const bodyText = (0, react.useMemo)(() => open && card === null && inputRaw !== null ? formatToolBody(variant, inputRaw) : null, [
@@ -1263,26 +1433,186 @@ window.__ModuleLoader__.load({
1263
1433
  variant
1264
1434
  ]);
1265
1435
  const status = stateStatus$1(state, t);
1266
- const failureLine = state === "error" ? errorSummary ?? null : null;
1267
- const summaryText = failureLine ?? terminalBody?.description ?? summary;
1436
+ const running = state === "running";
1437
+ const normalSummary = terminalBody?.description ?? (open ? detailsBody?.expandedSummary ?? summary : summary);
1438
+ const summaryText = (state === "error" ? errorSummary ?? normalSummary : null) ?? normalSummary;
1268
1439
  const diffStat = (0, react.useMemo)(() => {
1269
1440
  if (diffBody === null) return null;
1270
1441
  const { added, removed } = (0, _deepseek_ai_dsh_client_ui_primitives.diffTotals)(diffBody.card.diffs);
1271
1442
  return `+${added} -${removed}`;
1272
1443
  }, [diffBody]);
1273
- const suffix = failureLine === null ? summarySuffix ?? diffStat : null;
1274
- const toggleExpand = () => {
1275
- setExpanded((v) => !v);
1276
- };
1277
- const openFile = filePath !== void 0 && onOpenFile !== void 0 && failureLine === null ? (event) => {
1444
+ const settledWithCue = state === "error" || state === "stopped";
1445
+ const suffix = settledWithCue ? null : summarySuffix ?? diffStat;
1446
+ const openFile = (0, react.useMemo)(() => filePath !== void 0 && onOpenFile !== void 0 && !settledWithCue ? (event) => {
1278
1447
  event.stopPropagation();
1279
1448
  if (filePathLine === void 0) onOpenFile(filePath);
1280
1449
  else onOpenFile(filePath, { line: filePathLine });
1281
- } : void 0;
1282
- const fileLinkKeyDown = (event) => {
1450
+ } : void 0, [
1451
+ filePath,
1452
+ filePathLine,
1453
+ onOpenFile,
1454
+ settledWithCue
1455
+ ]);
1456
+ const fileLinkKeyDown = (0, react.useCallback)((event) => {
1283
1457
  if (event.key === "Enter" || event.key === " ") event.stopPropagation();
1284
- };
1458
+ }, []);
1285
1459
  const cardBody = variant === "code" ? null : bodyText;
1460
+ const collapsedContent = (0, react.useMemo)(() => summaryText !== "" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1461
+ (0, react_jsx_runtime.jsx)("span", {
1462
+ className: ToolRow_module_css_default.sep,
1463
+ "aria-hidden": true
1464
+ }),
1465
+ openFile !== void 0 ? (0, react_jsx_runtime.jsx)("button", {
1466
+ type: "button",
1467
+ className: ToolRow_module_css_default.fileLink,
1468
+ onClick: openFile,
1469
+ onKeyDown: fileLinkKeyDown,
1470
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1471
+ active: running,
1472
+ children: summaryText
1473
+ })
1474
+ }) : (0, react_jsx_runtime.jsx)("span", {
1475
+ className: clsx(ToolRow_module_css_default.summary, state === "error" && ToolRow_module_css_default.errorSummary, state === "stopped" && ToolRow_module_css_default.stoppedSummary),
1476
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1477
+ active: running,
1478
+ children: summaryText
1479
+ })
1480
+ }),
1481
+ suffix !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1482
+ className: clsx(ToolRow_module_css_default.summarySuffix, suffix === diffStat && ToolRow_module_css_default.diffStat),
1483
+ active: running,
1484
+ children: suffix
1485
+ })
1486
+ ] }), [
1487
+ diffStat,
1488
+ fileLinkKeyDown,
1489
+ openFile,
1490
+ running,
1491
+ state,
1492
+ suffix,
1493
+ summaryText
1494
+ ]);
1495
+ const expandedContent = (0, react.useMemo)(() => open ? (0, react_jsx_runtime.jsxs)("div", {
1496
+ className: clsx(ToolRow_module_css_default.bodyWrap, detailsBody !== null && ToolRow_module_css_default.detailsBodyWrap),
1497
+ children: [askQuestionBody !== null ? (0, react_jsx_runtime.jsx)(AskQuestionCard, { card: askQuestionBody }) : terminalBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
1498
+ ...terminalBody.card,
1499
+ maxLines: Infinity,
1500
+ labels: terminalLabels,
1501
+ className: ToolRow_module_css_default.terminalBody
1502
+ }) : diffBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DiffBlock, {
1503
+ ...diffBody.card,
1504
+ labels: diffLabels,
1505
+ maxLines: 9,
1506
+ className: ToolRow_module_css_default.diffBody
1507
+ }) : readBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ReadBlock, {
1508
+ ...readBody,
1509
+ labels: readLabels,
1510
+ maxLines: 8,
1511
+ className: ToolRow_module_css_default.readBody
1512
+ }) : imageBody !== null ? (0, react_jsx_runtime.jsxs)("div", {
1513
+ className: ToolRow_module_css_default.imageBody,
1514
+ children: [
1515
+ (0, react_jsx_runtime.jsx)("div", {
1516
+ className: ToolRow_module_css_default.imageLabel,
1517
+ children: imageBody.label
1518
+ }),
1519
+ renderSlot !== void 0 && loadImage !== void 0 && renderSlot("tool.call.images", {
1520
+ images: imageBody.images,
1521
+ loadImage,
1522
+ align: "start"
1523
+ }),
1524
+ (0, react_jsx_runtime.jsx)("div", {
1525
+ className: ToolRow_module_css_default.imageMeta,
1526
+ children: imageBody.text
1527
+ })
1528
+ ]
1529
+ }) : searchBody !== null ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SearchBlock, {
1530
+ ...searchBody.card,
1531
+ labels: searchLabels,
1532
+ maxLines: 8,
1533
+ className: ToolRow_module_css_default.searchBody
1534
+ }), searchBody.recovery !== void 0 && (0, react_jsx_runtime.jsx)("div", {
1535
+ className: ToolRow_module_css_default.searchRecovery,
1536
+ children: searchBody.recovery
1537
+ })] }) : webBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.WebBlock, {
1538
+ ...webBody,
1539
+ labels: webLabels,
1540
+ className: ToolRow_module_css_default.webBody
1541
+ }) : detailsBody !== null ? (0, react_jsx_runtime.jsx)(ToolDetails, {
1542
+ model: detailsBody,
1543
+ hasInspect: inspect !== void 0,
1544
+ t,
1545
+ onOpenFile
1546
+ }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [variant === "code" && bodyText !== null && (0, react_jsx_runtime.jsx)("div", {
1547
+ className: ToolRow_module_css_default.bodyScroll,
1548
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.CodeBlock, {
1549
+ code: bodyText,
1550
+ lang: "typescript",
1551
+ copyLabel: t("copy"),
1552
+ copiedLabel: t("copied"),
1553
+ className: ToolRow_module_css_default.codeBody
1554
+ })
1555
+ }), (cardBody !== null || outputText !== null) && (0, react_jsx_runtime.jsxs)("div", {
1556
+ className: ToolRow_module_css_default.ioCard,
1557
+ children: [
1558
+ cardBody !== null && (0, react_jsx_runtime.jsxs)("div", {
1559
+ className: ToolRow_module_css_default.ioSection,
1560
+ children: [(0, react_jsx_runtime.jsx)("span", {
1561
+ className: ToolRow_module_css_default.ioLabel,
1562
+ children: t("row.input")
1563
+ }), (0, react_jsx_runtime.jsx)("span", {
1564
+ className: ToolRow_module_css_default.ioText,
1565
+ children: cardBody
1566
+ })]
1567
+ }),
1568
+ cardBody !== null && outputText !== null && (0, react_jsx_runtime.jsx)("span", {
1569
+ className: ToolRow_module_css_default.ioDivider,
1570
+ "aria-hidden": true
1571
+ }),
1572
+ outputText !== null && (0, react_jsx_runtime.jsxs)("div", {
1573
+ className: ToolRow_module_css_default.ioSection,
1574
+ children: [(0, react_jsx_runtime.jsx)("span", {
1575
+ className: ToolRow_module_css_default.ioLabel,
1576
+ children: t("row.output")
1577
+ }), (0, react_jsx_runtime.jsx)("span", {
1578
+ className: ToolRow_module_css_default.ioText,
1579
+ "data-error": state === "error" || void 0,
1580
+ children: outputText
1581
+ })]
1582
+ })
1583
+ ]
1584
+ })] }), inspect !== void 0 && (0, react_jsx_runtime.jsxs)("button", {
1585
+ type: "button",
1586
+ className: ToolRow_module_css_default.inspectButton,
1587
+ onClick: inspect,
1588
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutlineRegular, {}), t("row.inspect")]
1589
+ })]
1590
+ }) : void 0, [
1591
+ open,
1592
+ detailsBody,
1593
+ askQuestionBody,
1594
+ terminalBody,
1595
+ terminalLabels,
1596
+ diffBody,
1597
+ diffLabels,
1598
+ readBody,
1599
+ readLabels,
1600
+ imageBody,
1601
+ renderSlot,
1602
+ loadImage,
1603
+ searchBody,
1604
+ searchLabels,
1605
+ webBody,
1606
+ webLabels,
1607
+ inspect,
1608
+ t,
1609
+ onOpenFile,
1610
+ variant,
1611
+ bodyText,
1612
+ cardBody,
1613
+ outputText,
1614
+ state
1615
+ ]);
1286
1616
  return (0, react_jsx_runtime.jsxs)("div", {
1287
1617
  className: ToolRow_module_css_default.root,
1288
1618
  "data-variant": variant,
@@ -1296,140 +1626,32 @@ window.__ModuleLoader__.load({
1296
1626
  leadingClassName: ToolRow_module_css_default.leading,
1297
1627
  titleClassName: ToolRow_module_css_default.title,
1298
1628
  chevronClassName: ToolRow_module_css_default.chevron,
1299
- icon: leadingFor$1(state, icon),
1629
+ icon,
1300
1630
  title,
1631
+ running,
1301
1632
  open,
1302
1633
  expandable,
1303
1634
  expandOnRowClick: true,
1304
1635
  keepContentWhenOpen: true,
1305
1636
  onToggle: toggleExpand,
1306
- collapsedContent: summaryText !== "" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1307
- (0, react_jsx_runtime.jsx)("span", {
1308
- className: ToolRow_module_css_default.sep,
1309
- "aria-hidden": true
1310
- }),
1311
- openFile !== void 0 ? (0, react_jsx_runtime.jsx)("button", {
1312
- type: "button",
1313
- className: ToolRow_module_css_default.fileLink,
1314
- onClick: openFile,
1315
- onKeyDown: fileLinkKeyDown,
1316
- children: summaryText
1317
- }) : (0, react_jsx_runtime.jsx)("span", {
1318
- className: clsx(ToolRow_module_css_default.summary, failureLine !== null && ToolRow_module_css_default.errorSummary),
1319
- children: summaryText
1320
- }),
1321
- suffix !== null && (0, react_jsx_runtime.jsx)("span", {
1322
- className: clsx(ToolRow_module_css_default.summarySuffix, suffix === diffStat && ToolRow_module_css_default.diffStat),
1323
- children: suffix
1324
- })
1325
- ] }),
1326
- children: (0, react_jsx_runtime.jsxs)("div", {
1327
- className: ToolRow_module_css_default.bodyWrap,
1328
- children: [askQuestionBody !== null ? (0, react_jsx_runtime.jsx)(AskQuestionCard, { card: askQuestionBody }) : terminalBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
1329
- ...terminalBody.card,
1330
- maxLines: Infinity,
1331
- labels: terminalLabels,
1332
- className: ToolRow_module_css_default.terminalBody
1333
- }) : diffBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DiffBlock, {
1334
- ...diffBody.card,
1335
- labels: diffLabels,
1336
- maxLines: 9,
1337
- className: ToolRow_module_css_default.diffBody
1338
- }) : readBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ReadBlock, {
1339
- ...readBody,
1340
- labels: readLabels,
1341
- maxLines: 8,
1342
- className: ToolRow_module_css_default.readBody
1343
- }) : imageBody !== null ? (0, react_jsx_runtime.jsxs)("div", {
1344
- className: ToolRow_module_css_default.imageBody,
1345
- children: [
1346
- (0, react_jsx_runtime.jsx)("div", {
1347
- className: ToolRow_module_css_default.imageLabel,
1348
- children: imageBody.label
1349
- }),
1350
- renderSlot !== void 0 && loadImage !== void 0 && renderSlot("tool.call.images", {
1351
- images: imageBody.images,
1352
- loadImage,
1353
- align: "start"
1354
- }),
1355
- (0, react_jsx_runtime.jsx)("div", {
1356
- className: ToolRow_module_css_default.imageMeta,
1357
- children: imageBody.text
1358
- })
1359
- ]
1360
- }) : searchBody !== null ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SearchBlock, {
1361
- ...searchBody.card,
1362
- labels: searchLabels,
1363
- maxLines: 8,
1364
- className: ToolRow_module_css_default.searchBody
1365
- }), searchBody.recovery !== void 0 && (0, react_jsx_runtime.jsx)("div", {
1366
- className: ToolRow_module_css_default.searchRecovery,
1367
- children: searchBody.recovery
1368
- })] }) : webBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.WebBlock, {
1369
- ...webBody,
1370
- labels: webLabels,
1371
- className: ToolRow_module_css_default.webBody
1372
- }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [variant === "code" && bodyText !== null && (0, react_jsx_runtime.jsx)("div", {
1373
- className: ToolRow_module_css_default.bodyScroll,
1374
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.CodeBlock, {
1375
- code: bodyText,
1376
- lang: "typescript",
1377
- copyLabel: t("copy"),
1378
- copiedLabel: t("copied"),
1379
- className: ToolRow_module_css_default.codeBody
1380
- })
1381
- }), (cardBody !== null || outputText !== null) && (0, react_jsx_runtime.jsxs)("div", {
1382
- className: ToolRow_module_css_default.ioCard,
1383
- children: [
1384
- cardBody !== null && (0, react_jsx_runtime.jsxs)("div", {
1385
- className: ToolRow_module_css_default.ioSection,
1386
- children: [(0, react_jsx_runtime.jsx)("span", {
1387
- className: ToolRow_module_css_default.ioLabel,
1388
- children: t("row.input")
1389
- }), (0, react_jsx_runtime.jsx)("span", {
1390
- className: ToolRow_module_css_default.ioText,
1391
- children: cardBody
1392
- })]
1393
- }),
1394
- cardBody !== null && outputText !== null && (0, react_jsx_runtime.jsx)("span", {
1395
- className: ToolRow_module_css_default.ioDivider,
1396
- "aria-hidden": true
1397
- }),
1398
- outputText !== null && (0, react_jsx_runtime.jsxs)("div", {
1399
- className: ToolRow_module_css_default.ioSection,
1400
- children: [(0, react_jsx_runtime.jsx)("span", {
1401
- className: ToolRow_module_css_default.ioLabel,
1402
- children: t("row.output")
1403
- }), (0, react_jsx_runtime.jsx)("span", {
1404
- className: ToolRow_module_css_default.ioText,
1405
- "data-error": state === "error" || void 0,
1406
- children: outputText
1407
- })]
1408
- })
1409
- ]
1410
- })] }), inspect !== void 0 && (0, react_jsx_runtime.jsxs)("button", {
1411
- type: "button",
1412
- className: ToolRow_module_css_default.inspectButton,
1413
- onClick: inspect,
1414
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), t("row.inspect")]
1415
- })]
1416
- })
1637
+ collapsedContent,
1638
+ children: expandedContent
1417
1639
  })]
1418
1640
  });
1419
- }
1641
+ });
1420
1642
  //#endregion
1421
1643
  //#region lib/types/client/tool/toolviews/GenericToolCard.js
1422
1644
  /** Variant leading icons (figma table); all glyphs render at 14 inside the 16px leading box. */
1423
1645
  const VARIANT_ICONS = {
1424
- search: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 14 }),
1425
- read: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
1426
- bash: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutline14, { size: 14 }),
1427
- write: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
1428
- edit: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
1429
- code: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutline16, { size: 14 }),
1430
- others: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkle16, { size: 14 })
1646
+ search: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: 14 }),
1647
+ read: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutlineRegular, { size: 14 }),
1648
+ bash: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutlineRegular, { size: 14 }),
1649
+ write: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 }),
1650
+ edit: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 }),
1651
+ code: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutlineRegular, { size: 14 }),
1652
+ others: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkleRegular, { size: 14 })
1431
1653
  };
1432
- function GenericToolCard({ toolName, block, cwd, home, openFile, inspect, t }) {
1654
+ function GenericToolCard({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
1433
1655
  const model = toolRowModel(toolName, block, cwd, home);
1434
1656
  const autoReview = model.autoReviewDenial === null ? null : localizeAutoReviewDenial(model.autoReviewDenial, t);
1435
1657
  const terminal = terminalCardModel(block, cwd);
@@ -1440,6 +1662,7 @@ window.__ModuleLoader__.load({
1440
1662
  const state = model.state === "ok" && terminal !== null && terminalFailed(terminal) ? "error" : model.state;
1441
1663
  const singleFile = model.filePath !== void 0;
1442
1664
  return (0, react_jsx_runtime.jsx)(ToolRow, {
1665
+ useDisclosure,
1443
1666
  t,
1444
1667
  variant: model.variant,
1445
1668
  toolName,
@@ -1483,7 +1706,7 @@ window.__ModuleLoader__.load({
1483
1706
  return "kind" in node ? node.call?.name ?? "" : node.name;
1484
1707
  }
1485
1708
  /** One atomic call dispatched through the Tool-owned keyed slot. */
1486
- const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, block, openFile, cwd, home, inspectCall, loadImage, t, children }) {
1709
+ const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, block, openFile, cwd, home, inspectCall, loadImage, useDisclosure, t, children }) {
1487
1710
  const owner = (0, react.useMemo)(() => ({
1488
1711
  callId,
1489
1712
  toolName,
@@ -1492,7 +1715,8 @@ window.__ModuleLoader__.load({
1492
1715
  cwd,
1493
1716
  home,
1494
1717
  loadImage,
1495
- inspect: () => {
1718
+ useDisclosure,
1719
+ inspect: inspectCall === void 0 ? void 0 : () => {
1496
1720
  inspectCall(callId);
1497
1721
  }
1498
1722
  }), [
@@ -1503,7 +1727,8 @@ window.__ModuleLoader__.load({
1503
1727
  cwd,
1504
1728
  home,
1505
1729
  loadImage,
1506
- inspectCall
1730
+ inspectCall,
1731
+ useDisclosure
1507
1732
  ]);
1508
1733
  const autoReviewDenied = (0, react.useMemo)(() => toolRowModel(toolName, block).autoReviewDenial !== null, [toolName, block]);
1509
1734
  return (0, react_jsx_runtime.jsxs)("div", {
@@ -1522,7 +1747,7 @@ window.__ModuleLoader__.load({
1522
1747
  }), children]
1523
1748
  });
1524
1749
  });
1525
- const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, cwd, home, openFile, inspectCall, loadImage, t }) {
1750
+ const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, cwd, home, openFile, inspectCall, loadImage, useDisclosure, t }) {
1526
1751
  return (0, react_jsx_runtime.jsx)(ToolCall, {
1527
1752
  renderSlot,
1528
1753
  callId: block.callId,
@@ -1532,6 +1757,7 @@ window.__ModuleLoader__.load({
1532
1757
  cwd,
1533
1758
  home,
1534
1759
  inspectCall,
1760
+ useDisclosure,
1535
1761
  loadImage,
1536
1762
  t,
1537
1763
  children: block.subCalls.length > 0 ? (0, react_jsx_runtime.jsx)("div", {
@@ -1544,6 +1770,7 @@ window.__ModuleLoader__.load({
1544
1770
  home,
1545
1771
  openFile,
1546
1772
  inspectCall,
1773
+ useDisclosure,
1547
1774
  loadImage,
1548
1775
  t
1549
1776
  }, child.callId))
@@ -1556,7 +1783,7 @@ window.__ModuleLoader__.load({
1556
1783
  * @param props - whole-Tool owner data and the Tool-owned child-slot share.
1557
1784
  * @returns the Tool call tree.
1558
1785
  */
1559
- function ToolCallTree({ renderSlot, node, cwd, openFile, inspectCall, loadImage, useHostInfo, t }) {
1786
+ function ToolCallTree({ renderSlot, node, cwd, openFile, inspectCall, loadImage, useDisclosure, useHostInfo, t }) {
1560
1787
  const home = useHostInfo((info) => info.home);
1561
1788
  const block = node.data.root;
1562
1789
  return (0, react_jsx_runtime.jsx)(ToolCallBranch, {
@@ -1566,6 +1793,7 @@ window.__ModuleLoader__.load({
1566
1793
  home,
1567
1794
  openFile,
1568
1795
  inspectCall,
1796
+ useDisclosure,
1569
1797
  loadImage,
1570
1798
  t
1571
1799
  });
@@ -1665,7 +1893,7 @@ window.__ModuleLoader__.load({
1665
1893
  });
1666
1894
  }
1667
1895
  /** Summarizes a pending, answered, cancelled, or interrupted question set. */
1668
- function AskQuestionRow({ toolName, block, inspect, t }) {
1896
+ function AskQuestionRow({ toolName, block, inspect, useDisclosure, t }) {
1669
1897
  const model = toolRowModel(toolName, block);
1670
1898
  const code = "kind" in block ? block.error?.code : void 0;
1671
1899
  const argsRaw = ("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "";
@@ -1704,10 +1932,11 @@ window.__ModuleLoader__.load({
1704
1932
  }
1705
1933
  }
1706
1934
  return (0, react_jsx_runtime.jsx)(ToolRow, {
1935
+ useDisclosure,
1707
1936
  t,
1708
1937
  variant: model.variant,
1709
1938
  toolName,
1710
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutline14, {}),
1939
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutlineRegular, {}),
1711
1940
  title: t("ask.rowTitle"),
1712
1941
  summary,
1713
1942
  bodyRaw: transcript === null ? model.bodyRaw : null,
@@ -1731,7 +1960,7 @@ window.__ModuleLoader__.load({
1731
1960
  };
1732
1961
  //#endregion
1733
1962
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css.mjs
1734
- 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;position:relative;overflow:hidden}.CY-8Ka_root[data-state=running]:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite CY-8Ka_dsh-bash-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes CY-8Ka_dsh-bash-row-sweep{0%{left:-300px}90%,to{left:100%}}.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}.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;overflow:hidden}.CY-8Ka_errorSummary{color:var(--dsw-alias-state-error-primary)}.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}";
1963
+ 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}";
1735
1964
  const tagId = "@deepseek-ai/dsh-client-ui-tool/bash-sample.module.css";
1736
1965
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1737
1966
  const tag = document.createElement("style");
@@ -1745,7 +1974,6 @@ window.__ModuleLoader__.load({
1745
1974
  "card": "CY-8Ka_card",
1746
1975
  "chevron": "CY-8Ka_chevron",
1747
1976
  "chevronHover": "CY-8Ka_chevronHover",
1748
- "dsh-bash-row-sweep": "CY-8Ka_dsh-bash-row-sweep",
1749
1977
  "errorSummary": "CY-8Ka_errorSummary",
1750
1978
  "iconIdle": "CY-8Ka_iconIdle",
1751
1979
  "inspectButton": "CY-8Ka_inspectButton",
@@ -1757,6 +1985,7 @@ window.__ModuleLoader__.load({
1757
1985
  "leading": "CY-8Ka_leading",
1758
1986
  "root": "CY-8Ka_root",
1759
1987
  "sep": "CY-8Ka_sep",
1988
+ "stoppedSummary": "CY-8Ka_stoppedSummary",
1760
1989
  "summary": "CY-8Ka_summary",
1761
1990
  "terminal": "CY-8Ka_terminal",
1762
1991
  "title": "CY-8Ka_title",
@@ -1764,14 +1993,8 @@ window.__ModuleLoader__.load({
1764
1993
  };
1765
1994
  //#endregion
1766
1995
  //#region lib/types/client/tool/toolviews/bash-sample.js
1767
- function leadingFor(state) {
1768
- switch (state) {
1769
- case "error": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" });
1770
- case "stopped": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
1771
- default: return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutline14, { size: 14 });
1772
- }
1773
- }
1774
- /** Visually hidden status — StateDot is aria-hidden; AT needs a text label. */
1996
+ const BASH_ICON = (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutlineRegular, { size: 14 });
1997
+ /** Visually hidden status for the color-only running sweep and error tone. */
1775
1998
  function stateStatus(state, t) {
1776
1999
  switch (state) {
1777
2000
  case "running": return t("bash.running");
@@ -1780,14 +2003,20 @@ window.__ModuleLoader__.load({
1780
2003
  default: return null;
1781
2004
  }
1782
2005
  }
1783
- /** Renders expandable Bash output with an accessible lifecycle label. */
1784
- function BashRow({ toolName, block, sessionId, useSessions, inspect, t }) {
1785
- const model = toolRowModel(toolName, block);
1786
- const terminalModel = terminalCardModel(block, useSessions((list) => list.byId[sessionId]?.cwd));
1787
- const terminal = terminalModel === null ? null : localizeTerminalCardModel(terminalModel, t);
2006
+ /**
2007
+ * Render expandable Bash output with an accessible lifecycle label.
2008
+ * @param props - tool call, Session sources, locale, and inspection callback.
2009
+ * @returns the Bash output row.
2010
+ */
2011
+ const BashRow = (0, react.memo)(function BashRow({ toolName, block, sessionId, useSessions, inspect, useDisclosure, t }) {
2012
+ const model = (0, react.useMemo)(() => toolRowModel(toolName, block), [toolName, block]);
2013
+ const cwd = useSessions((list) => list.byId[sessionId]?.cwd);
2014
+ const terminalModel = (0, react.useMemo)(() => terminalCardModel(block, cwd), [block, cwd]);
2015
+ const terminal = (0, react.useMemo)(() => terminalModel === null ? null : localizeTerminalCardModel(terminalModel, t), [terminalModel, t]);
2016
+ const labels = (0, react.useMemo)(() => terminalBlockLabels(t), [t]);
1788
2017
  const state = model.state === "ok" && terminalModel !== null && terminalFailed(terminalModel) ? "error" : model.state;
1789
2018
  const status = stateStatus(state, t);
1790
- const [expanded, setExpanded] = (0, react.useState)(false);
2019
+ const { expanded, toggle: toggleExpand } = useDisclosure();
1791
2020
  const genericBody = terminal === null && (model.state === "error" || isSettledPersistentShellCall(block) || isSpilledShellCall(block)) && (model.bodyRaw !== null || model.output !== null);
1792
2021
  const expandable = terminal !== null || genericBody;
1793
2022
  const open = expanded && expandable;
@@ -1797,19 +2026,18 @@ window.__ModuleLoader__.load({
1797
2026
  model.variant,
1798
2027
  open
1799
2028
  ]);
1800
- const failureLine = model.state === "error" ? model.errorSummary : null;
1801
- const toggleExpand = () => {
1802
- setExpanded((v) => !v);
1803
- };
1804
- const toggleFromKeyboard = (event) => {
2029
+ const normalSummary = terminal?.description ?? model.summary;
2030
+ const settlementLine = state === "error" ? model.errorSummary ?? normalSummary : state === "stopped" ? t("bash.stopped") : null;
2031
+ const running = state === "running";
2032
+ const toggleFromKeyboard = (0, react.useCallback)((event) => {
1805
2033
  if (!expandable || event.key !== "Enter" && event.key !== " ") return;
1806
2034
  event.preventDefault();
1807
2035
  toggleExpand();
1808
- };
1809
- const leading = open ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: bash_sample_module_css_default.chevron }) : expandable ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
2036
+ }, [expandable, toggleExpand]);
2037
+ const leading = open ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutlineRegular, { className: bash_sample_module_css_default.chevron }) : expandable ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
1810
2038
  className: bash_sample_module_css_default.iconIdle,
1811
- children: leadingFor(state)
1812
- }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: clsx(bash_sample_module_css_default.chevron, bash_sample_module_css_default.chevronHover) })] }) : leadingFor(state);
2039
+ children: BASH_ICON
2040
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: clsx(bash_sample_module_css_default.chevron, bash_sample_module_css_default.chevronHover) })] }) : BASH_ICON;
1813
2041
  return (0, react_jsx_runtime.jsxs)("div", {
1814
2042
  className: bash_sample_module_css_default.card,
1815
2043
  children: [(0, react_jsx_runtime.jsxs)("div", {
@@ -1832,8 +2060,9 @@ window.__ModuleLoader__.load({
1832
2060
  className: bash_sample_module_css_default.visuallyHidden,
1833
2061
  children: status
1834
2062
  }),
1835
- (0, react_jsx_runtime.jsx)("span", {
2063
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
1836
2064
  className: bash_sample_module_css_default.title,
2065
+ active: running,
1837
2066
  children: t(model.titleKey)
1838
2067
  }),
1839
2068
  (0, react_jsx_runtime.jsx)("span", {
@@ -1841,8 +2070,11 @@ window.__ModuleLoader__.load({
1841
2070
  "aria-hidden": true
1842
2071
  }),
1843
2072
  (0, react_jsx_runtime.jsx)("span", {
1844
- className: clsx(bash_sample_module_css_default.summary, failureLine !== null && bash_sample_module_css_default.errorSummary),
1845
- children: failureLine ?? terminal?.description ?? model.summary
2073
+ className: clsx(bash_sample_module_css_default.summary, state === "error" && bash_sample_module_css_default.errorSummary, state === "stopped" && bash_sample_module_css_default.stoppedSummary),
2074
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TextShimmer, {
2075
+ active: running,
2076
+ children: settlementLine ?? normalSummary
2077
+ })
1846
2078
  })
1847
2079
  ]
1848
2080
  }), open && (0, react_jsx_runtime.jsxs)("div", {
@@ -1850,7 +2082,7 @@ window.__ModuleLoader__.load({
1850
2082
  children: [terminal !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
1851
2083
  ...terminal.card,
1852
2084
  maxLines: Infinity,
1853
- labels: terminalBlockLabels(t),
2085
+ labels,
1854
2086
  className: bash_sample_module_css_default.terminal
1855
2087
  }) : (0, react_jsx_runtime.jsxs)("div", {
1856
2088
  className: bash_sample_module_css_default.ioCard,
@@ -1885,11 +2117,11 @@ window.__ModuleLoader__.load({
1885
2117
  type: "button",
1886
2118
  className: bash_sample_module_css_default.inspectButton,
1887
2119
  onClick: inspect,
1888
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), t("row.inspect")]
2120
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutlineRegular, {}), t("row.inspect")]
1889
2121
  })]
1890
2122
  })]
1891
2123
  });
1892
- }
2124
+ });
1893
2125
  /** Registers the standalone Bash conversation-row sample. */
1894
2126
  const bashToolviewSample = {
1895
2127
  name: "bash-toolview-sample",
@@ -1907,14 +2139,15 @@ window.__ModuleLoader__.load({
1907
2139
  /**
1908
2140
  * Lets users expand an applied file diff and open the reported path.
1909
2141
  */
1910
- function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, t }) {
2142
+ function FileMutationRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
1911
2143
  const model = toolRowModel(toolName, block, cwd, home);
1912
2144
  const diff = diffCardModel(block);
1913
2145
  return (0, react_jsx_runtime.jsx)(ToolRow, {
2146
+ useDisclosure,
1914
2147
  t,
1915
2148
  variant: model.variant,
1916
2149
  toolName,
1917
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
2150
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineRegular, { size: 14 }),
1918
2151
  title: t(model.titleKey),
1919
2152
  summary: model.summary,
1920
2153
  output: model.output,
@@ -1954,13 +2187,14 @@ window.__ModuleLoader__.load({
1954
2187
  * @param card - the card props this row owns.
1955
2188
  * @returns the assembled ToolRow.
1956
2189
  */
1957
- function readFamilyRow({ toolName, block, cwd, home, openFile, inspect, t }, card) {
2190
+ function readFamilyRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }, card) {
1958
2191
  const model = toolRowModel(toolName, block, cwd, home);
1959
2192
  return (0, react_jsx_runtime.jsx)(ToolRow, {
2193
+ useDisclosure,
1960
2194
  t,
1961
2195
  variant: model.variant,
1962
2196
  toolName,
1963
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
2197
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutlineRegular, { size: 14 }),
1964
2198
  title: t(model.titleKey),
1965
2199
  summary: model.summary,
1966
2200
  bodyRaw: null,
@@ -2213,14 +2447,15 @@ window.__ModuleLoader__.load({
2213
2447
  glob: "tool.title.glob"
2214
2448
  };
2215
2449
  /** Lets users expand grep or glob results and recover capped searches. */
2216
- function SearchRow({ toolName, block, inspect, t }) {
2450
+ function SearchRow({ toolName, block, inspect, useDisclosure, t }) {
2217
2451
  const model = toolRowModel(toolName, block);
2218
2452
  const search = searchCardModel(block);
2219
2453
  return (0, react_jsx_runtime.jsx)(ToolRow, {
2454
+ useDisclosure,
2220
2455
  t,
2221
2456
  variant: model.variant,
2222
2457
  toolName,
2223
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 14 }),
2458
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: 14 }),
2224
2459
  title: t(toolName === "grep" ? SEARCH_TITLE_KEYS.grep : toolName === "glob" ? SEARCH_TITLE_KEYS.glob : model.titleKey),
2225
2460
  summary: model.summary,
2226
2461
  output: model.output,
@@ -2250,6 +2485,1440 @@ window.__ModuleLoader__.load({
2250
2485
  }
2251
2486
  };
2252
2487
  //#endregion
2488
+ //#region lib/types/client/tool/models/detail-model-shared.js
2489
+ /**
2490
+ * Narrow parsed JSON to an object record.
2491
+ * @param value - Parsed result or argument value.
2492
+ * @returns Whether named fields can be read.
2493
+ */
2494
+ function detailRecord(value) {
2495
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2496
+ }
2497
+ /**
2498
+ * Check a recorded string field that must contain visible text.
2499
+ * @param value - Parsed field value.
2500
+ * @returns Whether the field is a non-empty string after trimming.
2501
+ */
2502
+ function nonempty(value) {
2503
+ return typeof value === "string" && value.trim() !== "";
2504
+ }
2505
+ /**
2506
+ * Decode an entire JSON result without accepting a partial prefix.
2507
+ * @param text - Recorded text.
2508
+ * @returns Parsed JSON, or undefined for non-JSON output.
2509
+ */
2510
+ function detailJson(text) {
2511
+ try {
2512
+ return JSON.parse(text);
2513
+ } catch {
2514
+ return;
2515
+ }
2516
+ }
2517
+ const STATUS_KEYS = {
2518
+ running: "detail.status.running",
2519
+ idle: "detail.status.idle",
2520
+ ready: "detail.status.ready",
2521
+ inactive: "detail.status.inactive",
2522
+ provisioning: "detail.status.provisioning",
2523
+ failed: "detail.status.failed",
2524
+ error: "detail.status.failed",
2525
+ completed: "detail.status.completed",
2526
+ complete: "detail.status.completed",
2527
+ done: "detail.status.completed",
2528
+ pending: "detail.todo.pending",
2529
+ in_progress: "detail.todo.in_progress",
2530
+ deleted: "detail.status.deleted",
2531
+ killed: "detail.status.killed",
2532
+ blocked: "detail.goal.blocked",
2533
+ accepted: "detail.status.accepted",
2534
+ queued: "detail.status.queued"
2535
+ };
2536
+ /**
2537
+ * Give a recorded status its localized name and a static semantic color.
2538
+ * @param status - Result status, retained verbatim when the vocabulary is unknown.
2539
+ * @param t - Conversation translator.
2540
+ * @returns A badge that does not imply a live subscription.
2541
+ */
2542
+ function detailBadge(status, t) {
2543
+ const key = Object.hasOwn(STATUS_KEYS, status) ? STATUS_KEYS[status] : void 0;
2544
+ const tone = [
2545
+ "completed",
2546
+ "complete",
2547
+ "done",
2548
+ "accepted"
2549
+ ].includes(status) ? "success" : ["failed", "error"].includes(status) ? "error" : [
2550
+ "blocked",
2551
+ "killed",
2552
+ "pending",
2553
+ "queued",
2554
+ "inactive"
2555
+ ].includes(status) ? "warning" : [
2556
+ "running",
2557
+ "in_progress",
2558
+ "provisioning"
2559
+ ].includes(status) ? "info" : "neutral";
2560
+ return {
2561
+ label: key === void 0 ? status : t(key),
2562
+ tone
2563
+ };
2564
+ }
2565
+ const FIELD_KEYS = {
2566
+ id: "detail.field.id",
2567
+ revision: "detail.field.revision",
2568
+ platform: "detail.field.platform",
2569
+ provider: "detail.field.provider",
2570
+ model: "detail.field.model",
2571
+ role: "detail.field.role",
2572
+ context: "detail.field.context",
2573
+ ownerName: "detail.field.owner",
2574
+ ready: "detail.field.ready",
2575
+ blockedBy: "detail.field.dependencies",
2576
+ writeScopes: "detail.field.writeScopes",
2577
+ writeScopeWarnings: "detail.field.warnings",
2578
+ diagnostics: "detail.field.diagnostics",
2579
+ methods: "detail.field.methods",
2580
+ inputSchema: "detail.field.inputSchema",
2581
+ outputSchema: "detail.field.outputSchema",
2582
+ currentPackageId: "detail.field.currentPackage",
2583
+ nextPackageId: "detail.field.nextPackage",
2584
+ latestRun: "detail.field.latestRun",
2585
+ packages: "detail.field.packages",
2586
+ registrations: "detail.field.registrations",
2587
+ props: "detail.field.props",
2588
+ data: "detail.field.data",
2589
+ source: "detail.field.source",
2590
+ arguments: "row.input",
2591
+ content: "detail.field.content",
2592
+ message: "detail.field.message",
2593
+ messageId: "detail.field.messageId",
2594
+ status: "detail.state",
2595
+ root: "detail.field.root",
2596
+ pid: "detail.field.pid",
2597
+ type: "detail.field.type",
2598
+ time: "detail.field.time",
2599
+ seq: "detail.field.seq",
2600
+ turn: "detail.field.turn",
2601
+ step: "detail.field.step",
2602
+ callId: "detail.field.callId",
2603
+ agentsStarted: "detail.field.agents",
2604
+ output: "row.output",
2605
+ result: "detail.field.result"
2606
+ };
2607
+ /**
2608
+ * Name a known tool field while preserving extension-owned field names.
2609
+ * @param key - Recorded JSON property name.
2610
+ * @param t - Conversation translator.
2611
+ * @returns Localized known label or the original property name.
2612
+ */
2613
+ function detailLabel(key, t) {
2614
+ const label = Object.hasOwn(FIELD_KEYS, key) ? FIELD_KEYS[key] : void 0;
2615
+ return label === void 0 ? key : t(label);
2616
+ }
2617
+ function scalar(value, t) {
2618
+ if (value === null) return t("detail.none");
2619
+ if (typeof value === "boolean") return t(value ? "detail.yes" : "detail.no");
2620
+ return typeof value === "string" ? value : JSON.stringify(value);
2621
+ }
2622
+ const INSPECTION_KEY_ORDER = [
2623
+ "subject",
2624
+ "title",
2625
+ "name",
2626
+ "pluginId",
2627
+ "packageId",
2628
+ "id",
2629
+ "summary"
2630
+ ];
2631
+ const INSPECTION_DETAIL_KEYS = ["description", "purpose"];
2632
+ const MAX_INSPECTION_ITEMS = 40;
2633
+ /**
2634
+ * Project open inspection records into readable fields and named disclosures.
2635
+ * @param value - Parsed JSON, including provider-owned extension fields.
2636
+ * @param t - Conversation translator.
2637
+ * @param depth - Current disclosure depth; deeper records remain available as code.
2638
+ * @returns Entity rows preserving the order of visible values.
2639
+ */
2640
+ function inspectionItems(value, t, depth = 0) {
2641
+ if (depth > 4 && value !== null && typeof value === "object") return [{
2642
+ code: {
2643
+ text: JSON.stringify(value, null, 2),
2644
+ language: "json"
2645
+ },
2646
+ fields: []
2647
+ }];
2648
+ if (Array.isArray(value)) {
2649
+ const items = value.slice(0, MAX_INSPECTION_ITEMS).flatMap((entry) => inspectionItems(entry, t, depth + 1));
2650
+ if (value.length > MAX_INSPECTION_ITEMS) items.push({
2651
+ description: t("detail.moreInInspect", { count: value.length - MAX_INSPECTION_ITEMS }),
2652
+ fields: []
2653
+ });
2654
+ return items.length === 0 ? [{
2655
+ description: t("detail.empty"),
2656
+ fields: []
2657
+ }] : items;
2658
+ }
2659
+ if (!detailRecord(value)) return [{
2660
+ description: scalar(value, t),
2661
+ fields: []
2662
+ }];
2663
+ const titleKey = INSPECTION_KEY_ORDER.find((key) => typeof value[key] === "string" && value[key] !== "");
2664
+ const descriptionKey = INSPECTION_DETAIL_KEYS.find((key) => typeof value[key] === "string" && value[key] !== "");
2665
+ const title = titleKey === void 0 ? void 0 : String(value[titleKey]);
2666
+ const fields = [];
2667
+ const groups = [];
2668
+ for (const [key, field] of Object.entries(value)) {
2669
+ if (key === titleKey || key === descriptionKey || key === "status" && typeof field === "string") continue;
2670
+ if (key === "inputSchema" || key === "outputSchema") {
2671
+ groups.push({
2672
+ label: detailLabel(key, t),
2673
+ items: [{
2674
+ fields: [],
2675
+ code: {
2676
+ text: JSON.stringify(field, null, 2),
2677
+ language: "json"
2678
+ }
2679
+ }]
2680
+ });
2681
+ continue;
2682
+ }
2683
+ if (Array.isArray(field) && field.length === 0) continue;
2684
+ if (key === "arguments" && typeof field === "string") {
2685
+ const args = detailJson(field);
2686
+ if (detailRecord(args)) {
2687
+ groups.push({
2688
+ label: detailLabel(key, t),
2689
+ items: inspectionItems(args, t, depth + 1)
2690
+ });
2691
+ continue;
2692
+ }
2693
+ }
2694
+ if (field !== null && typeof field === "object") groups.push({
2695
+ label: detailLabel(key, t),
2696
+ items: inspectionItems(field, t, depth + 1)
2697
+ });
2698
+ else fields.push({
2699
+ label: detailLabel(key, t),
2700
+ value: scalar(field, t)
2701
+ });
2702
+ }
2703
+ return [{
2704
+ ...title === void 0 && typeof value.status !== "string" ? {} : { title: title ?? t("detail.field.result") },
2705
+ ...descriptionKey === void 0 ? {} : { description: String(value[descriptionKey]) },
2706
+ ...typeof value.status === "string" ? { badge: detailBadge(value.status, t) } : {},
2707
+ fields,
2708
+ ...groups.length === 0 ? {} : { groups }
2709
+ }];
2710
+ }
2711
+ /**
2712
+ * Give a result list consistent historical context and empty-state copy.
2713
+ * @param items - Recorded result rows.
2714
+ * @param summary - Collapsed-row summary.
2715
+ * @param t - Conversation translator.
2716
+ * @returns A complete compact detail model.
2717
+ */
2718
+ function detailList(items, summary, t) {
2719
+ return {
2720
+ items,
2721
+ summary,
2722
+ caption: t("detail.recordedResult"),
2723
+ empty: t("detail.empty")
2724
+ };
2725
+ }
2726
+ //#endregion
2727
+ //#region lib/types/client/tool/models/control-details-model.js
2728
+ const OUTPUT_TRUNCATED = "\n[output truncated]";
2729
+ function arg(args, key) {
2730
+ const value = args[key];
2731
+ return typeof value === "string" ? value : "";
2732
+ }
2733
+ function receipt(title, badge, t, fields = [], description) {
2734
+ return {
2735
+ ...detailList([{
2736
+ title,
2737
+ badge,
2738
+ fields,
2739
+ ...description === void 0 ? {} : { description }
2740
+ }], `${title} · ${badge.label}`, t),
2741
+ expandedSummary: title
2742
+ };
2743
+ }
2744
+ function agentList(text, json, t) {
2745
+ if (Array.isArray(json)) return detailList(inspectionItems(json, t), t("detail.agents.count", { count: json.length }), t);
2746
+ if (text === "(no subagents)") return detailList([], t("detail.agents.count", { count: 0 }), t);
2747
+ const items = [];
2748
+ for (const line of text.split("\n")) {
2749
+ const match = /^(\S+) \[([^\]]+)\](?: parent=(\S+) depth=(\d+))?(?: — (.*))?$/u.exec(line);
2750
+ if (match === null) return null;
2751
+ const [, id, state, parent, depth, title] = match;
2752
+ if (id === void 0 || state === void 0) return null;
2753
+ items.push({
2754
+ title: title ?? id,
2755
+ ...title === void 0 ? {} : { subtitle: id },
2756
+ badge: detailBadge(state, t),
2757
+ fields: parent === void 0 ? [] : [{
2758
+ label: t("detail.field.parent"),
2759
+ value: parent
2760
+ }, {
2761
+ label: t("detail.field.depth"),
2762
+ value: depth ?? ""
2763
+ }]
2764
+ });
2765
+ }
2766
+ return detailList(items, t("detail.agents.count", { count: items.length }), t);
2767
+ }
2768
+ function jobList(text, t) {
2769
+ if (text === "(no background jobs)") return detailList([], t("detail.jobs.count", { count: 0 }), t);
2770
+ const items = [];
2771
+ for (const line of text.split("\n")) {
2772
+ const match = /^(\S+) \[([^\]]+)\] (\S+) — (.*)$/u.exec(line);
2773
+ if (match === null) return null;
2774
+ const [, id, kind, state, title] = match;
2775
+ if (id === void 0 || kind === void 0 || state === void 0 || title === void 0) return null;
2776
+ items.push({
2777
+ title,
2778
+ subtitle: id,
2779
+ badge: detailBadge(state, t),
2780
+ fields: [{
2781
+ label: t("detail.field.type"),
2782
+ value: kind
2783
+ }]
2784
+ });
2785
+ }
2786
+ return detailList(items, t("detail.jobs.count", { count: items.length }), t);
2787
+ }
2788
+ function terminalList(text, t) {
2789
+ if (text === "(no terminal sessions)") return detailList([], t("detail.terminals.count", { count: 0 }), t);
2790
+ const items = [];
2791
+ for (const line of text.split("\n")) {
2792
+ const match = /^(\S+)(?: \((.*?)\))? \[([^\]]+)\] (running|exited code=(\S+) signal=(\S+))(?: pid=(\d+))?$/u.exec(line);
2793
+ if (match === null) return null;
2794
+ const [, id, name, type, state, exitCode, signal, pid] = match;
2795
+ if (id === void 0 || type === void 0 || state === void 0) return null;
2796
+ const fields = [{
2797
+ label: t("detail.field.type"),
2798
+ value: type
2799
+ }];
2800
+ if (pid !== void 0) fields.push({
2801
+ label: t("detail.field.pid"),
2802
+ value: pid
2803
+ });
2804
+ if (exitCode !== void 0) fields.push({
2805
+ label: t("detail.field.exitCode"),
2806
+ value: exitCode
2807
+ });
2808
+ if (signal !== void 0 && signal !== "null") fields.push({
2809
+ label: t("detail.field.signal"),
2810
+ value: signal
2811
+ });
2812
+ items.push({
2813
+ title: name ?? id,
2814
+ ...name === void 0 ? {} : { subtitle: id },
2815
+ badge: state === "running" ? detailBadge("running", t) : {
2816
+ label: t("detail.status.exited"),
2817
+ tone: exitCode === "0" ? "success" : "neutral"
2818
+ },
2819
+ fields
2820
+ });
2821
+ }
2822
+ return detailList(items, t("detail.terminals.count", { count: items.length }), t);
2823
+ }
2824
+ function lspDetails(args, text, t) {
2825
+ const file = arg(args, "file_path");
2826
+ const operation = arg(args, "operation");
2827
+ if (file === "" || typeof args.line !== "number" || typeof args.character !== "number") return null;
2828
+ const source = `${file}:${args.line}:${args.character}`;
2829
+ if (operation === "hover") return detailList([{
2830
+ title: source,
2831
+ location: {
2832
+ path: file,
2833
+ line: args.line
2834
+ },
2835
+ markdown: text,
2836
+ fields: []
2837
+ }], source, t);
2838
+ if (text === "No results.") return detailList([], t("detail.locations.count", { count: 0 }), t);
2839
+ const items = [];
2840
+ for (const line of text.split("\n")) {
2841
+ if (line.startsWith("… ")) {
2842
+ items.push({
2843
+ description: line,
2844
+ fields: []
2845
+ });
2846
+ continue;
2847
+ }
2848
+ const match = /^(.*):(\d+):(\d+)$/u.exec(line);
2849
+ if (match === null) return null;
2850
+ const [, path, row, column] = match;
2851
+ if (path === void 0 || row === void 0 || column === void 0) return null;
2852
+ const isUri = /^[a-z][a-z\d+.-]*:/iu.test(path) && !/^[a-z]:[\\/]/iu.test(path);
2853
+ items.push({
2854
+ title: path,
2855
+ subtitle: t("detail.location", {
2856
+ line: row,
2857
+ column
2858
+ }),
2859
+ fields: [],
2860
+ ...isUri ? {} : { location: {
2861
+ path,
2862
+ line: Number(row)
2863
+ } }
2864
+ });
2865
+ }
2866
+ const count = items.filter((item) => item.title !== void 0).length;
2867
+ return detailList(items, `${file} · ${t("detail.locations.count", { count })}`, t);
2868
+ }
2869
+ /**
2870
+ * Derive entity lists and operation receipts from supported recorded output formats.
2871
+ * @param name - Wire tool name, including Team-scoped aliases.
2872
+ * @param args - Parsed recorded arguments.
2873
+ * @param text - Successful recorded result text.
2874
+ * @param json - Parsed whole-result JSON, or undefined for non-JSON text.
2875
+ * @param t - Conversation translator.
2876
+ * @returns Compact details, or null when the output format is not recognized.
2877
+ */
2878
+ function controlDetails(name, args, text, json, t) {
2879
+ const target = arg(args, "target") || arg(args, "agent_id") || arg(args, "sessionId") || arg(args, "job_id");
2880
+ switch (name) {
2881
+ case "list_agents": return agentList(text, json, t);
2882
+ case "job_list": return jobList(text, t);
2883
+ case "terminal_list": return terminalList(text, t);
2884
+ case "lsp": return lspDetails(args, text, t);
2885
+ case "spawn_teammate":
2886
+ if (!detailRecord(json) || !detailRecord(json.member)) return null;
2887
+ return detailList(inspectionItems(json.member, t), arg(args, "name"), t);
2888
+ case "team_task_create":
2889
+ case "team_task_get":
2890
+ case "team_task_update":
2891
+ if (!detailRecord(json) || typeof json.subject !== "string") return null;
2892
+ return detailList(inspectionItems(json, t), json.subject, t);
2893
+ case "team_task_list":
2894
+ if (!detailRecord(json) || !Array.isArray(json.tasks)) return null;
2895
+ if (json.nextCursor !== void 0 && typeof json.nextCursor !== "number") return null;
2896
+ return {
2897
+ ...detailList(inspectionItems(json.tasks, t), t("detail.tasks.count", { count: json.tasks.length }), t),
2898
+ ...json.nextCursor === void 0 ? {} : { caption: t("detail.tasks.nextPage", { cursor: String(json.nextCursor) }) }
2899
+ };
2900
+ case "send_message": {
2901
+ const status = detailRecord(json) ? json.status : void 0;
2902
+ if (status === "accepted" || status === "queued") return receipt(target, {
2903
+ label: t(status === "queued" ? "detail.status.queued" : "detail.receipt.delivered"),
2904
+ tone: status === "queued" ? "warning" : "success"
2905
+ }, t, [], arg(args, "message"));
2906
+ return text === `message delivered to agent ${target}` ? receipt(target, {
2907
+ label: t("detail.receipt.delivered"),
2908
+ tone: "success"
2909
+ }, t, [], arg(args, "message")) : null;
2910
+ }
2911
+ case "interrupt_agent":
2912
+ if (detailRecord(json) && typeof json.previousStatus === "string") return receipt(target, {
2913
+ label: t("detail.receipt.interrupt"),
2914
+ tone: "warning"
2915
+ }, t, [{
2916
+ label: t("detail.field.previousStatus"),
2917
+ value: detailBadge(json.previousStatus, t).label
2918
+ }]);
2919
+ return text === `interrupt requested for agent ${target}` ? receipt(target, {
2920
+ label: t("detail.receipt.interrupt"),
2921
+ tone: "warning"
2922
+ }, t) : null;
2923
+ case "wait_agent":
2924
+ if (!detailRecord(json) || typeof json.timedOut !== "boolean") return null;
2925
+ if (detailRecord(json.noProgress) && typeof json.noProgress.message === "string") return detailList([{
2926
+ title: t("detail.wait.noProgress"),
2927
+ description: json.noProgress.message,
2928
+ fields: []
2929
+ }], t("detail.wait.noProgress"), t);
2930
+ return receipt(t("detail.wait.title"), {
2931
+ label: t(json.timedOut ? "detail.wait.timeout" : "detail.wait.changed"),
2932
+ tone: "neutral"
2933
+ }, t);
2934
+ case "subagent": {
2935
+ const started = /^started (background subagent job|subagent) (\S+)$/u.exec(text);
2936
+ if (started !== null) return receipt(arg(args, "prompt"), {
2937
+ label: t("detail.receipt.started"),
2938
+ tone: "info"
2939
+ }, t, [{
2940
+ label: t(started[1] === "subagent" ? "detail.field.agent" : "detail.field.job"),
2941
+ value: started[2] ?? ""
2942
+ }]);
2943
+ return detailList([{
2944
+ title: t("detail.agent.reply"),
2945
+ markdown: text,
2946
+ fields: [],
2947
+ groups: [{
2948
+ label: t("detail.field.task"),
2949
+ items: [{
2950
+ description: arg(args, "prompt"),
2951
+ fields: []
2952
+ }]
2953
+ }]
2954
+ }], t("detail.agent.reply"), t);
2955
+ }
2956
+ case "list_subagent_models": return detailList(text.split("\n").map((line) => {
2957
+ const split = line.indexOf(" — ");
2958
+ return split < 0 ? {
2959
+ description: line,
2960
+ fields: []
2961
+ } : {
2962
+ title: line.slice(0, split),
2963
+ description: line.slice(split + 3),
2964
+ fields: []
2965
+ };
2966
+ }), arg(args, "model") || arg(args, "provider") || t("detail.models.title"), t);
2967
+ case "job_output": {
2968
+ const match = /\n\[status: ([^,\]\n]+)(?:, ([^\]\n]+))?\]$/u.exec(text);
2969
+ if (match === null || match[1] === void 0) return null;
2970
+ const output = text.slice(0, match.index);
2971
+ const truncated = output.endsWith(OUTPUT_TRUNCATED);
2972
+ const code = truncated ? output.slice(0, -19) : output;
2973
+ const description = [match[2], truncated ? t("detail.output.truncated") : void 0].filter((value) => value !== void 0).join(" · ");
2974
+ return {
2975
+ ...detailList([{
2976
+ title: target,
2977
+ badge: detailBadge(match[1], t),
2978
+ fields: [],
2979
+ ...description === "" ? {} : { description },
2980
+ code: { text: code }
2981
+ }], `${target} · ${detailBadge(match[1], t).label}`, t),
2982
+ expandedSummary: target
2983
+ };
2984
+ }
2985
+ case "job_kill":
2986
+ if (text === `requested cancellation of job ${target}`) return receipt(target, {
2987
+ label: t("detail.receipt.cancel"),
2988
+ tone: "warning"
2989
+ }, t, [], arg(args, "reason"));
2990
+ if (text.startsWith(`job ${target} had already finished `)) return receipt(target, {
2991
+ label: t("detail.receipt.alreadyFinished"),
2992
+ tone: "neutral"
2993
+ }, t);
2994
+ return null;
2995
+ case "terminal_open": {
2996
+ const match = /^started terminal session (\S+)(?: \((.*?)\))? \[type: ([^\]]+)\]\n([\s\S]*)$/u.exec(text);
2997
+ if (match === null || match[1] === void 0 || match[3] === void 0 || match[4] === void 0) return null;
2998
+ return detailList([{
2999
+ title: match[2] ?? match[1],
3000
+ ...match[2] === void 0 ? {} : { subtitle: match[1] },
3001
+ badge: {
3002
+ label: t("detail.receipt.started"),
3003
+ tone: "info"
3004
+ },
3005
+ fields: [{
3006
+ label: t("detail.field.type"),
3007
+ value: match[3]
3008
+ }],
3009
+ code: { text: match[4] }
3010
+ }], match[2] ?? match[1], t);
3011
+ }
3012
+ case "terminal_read": {
3013
+ const match = /\n\[lines: (\d+)-(\d+) of (\d+)\](\n\[output truncated\])?$/u.exec(text);
3014
+ if (match === null) return null;
3015
+ return detailList([{
3016
+ title: target,
3017
+ subtitle: t("detail.output.lines", {
3018
+ begin: match[1] ?? "",
3019
+ end: match[2] ?? "",
3020
+ total: match[3] ?? ""
3021
+ }),
3022
+ fields: [],
3023
+ code: { text: text.slice(0, match.index) },
3024
+ ...match[4] === void 0 ? {} : { description: t("detail.output.truncated") }
3025
+ }], target, t);
3026
+ }
3027
+ case "terminal_signal": {
3028
+ const match = /^delivered (\S+) to foreground process group (\d+)$/u.exec(text);
3029
+ if (match === null || match[1] === void 0 || match[2] === void 0) return null;
3030
+ return receipt(target, {
3031
+ label: t("detail.receipt.signal"),
3032
+ tone: "success"
3033
+ }, t, [{
3034
+ label: t("detail.field.signal"),
3035
+ value: match[1]
3036
+ }, {
3037
+ label: t("detail.field.processGroup"),
3038
+ value: match[2]
3039
+ }]);
3040
+ }
3041
+ case "terminal_close":
3042
+ if (text === `closed terminal session ${target}`) return receipt(target, {
3043
+ label: t("detail.receipt.closed"),
3044
+ tone: "neutral"
3045
+ }, t);
3046
+ if (text === `terminal session ${target} was already closing`) return receipt(target, {
3047
+ label: t("detail.receipt.closing"),
3048
+ tone: "neutral"
3049
+ }, t);
3050
+ return null;
3051
+ default: return null;
3052
+ }
3053
+ }
3054
+ //#endregion
3055
+ //#region lib/types/client/tool/models/inspection-details-model.js
3056
+ function dateText(value, locale) {
3057
+ const date = new Date(value);
3058
+ if (!Number.isFinite(date.getTime())) return String(value);
3059
+ try {
3060
+ return new Intl.DateTimeFormat(locale, {
3061
+ dateStyle: "medium",
3062
+ timeStyle: "short"
3063
+ }).format(date);
3064
+ } catch {
3065
+ return String(value);
3066
+ }
3067
+ }
3068
+ function cordisDetails(name, args, value, t) {
3069
+ if (!detailRecord(value)) return null;
3070
+ if (name === "cordis_inspect_list") {
3071
+ if (!Array.isArray(value.providers)) return null;
3072
+ return detailList(inspectionItems(value.providers, t), t("detail.providers.count", { count: value.providers.length }), t);
3073
+ }
3074
+ if (name === "cordis_inspect_query") {
3075
+ if (!("data" in value) || typeof value.provider !== "string" || typeof value.method !== "string") return null;
3076
+ return detailList(inspectionItems(value.data, t), `${value.provider}.${value.method}`, t);
3077
+ }
3078
+ if (name === "cordis_inspect_self") {
3079
+ if (Array.isArray(value.plugins)) return detailList(inspectionItems(value.plugins, t), t("detail.plugins.count", { count: value.plugins.length }), t);
3080
+ return detailList(inspectionItems(value, t), String(args.pluginId ?? args.packageId ?? value.mode), t);
3081
+ }
3082
+ return null;
3083
+ }
3084
+ function workflowDetails(name, args, text, t) {
3085
+ if (name === "workflow") {
3086
+ const match = /^workflow "([\s\S]*?)" completed \((\d+) agents?\)\.\nReturn value:\n([\s\S]*)$/u.exec(text);
3087
+ if (match === null || match[1] === void 0 || match[2] === void 0 || match[3] === void 0) return null;
3088
+ const value = detailJson(match[3]);
3089
+ if (value === void 0) return null;
3090
+ return detailList([{
3091
+ title: match[1],
3092
+ badge: {
3093
+ label: t("detail.status.completed"),
3094
+ tone: "success"
3095
+ },
3096
+ fields: [{
3097
+ label: t("detail.field.agents"),
3098
+ value: match[2]
3099
+ }],
3100
+ ...typeof args.code === "string" ? { groups: [{
3101
+ label: t("detail.workflow.script"),
3102
+ items: [{
3103
+ fields: [],
3104
+ code: {
3105
+ text: args.code,
3106
+ language: "javascript"
3107
+ }
3108
+ }]
3109
+ }] } : {}
3110
+ }, ...inspectionItems(value, t)], match[1], t);
3111
+ }
3112
+ const split = text.indexOf("\nFinal report:\n");
3113
+ if (split < 0) return null;
3114
+ const header = text.slice(0, split);
3115
+ const rounds = /\b(\d+) rounds?\b/u.exec(header)?.[1];
3116
+ const report = detailJson(text.slice(split + 15));
3117
+ if (!detailRecord(report) || typeof report.summary !== "string" || !Array.isArray(report.evidence) || !report.evidence.every((value) => typeof value === "string") || !Array.isArray(report.nextSteps) || !report.nextSteps.every((value) => typeof value === "string") || typeof report.blocker !== "string") return null;
3118
+ const badge = header.startsWith("Ralph worker reported completion ") ? {
3119
+ label: t("detail.ralph.reportedComplete"),
3120
+ tone: "success"
3121
+ } : header.startsWith("Ralph worker reported a blocker ") ? {
3122
+ label: t("detail.ralph.reportedBlocker"),
3123
+ tone: "warning"
3124
+ } : header.startsWith("Ralph reached its ") ? {
3125
+ label: t("detail.ralph.limit"),
3126
+ tone: "warning"
3127
+ } : void 0;
3128
+ if (badge === void 0) return null;
3129
+ const groups = [];
3130
+ if (report.nextSteps.length > 0) groups.push({
3131
+ label: t("detail.report.nextSteps"),
3132
+ items: [{
3133
+ fields: [],
3134
+ lines: report.nextSteps
3135
+ }]
3136
+ });
3137
+ if (typeof args.objective === "string") groups.push({
3138
+ label: t("detail.field.task"),
3139
+ items: [{
3140
+ fields: [],
3141
+ description: args.objective
3142
+ }]
3143
+ });
3144
+ const fields = rounds === void 0 ? [] : [{
3145
+ label: t("detail.goal.rounds"),
3146
+ value: rounds
3147
+ }];
3148
+ if (report.blocker !== "") fields.push({
3149
+ label: t("detail.goal.reason"),
3150
+ value: report.blocker
3151
+ });
3152
+ return detailList([{
3153
+ title: report.summary,
3154
+ badge,
3155
+ fields,
3156
+ ...report.evidence.length === 0 ? {} : { lines: report.evidence },
3157
+ groups
3158
+ }], report.summary, t);
3159
+ }
3160
+ const TRACE_FIELDS = {
3161
+ Created: "detail.field.time",
3162
+ Availability: "detail.field.availability",
3163
+ Parent: "detail.field.parent",
3164
+ "Best match": "detail.field.bestMatch",
3165
+ Target: "detail.field.target",
3166
+ "Replaced by": "detail.trace.replacedBy",
3167
+ "Replacement chain": "detail.trace.replacementChain",
3168
+ "Events replaced by target": "detail.trace.replaces",
3169
+ "Events cited directly as sources": "detail.trace.sources",
3170
+ "Direct derived events": "detail.trace.derived"
3171
+ };
3172
+ function textFields(text, t, locale) {
3173
+ return text.split("\n").flatMap((line) => {
3174
+ const match = /^\s*([^:]+): (.+)$/u.exec(line);
3175
+ if (match === null || match[1] === void 0 || match[2] === void 0) return [];
3176
+ const key = Object.hasOwn(TRACE_FIELDS, match[1]) ? TRACE_FIELDS[match[1]] : void 0;
3177
+ if (key === void 0) return [];
3178
+ return [{
3179
+ label: t(key),
3180
+ value: match[1] === "Created" ? dateText(match[2], locale) : match[2] === "none" ? t("detail.none") : match[2]
3181
+ }];
3182
+ });
3183
+ }
3184
+ function searchDetails(name, text, t, locale) {
3185
+ if (text === "No prior session matches found." || text.endsWith("\n\nNo prior event matches found.")) return detailList([], t("detail.matches.count", { count: 0 }), t);
3186
+ const blocks = text.split(/\n(?=\d+\. )/u).filter((block) => /^\d+\. /u.test(block));
3187
+ if (blocks.length === 0) return null;
3188
+ const items = [];
3189
+ for (const block of blocks) {
3190
+ const snippet = /\n\s*Snippet: ([\s\S]*?)(?:\n\nResult cap reached\.|$)/u.exec(block)?.[1];
3191
+ if (name === "session_search") {
3192
+ const match = /^\d+\. Session (\S+) — (.*)/u.exec(block);
3193
+ if (match === null || match[1] === void 0 || match[2] === void 0) return null;
3194
+ items.push({
3195
+ title: match[2],
3196
+ subtitle: match[1],
3197
+ ...snippet === void 0 ? {} : { description: snippet.trimEnd() },
3198
+ fields: textFields(block, t, locale)
3199
+ });
3200
+ } else {
3201
+ const match = /^\d+\. seq (\d+) \| ([^|]+) \| ([^|]+) \| ([^\n]+)/u.exec(block);
3202
+ if (match === null || match[1] === void 0 || match[2] === void 0 || match[3] === void 0 || match[4] === void 0) return null;
3203
+ items.push({
3204
+ title: snippet?.trimEnd() ?? match[2],
3205
+ subtitle: `${match[2].trim()} · #${match[1]}`,
3206
+ fields: [{
3207
+ label: t("detail.field.time"),
3208
+ value: dateText(match[4], locale)
3209
+ }, {
3210
+ label: t("detail.field.surface"),
3211
+ value: match[3].trim()
3212
+ }]
3213
+ });
3214
+ }
3215
+ }
3216
+ return {
3217
+ ...detailList(items, t("detail.matches.count", { count: items.length }), t),
3218
+ ...text.includes("Result cap reached.") ? { caption: t("detail.matches.capped") } : {}
3219
+ };
3220
+ }
3221
+ function eventReadDetails(text, t, locale) {
3222
+ const match = /^Session (\S+) — ([^\n]*)\nTarget event seq (\d+):\n```json\n([\s\S]*?)\n```([\s\S]*)$/u.exec(text);
3223
+ if (match === null || match[1] === void 0 || match[2] === void 0 || match[3] === void 0 || match[4] === void 0) return null;
3224
+ const event = detailJson(match[4]);
3225
+ if (!detailRecord(event) || typeof event.type !== "string" || !detailRecord(event.data)) return null;
3226
+ const fields = [{
3227
+ label: t("detail.field.seq"),
3228
+ value: match[3]
3229
+ }];
3230
+ if (typeof event.time === "number") fields.push({
3231
+ label: t("detail.field.time"),
3232
+ value: dateText(event.time, locale)
3233
+ });
3234
+ const groups = [];
3235
+ const adjacent = match[5]?.trim();
3236
+ if (adjacent) groups.push({
3237
+ label: t("detail.event.neighbors"),
3238
+ items: [{
3239
+ fields: [],
3240
+ description: adjacent
3241
+ }]
3242
+ });
3243
+ return detailList([
3244
+ {
3245
+ title: event.type,
3246
+ subtitle: `${match[2]} · ${match[1]}`,
3247
+ fields
3248
+ },
3249
+ ...inspectionItems(event.data, t),
3250
+ ...groups.length === 0 ? [] : [{
3251
+ fields: [],
3252
+ groups
3253
+ }]
3254
+ ], `${event.type} · #${match[3]}`, t);
3255
+ }
3256
+ function traceDetails(name, text, t, locale) {
3257
+ const match = /^Session (\S+) — ([^\n]*)\n([\s\S]*)$/u.exec(text);
3258
+ if (match === null || match[1] === void 0 || match[2] === void 0 || match[3] === void 0) return null;
3259
+ if (name === "session_event_trace") return detailList([{
3260
+ title: match[2],
3261
+ subtitle: match[1],
3262
+ fields: textFields(match[3], t, locale)
3263
+ }], match[2], t);
3264
+ const sections = match[3].split("\n\n");
3265
+ const items = [{
3266
+ title: match[2],
3267
+ subtitle: match[1],
3268
+ fields: textFields(sections[0] ?? "", t, locale)
3269
+ }];
3270
+ for (const section of sections.slice(1)) {
3271
+ const firstBreak = section.indexOf("\n");
3272
+ const label = section.startsWith("Ancestors (nearest first):") ? t("detail.trace.ancestors") : section.startsWith("Descendants:") ? t("detail.trace.descendants") : void 0;
3273
+ if (label === void 0 || firstBreak < 0) return null;
3274
+ const body = section.slice(firstBreak + 1);
3275
+ items.push({
3276
+ title: label,
3277
+ fields: [],
3278
+ ...body === "- none" || body === "- none (target is a root session)" ? { description: t("detail.none") } : { lines: body.split("\n").map((line) => line.replace(/^(\s*)- /u, "$1")) }
3279
+ });
3280
+ }
3281
+ return detailList(items, match[2], t);
3282
+ }
3283
+ /**
3284
+ * Present successful inspection, query, and workflow text as named records.
3285
+ * @param name - Wire tool name.
3286
+ * @param args - Recorded argument object.
3287
+ * @param text - Recorded result text.
3288
+ * @param json - Parsed whole-result JSON, or undefined for non-JSON text.
3289
+ * @param t - Conversation translator.
3290
+ * @param locale - Date display locale.
3291
+ * @returns Structured details, or null when an output format is unknown.
3292
+ */
3293
+ function inspectionDetails(name, args, text, json, t, locale) {
3294
+ if (hasSpillNotice(text)) return null;
3295
+ switch (name) {
3296
+ case "cordis_inspect_list":
3297
+ case "cordis_inspect_query":
3298
+ case "cordis_inspect_self": return cordisDetails(name, args, json, t);
3299
+ case "workflow":
3300
+ case "ralph": return workflowDetails(name, args, text, t);
3301
+ case "session_search":
3302
+ case "session_event_search": return searchDetails(name, text, t, locale);
3303
+ case "session_event_read": return eventReadDetails(text, t, locale);
3304
+ case "session_trace":
3305
+ case "session_event_trace": return traceDetails(name, text, t, locale);
3306
+ default: return null;
3307
+ }
3308
+ }
3309
+ //#endregion
3310
+ //#region lib/types/client/tool/models/details-card-model.js
3311
+ function count(value) {
3312
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
3313
+ }
3314
+ function formatDate(date, locale, fallback) {
3315
+ try {
3316
+ return new Intl.DateTimeFormat(locale, {
3317
+ year: "numeric",
3318
+ month: "short",
3319
+ day: "numeric",
3320
+ hour: "2-digit",
3321
+ minute: "2-digit",
3322
+ second: "2-digit",
3323
+ timeZoneName: "short"
3324
+ }).format(date);
3325
+ } catch {
3326
+ return fallback;
3327
+ }
3328
+ }
3329
+ /**
3330
+ * Derive the compact todo list from a todo_write call.
3331
+ * @param args - Parsed todo_write arguments.
3332
+ * @param t - Conversation dictionary translator.
3333
+ * @returns Localized todo details, or null for unsupported input.
3334
+ */
3335
+ function todosDetail(args, t) {
3336
+ if (!Array.isArray(args.todos)) return null;
3337
+ const items = [];
3338
+ const seen = /* @__PURE__ */ new Set();
3339
+ for (const todo of args.todos) {
3340
+ if (!detailRecord(todo) || !nonempty(todo.content)) return null;
3341
+ const status = todo.status;
3342
+ if (status !== "completed" && status !== "in_progress" && status !== "pending") return null;
3343
+ const title = todo.content.trim();
3344
+ if (seen.has(title)) return null;
3345
+ seen.add(title);
3346
+ items.push({
3347
+ title,
3348
+ status: {
3349
+ value: status,
3350
+ label: t(`detail.todo.${status}`)
3351
+ },
3352
+ fields: []
3353
+ });
3354
+ }
3355
+ return {
3356
+ items,
3357
+ empty: t("detail.todo.empty")
3358
+ };
3359
+ }
3360
+ function goalDetail(value, t) {
3361
+ if (!detailRecord(value)) return null;
3362
+ if (value.goal === null) return {
3363
+ items: [],
3364
+ empty: t("detail.goal.empty")
3365
+ };
3366
+ const goal = value.goal;
3367
+ if (!detailRecord(goal) || !nonempty(goal.id) || !nonempty(goal.objective) || !count(goal.revision) || !count(goal.roundsStarted) || !count(goal.maxGoalRounds)) return null;
3368
+ const phase = goal.phase;
3369
+ if (phase !== "active" && phase !== "paused" && phase !== "blocked" && phase !== "complete") return null;
3370
+ if (value.activation !== "armed" && value.activation !== "disarmed") return null;
3371
+ const fields = [{
3372
+ label: t("detail.state"),
3373
+ value: t(phase === "active" && value.activation === "disarmed" ? "detail.goal.disarmed" : `detail.goal.${phase}`)
3374
+ }, {
3375
+ label: t("detail.goal.rounds"),
3376
+ value: `${goal.roundsStarted} / ${goal.maxGoalRounds}`
3377
+ }];
3378
+ if (goal.blockedReason !== void 0) {
3379
+ if (!detailRecord(goal.blockedReason) || !nonempty(goal.blockedReason.code) || !nonempty(goal.blockedReason.message)) return null;
3380
+ fields.push({
3381
+ label: t("detail.goal.reason"),
3382
+ value: goal.blockedReason.message
3383
+ });
3384
+ }
3385
+ return { items: [{
3386
+ title: goal.objective,
3387
+ fields
3388
+ }] };
3389
+ }
3390
+ function interval(seconds, t) {
3391
+ if (seconds % 86400 === 0) return t("detail.days", { count: seconds / 86400 });
3392
+ if (seconds % 3600 === 0) return t("detail.hours", { count: seconds / 3600 });
3393
+ if (seconds % 60 === 0) return t("detail.minutes", { count: seconds / 60 });
3394
+ return t("detail.seconds", { count: seconds });
3395
+ }
3396
+ function scheduleItem(value, t, locale) {
3397
+ if (!detailRecord(value) || !nonempty(value.id) || !nonempty(value.prompt) || typeof value.scheduledAt !== "string" || value.deliveryMode !== "session-local" || value.state !== "scheduled" && value.state !== "overdue") return null;
3398
+ const date = new Date(value.scheduledAt);
3399
+ if (!Number.isFinite(date.getTime()) || date.toISOString() !== value.scheduledAt) return null;
3400
+ let frequency;
3401
+ switch (value.kind) {
3402
+ case "at":
3403
+ frequency = t("detail.schedule.once");
3404
+ break;
3405
+ case "after":
3406
+ if (!count(value.afterSeconds) || value.afterSeconds === 0) return null;
3407
+ frequency = t("detail.schedule.once");
3408
+ break;
3409
+ case "every":
3410
+ if (!count(value.everySeconds) || value.everySeconds === 0) return null;
3411
+ frequency = t("detail.schedule.every", { interval: interval(value.everySeconds, t) });
3412
+ break;
3413
+ default: return null;
3414
+ }
3415
+ const dateText = formatDate(date, locale, value.scheduledAt);
3416
+ return {
3417
+ title: value.prompt,
3418
+ fields: [
3419
+ {
3420
+ label: t("detail.schedule.when"),
3421
+ value: dateText
3422
+ },
3423
+ {
3424
+ label: t("detail.schedule.frequency"),
3425
+ value: frequency
3426
+ },
3427
+ {
3428
+ label: t("detail.state"),
3429
+ value: t(`detail.schedule.${value.state}`)
3430
+ }
3431
+ ]
3432
+ };
3433
+ }
3434
+ /**
3435
+ * Derive a supported successful result, retaining generic output on unknown or malformed data.
3436
+ * @param block - Logged root or nested Tool call and its optional result.
3437
+ * @param t - Conversation dictionary translator.
3438
+ * @param locale - Display locale for absolute dates in the viewer's time zone.
3439
+ * @returns Localized detail data, or null for raw input/output.
3440
+ */
3441
+ function detailsCardModel(block, t, locale) {
3442
+ if (!("kind" in block) || block.isError) return null;
3443
+ const call = parsedToolCall(block);
3444
+ if (call === null) return null;
3445
+ const text = singleResultText(block);
3446
+ if (text === void 0) return null;
3447
+ const value = detailJson(text);
3448
+ const details = controlDetails(call.name, call.args, text, value, t) ?? inspectionDetails(call.name, call.args, text, value, t, locale);
3449
+ if (details !== null) return details;
3450
+ if (value === void 0) return null;
3451
+ switch (call.name) {
3452
+ case "create_goal":
3453
+ case "get_goal":
3454
+ case "update_goal": return goalDetail(value, t);
3455
+ case "schedule_create": {
3456
+ const item = scheduleItem(value, t, locale);
3457
+ return item === null ? null : { items: [item] };
3458
+ }
3459
+ case "schedule_list": {
3460
+ if (!Array.isArray(value)) return null;
3461
+ const items = [];
3462
+ for (const entry of value) {
3463
+ const item = scheduleItem(entry, t, locale);
3464
+ if (item === null) return null;
3465
+ items.push(item);
3466
+ }
3467
+ return {
3468
+ items,
3469
+ summary: t("detail.schedule.count", { count: items.length }),
3470
+ empty: t("detail.schedule.empty")
3471
+ };
3472
+ }
3473
+ case "schedule_delete":
3474
+ if (!detailRecord(value) || !nonempty(value.id) || value.deleted !== true) return null;
3475
+ return { items: [{
3476
+ title: value.id,
3477
+ fields: [{
3478
+ label: t("detail.state"),
3479
+ value: t("detail.schedule.deleted")
3480
+ }]
3481
+ }] };
3482
+ default: return null;
3483
+ }
3484
+ }
3485
+ //#endregion
3486
+ //#region lib/types/client/tool/toolviews/details-row.js
3487
+ /** 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
+ const LSP_TITLE_KEYS = {
3527
+ goToDefinition: "tool.title.findDefinition",
3528
+ findReferences: "tool.title.findReferences",
3529
+ goToImplementation: "tool.title.findImplementation",
3530
+ hover: "tool.title.hoverSymbol"
3531
+ };
3532
+ function detailIcon(toolName) {
3533
+ if (toolName.startsWith("schedule_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconClockOutlineRegular, { size: 14 });
3534
+ if (toolName.endsWith("_goal")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGoalOutlineRegular, { size: 14 });
3535
+ if (toolName.startsWith("cordis_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCordisPluginOutlineRegular, {});
3536
+ if (toolName.startsWith("terminal_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutlineRegular, { size: 14 });
3537
+ if (toolName.startsWith("session_") || toolName === "lsp") return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { size: 14 });
3538
+ if (toolName.startsWith("job_") || toolName.startsWith("team_task_")) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutlineRegular, {});
3539
+ if (toolName === "workflow" || toolName === "ralph") return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { size: 14 });
3540
+ return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconAgentPresetOutlineRegular, { size: 14 });
3541
+ }
3542
+ /**
3543
+ * Present recorded entities, receipts, and report fields in the existing expandable row.
3544
+ * @param props - Tool call, row actions, and locale supplied by the keyed slot.
3545
+ * @returns A Tool row with structured details or generic input/output.
3546
+ */
3547
+ function DetailsRow({ toolName, block, cwd, home, openFile, inspect, useDisclosure, t }) {
3548
+ const model = toolRowModel(toolName, block, cwd, home);
3549
+ const locale = document.documentElement.lang;
3550
+ const details = (0, react.useMemo)(() => detailsCardModel(block, t, locale), [
3551
+ block,
3552
+ t,
3553
+ locale
3554
+ ]);
3555
+ 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;
3557
+ return (0, react_jsx_runtime.jsx)(ToolRow, {
3558
+ useDisclosure,
3559
+ t,
3560
+ variant: model.variant,
3561
+ toolName,
3562
+ icon: detailIcon(toolName),
3563
+ title: t(titleKey),
3564
+ summary: details?.summary ?? details?.items[0]?.title ?? details?.empty ?? model.summary,
3565
+ details,
3566
+ bodyRaw: model.bodyRaw,
3567
+ output: model.output,
3568
+ errorSummary: model.errorSummary,
3569
+ state: model.state,
3570
+ inspect,
3571
+ onOpenFile: openFile
3572
+ });
3573
+ }
3574
+ /** Register recorded-result details through the standard atomic Tool slot. */
3575
+ const detailsToolview = {
3576
+ name: "details-toolview",
3577
+ inject: ["slots"],
3578
+ apply(ctx) {
3579
+ ctx.slots.inject("tool.call.toolview", function* () {
3580
+ yield ctx.slots.register({
3581
+ name: "tool.call.toolview",
3582
+ key: "create_goal",
3583
+ locale: CONVERSATION_NS
3584
+ }, DetailsRow);
3585
+ yield ctx.slots.register({
3586
+ name: "tool.call.toolview",
3587
+ key: "get_goal",
3588
+ locale: CONVERSATION_NS
3589
+ }, DetailsRow);
3590
+ yield ctx.slots.register({
3591
+ name: "tool.call.toolview",
3592
+ key: "update_goal",
3593
+ locale: CONVERSATION_NS
3594
+ }, DetailsRow);
3595
+ yield ctx.slots.register({
3596
+ name: "tool.call.toolview",
3597
+ key: "schedule_create",
3598
+ locale: CONVERSATION_NS
3599
+ }, DetailsRow);
3600
+ yield ctx.slots.register({
3601
+ name: "tool.call.toolview",
3602
+ key: "schedule_list",
3603
+ locale: CONVERSATION_NS
3604
+ }, DetailsRow);
3605
+ yield ctx.slots.register({
3606
+ name: "tool.call.toolview",
3607
+ key: "schedule_delete",
3608
+ locale: CONVERSATION_NS
3609
+ }, DetailsRow);
3610
+ yield ctx.slots.register({
3611
+ name: "tool.call.toolview",
3612
+ key: "cordis_inspect_list",
3613
+ locale: CONVERSATION_NS
3614
+ }, DetailsRow);
3615
+ yield ctx.slots.register({
3616
+ name: "tool.call.toolview",
3617
+ key: "cordis_inspect_query",
3618
+ locale: CONVERSATION_NS
3619
+ }, DetailsRow);
3620
+ yield ctx.slots.register({
3621
+ name: "tool.call.toolview",
3622
+ key: "cordis_inspect_self",
3623
+ locale: CONVERSATION_NS
3624
+ }, DetailsRow);
3625
+ yield ctx.slots.register({
3626
+ name: "tool.call.toolview",
3627
+ key: "workflow",
3628
+ locale: CONVERSATION_NS
3629
+ }, DetailsRow);
3630
+ yield ctx.slots.register({
3631
+ name: "tool.call.toolview",
3632
+ key: "ralph",
3633
+ locale: CONVERSATION_NS
3634
+ }, DetailsRow);
3635
+ yield ctx.slots.register({
3636
+ name: "tool.call.toolview",
3637
+ key: "session_event_read",
3638
+ locale: CONVERSATION_NS
3639
+ }, DetailsRow);
3640
+ yield ctx.slots.register({
3641
+ name: "tool.call.toolview",
3642
+ key: "session_event_search",
3643
+ locale: CONVERSATION_NS
3644
+ }, DetailsRow);
3645
+ yield ctx.slots.register({
3646
+ name: "tool.call.toolview",
3647
+ key: "session_event_trace",
3648
+ locale: CONVERSATION_NS
3649
+ }, DetailsRow);
3650
+ yield ctx.slots.register({
3651
+ name: "tool.call.toolview",
3652
+ key: "session_search",
3653
+ locale: CONVERSATION_NS
3654
+ }, DetailsRow);
3655
+ yield ctx.slots.register({
3656
+ name: "tool.call.toolview",
3657
+ key: "session_trace",
3658
+ locale: CONVERSATION_NS
3659
+ }, DetailsRow);
3660
+ yield ctx.slots.register({
3661
+ name: "tool.call.toolview",
3662
+ key: "list_subagent_models",
3663
+ locale: CONVERSATION_NS
3664
+ }, DetailsRow);
3665
+ yield ctx.slots.register({
3666
+ name: "tool.call.toolview",
3667
+ key: "subagent",
3668
+ locale: CONVERSATION_NS
3669
+ }, DetailsRow);
3670
+ yield ctx.slots.register({
3671
+ name: "tool.call.toolview",
3672
+ key: "list_agents",
3673
+ locale: CONVERSATION_NS
3674
+ }, DetailsRow);
3675
+ yield ctx.slots.register({
3676
+ name: "tool.call.toolview",
3677
+ key: "send_message",
3678
+ locale: CONVERSATION_NS
3679
+ }, DetailsRow);
3680
+ yield ctx.slots.register({
3681
+ name: "tool.call.toolview",
3682
+ key: "interrupt_agent",
3683
+ locale: CONVERSATION_NS
3684
+ }, DetailsRow);
3685
+ yield ctx.slots.register({
3686
+ name: "tool.call.toolview",
3687
+ key: "job_list",
3688
+ locale: CONVERSATION_NS
3689
+ }, DetailsRow);
3690
+ yield ctx.slots.register({
3691
+ name: "tool.call.toolview",
3692
+ key: "job_output",
3693
+ locale: CONVERSATION_NS
3694
+ }, DetailsRow);
3695
+ yield ctx.slots.register({
3696
+ name: "tool.call.toolview",
3697
+ key: "job_kill",
3698
+ locale: CONVERSATION_NS
3699
+ }, DetailsRow);
3700
+ yield ctx.slots.register({
3701
+ name: "tool.call.toolview",
3702
+ key: "terminal_open",
3703
+ locale: CONVERSATION_NS
3704
+ }, DetailsRow);
3705
+ yield ctx.slots.register({
3706
+ name: "tool.call.toolview",
3707
+ key: "terminal_read",
3708
+ locale: CONVERSATION_NS
3709
+ }, DetailsRow);
3710
+ yield ctx.slots.register({
3711
+ name: "tool.call.toolview",
3712
+ key: "terminal_list",
3713
+ locale: CONVERSATION_NS
3714
+ }, DetailsRow);
3715
+ yield ctx.slots.register({
3716
+ name: "tool.call.toolview",
3717
+ key: "terminal_signal",
3718
+ locale: CONVERSATION_NS
3719
+ }, DetailsRow);
3720
+ yield ctx.slots.register({
3721
+ name: "tool.call.toolview",
3722
+ key: "terminal_close",
3723
+ locale: CONVERSATION_NS
3724
+ }, DetailsRow);
3725
+ yield ctx.slots.register({
3726
+ name: "tool.call.toolview",
3727
+ key: "lsp",
3728
+ locale: CONVERSATION_NS
3729
+ }, DetailsRow);
3730
+ yield ctx.slots.register({
3731
+ name: "tool.call.toolview",
3732
+ key: "spawn_teammate",
3733
+ locale: CONVERSATION_NS
3734
+ }, DetailsRow);
3735
+ yield ctx.slots.register({
3736
+ name: "tool.call.toolview",
3737
+ key: "team_task_create",
3738
+ locale: CONVERSATION_NS
3739
+ }, DetailsRow);
3740
+ yield ctx.slots.register({
3741
+ name: "tool.call.toolview",
3742
+ key: "team_task_get",
3743
+ locale: CONVERSATION_NS
3744
+ }, DetailsRow);
3745
+ yield ctx.slots.register({
3746
+ name: "tool.call.toolview",
3747
+ key: "team_task_update",
3748
+ locale: CONVERSATION_NS
3749
+ }, DetailsRow);
3750
+ yield ctx.slots.register({
3751
+ name: "tool.call.toolview",
3752
+ key: "team_task_list",
3753
+ locale: CONVERSATION_NS
3754
+ }, DetailsRow);
3755
+ yield ctx.slots.register({
3756
+ name: "tool.call.toolview",
3757
+ key: "wait_agent",
3758
+ locale: CONVERSATION_NS
3759
+ }, DetailsRow);
3760
+ });
3761
+ }
3762
+ };
3763
+ //#endregion
3764
+ //#region lib/types/client/tool/models/todo-history.js
3765
+ /** Durable writes are indexed independently of Tool success receipts. */
3766
+ const todoWriteDefinition = {
3767
+ kind: "tool-todo-write",
3768
+ match: (event) => event.type === "todo/write" ? {
3769
+ id: String(event.seq),
3770
+ role: "start"
3771
+ } : null,
3772
+ start: (_context, match) => {
3773
+ if (match.event.type !== "todo/write") throw new Error("tool-todo-write requires todo/write");
3774
+ return match.event.data.todos;
3775
+ },
3776
+ update: (context) => context.state,
3777
+ publication: () => "none"
3778
+ };
3779
+ /** Invocation predecessors are repaired by the assembler when older history arrives. */
3780
+ const todoCallDefinition = {
3781
+ kind: "tool-todo-call",
3782
+ target: "tool-todo-history",
3783
+ match: (event) => {
3784
+ if (event.type === "tool/call" && event.data.name === "todo_write") return {
3785
+ id: String(event.data.callId),
3786
+ role: "start"
3787
+ };
3788
+ if (event.type === "tool/ptc-dispatch-start" && event.data.name === "todo_write") return {
3789
+ id: String(event.data.subCallId),
3790
+ role: "start"
3791
+ };
3792
+ return null;
3793
+ },
3794
+ start: (_context, _match, reader) => ({ todos: reader.previous("tool-todo-write")?.state }),
3795
+ update: (context) => context.state,
3796
+ buildViewNode: (context) => context.state === void 0 ? null : {
3797
+ key: context.key,
3798
+ kind: context.kind,
3799
+ id: context.id,
3800
+ target: "tool-todo-history",
3801
+ data: context.state
3802
+ }
3803
+ };
3804
+ /** Incremental lookup snapshots preserve earlier call baselines across later writes. */
3805
+ const todoHistoryView = {
3806
+ target: "tool-todo-history",
3807
+ create: () => {
3808
+ let calls = /* @__PURE__ */ new Map();
3809
+ return {
3810
+ empty: calls,
3811
+ replace: ({ nodes }) => calls = new Map(nodes.map((node) => [node.id, node.data])),
3812
+ apply: ({ upserts }) => {
3813
+ if (upserts.length > 0) {
3814
+ calls = new Map(calls);
3815
+ for (const node of upserts) calls.set(node.id, node.data);
3816
+ }
3817
+ return calls;
3818
+ }
3819
+ };
3820
+ }
3821
+ };
3822
+ /**
3823
+ * Install the recorded-write index and call predecessor target.
3824
+ * @param ctx - Tool presentation plugin context.
3825
+ */
3826
+ function registerTodoHistory(ctx) {
3827
+ ctx.uiConversation.events.register(todoWriteDefinition);
3828
+ ctx.uiConversation.events.register(todoCallDefinition);
3829
+ ctx.uiConversation.views.register(todoHistoryView);
3830
+ }
3831
+ //#endregion
3832
+ //#region lib/types/client/tool/models/todo-diff-model.js
3833
+ /**
3834
+ * Compare this write with its predecessor in the loaded call history.
3835
+ * @param block - The write being displayed.
3836
+ * @param baseline - List recorded before this call, or undefined when its start is unavailable.
3837
+ * @param hasMore - Whether older unloaded history may contain a preceding list.
3838
+ * @param t - Conversation dictionary translator.
3839
+ * @returns Details and a change summary, or null for generic Tool output.
3840
+ */
3841
+ function todoDiffModel(block, baseline, hasMore, t) {
3842
+ if (!("kind" in block) || block.isError) return null;
3843
+ const call = parsedToolCall(block);
3844
+ const current = call?.name === "todo_write" ? todosDetail(call.args, t) : null;
3845
+ if (current === null) return null;
3846
+ const previous = baseline?.todos === void 0 ? null : { items: baseline.todos.map((todo) => ({
3847
+ title: todo.content,
3848
+ status: {
3849
+ value: todo.status,
3850
+ label: t(`detail.todo.${todo.status}`)
3851
+ },
3852
+ fields: []
3853
+ })) };
3854
+ if (baseline === void 0 || previous === null && hasMore) return {
3855
+ details: {
3856
+ ...current,
3857
+ caption: t("todo.diff.unavailable")
3858
+ },
3859
+ summary: null
3860
+ };
3861
+ const previousByTitle = new Map(previous?.items.map((item) => [item.title, item]));
3862
+ const currentTitles = new Set(current.items.map((item) => item.title));
3863
+ const retainedPositions = new Map(previous?.items.filter((item) => currentTitles.has(item.title)).map((item, index) => [item.title, index]));
3864
+ let retainedIndex = 0;
3865
+ const items = [];
3866
+ const unchanged = [];
3867
+ let added = 0;
3868
+ let updated = 0;
3869
+ for (const item of current.items) {
3870
+ const before = previousByTitle.get(item.title);
3871
+ previousByTitle.delete(item.title);
3872
+ if (before === void 0) {
3873
+ added++;
3874
+ items.push({
3875
+ ...item,
3876
+ change: {
3877
+ value: "added",
3878
+ label: t("todo.diff.addedItem")
3879
+ }
3880
+ });
3881
+ } else {
3882
+ const moved = retainedPositions.get(item.title) !== retainedIndex++;
3883
+ const statusChanged = before.status?.value !== item.status?.value;
3884
+ if (statusChanged || moved) {
3885
+ updated++;
3886
+ items.push({
3887
+ ...item,
3888
+ ...statusChanged && before.status !== void 0 ? { previousStatus: before.status.label } : {},
3889
+ change: {
3890
+ value: "updated",
3891
+ label: t(statusChanged ? "todo.diff.updatedItem" : "todo.diff.movedItem")
3892
+ }
3893
+ });
3894
+ } else unchanged.push(item);
3895
+ }
3896
+ }
3897
+ for (const item of previousByTitle.values()) items.push({
3898
+ ...item,
3899
+ change: {
3900
+ value: "removed",
3901
+ label: t("todo.diff.removedItem")
3902
+ }
3903
+ });
3904
+ return {
3905
+ summary: [
3906
+ added > 0 ? t("todo.diff.added", { count: added }) : null,
3907
+ updated > 0 ? t("todo.diff.updated", { count: updated }) : null,
3908
+ previousByTitle.size > 0 ? t("todo.diff.removed", { count: previousByTitle.size }) : null
3909
+ ].filter((part) => part !== null).join(" · ") || t("todo.diff.noChanges"),
3910
+ details: {
3911
+ items,
3912
+ caption: t(previous === null ? "todo.diff.initial" : "todo.diff.compare"),
3913
+ empty: current.items.length === 0 && previous === null ? t("detail.todo.empty") : t("todo.diff.noChanges"),
3914
+ ...unchanged.length === 0 ? {} : { unchanged: {
3915
+ label: t("todo.diff.unchanged", { count: unchanged.length }),
3916
+ items: unchanged
3917
+ } }
3918
+ }
3919
+ };
3920
+ }
3921
+ //#endregion
2253
3922
  //#region lib/types/client/tool/toolviews/plan-summary.js
2254
3923
  /**
2255
3924
  * Pure plan derivation for the todo_write row's one-line summary. Several items
@@ -2311,22 +3980,32 @@ window.__ModuleLoader__.load({
2311
3980
  };
2312
3981
  }
2313
3982
  /** Summarizes a plan update without presenting a cancelled call as completed. */
2314
- function TodoRow({ toolName, block, inspect, t }) {
3983
+ function TodoRow({ toolName, block, inspect, useDisclosure, useTodoHistory, useSession, t }) {
3984
+ const baseline = useTodoHistory((snapshot) => snapshot?.get(block.callId));
3985
+ const hasMore = useSession((snapshot) => snapshot.hasMore);
3986
+ const diff = (0, react.useMemo)(() => todoDiffModel(block, baseline, hasMore, t), [
3987
+ block,
3988
+ baseline,
3989
+ hasMore,
3990
+ t
3991
+ ]);
2315
3992
  const model = toolRowModel(toolName, block);
2316
3993
  const summary = summarize(("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "", t) ?? {
2317
3994
  text: model.summary,
2318
3995
  extra: 0
2319
3996
  };
2320
3997
  return (0, react_jsx_runtime.jsx)(ToolRow, {
3998
+ useDisclosure,
2321
3999
  t,
2322
4000
  variant: model.variant,
2323
4001
  toolName,
2324
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutline14, {}),
4002
+ icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutlineRegular, {}),
2325
4003
  title: t("todo.rowTitle"),
2326
4004
  summary: summary.text,
2327
- summarySuffix: summary.extra > 0 ? `+${summary.extra}` : null,
4005
+ summarySuffix: [diff?.summary, summary.extra > 0 ? `+${summary.extra}` : null].filter((part) => part !== null && part !== void 0).join(" · ") || null,
2328
4006
  bodyRaw: model.bodyRaw,
2329
4007
  output: model.output,
4008
+ details: diff?.details,
2330
4009
  errorSummary: model.errorSummary,
2331
4010
  state: model.state,
2332
4011
  inspect
@@ -2335,12 +4014,14 @@ window.__ModuleLoader__.load({
2335
4014
  /** Registers the todo conversation row. */
2336
4015
  const todoToolview = {
2337
4016
  name: "todo-toolview",
2338
- inject: ["slots"],
4017
+ inject: ["slots", "uiConversation"],
2339
4018
  apply(ctx) {
4019
+ registerTodoHistory(ctx);
2340
4020
  ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
2341
4021
  name: "tool.call.toolview",
2342
4022
  key: "todo_write",
2343
- locale: CONVERSATION_NS
4023
+ locale: CONVERSATION_NS,
4024
+ inject: (sessionId) => ({ hooks: { todoHistory: ctx.uiConversation.binding(sessionId).target("tool-todo-history") } })
2344
4025
  }, TodoRow));
2345
4026
  }
2346
4027
  };
@@ -2351,11 +4032,12 @@ window.__ModuleLoader__.load({
2351
4032
  web_fetch: "tool.title.webFetch"
2352
4033
  };
2353
4034
  /** Lets users expand a completed web search or fetch result. */
2354
- function WebRow({ toolName, block, inspect, t }) {
4035
+ function WebRow({ toolName, block, inspect, useDisclosure, t }) {
2355
4036
  const model = toolRowModel(toolName, block);
2356
4037
  const web = webCardModel(block);
2357
- const icon = toolName === "web_fetch" ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGlobeOutline14, { size: 14 });
4038
+ const icon = toolName === "web_fetch" ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutlineRegular, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGlobeOutlineRegular, { size: 14 });
2358
4039
  return (0, react_jsx_runtime.jsx)(ToolRow, {
4040
+ useDisclosure,
2359
4041
  t,
2360
4042
  variant: model.variant,
2361
4043
  toolName,
@@ -2419,6 +4101,7 @@ window.__ModuleLoader__.load({
2419
4101
  ctx.plugin(searchToolview);
2420
4102
  ctx.plugin(webToolview);
2421
4103
  ctx.plugin(todoToolview);
4104
+ ctx.plugin(detailsToolview);
2422
4105
  ctx.plugin(askQuestionToolview);
2423
4106
  }
2424
4107
  //#endregion