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