@springbrand/message-panel 0.1.2 → 0.1.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/camel-chat-showcase.tsx +1265 -0
- package/demo/fixtures.ts +292 -0
- package/demo/message-panel-chat-showcase.tsx +250 -0
- package/demo/message-panel-gallery.tsx +389 -0
- package/package.json +6 -16
- package/src/adapters/ai-sdk.ts +32 -0
- package/src/camel/camel-chat-messages.tsx +1435 -0
- package/src/camel/camel-model-select.tsx +88 -0
- package/src/camel/camel-plan-bar.tsx +115 -0
- package/src/camel/camel-prompt-input.tsx +547 -0
- package/src/camel/camel-tool-presentation.tsx +1270 -0
- package/src/camel/camel-turn.ts +334 -0
- package/src/camel/turn-summary-bar.tsx +81 -0
- package/src/chat-summary-panel.tsx +229 -0
- package/src/composer/chat-composer.tsx +216 -0
- package/src/composer/composer-attachments.tsx +138 -0
- package/src/composer/composer-trigger-popover.tsx +236 -0
- package/src/composer/composer.tsx +425 -0
- package/src/composer/drop-controller.ts +80 -0
- package/src/composer/types.ts +79 -0
- package/src/contracts.ts +138 -0
- package/src/conversation.tsx +76 -0
- package/src/internal/cn.ts +3 -0
- package/src/message-panel.tsx +368 -0
- package/src/message.tsx +254 -0
- package/src/parts/index.tsx +1149 -0
- package/src/parts/kind.ts +67 -0
- package/src/parts/plan.ts +64 -0
- package/src/parts/primitives.tsx +439 -0
- package/src/registry.ts +44 -0
- package/src/status.tsx +132 -0
- package/dist/demo/camel-chat-showcase.d.ts +0 -1
- package/dist/demo/camel-chat-showcase.js +0 -1007
- package/dist/demo/fixtures.d.ts +0 -32
- package/dist/demo/fixtures.js +0 -250
- package/dist/demo/index.js +0 -4
- package/dist/demo/message-panel-chat-showcase.d.ts +0 -1
- package/dist/demo/message-panel-chat-showcase.js +0 -114
- package/dist/demo/message-panel-gallery.d.ts +0 -1
- package/dist/demo/message-panel-gallery.js +0 -130
- package/dist/src/adapters/ai-sdk.d.ts +0 -4
- package/dist/src/adapters/ai-sdk.js +0 -25
- package/dist/src/camel/camel-chat-messages.d.ts +0 -44
- package/dist/src/camel/camel-chat-messages.js +0 -421
- package/dist/src/camel/camel-model-select.d.ts +0 -13
- package/dist/src/camel/camel-model-select.js +0 -7
- package/dist/src/camel/camel-plan-bar.d.ts +0 -5
- package/dist/src/camel/camel-plan-bar.js +0 -24
- package/dist/src/camel/camel-prompt-input.d.ts +0 -32
- package/dist/src/camel/camel-prompt-input.js +0 -182
- package/dist/src/camel/camel-tool-presentation.d.ts +0 -21
- package/dist/src/camel/camel-tool-presentation.js +0 -784
- package/dist/src/camel/camel-turn.d.ts +0 -57
- package/dist/src/camel/camel-turn.js +0 -203
- package/dist/src/camel/index.js +0 -7
- package/dist/src/camel/turn-summary-bar.d.ts +0 -8
- package/dist/src/camel/turn-summary-bar.js +0 -12
- package/dist/src/chat-summary-panel.d.ts +0 -22
- package/dist/src/chat-summary-panel.js +0 -26
- package/dist/src/composer/chat-composer.d.ts +0 -4
- package/dist/src/composer/chat-composer.js +0 -90
- package/dist/src/composer/composer-attachments.d.ts +0 -13
- package/dist/src/composer/composer-attachments.js +0 -47
- package/dist/src/composer/composer-trigger-popover.d.ts +0 -31
- package/dist/src/composer/composer-trigger-popover.js +0 -29
- package/dist/src/composer/composer.d.ts +0 -15
- package/dist/src/composer/composer.js +0 -180
- package/dist/src/composer/drop-controller.d.ts +0 -8
- package/dist/src/composer/drop-controller.js +0 -69
- package/dist/src/composer/index.js +0 -6
- package/dist/src/composer/types.d.ts +0 -62
- package/dist/src/composer/types.js +0 -1
- package/dist/src/contracts.d.ts +0 -94
- package/dist/src/contracts.js +0 -1
- package/dist/src/conversation.d.ts +0 -13
- package/dist/src/conversation.js +0 -18
- package/dist/src/index.js +0 -12
- package/dist/src/internal/cn.d.ts +0 -1
- package/dist/src/internal/cn.js +0 -3
- package/dist/src/message-panel.d.ts +0 -4
- package/dist/src/message-panel.js +0 -144
- package/dist/src/message.d.ts +0 -36
- package/dist/src/message.js +0 -83
- package/dist/src/parts/index.d.ts +0 -187
- package/dist/src/parts/index.js +0 -332
- package/dist/src/parts/kind.d.ts +0 -3
- package/dist/src/parts/kind.js +0 -69
- package/dist/src/parts/plan.d.ts +0 -10
- package/dist/src/parts/plan.js +0 -40
- package/dist/src/parts/primitives.d.ts +0 -70
- package/dist/src/parts/primitives.js +0 -153
- package/dist/src/registry.d.ts +0 -4
- package/dist/src/registry.js +0 -31
- package/dist/src/status.d.ts +0 -26
- package/dist/src/status.js +0 -74
- /package/{dist/demo/index.d.ts → demo/index.ts} +0 -0
- /package/{dist/src/camel/index.d.ts → src/camel/index.ts} +0 -0
- /package/{dist/src/composer/index.d.ts → src/composer/index.ts} +0 -0
- /package/{dist/src/index.d.ts → src/index.ts} +0 -0
|
@@ -1,784 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { CheckIcon, CopyIcon, } from "lucide-react";
|
|
3
|
-
import { useEffect, useRef, useState, } from "react";
|
|
4
|
-
import { MessageResponse } from "../message";
|
|
5
|
-
import { toolNameOfPart } from "../parts";
|
|
6
|
-
import { cn } from "../internal/cn";
|
|
7
|
-
function recordOf(value) {
|
|
8
|
-
return value != null && typeof value === "object" && !Array.isArray(value)
|
|
9
|
-
? value
|
|
10
|
-
: {};
|
|
11
|
-
}
|
|
12
|
-
function safeStringify(value) {
|
|
13
|
-
if (typeof value === "string")
|
|
14
|
-
return value;
|
|
15
|
-
try {
|
|
16
|
-
return JSON.stringify(value, null, 2);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return String(value);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function stringField(record, ...keys) {
|
|
23
|
-
for (const key of keys) {
|
|
24
|
-
const value = record[key];
|
|
25
|
-
if (typeof value === "string" && value.trim())
|
|
26
|
-
return value.trim();
|
|
27
|
-
}
|
|
28
|
-
return "";
|
|
29
|
-
}
|
|
30
|
-
function numberField(record, ...keys) {
|
|
31
|
-
for (const key of keys) {
|
|
32
|
-
const value = record[key];
|
|
33
|
-
if (typeof value === "number" && Number.isFinite(value))
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
function normalizeOutputText(value) {
|
|
39
|
-
if (value == null)
|
|
40
|
-
return "";
|
|
41
|
-
if (typeof value === "string")
|
|
42
|
-
return value;
|
|
43
|
-
if (Array.isArray(value)) {
|
|
44
|
-
return value
|
|
45
|
-
.map((item) => {
|
|
46
|
-
const record = recordOf(item);
|
|
47
|
-
return typeof record.text === "string"
|
|
48
|
-
? record.text
|
|
49
|
-
: safeStringify(item);
|
|
50
|
-
})
|
|
51
|
-
.filter(Boolean)
|
|
52
|
-
.join("\n\n");
|
|
53
|
-
}
|
|
54
|
-
const record = recordOf(value);
|
|
55
|
-
if (typeof record.text === "string")
|
|
56
|
-
return record.text;
|
|
57
|
-
if (typeof record.content === "string")
|
|
58
|
-
return record.content;
|
|
59
|
-
if (Array.isArray(record.content))
|
|
60
|
-
return normalizeOutputText(record.content);
|
|
61
|
-
return safeStringify(value);
|
|
62
|
-
}
|
|
63
|
-
function stripAnsi(value) {
|
|
64
|
-
// ANSI CSI and OSC sequences should never affect chat layout.
|
|
65
|
-
// eslint-disable-next-line no-control-regex
|
|
66
|
-
return value.replace(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\].*?(?:\x07|\x1b\\)/g, "");
|
|
67
|
-
}
|
|
68
|
-
function previewLines(value, maxLines) {
|
|
69
|
-
if (!value)
|
|
70
|
-
return "";
|
|
71
|
-
const lines = value.split(/\r?\n/);
|
|
72
|
-
return lines.length <= maxLines
|
|
73
|
-
? value
|
|
74
|
-
: [...lines.slice(0, maxLines), "..."].join("\n");
|
|
75
|
-
}
|
|
76
|
-
function truncate(value, maxLength) {
|
|
77
|
-
return value.length <= maxLength
|
|
78
|
-
? value
|
|
79
|
-
: `${value.slice(0, maxLength)}...`;
|
|
80
|
-
}
|
|
81
|
-
function filenameOf(path) {
|
|
82
|
-
const trimmed = path.trim().replace(/\/+$/, "");
|
|
83
|
-
return trimmed.split("/").pop() || trimmed;
|
|
84
|
-
}
|
|
85
|
-
function hostnameOf(url) {
|
|
86
|
-
try {
|
|
87
|
-
return new URL(url).hostname;
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return url;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function humanize(name) {
|
|
94
|
-
const spaced = name
|
|
95
|
-
.replace(/^mcp__/, "")
|
|
96
|
-
.replace(/__/g, " ")
|
|
97
|
-
.replace(/[_-]+/g, " ")
|
|
98
|
-
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
99
|
-
.trim();
|
|
100
|
-
return spaced
|
|
101
|
-
? spaced.replace(/\b\w/g, (character) => character.toUpperCase())
|
|
102
|
-
: "Tool";
|
|
103
|
-
}
|
|
104
|
-
function canonicalToolKind(name) {
|
|
105
|
-
const normalized = name.trim().replaceAll("-", "_").toLowerCase();
|
|
106
|
-
if (normalized.startsWith("mcp__"))
|
|
107
|
-
return "mcp";
|
|
108
|
-
if ([
|
|
109
|
-
"read",
|
|
110
|
-
"read_file",
|
|
111
|
-
"read_text_file",
|
|
112
|
-
"read_document",
|
|
113
|
-
].includes(normalized)) {
|
|
114
|
-
return "read";
|
|
115
|
-
}
|
|
116
|
-
if ([
|
|
117
|
-
"write",
|
|
118
|
-
"write_file",
|
|
119
|
-
"create_file",
|
|
120
|
-
"save_file",
|
|
121
|
-
].includes(normalized)) {
|
|
122
|
-
return "write";
|
|
123
|
-
}
|
|
124
|
-
if ([
|
|
125
|
-
"edit",
|
|
126
|
-
"edit_file",
|
|
127
|
-
"apply_patch",
|
|
128
|
-
"patch_file",
|
|
129
|
-
].includes(normalized)) {
|
|
130
|
-
return "edit";
|
|
131
|
-
}
|
|
132
|
-
if ([
|
|
133
|
-
"bash",
|
|
134
|
-
"shell",
|
|
135
|
-
"exec",
|
|
136
|
-
"exec_command",
|
|
137
|
-
"run_command",
|
|
138
|
-
"terminal",
|
|
139
|
-
].includes(normalized)) {
|
|
140
|
-
return "bash";
|
|
141
|
-
}
|
|
142
|
-
if (["glob", "find_files", "list_files_recursive"].includes(normalized)) {
|
|
143
|
-
return "glob";
|
|
144
|
-
}
|
|
145
|
-
if ([
|
|
146
|
-
"grep",
|
|
147
|
-
"rg",
|
|
148
|
-
"search_files",
|
|
149
|
-
"search_code",
|
|
150
|
-
].includes(normalized)) {
|
|
151
|
-
return "grep";
|
|
152
|
-
}
|
|
153
|
-
if (["ls", "list_directory", "list_files"].includes(normalized)) {
|
|
154
|
-
return "list";
|
|
155
|
-
}
|
|
156
|
-
if (["find", "find_file"].includes(normalized))
|
|
157
|
-
return "find";
|
|
158
|
-
if ([
|
|
159
|
-
"web_search",
|
|
160
|
-
"search_web",
|
|
161
|
-
"search_query",
|
|
162
|
-
].includes(normalized)) {
|
|
163
|
-
return "web-search";
|
|
164
|
-
}
|
|
165
|
-
if ([
|
|
166
|
-
"web_fetch",
|
|
167
|
-
"fetch_url",
|
|
168
|
-
"open_url",
|
|
169
|
-
"fetch_page",
|
|
170
|
-
].includes(normalized)) {
|
|
171
|
-
return "web-fetch";
|
|
172
|
-
}
|
|
173
|
-
if ([
|
|
174
|
-
"javascript",
|
|
175
|
-
"js_exec",
|
|
176
|
-
"node_repl",
|
|
177
|
-
"execute_javascript",
|
|
178
|
-
].includes(normalized)) {
|
|
179
|
-
return "javascript";
|
|
180
|
-
}
|
|
181
|
-
if ([
|
|
182
|
-
"todo_write",
|
|
183
|
-
"update_todo",
|
|
184
|
-
"update_plan",
|
|
185
|
-
].includes(normalized)) {
|
|
186
|
-
return "tasks";
|
|
187
|
-
}
|
|
188
|
-
if ([
|
|
189
|
-
"task",
|
|
190
|
-
"task_output",
|
|
191
|
-
"agent",
|
|
192
|
-
"run_agent",
|
|
193
|
-
"run_temporary_agent",
|
|
194
|
-
"subagents",
|
|
195
|
-
"fanout",
|
|
196
|
-
"extract",
|
|
197
|
-
"dispatch_background",
|
|
198
|
-
"explore",
|
|
199
|
-
"research",
|
|
200
|
-
"oracle",
|
|
201
|
-
].includes(normalized)) {
|
|
202
|
-
return "agent";
|
|
203
|
-
}
|
|
204
|
-
if (["skill", "read_skill"].includes(normalized))
|
|
205
|
-
return "skill";
|
|
206
|
-
if (normalized === "read_skill_resource")
|
|
207
|
-
return "skill-resource";
|
|
208
|
-
if ([
|
|
209
|
-
"ask_user",
|
|
210
|
-
"ask_user_question",
|
|
211
|
-
"request_user_input",
|
|
212
|
-
].includes(normalized)) {
|
|
213
|
-
return "ask-user";
|
|
214
|
-
}
|
|
215
|
-
if (["suggest_followups", "suggestions"].includes(normalized)) {
|
|
216
|
-
return "suggestions";
|
|
217
|
-
}
|
|
218
|
-
if (["notebook_edit", "edit_notebook"].includes(normalized)) {
|
|
219
|
-
return "notebook";
|
|
220
|
-
}
|
|
221
|
-
return "generic";
|
|
222
|
-
}
|
|
223
|
-
function parseMcpName(name) {
|
|
224
|
-
if (!name.startsWith("mcp__"))
|
|
225
|
-
return null;
|
|
226
|
-
const [, server = "", ...toolParts] = name.split("__");
|
|
227
|
-
if (!server || toolParts.length === 0)
|
|
228
|
-
return null;
|
|
229
|
-
return {
|
|
230
|
-
server: humanize(server),
|
|
231
|
-
tool: humanize(toolParts.join(" ")),
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
function toolInput(part) {
|
|
235
|
-
if (part.input != null)
|
|
236
|
-
return recordOf(part.input);
|
|
237
|
-
const data = recordOf(part.data);
|
|
238
|
-
if (data.input != null)
|
|
239
|
-
return recordOf(data.input);
|
|
240
|
-
return part.type === "tool" ? data : {};
|
|
241
|
-
}
|
|
242
|
-
function toolOutput(part) {
|
|
243
|
-
const data = recordOf(part.data);
|
|
244
|
-
return part.output ?? data.output ?? part.result;
|
|
245
|
-
}
|
|
246
|
-
function parseCount(outputText, key) {
|
|
247
|
-
const match = outputText.match(new RegExp(`Found\\s+(\\d+)\\s+${key}`, "i"));
|
|
248
|
-
return match ? Number.parseInt(match[1] ?? "0", 10) : null;
|
|
249
|
-
}
|
|
250
|
-
function fileSummary(input, state, labels) {
|
|
251
|
-
const path = stringField(input, "file_path", "path", "filename");
|
|
252
|
-
const filename = path ? filenameOf(path) : "";
|
|
253
|
-
if (state.running) {
|
|
254
|
-
return filename
|
|
255
|
-
? `${labels.running} ${filename}...`
|
|
256
|
-
: labels.runningGeneric;
|
|
257
|
-
}
|
|
258
|
-
if (state.failed) {
|
|
259
|
-
return filename ? `${labels.failed} ${filename}` : labels.failed;
|
|
260
|
-
}
|
|
261
|
-
return filename ? `${labels.complete} ${filename}` : labels.complete;
|
|
262
|
-
}
|
|
263
|
-
function questionsOf(input) {
|
|
264
|
-
if (Array.isArray(input.questions))
|
|
265
|
-
return input.questions.map(recordOf);
|
|
266
|
-
if (typeof input.question === "string") {
|
|
267
|
-
return [
|
|
268
|
-
{
|
|
269
|
-
question: input.question,
|
|
270
|
-
header: input.header,
|
|
271
|
-
options: input.options,
|
|
272
|
-
},
|
|
273
|
-
];
|
|
274
|
-
}
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
function summaryFor(kind, name, input, outputText, running, failed) {
|
|
278
|
-
const state = { running, failed };
|
|
279
|
-
switch (kind) {
|
|
280
|
-
case "read":
|
|
281
|
-
return fileSummary(input, state, {
|
|
282
|
-
running: "Reading",
|
|
283
|
-
runningGeneric: "Reading file...",
|
|
284
|
-
failed: "Failed to read",
|
|
285
|
-
complete: "Read",
|
|
286
|
-
});
|
|
287
|
-
case "write":
|
|
288
|
-
return fileSummary(input, state, {
|
|
289
|
-
running: "Creating",
|
|
290
|
-
runningGeneric: "Creating file...",
|
|
291
|
-
failed: "Failed to create",
|
|
292
|
-
complete: "Created",
|
|
293
|
-
});
|
|
294
|
-
case "edit":
|
|
295
|
-
return fileSummary(input, state, {
|
|
296
|
-
running: "Editing",
|
|
297
|
-
runningGeneric: "Editing file...",
|
|
298
|
-
failed: "Failed to edit",
|
|
299
|
-
complete: "Edited",
|
|
300
|
-
});
|
|
301
|
-
case "bash": {
|
|
302
|
-
const command = stringField(input, "command", "cmd");
|
|
303
|
-
const description = stringField(input, "description");
|
|
304
|
-
const label = description || truncate(command || "command", 30);
|
|
305
|
-
return running
|
|
306
|
-
? command || description
|
|
307
|
-
? `Running ${label}...`
|
|
308
|
-
: "Running command..."
|
|
309
|
-
: failed
|
|
310
|
-
? `Failed to run ${label}`
|
|
311
|
-
: `Ran ${label}`;
|
|
312
|
-
}
|
|
313
|
-
case "glob": {
|
|
314
|
-
const pattern = stringField(input, "pattern", "glob");
|
|
315
|
-
if (running) {
|
|
316
|
-
return pattern
|
|
317
|
-
? `Searching for "${truncate(pattern, 20)}"...`
|
|
318
|
-
: "Searching for files...";
|
|
319
|
-
}
|
|
320
|
-
if (failed)
|
|
321
|
-
return "Failed to search files";
|
|
322
|
-
const count = parseCount(outputText, "files");
|
|
323
|
-
if (count != null)
|
|
324
|
-
return `Found ${count} files`;
|
|
325
|
-
return /no files found/i.test(outputText)
|
|
326
|
-
? "No files found"
|
|
327
|
-
: "Searched files";
|
|
328
|
-
}
|
|
329
|
-
case "grep": {
|
|
330
|
-
const pattern = stringField(input, "pattern", "query");
|
|
331
|
-
if (running) {
|
|
332
|
-
return pattern
|
|
333
|
-
? `Searching for "${truncate(pattern, 20)}"...`
|
|
334
|
-
: "Searching...";
|
|
335
|
-
}
|
|
336
|
-
if (failed)
|
|
337
|
-
return "Failed to search codebase";
|
|
338
|
-
const count = parseCount(outputText, "matches");
|
|
339
|
-
if (count != null)
|
|
340
|
-
return `Found ${count} matches`;
|
|
341
|
-
return /no matches found/i.test(outputText)
|
|
342
|
-
? "No matches found"
|
|
343
|
-
: "Searched codebase";
|
|
344
|
-
}
|
|
345
|
-
case "list": {
|
|
346
|
-
const path = stringField(input, "path");
|
|
347
|
-
const filename = path ? filenameOf(path) : "";
|
|
348
|
-
if (running)
|
|
349
|
-
return filename ? `Listing ${filename}...` : "Listing files...";
|
|
350
|
-
if (failed)
|
|
351
|
-
return filename ? `Failed to list ${filename}` : "Failed to list files";
|
|
352
|
-
return filename ? `Listed ${filename}` : "Listed files";
|
|
353
|
-
}
|
|
354
|
-
case "find": {
|
|
355
|
-
const pattern = stringField(input, "pattern", "query");
|
|
356
|
-
if (running) {
|
|
357
|
-
return pattern
|
|
358
|
-
? `Finding "${truncate(pattern, 20)}"...`
|
|
359
|
-
: "Finding files...";
|
|
360
|
-
}
|
|
361
|
-
return failed ? "Failed to find files" : "Found files";
|
|
362
|
-
}
|
|
363
|
-
case "web-search":
|
|
364
|
-
return running
|
|
365
|
-
? "Searching web..."
|
|
366
|
-
: failed
|
|
367
|
-
? "Failed to search web"
|
|
368
|
-
: "Searched web";
|
|
369
|
-
case "web-fetch": {
|
|
370
|
-
const url = stringField(input, "url");
|
|
371
|
-
const host = url ? hostnameOf(url) : "web page";
|
|
372
|
-
return running
|
|
373
|
-
? `Fetching ${host}...`
|
|
374
|
-
: failed
|
|
375
|
-
? `Failed to fetch ${host}`
|
|
376
|
-
: `Fetched ${host}`;
|
|
377
|
-
}
|
|
378
|
-
case "javascript": {
|
|
379
|
-
const label = stringField(input, "description") || "JavaScript";
|
|
380
|
-
return running
|
|
381
|
-
? `Running ${label}...`
|
|
382
|
-
: failed
|
|
383
|
-
? `${label} failed`
|
|
384
|
-
: `Ran ${label}`;
|
|
385
|
-
}
|
|
386
|
-
case "tasks":
|
|
387
|
-
return running
|
|
388
|
-
? "Updating tasks..."
|
|
389
|
-
: failed
|
|
390
|
-
? "Failed to update tasks"
|
|
391
|
-
: "Updated tasks";
|
|
392
|
-
case "agent": {
|
|
393
|
-
const description = stringField(input, "description", "question", "prompt") || "subtask";
|
|
394
|
-
return running
|
|
395
|
-
? `Working on ${truncate(description, 52)}`
|
|
396
|
-
: failed
|
|
397
|
-
? `Could not finish ${truncate(description, 52)}`
|
|
398
|
-
: `Finished ${truncate(description, 52)}`;
|
|
399
|
-
}
|
|
400
|
-
case "skill": {
|
|
401
|
-
const skill = stringField(input, "skill", "name");
|
|
402
|
-
return running
|
|
403
|
-
? skill
|
|
404
|
-
? `Reading instructions for ${skill}...`
|
|
405
|
-
: "Reading instructions..."
|
|
406
|
-
: failed
|
|
407
|
-
? skill
|
|
408
|
-
? `Could not read instructions for ${skill}`
|
|
409
|
-
: "Could not read instructions"
|
|
410
|
-
: `Read instructions for ${skill || "task"}`;
|
|
411
|
-
}
|
|
412
|
-
case "skill-resource": {
|
|
413
|
-
const path = stringField(input, "path");
|
|
414
|
-
const resource = path ? filenameOf(path) : "resource";
|
|
415
|
-
return running
|
|
416
|
-
? `Reading ${resource}...`
|
|
417
|
-
: failed
|
|
418
|
-
? `Could not read ${resource}`
|
|
419
|
-
: `Read ${resource}`;
|
|
420
|
-
}
|
|
421
|
-
case "ask-user": {
|
|
422
|
-
const questions = questionsOf(input);
|
|
423
|
-
if (running)
|
|
424
|
-
return "Waiting for your input";
|
|
425
|
-
if (questions.length === 1) {
|
|
426
|
-
const header = stringField(questions[0] ?? {}, "header");
|
|
427
|
-
return header || "Asked a question";
|
|
428
|
-
}
|
|
429
|
-
return questions.length > 1
|
|
430
|
-
? `Asked ${questions.length} questions`
|
|
431
|
-
: "Asked a question";
|
|
432
|
-
}
|
|
433
|
-
case "suggestions":
|
|
434
|
-
return running ? "Preparing follow-ups..." : "Suggested follow-ups";
|
|
435
|
-
case "notebook":
|
|
436
|
-
return running
|
|
437
|
-
? "Editing notebook cell..."
|
|
438
|
-
: failed
|
|
439
|
-
? "Failed to edit notebook cell"
|
|
440
|
-
: "Edited notebook cell";
|
|
441
|
-
case "mcp": {
|
|
442
|
-
const parts = parseMcpName(name);
|
|
443
|
-
if (!parts)
|
|
444
|
-
break;
|
|
445
|
-
return running
|
|
446
|
-
? `Calling ${parts.tool} on ${parts.server}...`
|
|
447
|
-
: failed
|
|
448
|
-
? `Failed to call ${parts.tool} on ${parts.server}`
|
|
449
|
-
: `Called ${parts.tool} on ${parts.server}`;
|
|
450
|
-
}
|
|
451
|
-
case "generic":
|
|
452
|
-
break;
|
|
453
|
-
}
|
|
454
|
-
if (name === "create_agent") {
|
|
455
|
-
const agent = stringField(input, "name") || "agent";
|
|
456
|
-
return running
|
|
457
|
-
? `Creating ${agent}...`
|
|
458
|
-
: failed
|
|
459
|
-
? `Could not create ${agent}`
|
|
460
|
-
: `Created ${agent}`;
|
|
461
|
-
}
|
|
462
|
-
if (name === "publish_extension") {
|
|
463
|
-
const extension = humanize(stringField(input, "name") || "extension");
|
|
464
|
-
return running
|
|
465
|
-
? `Publishing ${extension}...`
|
|
466
|
-
: failed
|
|
467
|
-
? `Could not publish ${extension}`
|
|
468
|
-
: `Published ${extension}`;
|
|
469
|
-
}
|
|
470
|
-
if (name === "cancel_schedule") {
|
|
471
|
-
return running
|
|
472
|
-
? "Cancelling schedule..."
|
|
473
|
-
: failed
|
|
474
|
-
? "Schedule cancellation was denied"
|
|
475
|
-
: "Cancelled schedule";
|
|
476
|
-
}
|
|
477
|
-
const displayName = humanize(name);
|
|
478
|
-
return running
|
|
479
|
-
? `Using ${displayName}...`
|
|
480
|
-
: failed
|
|
481
|
-
? `Could not use ${displayName}`
|
|
482
|
-
: `Used ${displayName}`;
|
|
483
|
-
}
|
|
484
|
-
export function getCamelToolPresentation(part, isActive = false) {
|
|
485
|
-
const record = recordOf(part);
|
|
486
|
-
const name = toolNameOfPart(part) ?? (stringField(record, "name") || "tool");
|
|
487
|
-
const input = toolInput(record);
|
|
488
|
-
const output = toolOutput(record);
|
|
489
|
-
const outputText = normalizeOutputText(output);
|
|
490
|
-
const errorText = stringField(record, "errorText", "error");
|
|
491
|
-
const state = stringField(record, "state", "status");
|
|
492
|
-
const failed = state === "output-error" ||
|
|
493
|
-
state === "output-denied" ||
|
|
494
|
-
state === "failed" ||
|
|
495
|
-
Boolean(errorText);
|
|
496
|
-
const running = isActive &&
|
|
497
|
-
[
|
|
498
|
-
"input-streaming",
|
|
499
|
-
"input-available",
|
|
500
|
-
"approval-responded",
|
|
501
|
-
"approval-requested",
|
|
502
|
-
"running",
|
|
503
|
-
"",
|
|
504
|
-
].includes(state);
|
|
505
|
-
const kind = canonicalToolKind(name);
|
|
506
|
-
const hasDetails = Object.keys(input).length > 0 ||
|
|
507
|
-
output != null ||
|
|
508
|
-
Boolean(errorText);
|
|
509
|
-
return {
|
|
510
|
-
kind,
|
|
511
|
-
name,
|
|
512
|
-
summary: summaryFor(kind, name, input, errorText || outputText, running, failed),
|
|
513
|
-
input,
|
|
514
|
-
output,
|
|
515
|
-
outputText,
|
|
516
|
-
errorText,
|
|
517
|
-
running,
|
|
518
|
-
failed,
|
|
519
|
-
isSubAgent: kind === "agent",
|
|
520
|
-
hasDetails,
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
function ToolCopyButton({ value, label }) {
|
|
524
|
-
const [copied, setCopied] = useState(false);
|
|
525
|
-
const timerRef = useRef(null);
|
|
526
|
-
useEffect(() => () => {
|
|
527
|
-
if (timerRef.current != null)
|
|
528
|
-
window.clearTimeout(timerRef.current);
|
|
529
|
-
}, []);
|
|
530
|
-
if (!value)
|
|
531
|
-
return null;
|
|
532
|
-
return (_jsx("button", { type: "button", className: "inline-flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground/60 opacity-0 transition-opacity hover:bg-muted group-hover/details:opacity-100 group-focus-within/details:opacity-100", onClick: () => {
|
|
533
|
-
void navigator.clipboard.writeText(value).then(() => {
|
|
534
|
-
setCopied(true);
|
|
535
|
-
if (timerRef.current != null)
|
|
536
|
-
window.clearTimeout(timerRef.current);
|
|
537
|
-
timerRef.current = window.setTimeout(() => setCopied(false), 1500);
|
|
538
|
-
});
|
|
539
|
-
}, "aria-label": copied ? "Copied" : label, children: copied ? _jsx(CheckIcon, { className: "size-3" }) : _jsx(CopyIcon, { className: "size-3" }) }));
|
|
540
|
-
}
|
|
541
|
-
function DetailRow({ label, value, copyValue, mono = false, }) {
|
|
542
|
-
if (value == null || value === "")
|
|
543
|
-
return null;
|
|
544
|
-
return (_jsxs("div", { className: "flex items-start gap-2 py-0.5", children: [_jsx("span", { className: "shrink-0 text-muted-foreground/60", children: label }), _jsx("div", { className: cn("min-w-0 flex-1 break-words", mono && "font-mono"), children: value }), copyValue ? _jsx(ToolCopyButton, { value: copyValue, label: `Copy ${label}` }) : null] }));
|
|
545
|
-
}
|
|
546
|
-
function OutputBlock({ label, value, className, }) {
|
|
547
|
-
if (!value)
|
|
548
|
-
return null;
|
|
549
|
-
const displayValue = stripAnsi(value);
|
|
550
|
-
return (_jsxs("div", { className: cn("mt-2", className), children: [_jsxs("div", { className: "mb-1 flex items-center justify-between text-[0.7rem] text-muted-foreground/60", children: [_jsx("span", { children: label }), _jsx(ToolCopyButton, { value: displayValue, label: `Copy ${label}` })] }), _jsx("div", { className: "max-h-32 overflow-auto rounded bg-muted/30 p-2 font-mono text-xs", children: _jsx("pre", { className: "whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground/80", children: displayValue }) })] }));
|
|
551
|
-
}
|
|
552
|
-
function ProjectRow({ input }) {
|
|
553
|
-
const project = stringField(input, "project");
|
|
554
|
-
return project ? (_jsx(DetailRow, { label: "Project:", value: project, copyValue: project, mono: true })) : null;
|
|
555
|
-
}
|
|
556
|
-
function ReadDetails({ presentation }) {
|
|
557
|
-
const { input, outputText } = presentation;
|
|
558
|
-
const path = stringField(input, "file_path", "path", "filename");
|
|
559
|
-
const lines = outputText ? outputText.split(/\r?\n/).length : 0;
|
|
560
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Path:", value: path, copyValue: path, mono: true }), _jsx(ProjectRow, { input: input }), _jsx(DetailRow, { label: "Lines:", value: String(lines) }), _jsx(OutputBlock, { label: "Preview", value: previewLines(outputText, 10) })] }));
|
|
561
|
-
}
|
|
562
|
-
function WriteDetails({ presentation }) {
|
|
563
|
-
const { input } = presentation;
|
|
564
|
-
const path = stringField(input, "file_path", "path", "filename");
|
|
565
|
-
const content = normalizeOutputText(input.content);
|
|
566
|
-
const bytes = new TextEncoder().encode(content).byteLength;
|
|
567
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Path:", value: path, copyValue: path, mono: true }), _jsx(ProjectRow, { input: input }), content ? _jsx(DetailRow, { label: "Size:", value: formatBytes(bytes) }) : null, _jsx(OutputBlock, { label: "Preview", value: previewLines(content, 10) })] }));
|
|
568
|
-
}
|
|
569
|
-
function diffLines(input, output) {
|
|
570
|
-
const outputRecord = recordOf(output);
|
|
571
|
-
const rawDiff = stringField(outputRecord, "diff") ||
|
|
572
|
-
stringField(recordOf(outputRecord.details), "diff");
|
|
573
|
-
if (rawDiff) {
|
|
574
|
-
const lines = rawDiff.split(/\r?\n/);
|
|
575
|
-
return [
|
|
576
|
-
...lines.slice(0, 200).map((text) => ({
|
|
577
|
-
kind: text.startsWith("+")
|
|
578
|
-
? "add"
|
|
579
|
-
: text.startsWith("-")
|
|
580
|
-
? "remove"
|
|
581
|
-
: "context",
|
|
582
|
-
text,
|
|
583
|
-
})),
|
|
584
|
-
...(lines.length > 200
|
|
585
|
-
? [{ kind: "context", text: "... [diff truncated]" }]
|
|
586
|
-
: []),
|
|
587
|
-
];
|
|
588
|
-
}
|
|
589
|
-
const edits = Array.isArray(input.edits)
|
|
590
|
-
? input.edits.map(recordOf)
|
|
591
|
-
: [input];
|
|
592
|
-
const result = [];
|
|
593
|
-
for (const edit of edits) {
|
|
594
|
-
const oldText = stringField(edit, "old_string", "oldText");
|
|
595
|
-
const newText = stringField(edit, "new_string", "newText");
|
|
596
|
-
for (const text of oldText.split(/\r?\n/).filter(Boolean).slice(0, 6)) {
|
|
597
|
-
result.push({ kind: "remove", text: `- ${text}` });
|
|
598
|
-
}
|
|
599
|
-
for (const text of newText.split(/\r?\n/).filter(Boolean).slice(0, 6)) {
|
|
600
|
-
result.push({ kind: "add", text: `+ ${text}` });
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
return result;
|
|
604
|
-
}
|
|
605
|
-
function EditDetails({ presentation }) {
|
|
606
|
-
const { input, output } = presentation;
|
|
607
|
-
const path = stringField(input, "file_path", "path", "filename");
|
|
608
|
-
const edits = Array.isArray(input.edits)
|
|
609
|
-
? input.edits.length
|
|
610
|
-
: stringField(input, "old_string", "oldText", "new_string", "newText")
|
|
611
|
-
? 1
|
|
612
|
-
: 0;
|
|
613
|
-
const outputRecord = recordOf(output);
|
|
614
|
-
const replacementCount = numberField(outputRecord, "replacementCount") ??
|
|
615
|
-
numberField(recordOf(outputRecord.details), "replacementCount") ??
|
|
616
|
-
edits;
|
|
617
|
-
const lines = diffLines(input, output);
|
|
618
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Path:", value: path, copyValue: path, mono: true }), _jsx(ProjectRow, { input: input }), _jsx(DetailRow, { label: "Changes:", value: `${replacementCount} replacements` }), lines.length > 0 ? (_jsx("div", { className: "mt-2 max-h-32 overflow-auto rounded bg-muted/30 p-2 font-mono text-xs", children: lines.map((line, index) => (_jsx("div", { className: cn("whitespace-pre-wrap break-words", line.kind === "add" && "text-green-600/80 dark:text-green-400/80", line.kind === "remove" && "text-red-600/80 dark:text-red-400/80", line.kind === "context" && "text-muted-foreground/60"), children: line.text }, `${line.kind}:${index}`))) })) : (_jsx(DetailRow, { label: "Diff:", value: "No diff available" }))] }));
|
|
619
|
-
}
|
|
620
|
-
function BashDetails({ presentation }) {
|
|
621
|
-
const { input, output, outputText } = presentation;
|
|
622
|
-
const command = stringField(input, "command", "cmd");
|
|
623
|
-
const outputRecord = recordOf(output);
|
|
624
|
-
const parsedFromText = (() => {
|
|
625
|
-
if (!outputText.trim().startsWith("{"))
|
|
626
|
-
return {};
|
|
627
|
-
try {
|
|
628
|
-
return recordOf(JSON.parse(outputText));
|
|
629
|
-
}
|
|
630
|
-
catch {
|
|
631
|
-
return {};
|
|
632
|
-
}
|
|
633
|
-
})();
|
|
634
|
-
const result = Object.keys(outputRecord).length > 0
|
|
635
|
-
? outputRecord
|
|
636
|
-
: parsedFromText;
|
|
637
|
-
const stdout = stringField(result, "stdout");
|
|
638
|
-
const stderr = stringField(result, "stderr");
|
|
639
|
-
const exitCode = numberField(result, "exit_code", "exitCode");
|
|
640
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Command:", value: command, copyValue: command, mono: true }), _jsx(ProjectRow, { input: input }), _jsx(DetailRow, { label: "Description:", value: stringField(input, "description") }), exitCode != null ? (_jsx(DetailRow, { label: "Exit code:", value: String(exitCode) })) : null, _jsx(OutputBlock, { label: "Stdout", value: stdout }), _jsx(OutputBlock, { label: "Stderr", value: stderr }), !stdout && !stderr ? (_jsx(OutputBlock, { label: presentation.failed ? "Error" : "Output", value: presentation.errorText || outputText })) : null] }));
|
|
641
|
-
}
|
|
642
|
-
function SearchDetails({ presentation, label, }) {
|
|
643
|
-
const { input, outputText } = presentation;
|
|
644
|
-
const cleanedOutput = outputText
|
|
645
|
-
.split(/\r?\n/)
|
|
646
|
-
.filter((line) => !/^Found\s+\d+/i.test(line.trim()))
|
|
647
|
-
.join("\n");
|
|
648
|
-
const count = parseCount(outputText, label === "Files" ? "files" : "matches");
|
|
649
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Pattern:", value: stringField(input, "pattern", "glob", "query"), mono: true }), _jsx(DetailRow, { label: "Path:", value: stringField(input, "path", "cwd"), mono: true }), _jsx(ProjectRow, { input: input }), _jsx(DetailRow, { label: "Mode:", value: stringField(input, "output_mode") }), count != null ? _jsx(DetailRow, { label: "Count:", value: String(count) }) : null, _jsx(OutputBlock, { label: label, value: cleanedOutput || outputText })] }));
|
|
650
|
-
}
|
|
651
|
-
function ListDetails({ presentation }) {
|
|
652
|
-
const { input, outputText } = presentation;
|
|
653
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Path:", value: stringField(input, "path"), mono: true }), _jsx(ProjectRow, { input: input }), _jsx(OutputBlock, { label: "Files", value: outputText })] }));
|
|
654
|
-
}
|
|
655
|
-
function WebDetails({ presentation, mode, }) {
|
|
656
|
-
const { input, outputText } = presentation;
|
|
657
|
-
return (_jsxs("div", { className: "space-y-1", children: [mode === "fetch" ? (_jsx(DetailRow, { label: "URL:", value: stringField(input, "url"), copyValue: stringField(input, "url"), mono: true })) : (_jsx(DetailRow, { label: "Query:", value: stringField(input, "query", "q"), copyValue: stringField(input, "query", "q") })), _jsx(DetailRow, { label: "Prompt:", value: stringField(input, "prompt") }), _jsx(OutputBlock, { label: mode === "fetch" ? "Response" : "Response", value: outputText })] }));
|
|
658
|
-
}
|
|
659
|
-
function TaskDetails({ presentation }) {
|
|
660
|
-
const { input, output, outputText } = presentation;
|
|
661
|
-
const tasks = Array.isArray(input.todos)
|
|
662
|
-
? input.todos.map(recordOf)
|
|
663
|
-
: Array.isArray(input.steps)
|
|
664
|
-
? input.steps.map(recordOf)
|
|
665
|
-
: [];
|
|
666
|
-
return (_jsxs("div", { className: "space-y-2", children: [tasks.length > 0 ? (_jsxs("div", { className: "space-y-1", children: [_jsx("div", { className: "text-xs text-muted-foreground/60", children: "Tasks:" }), _jsx("div", { className: "space-y-1 pl-4", children: tasks.map((task, index) => {
|
|
667
|
-
const status = stringField(task, "status") || "pending";
|
|
668
|
-
const text = stringField(task, "content", "text", "activeForm") ||
|
|
669
|
-
"Untitled task";
|
|
670
|
-
return (_jsxs("div", { className: "flex items-start gap-2 text-xs", children: [_jsx("span", { className: "font-mono text-muted-foreground/60", children: ["done", "completed"].includes(status) ? "[x]" : "[ ]" }), _jsx("span", { className: "min-w-0 flex-1 text-muted-foreground/80", children: text }), _jsx("span", { className: "text-[0.65rem] uppercase text-muted-foreground/50", children: status })] }, `${status}:${index}`));
|
|
671
|
-
}) })] })) : (_jsx(DetailRow, { label: "Tasks:", value: "No tasks provided" })), _jsx(OutputBlock, { label: "Result", value: typeof output === "object"
|
|
672
|
-
? summarizeResult(recordOf(output))
|
|
673
|
-
: outputText })] }));
|
|
674
|
-
}
|
|
675
|
-
function summarizeResult(output) {
|
|
676
|
-
const preferred = [
|
|
677
|
-
"message",
|
|
678
|
-
"summary",
|
|
679
|
-
"status",
|
|
680
|
-
"result",
|
|
681
|
-
].flatMap((key) => {
|
|
682
|
-
const value = output[key];
|
|
683
|
-
return value == null ? [] : [`${humanize(key)}: ${normalizeOutputText(value)}`];
|
|
684
|
-
});
|
|
685
|
-
if (preferred.length > 0)
|
|
686
|
-
return preferred.join("\n");
|
|
687
|
-
const counts = ["done", "total", "success", "ok"].flatMap((key) => output[key] == null ? [] : [`${humanize(key)}: ${String(output[key])}`]);
|
|
688
|
-
return counts.join("\n");
|
|
689
|
-
}
|
|
690
|
-
function AgentDetails({ presentation }) {
|
|
691
|
-
const { input, output, outputText, running, failed } = presentation;
|
|
692
|
-
const outputRecord = recordOf(output);
|
|
693
|
-
const activities = Array.isArray(outputRecord.activities)
|
|
694
|
-
? outputRecord.activities
|
|
695
|
-
: Array.isArray(recordOf(outputRecord.details).activities)
|
|
696
|
-
? recordOf(outputRecord.details).activities
|
|
697
|
-
: [];
|
|
698
|
-
const request = stringField(input, "question", "prompt", "description");
|
|
699
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Task:", value: stringField(input, "description") }), _jsx(DetailRow, { label: "Agent:", value: stringField(input, "agent", "name") }), _jsx(DetailRow, { label: "Model:", value: stringField(input, "model") }), _jsx(DetailRow, { label: "Request:", value: request ? (_jsx("span", { className: "whitespace-pre-wrap break-words text-foreground/80", children: request })) : undefined }), _jsxs("div", { className: "mt-2", children: [_jsx("div", { className: "mb-1 text-[0.7rem] text-muted-foreground/60", children: "Activity" }), activities.length > 0 ? (_jsx("div", { className: "space-y-1", children: activities.slice(-10).map((activity, index) => (_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: cn("size-1.5 shrink-0 rounded-full bg-muted-foreground/40", running && index === activities.slice(-10).length - 1 &&
|
|
700
|
-
"animate-pulse bg-blue-500", failed && "bg-red-500") }), _jsx("span", { className: "min-w-0 truncate text-muted-foreground/70", children: normalizeOutputText(activity) })] }, `${normalizeOutputText(activity)}:${index}`))) })) : (_jsx("div", { className: "text-muted-foreground/60", children: running
|
|
701
|
-
? "Waiting for the first tool call..."
|
|
702
|
-
: failed
|
|
703
|
-
? "No tool activity was recorded before this run stopped."
|
|
704
|
-
: "Detailed tool activity was not recorded." }))] }), outputText ? (_jsxs("div", { className: "mt-2", children: [_jsx("div", { className: "mb-1 text-[0.7rem] text-muted-foreground/60", children: "Agent result" }), _jsx("div", { className: "max-h-72 overflow-auto rounded bg-muted/30 p-2 text-sm text-foreground/90", children: _jsx(MessageResponse, { children: outputText }) })] })) : null, numberField(recordOf(outputRecord.details), "durationMs") != null ? (_jsx(DetailRow, { label: "Duration:", value: `${Math.max(1, Math.round(numberField(recordOf(outputRecord.details), "durationMs") / 1000))}s` })) : null] }));
|
|
705
|
-
}
|
|
706
|
-
function SkillDetails({ presentation, resource = false, }) {
|
|
707
|
-
const { input, outputText } = presentation;
|
|
708
|
-
const skill = stringField(input, "skill", "name");
|
|
709
|
-
const path = stringField(input, "path");
|
|
710
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Skill:", value: skill, mono: true }), resource ? (_jsx(DetailRow, { label: "Resource:", value: path, copyValue: path, mono: true })) : null, _jsx(OutputBlock, { label: resource ? "Preview" : "Status", value: resource ? previewLines(outputText, 10) : outputText })] }));
|
|
711
|
-
}
|
|
712
|
-
function AskUserDetails({ presentation }) {
|
|
713
|
-
const questions = questionsOf(presentation.input);
|
|
714
|
-
const answer = presentation.outputText;
|
|
715
|
-
return (_jsx("div", { className: "space-y-2", children: questions.length > 0 ? (questions.map((question, index) => (_jsxs("div", { children: [_jsx("p", { className: "font-medium text-foreground/85", children: stringField(question, "question", "prompt") || "Question" }), _jsx("p", { className: "text-muted-foreground/60", children: answer || "—" })] }, `${stringField(question, "question", "prompt")}:${index}`)))) : (_jsx(GenericDetails, { presentation: presentation })) }));
|
|
716
|
-
}
|
|
717
|
-
function JavaScriptDetails({ presentation }) {
|
|
718
|
-
const { input, outputText } = presentation;
|
|
719
|
-
const timeout = numberField(input, "timeoutMs", "timeout_ms");
|
|
720
|
-
const outputLimit = numberField(input, "maxOutputCharacters", "max_output_characters");
|
|
721
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Runtime:", value: "JavaScript code mode" }), _jsx(DetailRow, { label: "Description:", value: stringField(input, "description") }), timeout != null ? (_jsx(DetailRow, { label: "Timeout:", value: `${timeout}ms` })) : null, outputLimit != null ? (_jsx(DetailRow, { label: "Output limit:", value: `${outputLimit} chars` })) : null, _jsx(OutputBlock, { label: "Code", value: stringField(input, "code") }), _jsx(OutputBlock, { label: "Output", value: outputText })] }));
|
|
722
|
-
}
|
|
723
|
-
function McpDetails({ presentation }) {
|
|
724
|
-
const parsed = parseMcpName(presentation.name);
|
|
725
|
-
return (_jsxs("div", { className: "space-y-1", children: [parsed ? (_jsxs(_Fragment, { children: [_jsx(DetailRow, { label: "MCP Server:", value: parsed.server }), _jsx(DetailRow, { label: "Tool:", value: parsed.tool })] })) : null, _jsx(GenericDetails, { presentation: presentation, hideProject: true })] }));
|
|
726
|
-
}
|
|
727
|
-
function GenericDetails({ presentation, hideProject = false, }) {
|
|
728
|
-
const { input, outputText, errorText } = presentation;
|
|
729
|
-
const inputText = Object.keys(input).length > 0 ? safeStringify(input) : "";
|
|
730
|
-
return (_jsxs("div", { className: "space-y-1", children: [!hideProject ? _jsx(ProjectRow, { input: input }) : null, _jsx(OutputBlock, { label: "Input", value: inputText }), _jsx(OutputBlock, { label: presentation.failed ? "Error" : "Output", value: errorText || outputText }), !inputText && !outputText && !errorText ? (_jsx(DetailRow, { label: "Details:", value: "No additional data" })) : null] }));
|
|
731
|
-
}
|
|
732
|
-
export function CamelToolDetails({ presentation, }) {
|
|
733
|
-
switch (presentation.kind) {
|
|
734
|
-
case "read":
|
|
735
|
-
return _jsx(ReadDetails, { presentation: presentation });
|
|
736
|
-
case "write":
|
|
737
|
-
return _jsx(WriteDetails, { presentation: presentation });
|
|
738
|
-
case "edit":
|
|
739
|
-
return _jsx(EditDetails, { presentation: presentation });
|
|
740
|
-
case "bash":
|
|
741
|
-
return _jsx(BashDetails, { presentation: presentation });
|
|
742
|
-
case "glob":
|
|
743
|
-
return _jsx(SearchDetails, { presentation: presentation, label: "Files" });
|
|
744
|
-
case "grep":
|
|
745
|
-
return _jsx(SearchDetails, { presentation: presentation, label: "Matches" });
|
|
746
|
-
case "list":
|
|
747
|
-
case "find":
|
|
748
|
-
return _jsx(ListDetails, { presentation: presentation });
|
|
749
|
-
case "web-search":
|
|
750
|
-
return _jsx(WebDetails, { presentation: presentation, mode: "search" });
|
|
751
|
-
case "web-fetch":
|
|
752
|
-
return _jsx(WebDetails, { presentation: presentation, mode: "fetch" });
|
|
753
|
-
case "javascript":
|
|
754
|
-
return _jsx(JavaScriptDetails, { presentation: presentation });
|
|
755
|
-
case "tasks":
|
|
756
|
-
return _jsx(TaskDetails, { presentation: presentation });
|
|
757
|
-
case "agent":
|
|
758
|
-
return _jsx(AgentDetails, { presentation: presentation });
|
|
759
|
-
case "skill":
|
|
760
|
-
return _jsx(SkillDetails, { presentation: presentation });
|
|
761
|
-
case "skill-resource":
|
|
762
|
-
return _jsx(SkillDetails, { presentation: presentation, resource: true });
|
|
763
|
-
case "ask-user":
|
|
764
|
-
return _jsx(AskUserDetails, { presentation: presentation });
|
|
765
|
-
case "suggestions":
|
|
766
|
-
return (_jsx(OutputBlock, { label: "Suggestions", value: presentation.outputText || safeStringify(presentation.input) }));
|
|
767
|
-
case "notebook":
|
|
768
|
-
return (_jsxs("div", { className: "space-y-1", children: [_jsx(DetailRow, { label: "Notebook:", value: stringField(presentation.input, "notebook_path", "path"), mono: true }), _jsx(DetailRow, { label: "Cell:", value: stringField(presentation.input, "cell_id", "cell_number") }), _jsx(OutputBlock, { label: "Code", value: stringField(presentation.input, "code", "new_source") })] }));
|
|
769
|
-
case "mcp":
|
|
770
|
-
return _jsx(McpDetails, { presentation: presentation });
|
|
771
|
-
case "generic":
|
|
772
|
-
return _jsx(GenericDetails, { presentation: presentation });
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
function formatBytes(bytes) {
|
|
776
|
-
if (!Number.isFinite(bytes))
|
|
777
|
-
return "";
|
|
778
|
-
if (bytes < 1024)
|
|
779
|
-
return `${bytes} B`;
|
|
780
|
-
const kilobytes = bytes / 1024;
|
|
781
|
-
if (kilobytes < 1024)
|
|
782
|
-
return `${kilobytes.toFixed(1)} KB`;
|
|
783
|
-
return `${(kilobytes / 1024).toFixed(1)} MB`;
|
|
784
|
-
}
|