@volter-ai-dev/supercode-ui 0.1.7 → 0.1.9
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/components.d.ts +1 -0
- package/components.mjs +352 -32
- package/controller.mjs +8 -2
- package/conversation.d.ts +2 -0
- package/conversation.mjs +318 -32
- package/core.d.ts +3 -0
- package/core.mjs +154 -3
- package/embed.mjs +351 -32
- package/index.d.ts +31 -1
- package/messenger.mjs +351 -32
- package/package.json +1 -1
- package/sessions.mjs +1 -1
- package/styles.css +17 -6
package/components.d.ts
CHANGED
package/components.mjs
CHANGED
|
@@ -64,6 +64,11 @@ var MODES = /* @__PURE__ */ new Set(["none", "control", "mirror"]);
|
|
|
64
64
|
var STRATEGIES = /* @__PURE__ */ new Set(["start", "resume", "attach", "branch", "reduce"]);
|
|
65
65
|
var STARTUP = /* @__PURE__ */ new Set(["connecting", "starting", "discovering", "ready"]);
|
|
66
66
|
var FIDELITY = /* @__PURE__ */ new Set(["byte_lossless", "value_lossless", "semantic"]);
|
|
67
|
+
var TOOL_CATEGORIES = /* @__PURE__ */ new Set(["read", "search", "edit", "command", "test", "web", "agent", "plan", "other"]);
|
|
68
|
+
var TOOL_DETAILS = /* @__PURE__ */ new Set(["file", "matches", "diff", "terminal", "web", "agent", "plan", "fields"]);
|
|
69
|
+
var MAX_TOOL_FIELDS = 8;
|
|
70
|
+
var MAX_TOOL_FIELD_CHARS = 800;
|
|
71
|
+
var MAX_TOOL_PREVIEW_CHARS = 4e3;
|
|
67
72
|
function record(value) {
|
|
68
73
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
69
74
|
}
|
|
@@ -76,6 +81,132 @@ function number(value, fallback = 0) {
|
|
|
76
81
|
function nullableNumber(value) {
|
|
77
82
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
78
83
|
}
|
|
84
|
+
function boundedString(value, max) {
|
|
85
|
+
if (typeof value !== "string") return "";
|
|
86
|
+
return value.length <= max ? value : `${value.slice(0, max)}\u2026`;
|
|
87
|
+
}
|
|
88
|
+
function argumentObject(argumentsText) {
|
|
89
|
+
if (!argumentsText) return null;
|
|
90
|
+
try {
|
|
91
|
+
return record(JSON.parse(argumentsText));
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function firstString(source, keys) {
|
|
97
|
+
for (const key of keys) {
|
|
98
|
+
if (typeof source?.[key] === "string" && source[key].trim()) return source[key].trim();
|
|
99
|
+
}
|
|
100
|
+
return "";
|
|
101
|
+
}
|
|
102
|
+
function explicitNumber(sources, keys) {
|
|
103
|
+
for (const source of sources) {
|
|
104
|
+
for (const key of keys) {
|
|
105
|
+
const value = source?.[key];
|
|
106
|
+
const parsed = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
|
|
107
|
+
if (typeof parsed === "number" && Number.isFinite(parsed)) return parsed;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
function toolDetail(category) {
|
|
113
|
+
return { read: "file", search: "matches", edit: "diff", command: "terminal", test: "terminal", web: "web", agent: "agent", plan: "plan" }[category] ?? "fields";
|
|
114
|
+
}
|
|
115
|
+
function usefulToolFields(args) {
|
|
116
|
+
if (!args) return [];
|
|
117
|
+
const hidden = /* @__PURE__ */ new Set(["command", "cmd", "file_path", "target_file", "path", "query", "pattern", "url", "patch", "diff", "old_string", "new_string", "content", "prompt", "description", "task", "plan", "todos"]);
|
|
118
|
+
return Object.entries(args).flatMap(([key, value]) => {
|
|
119
|
+
if (hidden.has(key) || value === null || value === void 0) return [];
|
|
120
|
+
const rendered = typeof value === "string" ? value : JSON.stringify(value);
|
|
121
|
+
if (!rendered) return [];
|
|
122
|
+
return [{ label: key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase()), value: boundedString(rendered, MAX_TOOL_FIELD_CHARS) }];
|
|
123
|
+
}).slice(0, MAX_TOOL_FIELDS);
|
|
124
|
+
}
|
|
125
|
+
function planItems(args) {
|
|
126
|
+
const source = Array.isArray(args?.plan) ? args.plan : Array.isArray(args?.todos) ? args.todos : [];
|
|
127
|
+
return source.flatMap((item) => {
|
|
128
|
+
if (typeof item === "string" && item.trim()) return [{ label: boundedString(item.trim(), 300), status: "" }];
|
|
129
|
+
const value = record(item);
|
|
130
|
+
const label = firstString(value, ["step", "title", "content", "text"]);
|
|
131
|
+
if (!label) return [];
|
|
132
|
+
return [{ label: boundedString(label, 300), status: firstString(value, ["status"]) }];
|
|
133
|
+
}).slice(0, 12);
|
|
134
|
+
}
|
|
135
|
+
function editPreview(args, resultText) {
|
|
136
|
+
const direct = firstString(args, ["patch", "diff"]);
|
|
137
|
+
if (direct) return direct;
|
|
138
|
+
const oldText = firstString(args, ["old_string"]);
|
|
139
|
+
const newText = firstString(args, ["new_string"]);
|
|
140
|
+
if (oldText || newText) {
|
|
141
|
+
return [
|
|
142
|
+
...oldText.split("\n").map((line) => `- ${line}`),
|
|
143
|
+
...newText.split("\n").map((line) => `+ ${line}`)
|
|
144
|
+
].join("\n");
|
|
145
|
+
}
|
|
146
|
+
return /^(?:diff --git|@@ |--- |\+\+\+ )/m.test(resultText ?? "") ? resultText : "";
|
|
147
|
+
}
|
|
148
|
+
function createToolPresentation(entry) {
|
|
149
|
+
const args = argumentObject(entry.arguments);
|
|
150
|
+
const category = toolCategory({ label: entry.label, arguments: entry.arguments });
|
|
151
|
+
const command = firstString(args, ["command", "cmd"]);
|
|
152
|
+
const path = firstString(args, ["file_path", "target_file", "path"]);
|
|
153
|
+
const query = firstString(args, ["query", "pattern"]);
|
|
154
|
+
const url = firstString(args, ["url"]);
|
|
155
|
+
const subject = firstString(args, ["description", "task", "prompt"]);
|
|
156
|
+
const target = path || command || query || url || subject || toolTarget(entry.arguments);
|
|
157
|
+
const previewSource = category === "edit" ? editPreview(args, entry.resultText) : entry.resultText ?? "";
|
|
158
|
+
const result = record(entry.resultContent);
|
|
159
|
+
const metadata = record(entry.metadata);
|
|
160
|
+
return {
|
|
161
|
+
category,
|
|
162
|
+
detail: toolDetail(category),
|
|
163
|
+
target: boundedString(target, 300),
|
|
164
|
+
command: boundedString(command, MAX_TOOL_FIELD_CHARS),
|
|
165
|
+
path: boundedString(path, MAX_TOOL_FIELD_CHARS),
|
|
166
|
+
query: boundedString(query, MAX_TOOL_FIELD_CHARS),
|
|
167
|
+
url: boundedString(url, MAX_TOOL_FIELD_CHARS),
|
|
168
|
+
subject: boundedString(subject, MAX_TOOL_FIELD_CHARS),
|
|
169
|
+
preview: boundedString(previewSource, MAX_TOOL_PREVIEW_CHARS),
|
|
170
|
+
fields: usefulToolFields(args),
|
|
171
|
+
items: planItems(args),
|
|
172
|
+
exitCode: explicitNumber([result, metadata], ["exit_code", "exitCode"]),
|
|
173
|
+
durationMs: explicitNumber([result, metadata], ["duration_ms", "durationMs", "elapsed_ms", "elapsedMs"]),
|
|
174
|
+
additions: explicitNumber([result, metadata], ["additions", "lines_added"]),
|
|
175
|
+
deletions: explicitNumber([result, metadata], ["deletions", "lines_removed"]),
|
|
176
|
+
matches: explicitNumber([result, metadata], ["matches", "match_count", "result_count"])
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function readToolPresentation(value, entry) {
|
|
180
|
+
const generated = createToolPresentation(entry);
|
|
181
|
+
const item = record(value);
|
|
182
|
+
if (!item) return generated;
|
|
183
|
+
const fields = Array.isArray(item.fields) ? item.fields.flatMap((raw) => {
|
|
184
|
+
const field = record(raw);
|
|
185
|
+
return field && typeof field.label === "string" && typeof field.value === "string" ? [{ label: boundedString(field.label, 80), value: boundedString(field.value, MAX_TOOL_FIELD_CHARS) }] : [];
|
|
186
|
+
}).slice(0, MAX_TOOL_FIELDS) : generated.fields;
|
|
187
|
+
const items = Array.isArray(item.items) ? item.items.flatMap((raw) => {
|
|
188
|
+
const planItem = record(raw);
|
|
189
|
+
return planItem && typeof planItem.label === "string" ? [{ label: boundedString(planItem.label, 300), status: boundedString(planItem.status, 40) }] : [];
|
|
190
|
+
}).slice(0, 12) : generated.items;
|
|
191
|
+
return {
|
|
192
|
+
category: TOOL_CATEGORIES.has(item.category) ? item.category : generated.category,
|
|
193
|
+
detail: TOOL_DETAILS.has(item.detail) ? item.detail : generated.detail,
|
|
194
|
+
target: boundedString(item.target, 300) || generated.target,
|
|
195
|
+
command: boundedString(item.command, MAX_TOOL_FIELD_CHARS) || generated.command,
|
|
196
|
+
path: boundedString(item.path, MAX_TOOL_FIELD_CHARS) || generated.path,
|
|
197
|
+
query: boundedString(item.query, MAX_TOOL_FIELD_CHARS) || generated.query,
|
|
198
|
+
url: boundedString(item.url, MAX_TOOL_FIELD_CHARS) || generated.url,
|
|
199
|
+
subject: boundedString(item.subject, MAX_TOOL_FIELD_CHARS) || generated.subject,
|
|
200
|
+
preview: boundedString(item.preview, MAX_TOOL_PREVIEW_CHARS) || generated.preview,
|
|
201
|
+
fields,
|
|
202
|
+
items,
|
|
203
|
+
exitCode: nullableNumber(item.exitCode) ?? generated.exitCode,
|
|
204
|
+
durationMs: nullableNumber(item.durationMs) ?? generated.durationMs,
|
|
205
|
+
additions: nullableNumber(item.additions) ?? generated.additions,
|
|
206
|
+
deletions: nullableNumber(item.deletions) ?? generated.deletions,
|
|
207
|
+
matches: nullableNumber(item.matches) ?? generated.matches
|
|
208
|
+
};
|
|
209
|
+
}
|
|
79
210
|
function readTranscript(value) {
|
|
80
211
|
if (!Array.isArray(value)) return [];
|
|
81
212
|
const result = [];
|
|
@@ -93,6 +224,7 @@ function readTranscript(value) {
|
|
|
93
224
|
if (typeof item[key] === "string") entry[key] = item[key];
|
|
94
225
|
}
|
|
95
226
|
if (["pending", "completed", "error"].includes(item.status)) entry.status = item.status;
|
|
227
|
+
if (item.role === "tool") entry.presentation = readToolPresentation(item.presentation, entry);
|
|
96
228
|
if (typeof item.streaming === "boolean") entry.streaming = item.streaming;
|
|
97
229
|
if (Array.isArray(item.context)) {
|
|
98
230
|
entry.context = item.context.flatMap((raw) => {
|
|
@@ -300,6 +432,7 @@ function groupConversation(entries) {
|
|
|
300
432
|
return blocks;
|
|
301
433
|
}
|
|
302
434
|
function toolCategory(entry) {
|
|
435
|
+
if (TOOL_CATEGORIES.has(entry.presentation?.category)) return entry.presentation.category;
|
|
303
436
|
const name = entry.label?.toLocaleLowerCase() ?? "";
|
|
304
437
|
if (/read|view|open_file|list_dir/.test(name)) return "read";
|
|
305
438
|
if (/search|find|grep|glob/.test(name)) return "search";
|
|
@@ -307,7 +440,8 @@ function toolCategory(entry) {
|
|
|
307
440
|
if (/test|typecheck|lint|build/.test(name)) return "test";
|
|
308
441
|
if (/terminal|bash|shell|command|exec/.test(name)) return /\b(test|typecheck|lint|build)\b/i.test(entry.arguments ?? "") ? "test" : "command";
|
|
309
442
|
if (/browser|web|fetch|url/.test(name)) return "web";
|
|
310
|
-
if (/
|
|
443
|
+
if (/update.?plan|todo|checklist/.test(name)) return "plan";
|
|
444
|
+
if (/subagent|spawn.?agent|delegate|^task$/.test(name)) return "agent";
|
|
311
445
|
return "other";
|
|
312
446
|
}
|
|
313
447
|
function toolTarget(argumentsText) {
|
|
@@ -329,9 +463,12 @@ function compactToolTarget(target, workspace) {
|
|
|
329
463
|
function activitySummary(entries) {
|
|
330
464
|
const counts = /* @__PURE__ */ new Map();
|
|
331
465
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
466
|
+
const failed = entries.filter((entry) => entry.status === "error").length;
|
|
467
|
+
const pending = entries.filter((entry) => entry.status === "pending").length;
|
|
468
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
469
|
+
if (failed) return `${entries.length} actions \xB7 ${failed} failed`;
|
|
332
470
|
if ([...counts.keys()].every((key) => key === "read" || key === "search")) return `Explored ${entries.length} ${entries.length === 1 ? "item" : "items"}`;
|
|
333
|
-
|
|
334
|
-
return `Activity \xB7 ${Object.entries(labels).flatMap(([key, label]) => counts.has(key) ? [`${counts.get(key)} ${label}`] : []).join(" \xB7 ")}`;
|
|
471
|
+
return `${entries.length} actions`;
|
|
335
472
|
}
|
|
336
473
|
function canContinueHere(state) {
|
|
337
474
|
if (state.mode !== "mirror" || state.canSend) return false;
|
|
@@ -467,7 +604,7 @@ function Markdown({ value }) {
|
|
|
467
604
|
}
|
|
468
605
|
|
|
469
606
|
// src/conversation.jsx
|
|
470
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
607
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
471
608
|
function LoadingStatus({ state, compact = false }) {
|
|
472
609
|
const copy = {
|
|
473
610
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -515,6 +652,185 @@ function ContextDisclosure({ context }) {
|
|
|
515
652
|
] }, item.id ?? index)) })
|
|
516
653
|
] });
|
|
517
654
|
}
|
|
655
|
+
var TOOL_ICONS = {
|
|
656
|
+
read: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
657
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.75h7.25L15 5.5v7.75A1.75 1.75 0 0 1 13.25 15h-8.5A1.75 1.75 0 0 1 3 13.25v-8.5A2 2 0 0 1 5 2.75Z" }),
|
|
658
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
659
|
+
] }),
|
|
660
|
+
search: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
661
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
662
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.5 11.5 3 3" })
|
|
663
|
+
] }),
|
|
664
|
+
edit: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
665
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
666
|
+
/* @__PURE__ */ jsx3("path", { d: "m10 5 3 3" })
|
|
667
|
+
] }),
|
|
668
|
+
command: () => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
669
|
+
test: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
670
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 2.5v3L3 12a2 2 0 0 0 1.8 3h8.4a2 2 0 0 0 1.8-3l-3-6.5v-3M5 9h8" }),
|
|
671
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.5h8" })
|
|
672
|
+
] }),
|
|
673
|
+
web: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
674
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
675
|
+
/* @__PURE__ */ jsx3("path", { d: "M2.75 9h12.5M9 2.5c2 1.8 3 4 3 6.5s-1 4.7-3 6.5c-2-1.8-3-4-3-6.5s1-4.7 3-6.5Z" })
|
|
676
|
+
] }),
|
|
677
|
+
agent: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
678
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
679
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
680
|
+
] }),
|
|
681
|
+
plan: () => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 1 1 2-2M3 9l1 1 2-2M3 13l1 1 2-2M8 5h7M8 9h7M8 13h7" }) }),
|
|
682
|
+
other: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
683
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
684
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
685
|
+
] })
|
|
686
|
+
};
|
|
687
|
+
function ToolIcon({ category }) {
|
|
688
|
+
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
689
|
+
return /* @__PURE__ */ jsx3("svg", { class: "scui-tool-icon", viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.35", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(Glyph, {}) });
|
|
690
|
+
}
|
|
691
|
+
function toolAction(entry, category) {
|
|
692
|
+
const status = entry.status ?? "completed";
|
|
693
|
+
const actions = {
|
|
694
|
+
read: ["Reading", "Read", "Read failed"],
|
|
695
|
+
search: ["Searching", "Searched", "Search failed"],
|
|
696
|
+
edit: ["Editing", "Edited", "Edit failed"],
|
|
697
|
+
command: ["Running command", "Ran command", "Command failed"],
|
|
698
|
+
test: ["Running tests", "Ran tests", "Tests failed"],
|
|
699
|
+
web: ["Browsing", "Browsed", "Browser action failed"],
|
|
700
|
+
agent: ["Starting agent", "Started agent", "Agent failed"],
|
|
701
|
+
plan: ["Updating plan", "Updated plan", "Plan update failed"]
|
|
702
|
+
};
|
|
703
|
+
const position = status === "pending" ? 0 : status === "error" ? 2 : 1;
|
|
704
|
+
if (actions[category]) return actions[category][position];
|
|
705
|
+
const label = entry.label?.split(/__|\//).at(-1)?.replaceAll(/[_-]+/g, " ") || "Tool";
|
|
706
|
+
return status === "error" ? `${label} failed` : label;
|
|
707
|
+
}
|
|
708
|
+
function argumentLabel(key) {
|
|
709
|
+
const labels = { cmd: "Command", command: "Command", cwd: "Working directory", file_path: "File", target_file: "File", path: "Path", query: "Query", pattern: "Pattern", url: "URL" };
|
|
710
|
+
return labels[key] ?? key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase());
|
|
711
|
+
}
|
|
712
|
+
function argumentRows(argumentsText) {
|
|
713
|
+
if (!argumentsText) return [];
|
|
714
|
+
try {
|
|
715
|
+
const value = JSON.parse(argumentsText);
|
|
716
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
717
|
+
return Object.entries(value).map(([key, item]) => ({
|
|
718
|
+
key,
|
|
719
|
+
label: argumentLabel(key),
|
|
720
|
+
value: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
721
|
+
}));
|
|
722
|
+
}
|
|
723
|
+
} catch {
|
|
724
|
+
}
|
|
725
|
+
return [{ key: "arguments", label: "Details", value: argumentsText }];
|
|
726
|
+
}
|
|
727
|
+
function stripAnsi(value) {
|
|
728
|
+
return value?.replaceAll(/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]+)*)?\u0007)|(?:(?:\d{1,4}(?:[;:]\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g, "") ?? "";
|
|
729
|
+
}
|
|
730
|
+
function formatDuration(value) {
|
|
731
|
+
if (value === null) return "";
|
|
732
|
+
if (value < 1e3) return `${Math.round(value)}ms`;
|
|
733
|
+
return `${(value / 1e3).toFixed(value < 1e4 ? 1 : 0)}s`;
|
|
734
|
+
}
|
|
735
|
+
function ToolMetrics({ presentation }) {
|
|
736
|
+
const metrics = [
|
|
737
|
+
presentation.matches === null ? "" : `${presentation.matches} ${presentation.matches === 1 ? "match" : "matches"}`,
|
|
738
|
+
presentation.additions === null ? "" : `+${presentation.additions}`,
|
|
739
|
+
presentation.deletions === null ? "" : `\u2212${presentation.deletions}`,
|
|
740
|
+
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
741
|
+
formatDuration(presentation.durationMs)
|
|
742
|
+
].filter(Boolean);
|
|
743
|
+
return metrics.length ? /* @__PURE__ */ jsx3("div", { class: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx3("span", { children: metric }, metric)) }) : null;
|
|
744
|
+
}
|
|
745
|
+
function LinePreview({ value, kind }) {
|
|
746
|
+
if (!value) return null;
|
|
747
|
+
return /* @__PURE__ */ jsx3("ol", { class: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
748
|
+
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
749
|
+
return /* @__PURE__ */ jsxs2("li", { "data-tone": tone, children: [
|
|
750
|
+
/* @__PURE__ */ jsx3("span", { children: index + 1 }),
|
|
751
|
+
/* @__PURE__ */ jsx3("code", { children: line || " " })
|
|
752
|
+
] }, index);
|
|
753
|
+
}) });
|
|
754
|
+
}
|
|
755
|
+
function TerminalPreview({ presentation, pending, failed }) {
|
|
756
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-terminal", children: [
|
|
757
|
+
/* @__PURE__ */ jsxs2("header", { children: [
|
|
758
|
+
/* @__PURE__ */ jsxs2("span", { "aria-hidden": "true", children: [
|
|
759
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
760
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
761
|
+
/* @__PURE__ */ jsx3("i", {})
|
|
762
|
+
] }),
|
|
763
|
+
/* @__PURE__ */ jsx3("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
764
|
+
] }),
|
|
765
|
+
presentation.preview ? /* @__PURE__ */ jsx3("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs2("div", { class: "scui-terminal-wait", children: [
|
|
766
|
+
/* @__PURE__ */ jsx3("i", {}),
|
|
767
|
+
" Waiting for output"
|
|
768
|
+
] }) : /* @__PURE__ */ jsx3("div", { class: "scui-terminal-empty", children: "No output" })
|
|
769
|
+
] });
|
|
770
|
+
}
|
|
771
|
+
function SearchPreview({ presentation }) {
|
|
772
|
+
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
773
|
+
return /* @__PURE__ */ jsxs2("section", { class: "scui-search-preview", children: [
|
|
774
|
+
presentation.query ? /* @__PURE__ */ jsxs2("header", { children: [
|
|
775
|
+
/* @__PURE__ */ jsx3("span", { children: "Search" }),
|
|
776
|
+
/* @__PURE__ */ jsx3("code", { children: presentation.query })
|
|
777
|
+
] }) : null,
|
|
778
|
+
lines.length ? /* @__PURE__ */ jsx3("ol", { children: lines.map((line, index) => {
|
|
779
|
+
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
780
|
+
return /* @__PURE__ */ jsx3("li", { children: match ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
781
|
+
/* @__PURE__ */ jsx3("code", { children: match[1] }),
|
|
782
|
+
/* @__PURE__ */ jsxs2("small", { children: [
|
|
783
|
+
match[2],
|
|
784
|
+
match[3] ? `:${match[3]}` : ""
|
|
785
|
+
] }),
|
|
786
|
+
/* @__PURE__ */ jsx3("span", { children: match[4] })
|
|
787
|
+
] }) : /* @__PURE__ */ jsx3("span", { children: line }) }, index);
|
|
788
|
+
}) }) : /* @__PURE__ */ jsx3("p", { children: "No textual results" })
|
|
789
|
+
] });
|
|
790
|
+
}
|
|
791
|
+
function ToolPreview({ presentation, entry }) {
|
|
792
|
+
const pending = entry.status === "pending";
|
|
793
|
+
const failed = entry.status === "error";
|
|
794
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx3(TerminalPreview, { presentation, pending, failed });
|
|
795
|
+
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx3(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx3("div", { class: "scui-tool-empty", children: "Edit completed without a textual diff" });
|
|
796
|
+
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx3(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx3("div", { class: "scui-tool-empty", children: "File contents were not included in this event" });
|
|
797
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx3(SearchPreview, { presentation });
|
|
798
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs2("section", { class: "scui-web-preview", children: [
|
|
799
|
+
presentation.url ? /* @__PURE__ */ jsx3("code", { children: presentation.url }) : null,
|
|
800
|
+
presentation.preview ? /* @__PURE__ */ jsx3("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx3("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
801
|
+
] });
|
|
802
|
+
if (presentation.detail === "agent") return /* @__PURE__ */ jsxs2("section", { class: "scui-agent-preview", children: [
|
|
803
|
+
presentation.subject ? /* @__PURE__ */ jsx3("p", { children: presentation.subject }) : null,
|
|
804
|
+
presentation.preview ? /* @__PURE__ */ jsx3("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx3("small", { children: pending ? "Agent is working" : "No textual handoff returned" })
|
|
805
|
+
] });
|
|
806
|
+
if (presentation.detail === "plan") return /* @__PURE__ */ jsx3("ol", { class: "scui-plan-preview", children: presentation.items?.map((item, index) => /* @__PURE__ */ jsxs2("li", { "data-status": item.status, children: [
|
|
807
|
+
/* @__PURE__ */ jsx3("i", { "aria-hidden": "true" }),
|
|
808
|
+
/* @__PURE__ */ jsx3("span", { children: item.label })
|
|
809
|
+
] }, `${item.label}:${index}`)) });
|
|
810
|
+
return presentation.preview ? /* @__PURE__ */ jsx3("pre", { class: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
811
|
+
}
|
|
812
|
+
function TechnicalDetails({ entry }) {
|
|
813
|
+
if (!entry.arguments && !entry.resultText) return null;
|
|
814
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool-technical", children: [
|
|
815
|
+
/* @__PURE__ */ jsx3("summary", { children: "Technical details" }),
|
|
816
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
817
|
+
entry.arguments ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
818
|
+
/* @__PURE__ */ jsx3("strong", { children: "Native arguments" }),
|
|
819
|
+
/* @__PURE__ */ jsx3("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
820
|
+
/* @__PURE__ */ jsx3("dt", { children: row.label }),
|
|
821
|
+
/* @__PURE__ */ jsx3("dd", { children: /* @__PURE__ */ jsx3("pre", { children: row.value }) })
|
|
822
|
+
] }, row.key)) })
|
|
823
|
+
] }) : null,
|
|
824
|
+
entry.resultText ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
825
|
+
/* @__PURE__ */ jsx3("strong", { children: "Native result" }),
|
|
826
|
+
/* @__PURE__ */ jsxs2("pre", { "data-error": entry.status === "error", children: [
|
|
827
|
+
entry.resultText,
|
|
828
|
+
entry.truncated ? "\n[truncated]" : ""
|
|
829
|
+
] })
|
|
830
|
+
] }) : null
|
|
831
|
+
] })
|
|
832
|
+
] });
|
|
833
|
+
}
|
|
518
834
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
519
835
|
if (entry.role === "request") return /* @__PURE__ */ jsx3(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
520
836
|
if (entry.role === "reasoning") {
|
|
@@ -530,36 +846,35 @@ function TranscriptEntry({ entry, state, adapter }) {
|
|
|
530
846
|
entry.truncated ? /* @__PURE__ */ jsx3("small", { class: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null
|
|
531
847
|
] });
|
|
532
848
|
}
|
|
533
|
-
function ToolRow({ entry, workspace }) {
|
|
534
|
-
const
|
|
535
|
-
const
|
|
536
|
-
const
|
|
537
|
-
const
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
/* @__PURE__ */
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
/* @__PURE__ */ jsx3("
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
] }) : null
|
|
559
|
-
] }) : null
|
|
849
|
+
function ToolRow({ entry, workspace, open = false }) {
|
|
850
|
+
const presentation = entry.presentation ?? createToolPresentation(entry);
|
|
851
|
+
const target = compactToolTarget(presentation.target, workspace);
|
|
852
|
+
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
853
|
+
const category = presentation.category ?? toolCategory(entry);
|
|
854
|
+
const summary = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
855
|
+
/* @__PURE__ */ jsx3(ToolIcon, { category }),
|
|
856
|
+
/* @__PURE__ */ jsx3("strong", { children: toolAction(entry, category) }),
|
|
857
|
+
target ? /* @__PURE__ */ jsx3("code", { class: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
858
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
859
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-tool-status", role: "status", "data-status": entry.status ?? "completed", "aria-label": entry.status ?? "completed", children: entry.status === "pending" ? /* @__PURE__ */ jsx3("i", {}) : entry.status === "error" ? "\xD7" : "\u2713" }),
|
|
860
|
+
hasDetail ? /* @__PURE__ */ jsx3("span", { class: "scui-tool-chevron", "aria-hidden": "true", children: "\u203A" }) : null
|
|
861
|
+
] });
|
|
862
|
+
if (!hasDetail) return /* @__PURE__ */ jsx3("div", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx3("div", { class: "scui-tool-head", children: summary }) });
|
|
863
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: open || entry.status === "pending", children: [
|
|
864
|
+
/* @__PURE__ */ jsx3("summary", { class: "scui-tool-head", children: summary }),
|
|
865
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-tool-detail", children: [
|
|
866
|
+
/* @__PURE__ */ jsx3(ToolMetrics, { presentation }),
|
|
867
|
+
/* @__PURE__ */ jsx3(ToolPreview, { presentation, entry }),
|
|
868
|
+
presentation.fields.length ? /* @__PURE__ */ jsx3("dl", { class: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
869
|
+
/* @__PURE__ */ jsx3("dt", { children: field.label }),
|
|
870
|
+
/* @__PURE__ */ jsx3("dd", { children: field.value })
|
|
871
|
+
] }, field.label)) }) : null,
|
|
872
|
+
/* @__PURE__ */ jsx3(TechnicalDetails, { entry })
|
|
873
|
+
] })
|
|
560
874
|
] });
|
|
561
875
|
}
|
|
562
876
|
function ActivityGroup({ entries, state }) {
|
|
877
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx3("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx3(ToolRow, { entry: entries[0], workspace: state.workspace }) });
|
|
563
878
|
const active = entries.some((entry) => entry.status === "pending");
|
|
564
879
|
const [open, setOpen] = useState2(active);
|
|
565
880
|
const id = useId();
|
|
@@ -572,7 +887,7 @@ function ActivityGroup({ entries, state }) {
|
|
|
572
887
|
/* @__PURE__ */ jsx3("strong", { children: activitySummary(entries) }),
|
|
573
888
|
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
574
889
|
/* @__PURE__ */ jsxs2("small", { children: [
|
|
575
|
-
entries.filter((entry) => entry.status
|
|
890
|
+
entries.filter((entry) => entry.status !== "pending").length,
|
|
576
891
|
"/",
|
|
577
892
|
entries.length
|
|
578
893
|
] })
|
|
@@ -942,9 +1257,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
942
1257
|
}
|
|
943
1258
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels }) {
|
|
944
1259
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1260
|
+
const startableKey = startable.map((item) => item.id).join("\0");
|
|
945
1261
|
const [harness, setHarness] = useState4(startable[0]?.id ?? "");
|
|
946
1262
|
const [draft, setDraft] = useState4("");
|
|
947
1263
|
const [starting, setStarting] = useState4(false);
|
|
1264
|
+
useEffect4(() => {
|
|
1265
|
+
if (!startable.some((item) => item.id === harness)) setHarness(startable[0]?.id ?? "");
|
|
1266
|
+
}, [harness, startableKey]);
|
|
948
1267
|
useEffect4(() => {
|
|
949
1268
|
if (starting && (state.busy || state.transcript.length)) onStarted();
|
|
950
1269
|
}, [onStarted, starting, state.busy, state.transcript.length]);
|
|
@@ -1044,6 +1363,7 @@ export {
|
|
|
1044
1363
|
SessionRow,
|
|
1045
1364
|
SupercodeMessenger,
|
|
1046
1365
|
TaskPlan,
|
|
1366
|
+
ToolRow,
|
|
1047
1367
|
TranscriptEntry,
|
|
1048
1368
|
hasHarnessLogo
|
|
1049
1369
|
};
|
package/controller.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeUiState } from './core.mjs';
|
|
1
|
+
import { createToolPresentation, normalizeUiState } from './core.mjs';
|
|
2
2
|
|
|
3
3
|
const HARNESS_LABELS = {
|
|
4
4
|
'claude-code': 'Claude Code',
|
|
@@ -126,7 +126,7 @@ function projectConversationEntry(entry, maxEntryChars) {
|
|
|
126
126
|
const argumentsText = truncate((entry.arguments ?? '').trim(), maxEntryChars);
|
|
127
127
|
const result = truncate((entry.resultText ?? '').trim(), maxEntryChars);
|
|
128
128
|
const primary = entry.status === 'pending' ? argumentsText : result;
|
|
129
|
-
|
|
129
|
+
const projected = {
|
|
130
130
|
id: entry.id,
|
|
131
131
|
role: 'tool',
|
|
132
132
|
text: primary.text,
|
|
@@ -137,6 +137,12 @@ function projectConversationEntry(entry, maxEntryChars) {
|
|
|
137
137
|
resultText: result.text,
|
|
138
138
|
status: entry.status,
|
|
139
139
|
};
|
|
140
|
+
projected.presentation = createToolPresentation({
|
|
141
|
+
...projected,
|
|
142
|
+
resultContent: entry.resultContent,
|
|
143
|
+
metadata: entry.metadata,
|
|
144
|
+
});
|
|
145
|
+
return projected;
|
|
140
146
|
}
|
|
141
147
|
if (entry.kind === 'reasoning') {
|
|
142
148
|
const body = truncate(entry.text, maxEntryChars);
|
package/conversation.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type {
|
|
|
5
5
|
SessionSemanticsModel,
|
|
6
6
|
SupercodeUiState,
|
|
7
7
|
TaskPlanProps,
|
|
8
|
+
ToolRowProps,
|
|
8
9
|
TaskPlanModel,
|
|
9
10
|
TranscriptEntryModel,
|
|
10
11
|
TranscriptEntryProps,
|
|
@@ -17,5 +18,6 @@ export {
|
|
|
17
18
|
RequestCard,
|
|
18
19
|
SessionDetails,
|
|
19
20
|
TaskPlan,
|
|
21
|
+
ToolRow,
|
|
20
22
|
TranscriptEntry,
|
|
21
23
|
} from './index.js';
|