dsh-edge 0.1.0
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/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +183 -0
- package/README.zh.md +183 -0
- package/THIRD_PARTY_NOTICES.md +199 -0
- package/dist/_headers +3 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/fonts/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/fonts/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/fonts/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/fonts/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/fonts/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/index-C-1AiF3k.js +112 -0
- package/dist/assets/index-CSGf6Qzd.css +1 -0
- package/dist/assets/langs/c-BIGW1oBm.js +2 -0
- package/dist/assets/langs/cpp-DIPi6g--.js +2 -0
- package/dist/assets/langs/csharp-DSvCPggb.js +2 -0
- package/dist/assets/langs/css-CLj8gQPS.js +2 -0
- package/dist/assets/langs/go-C27-OAKa.js +2 -0
- package/dist/assets/langs/html-CfGypltT.js +2 -0
- package/dist/assets/langs/ini-BEwlwnbL.js +2 -0
- package/dist/assets/langs/java-CylS5w8V.js +2 -0
- package/dist/assets/langs/kotlin-BdnUsdx6.js +2 -0
- package/dist/assets/langs/less-B1dDrJ26.js +2 -0
- package/dist/assets/langs/lua-BaeVxFsk.js +2 -0
- package/dist/assets/langs/markdown-Cvjx9yec.js +2 -0
- package/dist/assets/langs/mdx-Cmh6b_Ma.js +2 -0
- package/dist/assets/langs/php-D-uCvoST.js +2 -0
- package/dist/assets/langs/python-B6aJPvgy.js +2 -0
- package/dist/assets/langs/ruby-DEItuUFs.js +2 -0
- package/dist/assets/langs/rust-B1yitclQ.js +2 -0
- package/dist/assets/langs/scss-D5BDwBP9.js +2 -0
- package/dist/assets/langs/sql-CRqJ_cUM.js +2 -0
- package/dist/assets/langs/swift-D82vCrfD.js +2 -0
- package/dist/assets/langs/toml-vGWfd6FD.js +2 -0
- package/dist/assets/langs/xml-sdJ4AIDG.js +2 -0
- package/dist/assets/langs/yaml-Buea-lGh.js +2 -0
- package/dist/assets/vendor-Cjbwl5VI.js +411 -0
- package/dist/assets/vendor-CjyC-hUb.css +1 -0
- package/dist/favicon.svg +8 -0
- package/dist/index.html +35 -0
- package/dist/manifest.webmanifest +16 -0
- package/dist/plugins/@deepseek-ai/dsh-api-gateway/client.js +420 -0
- package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +5937 -0
- package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +10207 -0
- package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +1231 -0
- package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +259 -0
- package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +10539 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +1725 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +1116 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +9832 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +373 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-edge/client.js +549 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +859 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +280 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +456 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +804 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +461 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +254 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +609 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +292 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +327 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +710 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +1312 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +1630 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +7370 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +700 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +474 -0
- package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +2426 -0
- package/dist/plugins/@deepseek-ai/dsh-typert-registry/client.js +1372 -0
- package/package.json +97 -0
- package/scripts/assemble-web.mjs +230 -0
- package/scripts/bundle-size.d.mts +2 -0
- package/scripts/bundle-size.mjs +26 -0
- package/scripts/bundle.mjs +53 -0
- package/scripts/cli.d.mts +39 -0
- package/scripts/cli.mjs +496 -0
- package/scripts/install.d.mts +149 -0
- package/scripts/install.mjs +989 -0
- package/scripts/legal-files.mjs +24 -0
- package/scripts/verify-packed.mjs +32 -0
- package/scripts/wrangler-config.d.mts +18 -0
- package/scripts/wrangler-config.mjs +84 -0
- package/src/agent.ts +119 -0
- package/src/auth.ts +352 -0
- package/src/deepseek.ts +231 -0
- package/src/deployment.ts +147 -0
- package/src/direct-shell-core-empty.ts +10 -0
- package/src/direct-shell-protocol.ts +5 -0
- package/src/direct-shell.ts +341 -0
- package/src/do-session-persistence.ts +1064 -0
- package/src/edge-api.ts +796 -0
- package/src/edge-credentials.ts +56 -0
- package/src/edge-remotes.ts +41 -0
- package/src/edge-workspace-store.ts +339 -0
- package/src/http.ts +212 -0
- package/src/index.ts +196 -0
- package/src/instance.ts +1007 -0
- package/src/isolated-direct-shell-unavailable.ts +11 -0
- package/src/protocol.ts +39 -0
- package/src/release.ts +9 -0
- package/src/session-store.ts +1110 -0
- package/src/sse.ts +86 -0
- package/src/web-search.ts +38 -0
- package/src/workspace.ts +270 -0
- package/wrangler.jsonc +56 -0
|
@@ -0,0 +1,1630 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@deepseek-ai/dsh-client-ui-tool",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
11
|
+
//#region lib/types/client/tool/models/tool-call-model.js
|
|
12
|
+
/** Figma row titles per variant (design literals, not translatable copy). */
|
|
13
|
+
const VARIANT_TITLES = {
|
|
14
|
+
search: "Search",
|
|
15
|
+
read: "Read",
|
|
16
|
+
bash: "Bash",
|
|
17
|
+
write: "Write",
|
|
18
|
+
edit: "Edit",
|
|
19
|
+
code: "Code",
|
|
20
|
+
others: "Tool call"
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Known tool name -> variant.
|
|
24
|
+
*
|
|
25
|
+
* `cordis_define` is deliberately absent: ui-cordis registers a keyed
|
|
26
|
+
* `tool.call.toolview` entry for it, and a keyed hit REPLACES the generic row
|
|
27
|
+
* (this table is only reached through GenericToolCard, the dispatch fallback in
|
|
28
|
+
* ToolCallTree). An entry here would be unreachable, and a second title for the
|
|
29
|
+
* same call would be a second answer to a question the card already owns.
|
|
30
|
+
*/
|
|
31
|
+
const TOOL_VARIANTS = {
|
|
32
|
+
bash: "bash",
|
|
33
|
+
pwsh: "bash",
|
|
34
|
+
read: "read",
|
|
35
|
+
web_fetch: "read",
|
|
36
|
+
web_search: "search",
|
|
37
|
+
grep: "search",
|
|
38
|
+
glob: "search",
|
|
39
|
+
write: "write",
|
|
40
|
+
edit: "edit",
|
|
41
|
+
run_code: "code",
|
|
42
|
+
cordis_package_inspect: "read",
|
|
43
|
+
cordis_runtime_inspect: "read",
|
|
44
|
+
cordis_run: "others",
|
|
45
|
+
cordis_stop: "others",
|
|
46
|
+
cordis_undefine: "others"
|
|
47
|
+
};
|
|
48
|
+
/** Tool-owned titles that refine a generic row variant without replacing it. */
|
|
49
|
+
const TOOL_TITLES = {
|
|
50
|
+
cordis_package_inspect: "Inspect",
|
|
51
|
+
cordis_runtime_inspect: "Inspect",
|
|
52
|
+
cordis_run: "Run Cordis Plugin",
|
|
53
|
+
cordis_stop: "Stop Cordis Plugin",
|
|
54
|
+
cordis_undefine: "Remove Cordis Plugin",
|
|
55
|
+
pwsh: "Pwsh"
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Classify a tool name into its row variant.
|
|
59
|
+
* @param toolName - wire tool name.
|
|
60
|
+
* @returns matching variant, others when unknown.
|
|
61
|
+
*/
|
|
62
|
+
function classifyTool(toolName) {
|
|
63
|
+
return TOOL_VARIANTS[toolName] ?? "others";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Flatten a settled result's content blocks to display text: text blocks
|
|
67
|
+
* verbatim, other block shapes as pretty JSON. Empty content on a failed call
|
|
68
|
+
* falls back to the structured error's `name: code` line.
|
|
69
|
+
* @param node - the settled result node.
|
|
70
|
+
* @returns the flattened result text (may be empty).
|
|
71
|
+
*/
|
|
72
|
+
function resultText(node) {
|
|
73
|
+
const parts = [];
|
|
74
|
+
for (const block of node.content) if (block.type === "text") parts.push(block.text);
|
|
75
|
+
else parts.push(JSON.stringify(block, null, 2));
|
|
76
|
+
if (parts.length === 0 && node.error !== void 0) parts.push(`${node.error.name}: ${node.error.code}`);
|
|
77
|
+
return parts.join("\n");
|
|
78
|
+
}
|
|
79
|
+
function parseArgs(argsRaw) {
|
|
80
|
+
try {
|
|
81
|
+
return JSON.parse(argsRaw);
|
|
82
|
+
} catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function firstLine(text) {
|
|
87
|
+
const nl = text.indexOf("\n");
|
|
88
|
+
return nl === -1 ? text : text.slice(0, nl);
|
|
89
|
+
}
|
|
90
|
+
function pickString(args, keys) {
|
|
91
|
+
for (const key of keys) {
|
|
92
|
+
const v = args[key];
|
|
93
|
+
if (typeof v === "string" && v !== "") return v;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Summary key preference per variant (args-derived; result-derived summaries are a ledger item). */
|
|
97
|
+
const SUMMARY_KEYS = {
|
|
98
|
+
bash: ["description", "command"],
|
|
99
|
+
read: [
|
|
100
|
+
"path",
|
|
101
|
+
"file_path",
|
|
102
|
+
"url"
|
|
103
|
+
],
|
|
104
|
+
search: [
|
|
105
|
+
"query",
|
|
106
|
+
"pattern",
|
|
107
|
+
"url"
|
|
108
|
+
],
|
|
109
|
+
write: ["path", "file_path"],
|
|
110
|
+
edit: ["path", "file_path"],
|
|
111
|
+
code: ["description"],
|
|
112
|
+
others: []
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Strip the workspace root from a workspace-rooted absolute path (display only).
|
|
116
|
+
* @param text - the path to shorten.
|
|
117
|
+
* @param cwd - session workspace root; absent or empty leaves the path unchanged.
|
|
118
|
+
* @returns the path relative to the workspace root, or unchanged when it is not rooted there.
|
|
119
|
+
*/
|
|
120
|
+
function relativizeToCwd(text, cwd) {
|
|
121
|
+
if (cwd === void 0 || cwd === "") return text;
|
|
122
|
+
const root = cwd.replace(/[/\\]+$/, "");
|
|
123
|
+
if (text.startsWith(`${root}/`) || text.startsWith(`${root}\\`)) return text.slice(root.length + 1);
|
|
124
|
+
return text;
|
|
125
|
+
}
|
|
126
|
+
function deriveSummary(variant, argsRaw) {
|
|
127
|
+
const parsed = parseArgs(argsRaw);
|
|
128
|
+
if (typeof parsed !== "object" || parsed === null) return firstLine(argsRaw);
|
|
129
|
+
const args = parsed;
|
|
130
|
+
const picked = pickString(args, SUMMARY_KEYS[variant]);
|
|
131
|
+
if (picked !== void 0) return firstLine(picked);
|
|
132
|
+
for (const v of Object.values(args)) if (typeof v === "string" && v !== "") return firstLine(v);
|
|
133
|
+
return firstLine(argsRaw);
|
|
134
|
+
}
|
|
135
|
+
/** Path keys only — never `url` (web_fetch lands on the read variant). */
|
|
136
|
+
const FILE_PATH_KEYS = ["path", "file_path"];
|
|
137
|
+
/** File-tool variants whose summary may be an openable workspace path. */
|
|
138
|
+
const FILE_PATH_VARIANTS = new Set([
|
|
139
|
+
"read",
|
|
140
|
+
"write",
|
|
141
|
+
"edit"
|
|
142
|
+
]);
|
|
143
|
+
function deriveFilePath(variant, argsRaw) {
|
|
144
|
+
if (!FILE_PATH_VARIANTS.has(variant)) return void 0;
|
|
145
|
+
const parsed = parseArgs(argsRaw);
|
|
146
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
147
|
+
const picked = pickString(parsed, FILE_PATH_KEYS);
|
|
148
|
+
return picked === void 0 ? void 0 : firstLine(picked);
|
|
149
|
+
}
|
|
150
|
+
function deriveBody(variant, argsRaw) {
|
|
151
|
+
if (argsRaw === "") return null;
|
|
152
|
+
const parsed = parseArgs(argsRaw);
|
|
153
|
+
if (parsed === void 0) return argsRaw;
|
|
154
|
+
if (variant === "code" && typeof parsed === "object" && parsed !== null) {
|
|
155
|
+
const code = parsed.code;
|
|
156
|
+
if (typeof code === "string" && code !== "") return code;
|
|
157
|
+
}
|
|
158
|
+
return JSON.stringify(parsed, null, 2);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Derive the full row model from a frozen call slice.
|
|
162
|
+
* @param toolName - wire tool name (dispatch-supplied; survives windowless results).
|
|
163
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
164
|
+
* @param cwd - session workspace root; workspace-rooted path summaries display relative to it.
|
|
165
|
+
* @returns the row model.
|
|
166
|
+
*/
|
|
167
|
+
function toolRowModel(toolName, block, cwd) {
|
|
168
|
+
const variant = classifyTool(toolName);
|
|
169
|
+
const done = "kind" in block;
|
|
170
|
+
const argsRaw = (done ? block.call?.argsRaw : block.argsRaw) ?? "";
|
|
171
|
+
const state = !done ? "running" : block.error?.code === "interrupted" ? "stopped" : block.isError ? "error" : "ok";
|
|
172
|
+
const base = argsRaw === "" ? block.callId : relativizeToCwd(deriveSummary(variant, argsRaw), cwd);
|
|
173
|
+
const toolTitle = TOOL_TITLES[toolName];
|
|
174
|
+
const summary = variant === "others" && toolName !== "" && toolTitle === void 0 ? `${toolName} · ${base}` : base;
|
|
175
|
+
const output = done ? resultText(block) || null : null;
|
|
176
|
+
const errorSummary = state === "error" && output !== null ? firstLine(output) : null;
|
|
177
|
+
return {
|
|
178
|
+
variant,
|
|
179
|
+
title: toolTitle ?? VARIANT_TITLES[variant],
|
|
180
|
+
summary,
|
|
181
|
+
filePath: deriveFilePath(variant, argsRaw),
|
|
182
|
+
body: deriveBody(variant, argsRaw),
|
|
183
|
+
output,
|
|
184
|
+
errorSummary,
|
|
185
|
+
state
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region lib/types/client/tool/models/read-card-model.js
|
|
190
|
+
/**
|
|
191
|
+
* Derive the read-card props for a tool call, or null when this call is not a
|
|
192
|
+
* read card and belongs on the generic path.
|
|
193
|
+
*
|
|
194
|
+
* The read card is result-side only, so only a settled call whose result view
|
|
195
|
+
* declares `card:'read'` produces one. Every other case is null — the
|
|
196
|
+
* documented generic-card default:
|
|
197
|
+
*
|
|
198
|
+
* - A running call: it has no result view yet, and a read carries no content at
|
|
199
|
+
* call time.
|
|
200
|
+
* - A settled call whose result view is not a read card — including a `card`
|
|
201
|
+
* value this UI version does not know, which arrives over the wire and cannot
|
|
202
|
+
* be trusted to be one of the compiled variants, and the read tool's own
|
|
203
|
+
* generic fallback for an error result or a non-envelope body.
|
|
204
|
+
*
|
|
205
|
+
* The label is the read view's `title` when the tool supplied one (the
|
|
206
|
+
* presentation contract's replacement-title rule), otherwise the file path
|
|
207
|
+
* relativized to the session workspace so a workspace-rooted absolute path
|
|
208
|
+
* displays the same short form the row summary shows.
|
|
209
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
210
|
+
* @param sessionCwd - the session workspace root; a workspace-rooted absolute
|
|
211
|
+
* path label displays relative to it. Absent leaves the path as authored.
|
|
212
|
+
* @returns the read-card props, or null for the generic path.
|
|
213
|
+
*/
|
|
214
|
+
function readCardModel(block, sessionCwd) {
|
|
215
|
+
if (!("kind" in block)) return null;
|
|
216
|
+
const result = block.resultView?.card === "read" ? block.resultView : null;
|
|
217
|
+
if (result === null) return null;
|
|
218
|
+
const lines = result.lines.map((line) => ({
|
|
219
|
+
number: line.number,
|
|
220
|
+
text: line.text
|
|
221
|
+
}));
|
|
222
|
+
return {
|
|
223
|
+
label: result.title ?? relativizeToCwd(result.path, sessionCwd),
|
|
224
|
+
lines,
|
|
225
|
+
totalLines: result.totalLines,
|
|
226
|
+
lang: result.lang
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region lib/types/client/tool/models/diff-card-model.js
|
|
231
|
+
/**
|
|
232
|
+
* Narrow a wire `card:'diff'` view's `diffs` to well-formed hunks. The event
|
|
233
|
+
* view crosses the wire and `toolEventViewSchema` validates only the `card`
|
|
234
|
+
* string, so a version mismatch or an anomalous plugin can deliver a `diff` card
|
|
235
|
+
* whose `diffs` is absent, not an array, or carries malformed hunks. Returning
|
|
236
|
+
* null for any of those routes the block to the generic path instead of letting
|
|
237
|
+
* DiffBlock's `for...of`/`split` throw and crash the row or the details panel.
|
|
238
|
+
* @param diffs - the view's `diffs` field, unverified.
|
|
239
|
+
* @returns the validated hunks, or null when the payload is not usable.
|
|
240
|
+
*/
|
|
241
|
+
function narrowDiffs(diffs) {
|
|
242
|
+
if (!Array.isArray(diffs) || diffs.length === 0) return null;
|
|
243
|
+
const out = [];
|
|
244
|
+
for (const hunk of diffs) {
|
|
245
|
+
if (typeof hunk !== "object" || hunk === null) return null;
|
|
246
|
+
const { path, oldText, newText } = hunk;
|
|
247
|
+
if (typeof path !== "string") return null;
|
|
248
|
+
if (oldText !== null && typeof oldText !== "string") return null;
|
|
249
|
+
if (typeof newText !== "string") return null;
|
|
250
|
+
out.push({
|
|
251
|
+
path,
|
|
252
|
+
oldText,
|
|
253
|
+
newText
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Derive the diff-card props for a tool call, or null when this call is not a
|
|
260
|
+
* diff card and belongs on the generic path.
|
|
261
|
+
*
|
|
262
|
+
* The result side is authoritative once the call settles: the write/edit tools
|
|
263
|
+
* return the applied contextual hunks there (an edit's real before/after, a
|
|
264
|
+
* create's whole-file diff), which replace the call-time diff derived from the
|
|
265
|
+
* arguments alone. While the call is still running only the call side exists,
|
|
266
|
+
* so a running write/edit shows its intended change. Null is the documented
|
|
267
|
+
* generic-card default and covers every non-diff card — including a `card`
|
|
268
|
+
* value this UI version does not know, which arrives over the wire and cannot
|
|
269
|
+
* be trusted to be one of the compiled variants — and a settled call whose
|
|
270
|
+
* result view is generic (how write/edit keep their execution errors on the
|
|
271
|
+
* generic path).
|
|
272
|
+
*
|
|
273
|
+
* This derivation consumes only `diffs`; the render intent's `title` field is
|
|
274
|
+
* deliberately dropped. The row supplies its own title (`Edit`/`Write · path`
|
|
275
|
+
* from the args), which outranks the view's `title`. A tool that names its own
|
|
276
|
+
* diff header therefore does not surface that text on the Web row.
|
|
277
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
278
|
+
* @returns the diff-card props, or null for the generic path.
|
|
279
|
+
*/
|
|
280
|
+
function diffCardModel(block) {
|
|
281
|
+
if (!("kind" in block)) {
|
|
282
|
+
const call = block.callView?.card === "diff" ? block.callView : null;
|
|
283
|
+
const diffs = call === null ? null : narrowDiffs(call.diffs);
|
|
284
|
+
return diffs === null ? null : { card: { diffs } };
|
|
285
|
+
}
|
|
286
|
+
const result = block.resultView?.card === "diff" ? block.resultView : null;
|
|
287
|
+
const diffs = result === null ? null : narrowDiffs(result.diffs);
|
|
288
|
+
return diffs === null ? null : { card: { diffs } };
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region lib/types/client/tool/models/search-card-model.js
|
|
292
|
+
/**
|
|
293
|
+
* Whether every file group in a matches view is structurally valid: the wire
|
|
294
|
+
* frame carries `shape` and `card` as strings the host schema checks, but not the
|
|
295
|
+
* grouped `files` fields, so a version mismatch or loose producer could deliver
|
|
296
|
+
* `shape: 'matches'` with a missing or malformed `files`. Rendering that would
|
|
297
|
+
* crash {@link SearchBlock} at `.reduce`/`.map`; invalid fields select the
|
|
298
|
+
* generic path instead.
|
|
299
|
+
* @param files - the candidate `files` field off the untrusted result view.
|
|
300
|
+
* @returns whether `files` is a valid {@link SearchFileGroup} array.
|
|
301
|
+
*/
|
|
302
|
+
function isValidFiles(files) {
|
|
303
|
+
return Array.isArray(files) && files.every((file) => typeof file === "object" && file !== null && typeof file.path === "string" && Array.isArray(file.matches) && file.matches.every((match) => typeof match === "object" && match !== null && typeof match.lineNumber === "number" && typeof match.line === "string"));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Flatten a settled tool result's content blocks to their text, joined by
|
|
307
|
+
* newlines. The search view carries no result text — a UI without a card falls
|
|
308
|
+
* back to the raw `tool/result` content — so the truncation recovery footer is
|
|
309
|
+
* read from the block's own content here. Non-text blocks (a search result
|
|
310
|
+
* carries none) are skipped.
|
|
311
|
+
* @param content - the result node's content blocks.
|
|
312
|
+
* @returns the joined text, or undefined when empty.
|
|
313
|
+
*/
|
|
314
|
+
function flattenContent(content) {
|
|
315
|
+
const text = content.filter((block) => block.type === "text" && typeof block.text === "string").map((block) => block.text).join("\n");
|
|
316
|
+
return text === "" ? void 0 : text;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Derive the search-card props for a tool call, or null when this call is not a
|
|
320
|
+
* search card and belongs on the generic path.
|
|
321
|
+
*
|
|
322
|
+
* Only the result side matters: the search card carries no call-time state, so
|
|
323
|
+
* a still-running call (no result view) is null, as is a settled call whose
|
|
324
|
+
* result view is not a search card — including a `card` value this UI version
|
|
325
|
+
* does not know, which arrives over the wire and cannot be trusted to be one of
|
|
326
|
+
* the compiled variants, a `card: 'search'` view whose `shape` is neither
|
|
327
|
+
* `matches` nor `paths` (equally untrusted wire data), and a generic result a
|
|
328
|
+
* `grep`/`glob` failure or nested `run_code` dispatch produces (its text keeps
|
|
329
|
+
* the generic path).
|
|
330
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
331
|
+
* @returns the search-card props, or null for the generic path.
|
|
332
|
+
*/
|
|
333
|
+
function searchCardModel(block) {
|
|
334
|
+
if (!("kind" in block)) return null;
|
|
335
|
+
const result = block.resultView?.card === "search" ? block.resultView : null;
|
|
336
|
+
if (result === null) return null;
|
|
337
|
+
const common = {
|
|
338
|
+
truncated: result.truncated,
|
|
339
|
+
total: result.total
|
|
340
|
+
};
|
|
341
|
+
const recovery = result.truncated ? flattenContent(block.content) : void 0;
|
|
342
|
+
if (result.shape === "matches") {
|
|
343
|
+
if (!isValidFiles(result.files)) return null;
|
|
344
|
+
return {
|
|
345
|
+
title: result.title,
|
|
346
|
+
recovery,
|
|
347
|
+
card: {
|
|
348
|
+
kind: "matches",
|
|
349
|
+
files: result.files,
|
|
350
|
+
...common
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
if (result.shape !== "paths") return null;
|
|
355
|
+
if (!Array.isArray(result.paths) || !result.paths.every((path) => typeof path === "string")) return null;
|
|
356
|
+
return {
|
|
357
|
+
title: result.title,
|
|
358
|
+
recovery,
|
|
359
|
+
card: {
|
|
360
|
+
kind: "paths",
|
|
361
|
+
paths: result.paths,
|
|
362
|
+
...common
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region lib/types/client/tool/models/terminal-card-model.js
|
|
368
|
+
/**
|
|
369
|
+
* Pure derivation of the terminal-card props from a frozen call slice: the
|
|
370
|
+
* `card:'terminal'` render intent the shell tools declare arrives on the
|
|
371
|
+
* snapshot as `callView`/`resultView`, and this is the one place that turns
|
|
372
|
+
* that pair into what {@link TerminalBlock} draws. Both conversation render
|
|
373
|
+
* sites (the chat tool row's expanded body and the details panel's Output
|
|
374
|
+
* section) call this, so the command, cwd, output and exit status they show
|
|
375
|
+
* are derived once.
|
|
376
|
+
* @module
|
|
377
|
+
*/
|
|
378
|
+
/**
|
|
379
|
+
* Build the TerminalBlock display copy from the conversation locale seat —
|
|
380
|
+
* the one place the primitive's label surface pairs with this package's
|
|
381
|
+
* dictionary, shared by every terminal render site (chat row, bash row,
|
|
382
|
+
* details panel).
|
|
383
|
+
* @param t - the render site's conversation locale seat.
|
|
384
|
+
* @returns the full label set for {@link TerminalBlockProps}'s `labels`.
|
|
385
|
+
*/
|
|
386
|
+
function terminalBlockLabels(t) {
|
|
387
|
+
return {
|
|
388
|
+
signal: (signal) => t("terminal.signal", { signal }),
|
|
389
|
+
exitCode: (code) => t("terminal.exitCode", { code }),
|
|
390
|
+
running: t("terminal.running"),
|
|
391
|
+
failed: t("terminal.failed"),
|
|
392
|
+
done: t("terminal.done"),
|
|
393
|
+
copy: t("copy"),
|
|
394
|
+
copied: t("copied"),
|
|
395
|
+
noOutput: t("terminal.noOutput"),
|
|
396
|
+
collapseAria: t("terminal.collapseAria"),
|
|
397
|
+
collapse: t("collapse"),
|
|
398
|
+
expandAria: (hidden) => t("terminal.expandAria", { n: hidden }),
|
|
399
|
+
expand: (hidden) => t("terminal.expandRest", { n: hidden })
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* True when a settled terminal card reports a failing exit — a non-zero code
|
|
404
|
+
* or a terminating signal. The bash tool settles a failing command as a
|
|
405
|
+
* completed call (`isError` stays false: the exit status is result data), so
|
|
406
|
+
* this is the collapsed row's only failure signal; without it the red exit
|
|
407
|
+
* pill would be visible only after expanding the card.
|
|
408
|
+
* @param model - a derived terminal card.
|
|
409
|
+
* @returns whether the card's exit status is a failure.
|
|
410
|
+
*/
|
|
411
|
+
function terminalFailed(model) {
|
|
412
|
+
const { exitCode, signal, running } = model.card;
|
|
413
|
+
return running !== true && (exitCode !== void 0 && exitCode !== 0 || signal !== void 0);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Resolve a terminal view's working directory the way the render-intent
|
|
417
|
+
* contract assigns to the UI bridge: an absolute path is used as-is, a relative
|
|
418
|
+
* one joins under the session workspace, and an omitted one IS the session
|
|
419
|
+
* workspace. A pure presenter cannot see the session cwd, which is why this
|
|
420
|
+
* resolution belongs here rather than in the tool. Without a session cwd there
|
|
421
|
+
* is nothing to resolve against, so a relative path stays as authored and an
|
|
422
|
+
* omitted one stays absent (the prompt row then draws a bare `$`).
|
|
423
|
+
* @param viewCwd - the cwd the terminal call view carries, if any.
|
|
424
|
+
* @param sessionCwd - the session workspace root, if the caller knows it.
|
|
425
|
+
* @returns the working directory for the prompt label, or undefined.
|
|
426
|
+
*/
|
|
427
|
+
function resolveTerminalCwd(viewCwd, sessionCwd) {
|
|
428
|
+
if (viewCwd === void 0 || viewCwd === "") return sessionCwd;
|
|
429
|
+
if (sessionCwd === void 0 || sessionCwd === "") return normalizeSegments(viewCwd);
|
|
430
|
+
return normalizeSegments((0, _deepseek_ai_dsh_client_runtime_client.resolveWorkspacePath)(sessionCwd, viewCwd));
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Collapse `.` and `..` segments so the prompt label names the directory the
|
|
434
|
+
* command actually ran in. The bash executor resolves the workdir before
|
|
435
|
+
* running, so a joined `/w/app/..` must display as `w`, not as `..`. Separators
|
|
436
|
+
* are preserved as authored (a Windows path keeps its backslashes) because this
|
|
437
|
+
* value is only ever displayed; a `..` that would climb past the root is
|
|
438
|
+
* dropped, which is what a filesystem does with it. A UNC path's `server` and
|
|
439
|
+
* `share` are part of its root, not poppable segments: Windows cannot climb
|
|
440
|
+
* above a share, so `\\\\server\\share` with a `..` stays there.
|
|
441
|
+
* @param path - a joined or absolute path, possibly carrying `.`/`..` segments.
|
|
442
|
+
* @returns the same path with those segments resolved.
|
|
443
|
+
*/
|
|
444
|
+
function normalizeSegments(path) {
|
|
445
|
+
if (!/(?:^|[/\\])\.\.?(?:[/\\]|$)/.test(path)) return path;
|
|
446
|
+
const unc = /^[/\\]{2}([^/\\]+)[/\\]+([^/\\]+)/.exec(path);
|
|
447
|
+
if (unc !== null) {
|
|
448
|
+
const [matched, server, share] = unc;
|
|
449
|
+
const root = `\\\\${String(server)}\\${String(share)}`;
|
|
450
|
+
const rest = collapse(path.slice(matched.length), true);
|
|
451
|
+
return rest === "" ? root : `${root}\\${rest}`;
|
|
452
|
+
}
|
|
453
|
+
const separator = path.includes("\\") && !path.includes("/") ? "\\" : "/";
|
|
454
|
+
const rooted = /^[/\\]/.test(path);
|
|
455
|
+
const drive = /^[A-Za-z]:/.exec(path)?.[0] ?? "";
|
|
456
|
+
const body = collapse(path.slice(drive.length), rooted || drive !== "", separator);
|
|
457
|
+
const leading = rooted ? separator : "";
|
|
458
|
+
return drive === "" ? `${leading}${body}` : `${drive}${rooted ? leading : separator}${body}`;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Collapse the `.`/`..` segments of a path body against a known root state.
|
|
462
|
+
* @param body - the path after any drive letter or UNC root.
|
|
463
|
+
* @param rooted - the body hangs off a root, so a `..` at its top is dropped
|
|
464
|
+
* the way a filesystem drops one; without a root the `..` is kept, since it
|
|
465
|
+
* stays meaningful against a cwd this function cannot see.
|
|
466
|
+
* @param separator - separator to rejoin with (default `/`).
|
|
467
|
+
* @returns the collapsed body, without leading or trailing separators.
|
|
468
|
+
*/
|
|
469
|
+
function collapse(body, rooted, separator = "/") {
|
|
470
|
+
const kept = [];
|
|
471
|
+
for (const segment of body.split(/[/\\]/)) {
|
|
472
|
+
if (segment === "" || segment === ".") continue;
|
|
473
|
+
if (segment === "..") {
|
|
474
|
+
if (kept.length > 0 && kept[kept.length - 1] !== "..") kept.pop();
|
|
475
|
+
else if (!rooted) kept.push(segment);
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
kept.push(segment);
|
|
479
|
+
}
|
|
480
|
+
return kept.join(separator);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Derive the terminal-card props for a tool call, or null when this call is
|
|
484
|
+
* not a terminal card and belongs on the generic path.
|
|
485
|
+
*
|
|
486
|
+
* The call side supplies the command and its working directory; the result
|
|
487
|
+
* side supplies the captured output and exit status. Three cases produce
|
|
488
|
+
* null, all of them the documented generic-card default:
|
|
489
|
+
*
|
|
490
|
+
* - Neither side declares `card:'terminal'` — including a `card` value this
|
|
491
|
+
* UI version does not know, which arrives over the wire and therefore
|
|
492
|
+
* cannot be trusted to be one of the compiled variants.
|
|
493
|
+
* - A settled call whose result view is not a terminal card: the result
|
|
494
|
+
* presentation decides how the settled call renders, and the bash tool
|
|
495
|
+
* returns a generic fenced card for an execution error or a background
|
|
496
|
+
* start, whose text and error styling the generic path preserves.
|
|
497
|
+
*
|
|
498
|
+
* Window truncation can drop the call head from a settled result (see
|
|
499
|
+
* `ToolResultNode.call`/`callView` in dsh-client-runtime), leaving a terminal
|
|
500
|
+
* result with no call side. That still renders: the command falls back to the
|
|
501
|
+
* result view's replacement title, then to an empty command (the prompt line
|
|
502
|
+
* draws bare), and the prompt shows no cwd.
|
|
503
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
504
|
+
* @param sessionCwd - the session workspace root, which resolves an omitted or
|
|
505
|
+
* relative view cwd (see {@link resolveTerminalCwd}); absent leaves both unresolved.
|
|
506
|
+
* @returns the terminal-card props, or null for the generic path.
|
|
507
|
+
*/
|
|
508
|
+
function terminalCardModel(block, sessionCwd) {
|
|
509
|
+
const call = block.callView?.card === "terminal" ? block.callView : null;
|
|
510
|
+
if (!("kind" in block)) return call === null ? null : {
|
|
511
|
+
description: call.description,
|
|
512
|
+
card: {
|
|
513
|
+
command: call.title,
|
|
514
|
+
cwd: resolveTerminalCwd(call.cwd, sessionCwd),
|
|
515
|
+
output: void 0,
|
|
516
|
+
exitCode: void 0,
|
|
517
|
+
signal: void 0,
|
|
518
|
+
running: true
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
const result = block.resultView?.card === "terminal" ? block.resultView : null;
|
|
522
|
+
if (result === null) return null;
|
|
523
|
+
return {
|
|
524
|
+
description: call?.description,
|
|
525
|
+
card: {
|
|
526
|
+
command: result.title ?? call?.title ?? "",
|
|
527
|
+
cwd: call === null ? void 0 : resolveTerminalCwd(call.cwd, sessionCwd),
|
|
528
|
+
output: result.output,
|
|
529
|
+
exitCode: result.exitCode,
|
|
530
|
+
signal: result.signal,
|
|
531
|
+
running: false
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
//#endregion
|
|
536
|
+
//#region lib/types/client/tool/models/web-card-model.js
|
|
537
|
+
/**
|
|
538
|
+
* Derive the web-card props for a tool call, or null when this call is not a
|
|
539
|
+
* web card and belongs on the generic path.
|
|
540
|
+
*
|
|
541
|
+
* The result side supplies the whole card: the sources and answer for a
|
|
542
|
+
* `search`, the URL and status for a `fetch`. Cases producing null, all of
|
|
543
|
+
* them the documented generic-card default:
|
|
544
|
+
*
|
|
545
|
+
* - A running call (no `resultView` yet): the web tools keep a generic pending
|
|
546
|
+
* card, so nothing web-shaped exists until the call settles.
|
|
547
|
+
* - A settled call whose result view is not a web card — including a `card`
|
|
548
|
+
* value this UI version does not know, which arrives over the wire and so
|
|
549
|
+
* cannot be trusted to be one of the compiled variants, and a generic result
|
|
550
|
+
* view (a web tool's error path returns the generic card, whose text the
|
|
551
|
+
* generic path preserves).
|
|
552
|
+
* - A web card whose `kind` this UI version does not know (a newer host's
|
|
553
|
+
* value): the wire cannot be trusted to be `search` or `fetch`, so it takes
|
|
554
|
+
* the generic path rather than rendering as a malformed fetch.
|
|
555
|
+
* @param block - RunningToolCall or ToolResultNode off the snapshot caches.
|
|
556
|
+
* @returns the web-card props, or null for the generic path.
|
|
557
|
+
*/
|
|
558
|
+
function webCardModel(block) {
|
|
559
|
+
if (!("kind" in block)) return null;
|
|
560
|
+
const result = block.resultView;
|
|
561
|
+
if (result?.card !== "web") return null;
|
|
562
|
+
if (result.kind === "search") return {
|
|
563
|
+
kind: "search",
|
|
564
|
+
answer: result.answer,
|
|
565
|
+
sources: result.sources.map((source) => ({
|
|
566
|
+
url: source.url,
|
|
567
|
+
title: source.title,
|
|
568
|
+
snippet: source.snippet,
|
|
569
|
+
publishedAt: source.publishedAt
|
|
570
|
+
})),
|
|
571
|
+
truncated: result.truncated
|
|
572
|
+
};
|
|
573
|
+
if (result.kind === "fetch") return {
|
|
574
|
+
kind: "fetch",
|
|
575
|
+
url: result.url,
|
|
576
|
+
statusCode: result.statusCode,
|
|
577
|
+
truncated: result.truncated
|
|
578
|
+
};
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
//#endregion
|
|
582
|
+
//#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
583
|
+
function r(e) {
|
|
584
|
+
var t, f, n = "";
|
|
585
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
586
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
587
|
+
var o = e.length;
|
|
588
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
589
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
590
|
+
return n;
|
|
591
|
+
}
|
|
592
|
+
function clsx() {
|
|
593
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
594
|
+
return n;
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
597
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-tool/src/client/tool/components/ToolRow.module.css.mjs
|
|
598
|
+
const css$3 = "._3P0koG_root{flex-direction:column;display:flex}._3P0koG_row{position:relative;overflow:hidden}._3P0koG_root[data-state=running] ._3P0koG_row:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite _3P0koG_dsh-tool-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes _3P0koG_dsh-tool-row-sweep{0%{left:-300px}90%,to{left:100%}}._3P0koG_leading{flex-shrink:0}._3P0koG_root[data-tool^=cordis_] ._3P0koG_leading,._3P0koG_root[data-tool^=cordis_] ._3P0koG_title{color:var(--dsw-alias-state-business-primary)}._3P0koG_root[data-tool^=cordis_] ._3P0koG_title{font-weight:500}._3P0koG_root[data-tool^=cordis_] ._3P0koG_sep{background:var(--dsw-alias-state-business-primary)}._3P0koG_chevron{color:var(--dsw-alias-label-secondary)}._3P0koG_title{font-weight:400}._3P0koG_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}._3P0koG_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:auto;font-size:14px;line-height:24px;overflow:hidden}._3P0koG_summarySuffix{white-space:nowrap;color:var(--dsw-alias-label-tertiary);flex:none;margin-left:4px;font-size:14px;line-height:24px}._3P0koG_fileLink{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:inherit;text-align:left;color:var(--dsw-alias-label-secondary);text-decoration:underline;text-decoration-color:var(--dsw-alias-label-quaternary);text-underline-offset:3px;cursor:pointer;background:0 0;border:none;flex:auto;margin:0;padding:0;font-size:14px;line-height:24px;overflow:hidden}._3P0koG_fileLink:hover{color:var(--dsw-alias-label-primary);text-decoration-color:currentColor}._3P0koG_errorSummary{color:var(--dsw-alias-state-error-primary)}._3P0koG_bodyWrap{flex-direction:column;display:flex}._3P0koG_inspectButton{border:1px solid var(--dsw-alias-border-l2);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}._3P0koG_root:hover ._3P0koG_inspectButton,._3P0koG_inspectButton:focus-visible{opacity:1}._3P0koG_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}._3P0koG_bodyScroll{max-height:260px;overflow-y:auto}._3P0koG_ioCard{border:1px 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}._3P0koG_ioSection{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:14px;max-height:150px;padding:12px 16px;display:grid;overflow-y:auto}._3P0koG_ioSection::-webkit-scrollbar-thumb{background-clip:padding-box;border:2px solid #0000;border-radius:6px}._3P0koG_ioSection::-webkit-scrollbar-track{margin:6px 0}._3P0koG_ioLabel{color:var(--dsw-alias-label-caption);align-self:start;position:sticky;top:0}._3P0koG_ioDivider{background:var(--dsw-alias-border-l2);flex:none;height:1px}._3P0koG_ioText{white-space:pre-wrap;word-break:break-word;min-width:0;color:var(--dsw-alias-label-secondary)}._3P0koG_ioText[data-error]{color:var(--dsw-alias-state-error-primary)}._3P0koG_codeBody,._3P0koG_terminalBody,._3P0koG_diffBody,._3P0koG_readBody,._3P0koG_searchBody,._3P0koG_webBody{margin:4px 0 4px 4px}._3P0koG_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}._3P0koG_codeBody{--dsl-code-block-content-font:var(--dsw-font-markdown-code-block-small)}._3P0koG_terminalBody{--dsl-terminal-font:var(--dsw-font-markdown-code-block-small);--dsl-terminal-line-height:18px;--dsl-terminal-output-max-height:224px;border:1px solid var(--dsw-alias-border-l1)}._3P0koG_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
|
|
599
|
+
const tagId$3 = "@deepseek-ai/dsh-client-ui-tool/ToolRow.module.css";
|
|
600
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
601
|
+
const tag = document.createElement("style");
|
|
602
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
|
|
603
|
+
tag.dataset.pluginCss = tagId$3;
|
|
604
|
+
tag.textContent = css$3;
|
|
605
|
+
document.head.appendChild(tag);
|
|
606
|
+
}
|
|
607
|
+
var ToolRow_module_css_default = {
|
|
608
|
+
"leading": "_3P0koG_leading",
|
|
609
|
+
"summarySuffix": "_3P0koG_summarySuffix",
|
|
610
|
+
"inspectButton": "_3P0koG_inspectButton",
|
|
611
|
+
"searchBody": "_3P0koG_searchBody",
|
|
612
|
+
"ioSection": "_3P0koG_ioSection",
|
|
613
|
+
"codeBody": "_3P0koG_codeBody",
|
|
614
|
+
"summary": "_3P0koG_summary",
|
|
615
|
+
"fileLink": "_3P0koG_fileLink",
|
|
616
|
+
"searchRecovery": "_3P0koG_searchRecovery",
|
|
617
|
+
"bodyScroll": "_3P0koG_bodyScroll",
|
|
618
|
+
"webBody": "_3P0koG_webBody",
|
|
619
|
+
"sep": "_3P0koG_sep",
|
|
620
|
+
"visuallyHidden": "_3P0koG_visuallyHidden",
|
|
621
|
+
"title": "_3P0koG_title",
|
|
622
|
+
"bodyWrap": "_3P0koG_bodyWrap",
|
|
623
|
+
"ioCard": "_3P0koG_ioCard",
|
|
624
|
+
"ioDivider": "_3P0koG_ioDivider",
|
|
625
|
+
"ioText": "_3P0koG_ioText",
|
|
626
|
+
"dsh-tool-row-sweep": "_3P0koG_dsh-tool-row-sweep",
|
|
627
|
+
"errorSummary": "_3P0koG_errorSummary",
|
|
628
|
+
"ioLabel": "_3P0koG_ioLabel",
|
|
629
|
+
"chevron": "_3P0koG_chevron",
|
|
630
|
+
"terminalBody": "_3P0koG_terminalBody",
|
|
631
|
+
"readBody": "_3P0koG_readBody",
|
|
632
|
+
"root": "_3P0koG_root",
|
|
633
|
+
"row": "_3P0koG_row",
|
|
634
|
+
"diffBody": "_3P0koG_diffBody"
|
|
635
|
+
};
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region lib/types/client/tool/components/ToolRow.js
|
|
638
|
+
/** Leading-slot state substitution: the tool icon yields to the terminal state
|
|
639
|
+
* semantic (error = red, interrupted = amber halo). Running keeps the icon —
|
|
640
|
+
* the row sweep (CSS on data-state) carries the in-flight signal. */
|
|
641
|
+
function leadingFor$1(state, icon) {
|
|
642
|
+
switch (state) {
|
|
643
|
+
case "error": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" });
|
|
644
|
+
case "stopped": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
|
|
645
|
+
default: return icon;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
/** Visually hidden run-state label: the StateDot and the CSS sweep are both
|
|
649
|
+
* aria-hidden / colour-only, so assistive technology needs this text to know a
|
|
650
|
+
* row is running, failed, or interrupted. null in the ok state (the icon and
|
|
651
|
+
* summary already describe a settled row). */
|
|
652
|
+
function stateStatus$1(state, t) {
|
|
653
|
+
switch (state) {
|
|
654
|
+
case "running": return t("row.running");
|
|
655
|
+
case "error": return t("row.failed");
|
|
656
|
+
case "stopped": return t("row.stopped");
|
|
657
|
+
default: return null;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
function ToolRow({ t, variant, toolName, icon, title, summary, summarySuffix, body, output, errorSummary, terminal, diff, read, search, web, state, filePath, onOpenFile, inspect }) {
|
|
661
|
+
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
662
|
+
const terminalBody = terminal ?? null;
|
|
663
|
+
const diffBody = diff ?? null;
|
|
664
|
+
const readBody = read ?? null;
|
|
665
|
+
const searchBody = search ?? null;
|
|
666
|
+
const webBody = web ?? null;
|
|
667
|
+
const outputText = output ?? null;
|
|
668
|
+
const expandable = body !== null || outputText !== null || (terminalBody ?? diffBody ?? readBody ?? searchBody ?? webBody) !== null;
|
|
669
|
+
const open = expanded && expandable;
|
|
670
|
+
const status = stateStatus$1(state, t);
|
|
671
|
+
const failureLine = state === "error" ? errorSummary ?? null : null;
|
|
672
|
+
const summaryText = failureLine ?? summary;
|
|
673
|
+
const suffix = failureLine === null ? summarySuffix ?? null : null;
|
|
674
|
+
const fileLink = filePath !== void 0 && onOpenFile !== void 0 && failureLine === null;
|
|
675
|
+
const toggleExpand = () => {
|
|
676
|
+
setExpanded((v) => !v);
|
|
677
|
+
};
|
|
678
|
+
const openFile = (event) => {
|
|
679
|
+
event.stopPropagation();
|
|
680
|
+
if (filePath !== void 0) onOpenFile?.(filePath);
|
|
681
|
+
};
|
|
682
|
+
const fileLinkKeyDown = (event) => {
|
|
683
|
+
if (event.key === "Enter" || event.key === " ") event.stopPropagation();
|
|
684
|
+
};
|
|
685
|
+
const cardBody = variant === "code" ? null : body;
|
|
686
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
687
|
+
className: ToolRow_module_css_default.root,
|
|
688
|
+
"data-variant": variant,
|
|
689
|
+
"data-tool": toolName,
|
|
690
|
+
"data-state": state,
|
|
691
|
+
children: [status !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
692
|
+
className: ToolRow_module_css_default.visuallyHidden,
|
|
693
|
+
children: status
|
|
694
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
695
|
+
rowClassName: ToolRow_module_css_default.row,
|
|
696
|
+
leadingClassName: ToolRow_module_css_default.leading,
|
|
697
|
+
titleClassName: ToolRow_module_css_default.title,
|
|
698
|
+
chevronClassName: ToolRow_module_css_default.chevron,
|
|
699
|
+
icon: leadingFor$1(state, icon),
|
|
700
|
+
title,
|
|
701
|
+
open,
|
|
702
|
+
expandable,
|
|
703
|
+
expandOnRowClick: true,
|
|
704
|
+
keepContentWhenOpen: true,
|
|
705
|
+
onToggle: toggleExpand,
|
|
706
|
+
collapsedContent: summaryText !== "" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
707
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
708
|
+
className: ToolRow_module_css_default.sep,
|
|
709
|
+
"aria-hidden": true
|
|
710
|
+
}),
|
|
711
|
+
fileLink ? (0, react_jsx_runtime.jsx)("button", {
|
|
712
|
+
type: "button",
|
|
713
|
+
className: ToolRow_module_css_default.fileLink,
|
|
714
|
+
onClick: openFile,
|
|
715
|
+
onKeyDown: fileLinkKeyDown,
|
|
716
|
+
children: summaryText
|
|
717
|
+
}) : (0, react_jsx_runtime.jsx)("span", {
|
|
718
|
+
className: clsx(ToolRow_module_css_default.summary, failureLine !== null && ToolRow_module_css_default.errorSummary),
|
|
719
|
+
children: summaryText
|
|
720
|
+
}),
|
|
721
|
+
suffix !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
722
|
+
className: ToolRow_module_css_default.summarySuffix,
|
|
723
|
+
children: suffix
|
|
724
|
+
})
|
|
725
|
+
] }),
|
|
726
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
727
|
+
className: ToolRow_module_css_default.bodyWrap,
|
|
728
|
+
children: [terminalBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
|
|
729
|
+
...terminalBody.card,
|
|
730
|
+
maxLines: Infinity,
|
|
731
|
+
labels: terminalBlockLabels(t),
|
|
732
|
+
className: ToolRow_module_css_default.terminalBody
|
|
733
|
+
}) : diffBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DiffBlock, {
|
|
734
|
+
...diffBody.card,
|
|
735
|
+
maxLines: 8,
|
|
736
|
+
className: ToolRow_module_css_default.diffBody
|
|
737
|
+
}) : readBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ReadBlock, {
|
|
738
|
+
...readBody,
|
|
739
|
+
maxLines: 8,
|
|
740
|
+
className: ToolRow_module_css_default.readBody
|
|
741
|
+
}) : searchBody !== null ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SearchBlock, {
|
|
742
|
+
...searchBody.card,
|
|
743
|
+
maxLines: 8,
|
|
744
|
+
className: ToolRow_module_css_default.searchBody
|
|
745
|
+
}), searchBody.recovery !== void 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
746
|
+
className: ToolRow_module_css_default.searchRecovery,
|
|
747
|
+
children: searchBody.recovery
|
|
748
|
+
})] }) : webBody !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.WebBlock, {
|
|
749
|
+
...webBody,
|
|
750
|
+
className: ToolRow_module_css_default.webBody
|
|
751
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [variant === "code" && body !== null && (0, react_jsx_runtime.jsx)("div", {
|
|
752
|
+
className: ToolRow_module_css_default.bodyScroll,
|
|
753
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.CodeBlock, {
|
|
754
|
+
code: body,
|
|
755
|
+
lang: "typescript",
|
|
756
|
+
copyLabel: t("copy"),
|
|
757
|
+
copiedLabel: t("copied"),
|
|
758
|
+
className: ToolRow_module_css_default.codeBody
|
|
759
|
+
})
|
|
760
|
+
}), (cardBody !== null || outputText !== null) && (0, react_jsx_runtime.jsxs)("div", {
|
|
761
|
+
className: ToolRow_module_css_default.ioCard,
|
|
762
|
+
children: [
|
|
763
|
+
cardBody !== null && (0, react_jsx_runtime.jsxs)("div", {
|
|
764
|
+
className: ToolRow_module_css_default.ioSection,
|
|
765
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
766
|
+
className: ToolRow_module_css_default.ioLabel,
|
|
767
|
+
children: "IN"
|
|
768
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
769
|
+
className: ToolRow_module_css_default.ioText,
|
|
770
|
+
children: cardBody
|
|
771
|
+
})]
|
|
772
|
+
}),
|
|
773
|
+
cardBody !== null && outputText !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
774
|
+
className: ToolRow_module_css_default.ioDivider,
|
|
775
|
+
"aria-hidden": true
|
|
776
|
+
}),
|
|
777
|
+
outputText !== null && (0, react_jsx_runtime.jsxs)("div", {
|
|
778
|
+
className: ToolRow_module_css_default.ioSection,
|
|
779
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
780
|
+
className: ToolRow_module_css_default.ioLabel,
|
|
781
|
+
children: "OUT"
|
|
782
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
783
|
+
className: ToolRow_module_css_default.ioText,
|
|
784
|
+
"data-error": state === "error" || void 0,
|
|
785
|
+
children: outputText
|
|
786
|
+
})]
|
|
787
|
+
})
|
|
788
|
+
]
|
|
789
|
+
})] }), inspect !== void 0 && (0, react_jsx_runtime.jsxs)("button", {
|
|
790
|
+
type: "button",
|
|
791
|
+
className: ToolRow_module_css_default.inspectButton,
|
|
792
|
+
onClick: inspect,
|
|
793
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), "Inspect"]
|
|
794
|
+
})]
|
|
795
|
+
})
|
|
796
|
+
})]
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
//#endregion
|
|
800
|
+
//#region lib/types/client/tool/toolviews/GenericToolCard.js
|
|
801
|
+
/** Variant leading icons (figma table); all glyphs render at 14 inside the 16px leading box. */
|
|
802
|
+
const VARIANT_ICONS = {
|
|
803
|
+
search: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 14 }),
|
|
804
|
+
read: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
|
|
805
|
+
bash: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutline14, { size: 14 }),
|
|
806
|
+
write: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
|
|
807
|
+
edit: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
|
|
808
|
+
code: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutline16, { size: 14 }),
|
|
809
|
+
others: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkle16, { size: 14 })
|
|
810
|
+
};
|
|
811
|
+
function GenericToolCard({ toolName, block, cwd, openFile, inspect, t }) {
|
|
812
|
+
const model = toolRowModel(toolName, block, cwd);
|
|
813
|
+
const terminal = terminalCardModel(block, cwd);
|
|
814
|
+
const read = readCardModel(block, cwd);
|
|
815
|
+
const diff = diffCardModel(block);
|
|
816
|
+
const search = searchCardModel(block);
|
|
817
|
+
const web = webCardModel(block);
|
|
818
|
+
const state = model.state === "ok" && terminal !== null && terminalFailed(terminal) ? "error" : model.state;
|
|
819
|
+
const singleFile = model.filePath !== void 0;
|
|
820
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
821
|
+
t,
|
|
822
|
+
variant: model.variant,
|
|
823
|
+
toolName,
|
|
824
|
+
icon: VARIANT_ICONS[model.variant],
|
|
825
|
+
title: model.title,
|
|
826
|
+
summary: terminal?.description ?? search?.title ?? model.summary,
|
|
827
|
+
body: singleFile ? null : model.body,
|
|
828
|
+
output: model.output,
|
|
829
|
+
errorSummary: model.errorSummary,
|
|
830
|
+
terminal,
|
|
831
|
+
diff,
|
|
832
|
+
read,
|
|
833
|
+
search,
|
|
834
|
+
web,
|
|
835
|
+
state,
|
|
836
|
+
filePath: model.filePath,
|
|
837
|
+
onOpenFile: singleFile ? openFile : void 0,
|
|
838
|
+
inspect
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
//#endregion
|
|
842
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-tool/src/client/tool/ToolCallTree.module.css.mjs
|
|
843
|
+
const css$2 = ".ngI5ma_callRow{border-radius:6px}.ngI5ma_subCalls{border-left:1px solid var(--dsw-alias-border-l2);flex-direction:column;gap:4px;margin:4px 0 2px 22px;padding-left:8px;display:flex}";
|
|
844
|
+
const tagId$2 = "@deepseek-ai/dsh-client-ui-tool/ToolCallTree.module.css";
|
|
845
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
846
|
+
const tag = document.createElement("style");
|
|
847
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
|
|
848
|
+
tag.dataset.pluginCss = tagId$2;
|
|
849
|
+
tag.textContent = css$2;
|
|
850
|
+
document.head.appendChild(tag);
|
|
851
|
+
}
|
|
852
|
+
var ToolCallTree_module_css_default = {
|
|
853
|
+
"callRow": "ngI5ma_callRow",
|
|
854
|
+
"subCalls": "ngI5ma_subCalls"
|
|
855
|
+
};
|
|
856
|
+
//#endregion
|
|
857
|
+
//#region lib/types/client/tool/ToolCallTree.js
|
|
858
|
+
/** Root/subcall Tool composition with one keyed atomic dispatch path. */
|
|
859
|
+
/** Resolve a Tool call's wire name from either lifecycle form. */
|
|
860
|
+
function callName(node) {
|
|
861
|
+
return "kind" in node ? node.call?.name ?? "" : node.name;
|
|
862
|
+
}
|
|
863
|
+
/** One atomic call dispatched through the Tool-owned keyed slot. */
|
|
864
|
+
const ToolCall = (0, react.memo)(function ToolCall({ renderSlot, callId, toolName, block, openFile, selected, cwd, inspectCall, t, children }) {
|
|
865
|
+
const owner = (0, react.useMemo)(() => ({
|
|
866
|
+
callId,
|
|
867
|
+
toolName,
|
|
868
|
+
block,
|
|
869
|
+
openFile,
|
|
870
|
+
cwd,
|
|
871
|
+
inspect: () => {
|
|
872
|
+
inspectCall(callId);
|
|
873
|
+
}
|
|
874
|
+
}), [
|
|
875
|
+
callId,
|
|
876
|
+
toolName,
|
|
877
|
+
block,
|
|
878
|
+
openFile,
|
|
879
|
+
cwd,
|
|
880
|
+
inspectCall
|
|
881
|
+
]);
|
|
882
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
883
|
+
className: ToolCallTree_module_css_default.callRow,
|
|
884
|
+
"data-chat-anchor-key": `call:${callId}`,
|
|
885
|
+
"data-chat-call-id": callId,
|
|
886
|
+
"data-selected": selected || void 0,
|
|
887
|
+
children: [renderSlot("tool.call.toolview", owner, {
|
|
888
|
+
entryKey: toolName,
|
|
889
|
+
fallback: (0, react_jsx_runtime.jsx)(GenericToolCard, {
|
|
890
|
+
...owner,
|
|
891
|
+
t
|
|
892
|
+
})
|
|
893
|
+
}), children]
|
|
894
|
+
});
|
|
895
|
+
});
|
|
896
|
+
const ToolCallBranch = (0, react.memo)(function ToolCallBranch({ renderSlot, block, selectedCallId, cwd, openFile, inspectCall, t }) {
|
|
897
|
+
return (0, react_jsx_runtime.jsx)(ToolCall, {
|
|
898
|
+
renderSlot,
|
|
899
|
+
callId: block.callId,
|
|
900
|
+
toolName: callName(block),
|
|
901
|
+
block,
|
|
902
|
+
openFile,
|
|
903
|
+
selected: block.callId === selectedCallId,
|
|
904
|
+
cwd,
|
|
905
|
+
inspectCall,
|
|
906
|
+
t,
|
|
907
|
+
children: block.subCalls.length > 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
908
|
+
className: ToolCallTree_module_css_default.subCalls,
|
|
909
|
+
"data-subcalls": true,
|
|
910
|
+
children: block.subCalls.map((child) => (0, react_jsx_runtime.jsx)(ToolCallBranch, {
|
|
911
|
+
renderSlot,
|
|
912
|
+
block: child,
|
|
913
|
+
selectedCallId,
|
|
914
|
+
cwd,
|
|
915
|
+
openFile,
|
|
916
|
+
inspectCall,
|
|
917
|
+
t
|
|
918
|
+
}, child.callId))
|
|
919
|
+
}) : null
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
/**
|
|
923
|
+
* Render one root Tool call and its recursive children through the same
|
|
924
|
+
* atomic keyed dispatch.
|
|
925
|
+
* @param props - whole-Tool owner data and the Tool-owned child-slot share.
|
|
926
|
+
* @returns the Tool call tree.
|
|
927
|
+
*/
|
|
928
|
+
function ToolCallTree({ renderSlot, node, selectedCallId, cwd, openFile, inspectCall, t }) {
|
|
929
|
+
const block = node.data.root;
|
|
930
|
+
return (0, react_jsx_runtime.jsx)(ToolCallBranch, {
|
|
931
|
+
renderSlot,
|
|
932
|
+
block,
|
|
933
|
+
selectedCallId,
|
|
934
|
+
cwd,
|
|
935
|
+
openFile,
|
|
936
|
+
inspectCall,
|
|
937
|
+
t
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-tool/src/client/tool/ToolDetails.module.css.mjs
|
|
942
|
+
const css$1 = ".rnWy0a_description{color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xs-13);margin:0 0 6px}.rnWy0a_cardBody{margin:0}.rnWy0a_recovery{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xs-13);margin:6px 0 0}.rnWy0a_code{background:var(--dsw-alias-markdown-code-block);font-family:var(--ds-font-family-code);color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;border-radius:12px;margin:0;padding:16px;font-size:13px;line-height:22px}.rnWy0a_code[data-error]{color:var(--dsw-alias-state-error-primary)}.rnWy0a_read,.rnWy0a_web{margin:0}.rnWy0a_empty{color:var(--dsw-alias-label-tertiary);padding:8px 0;font-size:13px;line-height:20px}";
|
|
943
|
+
const tagId$1 = "@deepseek-ai/dsh-client-ui-tool/ToolDetails.module.css";
|
|
944
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
945
|
+
const tag = document.createElement("style");
|
|
946
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
|
|
947
|
+
tag.dataset.pluginCss = tagId$1;
|
|
948
|
+
tag.textContent = css$1;
|
|
949
|
+
document.head.appendChild(tag);
|
|
950
|
+
}
|
|
951
|
+
var ToolDetails_module_css_default = {
|
|
952
|
+
"cardBody": "rnWy0a_cardBody",
|
|
953
|
+
"read": "rnWy0a_read",
|
|
954
|
+
"code": "rnWy0a_code",
|
|
955
|
+
"description": "rnWy0a_description",
|
|
956
|
+
"recovery": "rnWy0a_recovery",
|
|
957
|
+
"web": "rnWy0a_web",
|
|
958
|
+
"empty": "rnWy0a_empty"
|
|
959
|
+
};
|
|
960
|
+
//#endregion
|
|
961
|
+
//#region lib/types/client/tool/ToolDetails.js
|
|
962
|
+
/** Card-aware output body for the selected Tool call in details. */
|
|
963
|
+
/**
|
|
964
|
+
* Render the selected Tool call's structured output when its presentation
|
|
965
|
+
* intent is known, otherwise preserve the flattened result text.
|
|
966
|
+
* @param props - selected call slice, workspace root, and locale seat.
|
|
967
|
+
* @returns the details output body.
|
|
968
|
+
*/
|
|
969
|
+
function ToolDetails({ block, cwd, t }) {
|
|
970
|
+
const terminal = terminalCardModel(block, cwd);
|
|
971
|
+
if (terminal !== null) return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [terminal.description !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
972
|
+
className: ToolDetails_module_css_default.description,
|
|
973
|
+
children: terminal.description
|
|
974
|
+
}) : null, (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
|
|
975
|
+
...terminal.card,
|
|
976
|
+
labels: terminalBlockLabels(t),
|
|
977
|
+
className: ToolDetails_module_css_default.cardBody
|
|
978
|
+
})] });
|
|
979
|
+
const read = readCardModel(block, cwd);
|
|
980
|
+
if (read !== null) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.ReadBlock, {
|
|
981
|
+
...read,
|
|
982
|
+
className: ToolDetails_module_css_default.read
|
|
983
|
+
});
|
|
984
|
+
const diff = diffCardModel(block);
|
|
985
|
+
if (diff !== null) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DiffBlock, {
|
|
986
|
+
...diff.card,
|
|
987
|
+
className: ToolDetails_module_css_default.cardBody
|
|
988
|
+
});
|
|
989
|
+
const search = searchCardModel(block);
|
|
990
|
+
if (search !== null) return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SearchBlock, {
|
|
991
|
+
...search.card,
|
|
992
|
+
className: ToolDetails_module_css_default.cardBody
|
|
993
|
+
}), search.recovery !== void 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
994
|
+
className: ToolDetails_module_css_default.recovery,
|
|
995
|
+
children: search.recovery
|
|
996
|
+
}) : null] });
|
|
997
|
+
const web = webCardModel(block);
|
|
998
|
+
if (web !== null) {
|
|
999
|
+
const body = "kind" in block ? resultText(block) : "";
|
|
1000
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.WebBlock, {
|
|
1001
|
+
...web,
|
|
1002
|
+
className: ToolDetails_module_css_default.web
|
|
1003
|
+
}), body !== "" ? (0, react_jsx_runtime.jsx)("pre", {
|
|
1004
|
+
className: ToolDetails_module_css_default.code,
|
|
1005
|
+
children: body
|
|
1006
|
+
}) : null] });
|
|
1007
|
+
}
|
|
1008
|
+
if (!("kind" in block)) return (0, react_jsx_runtime.jsx)("div", {
|
|
1009
|
+
className: ToolDetails_module_css_default.empty,
|
|
1010
|
+
children: t("details.running")
|
|
1011
|
+
});
|
|
1012
|
+
return (0, react_jsx_runtime.jsx)("pre", {
|
|
1013
|
+
className: ToolDetails_module_css_default.code,
|
|
1014
|
+
"data-error": block.isError || void 0,
|
|
1015
|
+
children: resultText(block)
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
//#endregion
|
|
1019
|
+
//#region lib/types/client/locale.js
|
|
1020
|
+
/** Locale namespace supplied by the conversation owner to Tool renderers. */
|
|
1021
|
+
const CONVERSATION_NS = "conversation";
|
|
1022
|
+
//#endregion
|
|
1023
|
+
//#region lib/types/client/tool/toolviews/ask-question-row.js
|
|
1024
|
+
function isAnswer(value) {
|
|
1025
|
+
return typeof value === "object" && value !== null;
|
|
1026
|
+
}
|
|
1027
|
+
/** Answered-count summary from the result JSON (a skipped question has
|
|
1028
|
+
* empty `selected` and no `custom`); null when answer fields are invalid. */
|
|
1029
|
+
function answeredSummary(text, t) {
|
|
1030
|
+
let parsed;
|
|
1031
|
+
try {
|
|
1032
|
+
parsed = JSON.parse(text);
|
|
1033
|
+
} catch {
|
|
1034
|
+
return null;
|
|
1035
|
+
}
|
|
1036
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1037
|
+
const answers = parsed.answers;
|
|
1038
|
+
if (!Array.isArray(answers) || !answers.every(isAnswer)) return null;
|
|
1039
|
+
const answered = answers.filter((a) => Array.isArray(a.selected) && a.selected.length > 0 || typeof a.custom === "string" && a.custom !== "").length;
|
|
1040
|
+
return t("ask.answered", {
|
|
1041
|
+
answered,
|
|
1042
|
+
total: answers.length
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
/** One-line question-interaction row (the whole row toggles the call's
|
|
1046
|
+
* Input/Output sections, ToolRow's unified expand). */
|
|
1047
|
+
function AskQuestionRow({ toolName, block, inspect, t }) {
|
|
1048
|
+
const model = toolRowModel(toolName, block);
|
|
1049
|
+
const code = "kind" in block ? block.error?.code : void 0;
|
|
1050
|
+
let summary = model.summary;
|
|
1051
|
+
let state = model.state;
|
|
1052
|
+
if (code === "ASK_CANCELLED") summary = t("ask.cancelled");
|
|
1053
|
+
else if (code === "ASK_ABORTED") {
|
|
1054
|
+
summary = t("ask.interrupted");
|
|
1055
|
+
state = "stopped";
|
|
1056
|
+
} else if (model.state === "running") summary = t("ask.waiting");
|
|
1057
|
+
else if ("kind" in block && model.state === "ok") summary = answeredSummary(block.content.filter((b) => b.type === "text").map((b) => b.text).join(""), t) ?? model.summary;
|
|
1058
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1059
|
+
t,
|
|
1060
|
+
variant: model.variant,
|
|
1061
|
+
toolName,
|
|
1062
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconQuestionOutline14, {}),
|
|
1063
|
+
title: t("ask.rowTitle"),
|
|
1064
|
+
summary,
|
|
1065
|
+
body: model.body,
|
|
1066
|
+
output: model.output,
|
|
1067
|
+
state,
|
|
1068
|
+
inspect
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* The ask-question row as a plain registrant plugin following the chat
|
|
1073
|
+
* toolview declaration across independent activation and reload lifetimes.
|
|
1074
|
+
*/
|
|
1075
|
+
const askQuestionToolview = {
|
|
1076
|
+
name: "ask-question-toolview",
|
|
1077
|
+
inject: ["slots"],
|
|
1078
|
+
/**
|
|
1079
|
+
* Register the ask-question row into the Tool-owned keyed view slot.
|
|
1080
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1081
|
+
*/
|
|
1082
|
+
apply(ctx) {
|
|
1083
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1084
|
+
name: "tool.call.toolview",
|
|
1085
|
+
key: "ask_user_question",
|
|
1086
|
+
locale: CONVERSATION_NS
|
|
1087
|
+
}, AskQuestionRow));
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
//#endregion
|
|
1091
|
+
//#region \0dsh-css:/private/var/folders/nm/n5smty9962gf5rhjc5855kt80000gn/T/dsh-edge-release-worktree.XXXXXX.RcJjogaGt4/repo/packages/client/ui-tool/src/client/tool/toolviews/bash-sample.module.css.mjs
|
|
1092
|
+
const css = ".PMP91q_card{flex-direction:column;display:flex}.PMP91q_terminal{--dsl-terminal-font:var(--dsw-font-markdown-code-block-small);--dsl-terminal-line-height:18px;--dsl-terminal-output-max-height:224px;border:1px solid var(--dsw-alias-border-l1);margin:4px 0 4px 4px}.PMP91q_ioCard{border:1px 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}.PMP91q_ioSection{grid-template-columns:max-content 1fr;align-items:baseline;column-gap:14px;max-height:150px;padding:12px 16px;display:grid;overflow-y:auto}.PMP91q_ioSection::-webkit-scrollbar-thumb{background-clip:padding-box;border:2px solid #0000;border-radius:6px}.PMP91q_ioSection::-webkit-scrollbar-track{margin:6px 0}.PMP91q_ioLabel{color:var(--dsw-alias-label-caption);align-self:start;position:sticky;top:0}.PMP91q_ioDivider{background:var(--dsw-alias-border-l2);flex:none;height:1px}.PMP91q_ioText{white-space:pre-wrap;word-break:break-word;min-width:0;color:var(--dsw-alias-label-secondary)}.PMP91q_ioText[data-error]{color:var(--dsw-alias-state-error-primary)}.PMP91q_root[data-expandable]{cursor:pointer}.PMP91q_root{align-items:center;min-width:0;height:24px;display:flex;position:relative;overflow:hidden}.PMP91q_root[data-state=running]:after{content:\"\";background:linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--dsw-alias-bg-base) 60%, transparent) 55%, transparent 100%);pointer-events:none;width:300px;animation:2.6s ease-out infinite PMP91q_dsh-bash-row-sweep;position:absolute;top:0;bottom:0;left:0}@keyframes PMP91q_dsh-bash-row-sweep{0%{left:-300px}90%,to{left:100%}}.PMP91q_leading{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;margin-right:6px;display:inline-flex;position:relative}.PMP91q_chevron{color:var(--dsw-alias-label-secondary)}.PMP91q_iconIdle{opacity:1;transition:opacity .1s;display:inline-flex}.PMP91q_chevronHover{opacity:0;margin:auto;transition:opacity .1s;position:absolute;inset:0}.PMP91q_root:hover .PMP91q_iconIdle{opacity:0}.PMP91q_root:hover .PMP91q_chevronHover{opacity:1}.PMP91q_title{color:var(--dsw-alias-label-secondary);flex:none;font-size:14px;line-height:24px}.PMP91q_sep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.PMP91q_summary{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-tertiary);flex:auto;font-size:14px;line-height:24px;overflow:hidden}.PMP91q_errorSummary{color:var(--dsw-alias-state-error-primary)}.PMP91q_bodyWrap{flex-direction:column;display:flex}.PMP91q_inspectButton{border:1px solid var(--dsw-alias-border-l2);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}.PMP91q_card:hover .PMP91q_inspectButton,.PMP91q_inspectButton:focus-visible{opacity:1}.PMP91q_inspectButton:hover{background:var(--dsw-alias-interactive-bg-hover-solid);color:var(--dsw-alias-label-primary)}.PMP91q_visuallyHidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
|
|
1093
|
+
const tagId = "@deepseek-ai/dsh-client-ui-tool/bash-sample.module.css";
|
|
1094
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1095
|
+
const tag = document.createElement("style");
|
|
1096
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-tool";
|
|
1097
|
+
tag.dataset.pluginCss = tagId;
|
|
1098
|
+
tag.textContent = css;
|
|
1099
|
+
document.head.appendChild(tag);
|
|
1100
|
+
}
|
|
1101
|
+
var bash_sample_module_css_default = {
|
|
1102
|
+
"ioDivider": "PMP91q_ioDivider",
|
|
1103
|
+
"sep": "PMP91q_sep",
|
|
1104
|
+
"summary": "PMP91q_summary",
|
|
1105
|
+
"bodyWrap": "PMP91q_bodyWrap",
|
|
1106
|
+
"title": "PMP91q_title",
|
|
1107
|
+
"ioSection": "PMP91q_ioSection",
|
|
1108
|
+
"terminal": "PMP91q_terminal",
|
|
1109
|
+
"dsh-bash-row-sweep": "PMP91q_dsh-bash-row-sweep",
|
|
1110
|
+
"iconIdle": "PMP91q_iconIdle",
|
|
1111
|
+
"ioCard": "PMP91q_ioCard",
|
|
1112
|
+
"visuallyHidden": "PMP91q_visuallyHidden",
|
|
1113
|
+
"ioLabel": "PMP91q_ioLabel",
|
|
1114
|
+
"root": "PMP91q_root",
|
|
1115
|
+
"chevronHover": "PMP91q_chevronHover",
|
|
1116
|
+
"card": "PMP91q_card",
|
|
1117
|
+
"ioText": "PMP91q_ioText",
|
|
1118
|
+
"chevron": "PMP91q_chevron",
|
|
1119
|
+
"errorSummary": "PMP91q_errorSummary",
|
|
1120
|
+
"inspectButton": "PMP91q_inspectButton",
|
|
1121
|
+
"leading": "PMP91q_leading"
|
|
1122
|
+
};
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region lib/types/client/tool/toolviews/bash-sample.js
|
|
1125
|
+
function leadingFor(state) {
|
|
1126
|
+
switch (state) {
|
|
1127
|
+
case "error": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" });
|
|
1128
|
+
case "stopped": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "warning" });
|
|
1129
|
+
default: return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutline14, { size: 14 });
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
/** Visually hidden status — StateDot is aria-hidden; AT needs a text label. */
|
|
1133
|
+
function stateStatus(state, t) {
|
|
1134
|
+
switch (state) {
|
|
1135
|
+
case "running": return t("bash.running");
|
|
1136
|
+
case "error": return t("bash.failed");
|
|
1137
|
+
case "stopped": return t("bash.stopped");
|
|
1138
|
+
default: return null;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Bash row: icon + Bash · {description} in the shared ToolRow chrome, the
|
|
1143
|
+
* whole row toggling the command's terminal or generic error card (ToolRow's unified
|
|
1144
|
+
* expand interaction, replicated locally per the registrant posture).
|
|
1145
|
+
*/
|
|
1146
|
+
function BashRow({ toolName, block, sessionId, useSessions, inspect, t }) {
|
|
1147
|
+
const model = toolRowModel(toolName, block);
|
|
1148
|
+
const terminal = terminalCardModel(block, useSessions((list) => list.byId[sessionId]?.cwd));
|
|
1149
|
+
const state = model.state === "ok" && terminal !== null && terminalFailed(terminal) ? "error" : model.state;
|
|
1150
|
+
const status = stateStatus(state, t);
|
|
1151
|
+
const [expanded, setExpanded] = (0, react.useState)(false);
|
|
1152
|
+
const genericError = terminal === null && model.state === "error" && (model.body !== null || model.output !== null);
|
|
1153
|
+
const expandable = terminal !== null || genericError;
|
|
1154
|
+
const open = expanded && expandable;
|
|
1155
|
+
const failureLine = model.state === "error" ? model.errorSummary : null;
|
|
1156
|
+
const toggleExpand = () => {
|
|
1157
|
+
setExpanded((v) => !v);
|
|
1158
|
+
};
|
|
1159
|
+
const toggleFromKeyboard = (event) => {
|
|
1160
|
+
if (!expandable || event.key !== "Enter" && event.key !== " ") return;
|
|
1161
|
+
event.preventDefault();
|
|
1162
|
+
toggleExpand();
|
|
1163
|
+
};
|
|
1164
|
+
const leading = open ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: bash_sample_module_css_default.chevron }) : expandable ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1165
|
+
className: bash_sample_module_css_default.iconIdle,
|
|
1166
|
+
children: leadingFor(state)
|
|
1167
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: clsx(bash_sample_module_css_default.chevron, bash_sample_module_css_default.chevronHover) })] }) : leadingFor(state);
|
|
1168
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1169
|
+
className: bash_sample_module_css_default.card,
|
|
1170
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1171
|
+
className: bash_sample_module_css_default.root,
|
|
1172
|
+
"data-sample": "bash",
|
|
1173
|
+
"data-variant": "bash",
|
|
1174
|
+
"data-state": state,
|
|
1175
|
+
"data-expandable": expandable || void 0,
|
|
1176
|
+
role: expandable ? "button" : void 0,
|
|
1177
|
+
tabIndex: expandable ? 0 : void 0,
|
|
1178
|
+
"aria-expanded": expandable ? open : void 0,
|
|
1179
|
+
onClick: expandable ? toggleExpand : void 0,
|
|
1180
|
+
onKeyDown: expandable ? toggleFromKeyboard : void 0,
|
|
1181
|
+
children: [
|
|
1182
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1183
|
+
className: bash_sample_module_css_default.leading,
|
|
1184
|
+
children: leading
|
|
1185
|
+
}),
|
|
1186
|
+
status !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
1187
|
+
className: bash_sample_module_css_default.visuallyHidden,
|
|
1188
|
+
children: status
|
|
1189
|
+
}),
|
|
1190
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1191
|
+
className: bash_sample_module_css_default.title,
|
|
1192
|
+
children: model.title
|
|
1193
|
+
}),
|
|
1194
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1195
|
+
className: bash_sample_module_css_default.sep,
|
|
1196
|
+
"aria-hidden": true
|
|
1197
|
+
}),
|
|
1198
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1199
|
+
className: clsx(bash_sample_module_css_default.summary, failureLine !== null && bash_sample_module_css_default.errorSummary),
|
|
1200
|
+
children: failureLine ?? terminal?.description ?? model.summary
|
|
1201
|
+
})
|
|
1202
|
+
]
|
|
1203
|
+
}), open && (0, react_jsx_runtime.jsxs)("div", {
|
|
1204
|
+
className: bash_sample_module_css_default.bodyWrap,
|
|
1205
|
+
children: [terminal !== null ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.TerminalBlock, {
|
|
1206
|
+
...terminal.card,
|
|
1207
|
+
maxLines: Infinity,
|
|
1208
|
+
labels: terminalBlockLabels(t),
|
|
1209
|
+
className: bash_sample_module_css_default.terminal
|
|
1210
|
+
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
1211
|
+
className: bash_sample_module_css_default.ioCard,
|
|
1212
|
+
children: [
|
|
1213
|
+
model.body !== null && (0, react_jsx_runtime.jsxs)("div", {
|
|
1214
|
+
className: bash_sample_module_css_default.ioSection,
|
|
1215
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1216
|
+
className: bash_sample_module_css_default.ioLabel,
|
|
1217
|
+
children: "IN"
|
|
1218
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1219
|
+
className: bash_sample_module_css_default.ioText,
|
|
1220
|
+
children: model.body
|
|
1221
|
+
})]
|
|
1222
|
+
}),
|
|
1223
|
+
model.body !== null && model.output !== null && (0, react_jsx_runtime.jsx)("span", {
|
|
1224
|
+
className: bash_sample_module_css_default.ioDivider,
|
|
1225
|
+
"aria-hidden": true
|
|
1226
|
+
}),
|
|
1227
|
+
model.output !== null && (0, react_jsx_runtime.jsxs)("div", {
|
|
1228
|
+
className: bash_sample_module_css_default.ioSection,
|
|
1229
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1230
|
+
className: bash_sample_module_css_default.ioLabel,
|
|
1231
|
+
children: "OUT"
|
|
1232
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1233
|
+
className: bash_sample_module_css_default.ioText,
|
|
1234
|
+
"data-error": true,
|
|
1235
|
+
children: model.output
|
|
1236
|
+
})]
|
|
1237
|
+
})
|
|
1238
|
+
]
|
|
1239
|
+
}), inspect !== void 0 && (0, react_jsx_runtime.jsxs)("button", {
|
|
1240
|
+
type: "button",
|
|
1241
|
+
className: bash_sample_module_css_default.inspectButton,
|
|
1242
|
+
onClick: inspect,
|
|
1243
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconInspectOutline12, {}), "Inspect"]
|
|
1244
|
+
})]
|
|
1245
|
+
})]
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* The sample as a plain registrant plugin. Slot injection follows the chat
|
|
1250
|
+
* toolview declaration across independent activation and reload lifetimes.
|
|
1251
|
+
*/
|
|
1252
|
+
const bashToolviewSample = {
|
|
1253
|
+
name: "bash-toolview-sample",
|
|
1254
|
+
inject: ["slots"],
|
|
1255
|
+
/**
|
|
1256
|
+
* Register the bash row into the Tool-owned keyed view slot.
|
|
1257
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1258
|
+
*/
|
|
1259
|
+
apply(ctx) {
|
|
1260
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1261
|
+
name: "tool.call.toolview",
|
|
1262
|
+
key: "bash",
|
|
1263
|
+
locale: CONVERSATION_NS
|
|
1264
|
+
}, BashRow));
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
//#endregion
|
|
1268
|
+
//#region lib/types/client/tool/toolviews/file-mutation-row.js
|
|
1269
|
+
/**
|
|
1270
|
+
* File-mutation row: icon + {Edit,Write} · {path} in the shared ToolRow chrome,
|
|
1271
|
+
* with the applied diff as the row's collapsed-by-default card body. The
|
|
1272
|
+
* summary is a path link (a file tool's interaction); the host's `openFile`
|
|
1273
|
+
* resolves it against the session cwd, so this passes the tool's own path
|
|
1274
|
+
* verbatim. An errored mutation has no diff card, so ToolRow surfaces the
|
|
1275
|
+
* model-facing error text through its Output section and its first line in the
|
|
1276
|
+
* collapsed summary instead.
|
|
1277
|
+
*/
|
|
1278
|
+
function FileMutationRow({ toolName, block, cwd, openFile, inspect, t }) {
|
|
1279
|
+
const model = toolRowModel(toolName, block, cwd);
|
|
1280
|
+
const diff = diffCardModel(block);
|
|
1281
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1282
|
+
t,
|
|
1283
|
+
variant: model.variant,
|
|
1284
|
+
toolName,
|
|
1285
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutline16, { size: 14 }),
|
|
1286
|
+
title: model.title,
|
|
1287
|
+
summary: model.summary,
|
|
1288
|
+
body: null,
|
|
1289
|
+
output: model.output,
|
|
1290
|
+
errorSummary: model.errorSummary,
|
|
1291
|
+
diff,
|
|
1292
|
+
state: model.state,
|
|
1293
|
+
filePath: model.filePath,
|
|
1294
|
+
onOpenFile: openFile,
|
|
1295
|
+
inspect
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* The file-mutation rows as a plain registrant plugin following the chat
|
|
1300
|
+
* toolview declaration across independent activation and reload lifetimes.
|
|
1301
|
+
*/
|
|
1302
|
+
const fileMutationToolview = {
|
|
1303
|
+
name: "file-mutation-toolview",
|
|
1304
|
+
inject: ["slots"],
|
|
1305
|
+
/**
|
|
1306
|
+
* Register the file-mutation row into the Tool-owned keyed view slot
|
|
1307
|
+
* under both mutation tool names.
|
|
1308
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1309
|
+
*/
|
|
1310
|
+
apply(ctx) {
|
|
1311
|
+
ctx.slots.inject("tool.call.toolview", function* () {
|
|
1312
|
+
yield ctx.slots.register({
|
|
1313
|
+
name: "tool.call.toolview",
|
|
1314
|
+
key: "edit",
|
|
1315
|
+
locale: CONVERSATION_NS
|
|
1316
|
+
}, FileMutationRow);
|
|
1317
|
+
yield ctx.slots.register({
|
|
1318
|
+
name: "tool.call.toolview",
|
|
1319
|
+
key: "write",
|
|
1320
|
+
locale: CONVERSATION_NS
|
|
1321
|
+
}, FileMutationRow);
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
//#endregion
|
|
1326
|
+
//#region lib/types/client/tool/toolviews/read-row.js
|
|
1327
|
+
/**
|
|
1328
|
+
* Read row: icon + Read · {path} in the shared ToolRow chrome, with the file's
|
|
1329
|
+
* read card as the row's collapsed-by-default card body. The summary path is an
|
|
1330
|
+
* openable host link when the row names a single file.
|
|
1331
|
+
*/
|
|
1332
|
+
function ReadRow({ toolName, block, cwd, openFile, inspect, t }) {
|
|
1333
|
+
const model = toolRowModel(toolName, block, cwd);
|
|
1334
|
+
const read = readCardModel(block, cwd);
|
|
1335
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1336
|
+
t,
|
|
1337
|
+
variant: model.variant,
|
|
1338
|
+
toolName,
|
|
1339
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
|
|
1340
|
+
title: model.title,
|
|
1341
|
+
summary: model.summary,
|
|
1342
|
+
body: null,
|
|
1343
|
+
output: model.output,
|
|
1344
|
+
errorSummary: model.errorSummary,
|
|
1345
|
+
read,
|
|
1346
|
+
state: model.state,
|
|
1347
|
+
filePath: model.filePath,
|
|
1348
|
+
onOpenFile: openFile,
|
|
1349
|
+
inspect
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* The read row as a plain registrant plugin following the atomic Tool-view
|
|
1354
|
+
* declaration across independent activation and reload lifetimes.
|
|
1355
|
+
*/
|
|
1356
|
+
const readToolview = {
|
|
1357
|
+
name: "read-toolview",
|
|
1358
|
+
inject: ["slots"],
|
|
1359
|
+
/**
|
|
1360
|
+
* Register the read row into the Tool-owned keyed view slot.
|
|
1361
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1362
|
+
*/
|
|
1363
|
+
apply(ctx) {
|
|
1364
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1365
|
+
name: "tool.call.toolview",
|
|
1366
|
+
key: "read",
|
|
1367
|
+
locale: CONVERSATION_NS
|
|
1368
|
+
}, ReadRow));
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
//#endregion
|
|
1372
|
+
//#region lib/types/client/tool/toolviews/search-row.js
|
|
1373
|
+
const SEARCH_TITLES = {
|
|
1374
|
+
grep: "Grep",
|
|
1375
|
+
glob: "Glob"
|
|
1376
|
+
};
|
|
1377
|
+
/**
|
|
1378
|
+
* Search row: icon + Grep/Glob · {summary} in the shared ToolRow chrome, with the
|
|
1379
|
+
* completed search's card as the row's collapsed-by-default card body (a capped
|
|
1380
|
+
* search's recovery footer rides below it, inside ToolRow). Registered under
|
|
1381
|
+
* both `grep` and `glob`; the derived model's `kind` decides the card shape. A
|
|
1382
|
+
* settled call with no search card surfaces its model-facing text through
|
|
1383
|
+
* ToolRow's Output section, since the keyed SearchRow owns this render slot.
|
|
1384
|
+
*/
|
|
1385
|
+
function SearchRow({ toolName, block, inspect, t }) {
|
|
1386
|
+
const model = toolRowModel(toolName, block);
|
|
1387
|
+
const search = searchCardModel(block);
|
|
1388
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1389
|
+
t,
|
|
1390
|
+
variant: model.variant,
|
|
1391
|
+
toolName,
|
|
1392
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: 14 }),
|
|
1393
|
+
title: SEARCH_TITLES[toolName] ?? model.title,
|
|
1394
|
+
summary: search?.title ?? model.summary,
|
|
1395
|
+
body: null,
|
|
1396
|
+
output: model.output,
|
|
1397
|
+
errorSummary: model.errorSummary,
|
|
1398
|
+
search,
|
|
1399
|
+
state: model.state,
|
|
1400
|
+
inspect
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* The search view follows the atomic Tool-view declaration across activation
|
|
1405
|
+
* and reload. One component registers under both keys because `grep` and
|
|
1406
|
+
* `glob` are the same visual object discriminated by the result view's `kind`.
|
|
1407
|
+
*/
|
|
1408
|
+
const searchToolview = {
|
|
1409
|
+
name: "search-toolview",
|
|
1410
|
+
inject: ["slots"],
|
|
1411
|
+
/**
|
|
1412
|
+
* Register the search row into the Tool-owned keyed view slot under both
|
|
1413
|
+
* the `grep` and `glob` tool names.
|
|
1414
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1415
|
+
*/
|
|
1416
|
+
apply(ctx) {
|
|
1417
|
+
ctx.slots.inject("tool.call.toolview", function* () {
|
|
1418
|
+
yield ctx.slots.register({
|
|
1419
|
+
name: "tool.call.toolview",
|
|
1420
|
+
key: "grep",
|
|
1421
|
+
locale: CONVERSATION_NS
|
|
1422
|
+
}, SearchRow);
|
|
1423
|
+
yield ctx.slots.register({
|
|
1424
|
+
name: "tool.call.toolview",
|
|
1425
|
+
key: "glob",
|
|
1426
|
+
locale: CONVERSATION_NS
|
|
1427
|
+
}, SearchRow);
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
//#endregion
|
|
1432
|
+
//#region lib/types/client/tool/toolviews/plan-summary.js
|
|
1433
|
+
/**
|
|
1434
|
+
* Pure plan derivation for the todo_write row's one-line summary. Several items
|
|
1435
|
+
* may be `in_progress` at once — parallel work runs concurrent tasks, so a
|
|
1436
|
+
* summary built from one active item would silently drop the rest. The plan
|
|
1437
|
+
* strip header derives its own counts inline and shares nothing with this, so
|
|
1438
|
+
* this stays inside the toolviews domain rather than in `contract/` (the
|
|
1439
|
+
* inter-domain face).
|
|
1440
|
+
* @module
|
|
1441
|
+
*/
|
|
1442
|
+
/**
|
|
1443
|
+
* Derive the counts and the active summary from a whole-list snapshot. It names
|
|
1444
|
+
* the first `in_progress` item and counts the remaining active ones, so a
|
|
1445
|
+
* parallel plan reports how many tasks are running rather than naming one and
|
|
1446
|
+
* hiding the others. `activeContent` is null when nothing is in progress, or
|
|
1447
|
+
* when the first active item's content is missing, mistyped, or blank once
|
|
1448
|
+
* trimmed — the tool's own rule for usable content, applied here because a
|
|
1449
|
+
* rejected call keeps its args verbatim. The row then renders the counts alone
|
|
1450
|
+
* rather than falling back to the generic tool summary: the counts are already
|
|
1451
|
+
* known to be good, and the active-item clause is the only part an unusable
|
|
1452
|
+
* name costs.
|
|
1453
|
+
* @param todos - the whole list, in model order.
|
|
1454
|
+
* @returns the done/total counts and the two summary halves.
|
|
1455
|
+
*/
|
|
1456
|
+
function planSummary(todos) {
|
|
1457
|
+
const active = todos.filter((t) => t.status === "in_progress");
|
|
1458
|
+
const first = active[0]?.content;
|
|
1459
|
+
const named = typeof first === "string" && first.trim() !== "";
|
|
1460
|
+
return {
|
|
1461
|
+
done: todos.filter((t) => t.status === "completed").length,
|
|
1462
|
+
total: todos.length,
|
|
1463
|
+
activeContent: named ? first : null,
|
|
1464
|
+
activeExtra: named ? active.length - 1 : 0
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
//#endregion
|
|
1468
|
+
//#region lib/types/client/tool/toolviews/todo-row.js
|
|
1469
|
+
function isItem(value) {
|
|
1470
|
+
return typeof value === "object" && value !== null;
|
|
1471
|
+
}
|
|
1472
|
+
function summarize(argsRaw, t) {
|
|
1473
|
+
let parsed;
|
|
1474
|
+
try {
|
|
1475
|
+
parsed = JSON.parse(argsRaw);
|
|
1476
|
+
} catch {
|
|
1477
|
+
return null;
|
|
1478
|
+
}
|
|
1479
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1480
|
+
const todos = parsed.todos;
|
|
1481
|
+
if (!Array.isArray(todos) || !todos.every(isItem)) return null;
|
|
1482
|
+
const { done, total, activeContent, activeExtra } = planSummary(todos);
|
|
1483
|
+
const head = t("todo.completed", {
|
|
1484
|
+
done,
|
|
1485
|
+
total
|
|
1486
|
+
});
|
|
1487
|
+
return {
|
|
1488
|
+
text: activeContent === null ? head : `${head} · ${activeContent}`,
|
|
1489
|
+
extra: activeExtra
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1492
|
+
/** One-line plan update row (the whole row toggles the call's Input/Output
|
|
1493
|
+
* sections, ToolRow's unified expand). Non-ok execution states keep the
|
|
1494
|
+
* shared row's dot semantics — a cancelled call wrote no todo/write, so it
|
|
1495
|
+
* must not read as a completed update. */
|
|
1496
|
+
function TodoRow({ toolName, block, inspect, t }) {
|
|
1497
|
+
const model = toolRowModel(toolName, block);
|
|
1498
|
+
const summary = summarize(("kind" in block ? block.call?.argsRaw : block.argsRaw) ?? "", t) ?? {
|
|
1499
|
+
text: model.summary,
|
|
1500
|
+
extra: 0
|
|
1501
|
+
};
|
|
1502
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1503
|
+
t,
|
|
1504
|
+
variant: model.variant,
|
|
1505
|
+
toolName,
|
|
1506
|
+
icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChecklistOutline14, {}),
|
|
1507
|
+
title: t("todo.rowTitle"),
|
|
1508
|
+
summary: summary.text,
|
|
1509
|
+
summarySuffix: summary.extra > 0 ? `+${summary.extra}` : null,
|
|
1510
|
+
body: model.body,
|
|
1511
|
+
output: model.output,
|
|
1512
|
+
errorSummary: model.errorSummary,
|
|
1513
|
+
state: model.state,
|
|
1514
|
+
inspect
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* The todo row as a plain registrant plugin following the atomic Tool-view
|
|
1519
|
+
* declaration across independent activation and reload lifetimes.
|
|
1520
|
+
*/
|
|
1521
|
+
const todoToolview = {
|
|
1522
|
+
name: "todo-toolview",
|
|
1523
|
+
inject: ["slots"],
|
|
1524
|
+
/**
|
|
1525
|
+
* Register the todo row into the Tool-owned keyed view slot.
|
|
1526
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1527
|
+
*/
|
|
1528
|
+
apply(ctx) {
|
|
1529
|
+
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1530
|
+
name: "tool.call.toolview",
|
|
1531
|
+
key: "todo_write",
|
|
1532
|
+
locale: CONVERSATION_NS
|
|
1533
|
+
}, TodoRow));
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
//#endregion
|
|
1537
|
+
//#region lib/types/client/tool/toolviews/web-row.js
|
|
1538
|
+
/** web_fetch reads one URL; web_search queries. Titles are figma literals. */
|
|
1539
|
+
const WEB_TITLES = {
|
|
1540
|
+
web_search: "Search",
|
|
1541
|
+
web_fetch: "Fetch"
|
|
1542
|
+
};
|
|
1543
|
+
/**
|
|
1544
|
+
* Web row: icon + Search/Fetch · {summary} in the shared ToolRow chrome, with
|
|
1545
|
+
* the completed retrieval's web card as the row's collapsed-by-default card
|
|
1546
|
+
* body. The row discriminates on `toolName` only to pick its icon and title.
|
|
1547
|
+
*/
|
|
1548
|
+
function WebRow({ toolName, block, inspect, t }) {
|
|
1549
|
+
const model = toolRowModel(toolName, block);
|
|
1550
|
+
const web = webCardModel(block);
|
|
1551
|
+
const icon = toolName === "web_fetch" ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconGlobeOutline14, { size: 14 });
|
|
1552
|
+
return (0, react_jsx_runtime.jsx)(ToolRow, {
|
|
1553
|
+
t,
|
|
1554
|
+
variant: model.variant,
|
|
1555
|
+
toolName,
|
|
1556
|
+
icon,
|
|
1557
|
+
title: WEB_TITLES[toolName] ?? model.title,
|
|
1558
|
+
summary: model.summary,
|
|
1559
|
+
body: null,
|
|
1560
|
+
output: model.output,
|
|
1561
|
+
errorSummary: model.errorSummary,
|
|
1562
|
+
web,
|
|
1563
|
+
state: model.state,
|
|
1564
|
+
inspect
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* The web rows follow the atomic Tool-view declaration across activation and
|
|
1569
|
+
* reload. One WebRow component registers under both web tool names.
|
|
1570
|
+
*/
|
|
1571
|
+
const webToolview = {
|
|
1572
|
+
name: "web-toolview",
|
|
1573
|
+
inject: ["slots"],
|
|
1574
|
+
/**
|
|
1575
|
+
* Register the web row under both web tool names' keyed toolview holes.
|
|
1576
|
+
* @param ctx - registrant context (disposal rides ctx.effect inside slots.register).
|
|
1577
|
+
*/
|
|
1578
|
+
apply(ctx) {
|
|
1579
|
+
ctx.slots.inject("tool.call.toolview", function* () {
|
|
1580
|
+
yield ctx.slots.register({
|
|
1581
|
+
name: "tool.call.toolview",
|
|
1582
|
+
key: "web_search",
|
|
1583
|
+
locale: CONVERSATION_NS
|
|
1584
|
+
}, WebRow);
|
|
1585
|
+
yield ctx.slots.register({
|
|
1586
|
+
name: "tool.call.toolview",
|
|
1587
|
+
key: "web_fetch",
|
|
1588
|
+
locale: CONVERSATION_NS
|
|
1589
|
+
}, WebRow);
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
//#endregion
|
|
1594
|
+
//#region lib/types/client/apply.js
|
|
1595
|
+
/** Required service: the slot registry that owns both Tool render seats. */
|
|
1596
|
+
const inject = ["slots"];
|
|
1597
|
+
/**
|
|
1598
|
+
* Mount the whole-Tool renderers and built-in atomic Tool registrations.
|
|
1599
|
+
* @param ctx - Client root context.
|
|
1600
|
+
*/
|
|
1601
|
+
function apply(ctx) {
|
|
1602
|
+
ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
|
|
1603
|
+
name: "conversation.chat.node",
|
|
1604
|
+
key: "tool-call",
|
|
1605
|
+
locale: CONVERSATION_NS,
|
|
1606
|
+
children: { "tool.call.toolview": {
|
|
1607
|
+
kind: "keyed",
|
|
1608
|
+
scope: "session"
|
|
1609
|
+
} }
|
|
1610
|
+
}, ToolCallTree));
|
|
1611
|
+
ctx.slots.inject("conversation.details.tool", () => ctx.slots.register({
|
|
1612
|
+
name: "conversation.details.tool",
|
|
1613
|
+
locale: CONVERSATION_NS
|
|
1614
|
+
}, ToolDetails));
|
|
1615
|
+
ctx.plugin(bashToolviewSample);
|
|
1616
|
+
ctx.plugin(readToolview);
|
|
1617
|
+
ctx.plugin(fileMutationToolview);
|
|
1618
|
+
ctx.plugin(searchToolview);
|
|
1619
|
+
ctx.plugin(webToolview);
|
|
1620
|
+
ctx.plugin(todoToolview);
|
|
1621
|
+
ctx.plugin(askQuestionToolview);
|
|
1622
|
+
}
|
|
1623
|
+
//#endregion
|
|
1624
|
+
exports.apply = apply;
|
|
1625
|
+
exports.inject = inject;
|
|
1626
|
+
return module.exports;
|
|
1627
|
+
}
|
|
1628
|
+
});
|
|
1629
|
+
|
|
1630
|
+
//# sourceMappingURL=client.js.map
|