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