@volter-ai-dev/supercode-ui 0.1.7 → 0.1.8
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.mjs +105 -26
- package/conversation.mjs +101 -26
- package/core.mjs +5 -2
- package/embed.mjs +105 -26
- package/messenger.mjs +105 -26
- package/package.json +1 -1
- package/sessions.mjs +1 -1
- package/styles.css +9 -6
package/components.mjs
CHANGED
|
@@ -329,9 +329,12 @@ function compactToolTarget(target, workspace) {
|
|
|
329
329
|
function activitySummary(entries) {
|
|
330
330
|
const counts = /* @__PURE__ */ new Map();
|
|
331
331
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
332
|
+
const failed = entries.filter((entry) => entry.status === "error").length;
|
|
333
|
+
const pending = entries.filter((entry) => entry.status === "pending").length;
|
|
334
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
335
|
+
if (failed) return `${entries.length} actions \xB7 ${failed} failed`;
|
|
332
336
|
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 ")}`;
|
|
337
|
+
return `${entries.length} actions`;
|
|
335
338
|
}
|
|
336
339
|
function canContinueHere(state) {
|
|
337
340
|
if (state.mode !== "mirror" || state.canSend) return false;
|
|
@@ -467,7 +470,7 @@ function Markdown({ value }) {
|
|
|
467
470
|
}
|
|
468
471
|
|
|
469
472
|
// src/conversation.jsx
|
|
470
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
473
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
471
474
|
function LoadingStatus({ state, compact = false }) {
|
|
472
475
|
const copy = {
|
|
473
476
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -515,6 +518,76 @@ function ContextDisclosure({ context }) {
|
|
|
515
518
|
] }, item.id ?? index)) })
|
|
516
519
|
] });
|
|
517
520
|
}
|
|
521
|
+
var TOOL_ICONS = {
|
|
522
|
+
read: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
523
|
+
/* @__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" }),
|
|
524
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
525
|
+
] }),
|
|
526
|
+
search: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
527
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
528
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.5 11.5 3 3" })
|
|
529
|
+
] }),
|
|
530
|
+
edit: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
531
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
532
|
+
/* @__PURE__ */ jsx3("path", { d: "m10 5 3 3" })
|
|
533
|
+
] }),
|
|
534
|
+
command: () => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
535
|
+
test: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
536
|
+
/* @__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" }),
|
|
537
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.5h8" })
|
|
538
|
+
] }),
|
|
539
|
+
web: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
540
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
541
|
+
/* @__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" })
|
|
542
|
+
] }),
|
|
543
|
+
agent: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
544
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
545
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
546
|
+
] }),
|
|
547
|
+
other: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
548
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
549
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
550
|
+
] })
|
|
551
|
+
};
|
|
552
|
+
function ToolIcon({ category }) {
|
|
553
|
+
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
554
|
+
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, {}) });
|
|
555
|
+
}
|
|
556
|
+
function toolAction(entry, category) {
|
|
557
|
+
const status = entry.status ?? "completed";
|
|
558
|
+
const actions = {
|
|
559
|
+
read: ["Reading", "Read", "Read failed"],
|
|
560
|
+
search: ["Searching", "Searched", "Search failed"],
|
|
561
|
+
edit: ["Editing", "Edited", "Edit failed"],
|
|
562
|
+
command: ["Running command", "Ran command", "Command failed"],
|
|
563
|
+
test: ["Running tests", "Ran tests", "Tests failed"],
|
|
564
|
+
web: ["Browsing", "Browsed", "Browser action failed"],
|
|
565
|
+
agent: ["Starting agent", "Started agent", "Agent failed"]
|
|
566
|
+
};
|
|
567
|
+
const position = status === "pending" ? 0 : status === "error" ? 2 : 1;
|
|
568
|
+
if (actions[category]) return actions[category][position];
|
|
569
|
+
const label = entry.label?.split(/__|\//).at(-1)?.replaceAll(/[_-]+/g, " ") || "Tool";
|
|
570
|
+
return status === "error" ? `${label} failed` : label;
|
|
571
|
+
}
|
|
572
|
+
function argumentLabel(key) {
|
|
573
|
+
const labels = { cmd: "Command", command: "Command", cwd: "Working directory", file_path: "File", target_file: "File", path: "Path", query: "Query", pattern: "Pattern", url: "URL" };
|
|
574
|
+
return labels[key] ?? key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase());
|
|
575
|
+
}
|
|
576
|
+
function argumentRows(argumentsText) {
|
|
577
|
+
if (!argumentsText) return [];
|
|
578
|
+
try {
|
|
579
|
+
const value = JSON.parse(argumentsText);
|
|
580
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
581
|
+
return Object.entries(value).map(([key, item]) => ({
|
|
582
|
+
key,
|
|
583
|
+
label: argumentLabel(key),
|
|
584
|
+
value: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
585
|
+
}));
|
|
586
|
+
}
|
|
587
|
+
} catch {
|
|
588
|
+
}
|
|
589
|
+
return [{ key: "arguments", label: "Details", value: argumentsText }];
|
|
590
|
+
}
|
|
518
591
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
519
592
|
if (entry.role === "request") return /* @__PURE__ */ jsx3(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
520
593
|
if (entry.role === "reasoning") {
|
|
@@ -531,35 +604,37 @@ function TranscriptEntry({ entry, state, adapter }) {
|
|
|
531
604
|
] });
|
|
532
605
|
}
|
|
533
606
|
function ToolRow({ entry, workspace }) {
|
|
534
|
-
const [open, setOpen] = useState2(entry.status === "pending");
|
|
535
|
-
const detailId = useId();
|
|
536
607
|
const target = compactToolTarget(toolTarget(entry.arguments), workspace);
|
|
537
608
|
const hasDetail = Boolean(entry.arguments || entry.resultText);
|
|
538
609
|
const category = toolCategory(entry);
|
|
539
|
-
|
|
540
|
-
/* @__PURE__ */
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
entry.
|
|
557
|
-
entry.
|
|
610
|
+
const summary = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
611
|
+
/* @__PURE__ */ jsx3(ToolIcon, { category }),
|
|
612
|
+
/* @__PURE__ */ jsx3("strong", { children: toolAction(entry, category) }),
|
|
613
|
+
target ? /* @__PURE__ */ jsx3("code", { class: "scui-tool-target", title: toolTarget(entry.arguments), children: target }) : null,
|
|
614
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
615
|
+
/* @__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" }),
|
|
616
|
+
hasDetail ? /* @__PURE__ */ jsx3("span", { class: "scui-tool-chevron", "aria-hidden": "true", children: "\u203A" }) : null
|
|
617
|
+
] });
|
|
618
|
+
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 }) });
|
|
619
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: [
|
|
620
|
+
/* @__PURE__ */ jsx3("summary", { class: "scui-tool-head", children: summary }),
|
|
621
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-tool-detail", children: [
|
|
622
|
+
entry.arguments ? /* @__PURE__ */ jsx3("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
623
|
+
/* @__PURE__ */ jsx3("dt", { children: row.label }),
|
|
624
|
+
/* @__PURE__ */ jsx3("dd", { children: /* @__PURE__ */ jsx3("pre", { children: row.value }) })
|
|
625
|
+
] }, row.key)) }) : null,
|
|
626
|
+
entry.resultText ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
627
|
+
/* @__PURE__ */ jsx3("strong", { children: entry.status === "error" ? "Error" : "Result" }),
|
|
628
|
+
/* @__PURE__ */ jsxs2("pre", { "data-error": entry.status === "error", children: [
|
|
629
|
+
entry.resultText,
|
|
630
|
+
entry.truncated ? "\n[truncated]" : ""
|
|
631
|
+
] })
|
|
558
632
|
] }) : null
|
|
559
|
-
] })
|
|
633
|
+
] })
|
|
560
634
|
] });
|
|
561
635
|
}
|
|
562
636
|
function ActivityGroup({ entries, state }) {
|
|
637
|
+
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
638
|
const active = entries.some((entry) => entry.status === "pending");
|
|
564
639
|
const [open, setOpen] = useState2(active);
|
|
565
640
|
const id = useId();
|
|
@@ -572,7 +647,7 @@ function ActivityGroup({ entries, state }) {
|
|
|
572
647
|
/* @__PURE__ */ jsx3("strong", { children: activitySummary(entries) }),
|
|
573
648
|
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
574
649
|
/* @__PURE__ */ jsxs2("small", { children: [
|
|
575
|
-
entries.filter((entry) => entry.status
|
|
650
|
+
entries.filter((entry) => entry.status !== "pending").length,
|
|
576
651
|
"/",
|
|
577
652
|
entries.length
|
|
578
653
|
] })
|
|
@@ -942,9 +1017,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
942
1017
|
}
|
|
943
1018
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels }) {
|
|
944
1019
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1020
|
+
const startableKey = startable.map((item) => item.id).join("\0");
|
|
945
1021
|
const [harness, setHarness] = useState4(startable[0]?.id ?? "");
|
|
946
1022
|
const [draft, setDraft] = useState4("");
|
|
947
1023
|
const [starting, setStarting] = useState4(false);
|
|
1024
|
+
useEffect4(() => {
|
|
1025
|
+
if (!startable.some((item) => item.id === harness)) setHarness(startable[0]?.id ?? "");
|
|
1026
|
+
}, [harness, startableKey]);
|
|
948
1027
|
useEffect4(() => {
|
|
949
1028
|
if (starting && (state.busy || state.transcript.length)) onStarted();
|
|
950
1029
|
}, [onStarted, starting, state.busy, state.transcript.length]);
|
package/conversation.mjs
CHANGED
|
@@ -105,9 +105,12 @@ function compactToolTarget(target, workspace) {
|
|
|
105
105
|
function activitySummary(entries) {
|
|
106
106
|
const counts = /* @__PURE__ */ new Map();
|
|
107
107
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
108
|
+
const failed = entries.filter((entry) => entry.status === "error").length;
|
|
109
|
+
const pending = entries.filter((entry) => entry.status === "pending").length;
|
|
110
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
111
|
+
if (failed) return `${entries.length} actions \xB7 ${failed} failed`;
|
|
108
112
|
if ([...counts.keys()].every((key) => key === "read" || key === "search")) return `Explored ${entries.length} ${entries.length === 1 ? "item" : "items"}`;
|
|
109
|
-
|
|
110
|
-
return `Activity \xB7 ${Object.entries(labels).flatMap(([key, label]) => counts.has(key) ? [`${counts.get(key)} ${label}`] : []).join(" \xB7 ")}`;
|
|
113
|
+
return `${entries.length} actions`;
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
// src/markdown.jsx
|
|
@@ -135,7 +138,7 @@ function boundedSet(map, key, value) {
|
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
// src/conversation.jsx
|
|
138
|
-
import { jsx as jsx2, jsxs } from "preact/jsx-runtime";
|
|
141
|
+
import { Fragment, jsx as jsx2, jsxs } from "preact/jsx-runtime";
|
|
139
142
|
function LoadingStatus({ state, compact = false }) {
|
|
140
143
|
const copy = {
|
|
141
144
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -183,6 +186,76 @@ function ContextDisclosure({ context }) {
|
|
|
183
186
|
] }, item.id ?? index)) })
|
|
184
187
|
] });
|
|
185
188
|
}
|
|
189
|
+
var TOOL_ICONS = {
|
|
190
|
+
read: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
191
|
+
/* @__PURE__ */ jsx2("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" }),
|
|
192
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
193
|
+
] }),
|
|
194
|
+
search: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
195
|
+
/* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
196
|
+
/* @__PURE__ */ jsx2("path", { d: "m11.5 11.5 3 3" })
|
|
197
|
+
] }),
|
|
198
|
+
edit: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
199
|
+
/* @__PURE__ */ jsx2("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
200
|
+
/* @__PURE__ */ jsx2("path", { d: "m10 5 3 3" })
|
|
201
|
+
] }),
|
|
202
|
+
command: () => /* @__PURE__ */ jsx2(Fragment, { children: /* @__PURE__ */ jsx2("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
203
|
+
test: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
204
|
+
/* @__PURE__ */ jsx2("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" }),
|
|
205
|
+
/* @__PURE__ */ jsx2("path", { d: "M5 2.5h8" })
|
|
206
|
+
] }),
|
|
207
|
+
web: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
208
|
+
/* @__PURE__ */ jsx2("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
209
|
+
/* @__PURE__ */ jsx2("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" })
|
|
210
|
+
] }),
|
|
211
|
+
agent: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
212
|
+
/* @__PURE__ */ jsx2("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
213
|
+
/* @__PURE__ */ jsx2("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
214
|
+
] }),
|
|
215
|
+
other: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
216
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
217
|
+
/* @__PURE__ */ jsx2("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
218
|
+
] })
|
|
219
|
+
};
|
|
220
|
+
function ToolIcon({ category }) {
|
|
221
|
+
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
222
|
+
return /* @__PURE__ */ jsx2("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__ */ jsx2(Glyph, {}) });
|
|
223
|
+
}
|
|
224
|
+
function toolAction(entry, category) {
|
|
225
|
+
const status = entry.status ?? "completed";
|
|
226
|
+
const actions = {
|
|
227
|
+
read: ["Reading", "Read", "Read failed"],
|
|
228
|
+
search: ["Searching", "Searched", "Search failed"],
|
|
229
|
+
edit: ["Editing", "Edited", "Edit failed"],
|
|
230
|
+
command: ["Running command", "Ran command", "Command failed"],
|
|
231
|
+
test: ["Running tests", "Ran tests", "Tests failed"],
|
|
232
|
+
web: ["Browsing", "Browsed", "Browser action failed"],
|
|
233
|
+
agent: ["Starting agent", "Started agent", "Agent failed"]
|
|
234
|
+
};
|
|
235
|
+
const position = status === "pending" ? 0 : status === "error" ? 2 : 1;
|
|
236
|
+
if (actions[category]) return actions[category][position];
|
|
237
|
+
const label = entry.label?.split(/__|\//).at(-1)?.replaceAll(/[_-]+/g, " ") || "Tool";
|
|
238
|
+
return status === "error" ? `${label} failed` : label;
|
|
239
|
+
}
|
|
240
|
+
function argumentLabel(key) {
|
|
241
|
+
const labels = { cmd: "Command", command: "Command", cwd: "Working directory", file_path: "File", target_file: "File", path: "Path", query: "Query", pattern: "Pattern", url: "URL" };
|
|
242
|
+
return labels[key] ?? key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase());
|
|
243
|
+
}
|
|
244
|
+
function argumentRows(argumentsText) {
|
|
245
|
+
if (!argumentsText) return [];
|
|
246
|
+
try {
|
|
247
|
+
const value = JSON.parse(argumentsText);
|
|
248
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
249
|
+
return Object.entries(value).map(([key, item]) => ({
|
|
250
|
+
key,
|
|
251
|
+
label: argumentLabel(key),
|
|
252
|
+
value: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
} catch {
|
|
256
|
+
}
|
|
257
|
+
return [{ key: "arguments", label: "Details", value: argumentsText }];
|
|
258
|
+
}
|
|
186
259
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
187
260
|
if (entry.role === "request") return /* @__PURE__ */ jsx2(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
188
261
|
if (entry.role === "reasoning") {
|
|
@@ -199,35 +272,37 @@ function TranscriptEntry({ entry, state, adapter }) {
|
|
|
199
272
|
] });
|
|
200
273
|
}
|
|
201
274
|
function ToolRow({ entry, workspace }) {
|
|
202
|
-
const [open, setOpen] = useState(entry.status === "pending");
|
|
203
|
-
const detailId = useId();
|
|
204
275
|
const target = compactToolTarget(toolTarget(entry.arguments), workspace);
|
|
205
276
|
const hasDetail = Boolean(entry.arguments || entry.resultText);
|
|
206
277
|
const category = toolCategory(entry);
|
|
207
|
-
|
|
208
|
-
/* @__PURE__ */
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
entry.
|
|
225
|
-
entry.
|
|
278
|
+
const summary = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
279
|
+
/* @__PURE__ */ jsx2(ToolIcon, { category }),
|
|
280
|
+
/* @__PURE__ */ jsx2("strong", { children: toolAction(entry, category) }),
|
|
281
|
+
target ? /* @__PURE__ */ jsx2("code", { class: "scui-tool-target", title: toolTarget(entry.arguments), children: target }) : null,
|
|
282
|
+
/* @__PURE__ */ jsx2("span", { class: "scui-spacer" }),
|
|
283
|
+
/* @__PURE__ */ jsx2("span", { class: "scui-tool-status", role: "status", "data-status": entry.status ?? "completed", "aria-label": entry.status ?? "completed", children: entry.status === "pending" ? /* @__PURE__ */ jsx2("i", {}) : entry.status === "error" ? "\xD7" : "\u2713" }),
|
|
284
|
+
hasDetail ? /* @__PURE__ */ jsx2("span", { class: "scui-tool-chevron", "aria-hidden": "true", children: "\u203A" }) : null
|
|
285
|
+
] });
|
|
286
|
+
if (!hasDetail) return /* @__PURE__ */ jsx2("div", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx2("div", { class: "scui-tool-head", children: summary }) });
|
|
287
|
+
return /* @__PURE__ */ jsxs("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: [
|
|
288
|
+
/* @__PURE__ */ jsx2("summary", { class: "scui-tool-head", children: summary }),
|
|
289
|
+
/* @__PURE__ */ jsxs("div", { class: "scui-tool-detail", children: [
|
|
290
|
+
entry.arguments ? /* @__PURE__ */ jsx2("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs("div", { children: [
|
|
291
|
+
/* @__PURE__ */ jsx2("dt", { children: row.label }),
|
|
292
|
+
/* @__PURE__ */ jsx2("dd", { children: /* @__PURE__ */ jsx2("pre", { children: row.value }) })
|
|
293
|
+
] }, row.key)) }) : null,
|
|
294
|
+
entry.resultText ? /* @__PURE__ */ jsxs("section", { children: [
|
|
295
|
+
/* @__PURE__ */ jsx2("strong", { children: entry.status === "error" ? "Error" : "Result" }),
|
|
296
|
+
/* @__PURE__ */ jsxs("pre", { "data-error": entry.status === "error", children: [
|
|
297
|
+
entry.resultText,
|
|
298
|
+
entry.truncated ? "\n[truncated]" : ""
|
|
299
|
+
] })
|
|
226
300
|
] }) : null
|
|
227
|
-
] })
|
|
301
|
+
] })
|
|
228
302
|
] });
|
|
229
303
|
}
|
|
230
304
|
function ActivityGroup({ entries, state }) {
|
|
305
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx2("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx2(ToolRow, { entry: entries[0], workspace: state.workspace }) });
|
|
231
306
|
const active = entries.some((entry) => entry.status === "pending");
|
|
232
307
|
const [open, setOpen] = useState(active);
|
|
233
308
|
const id = useId();
|
|
@@ -240,7 +315,7 @@ function ActivityGroup({ entries, state }) {
|
|
|
240
315
|
/* @__PURE__ */ jsx2("strong", { children: activitySummary(entries) }),
|
|
241
316
|
/* @__PURE__ */ jsx2("span", { class: "scui-spacer" }),
|
|
242
317
|
/* @__PURE__ */ jsxs("small", { children: [
|
|
243
|
-
entries.filter((entry) => entry.status
|
|
318
|
+
entries.filter((entry) => entry.status !== "pending").length,
|
|
244
319
|
"/",
|
|
245
320
|
entries.length
|
|
246
321
|
] })
|
package/core.mjs
CHANGED
|
@@ -390,9 +390,12 @@ export function compactToolTarget(target, workspace) {
|
|
|
390
390
|
export function activitySummary(entries) {
|
|
391
391
|
const counts = new Map();
|
|
392
392
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
393
|
+
const failed = entries.filter((entry) => entry.status === 'error').length;
|
|
394
|
+
const pending = entries.filter((entry) => entry.status === 'pending').length;
|
|
395
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
396
|
+
if (failed) return `${entries.length} actions · ${failed} failed`;
|
|
393
397
|
if ([...counts.keys()].every((key) => key === 'read' || key === 'search')) return `Explored ${entries.length} ${entries.length === 1 ? 'item' : 'items'}`;
|
|
394
|
-
|
|
395
|
-
return `Activity · ${Object.entries(labels).flatMap(([key, label]) => counts.has(key) ? [`${counts.get(key)} ${label}`] : []).join(' · ')}`;
|
|
398
|
+
return `${entries.length} actions`;
|
|
396
399
|
}
|
|
397
400
|
|
|
398
401
|
export function canContinueHere(state) {
|
package/embed.mjs
CHANGED
|
@@ -332,9 +332,12 @@ function compactToolTarget(target, workspace) {
|
|
|
332
332
|
function activitySummary(entries) {
|
|
333
333
|
const counts = /* @__PURE__ */ new Map();
|
|
334
334
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
335
|
+
const failed = entries.filter((entry) => entry.status === "error").length;
|
|
336
|
+
const pending = entries.filter((entry) => entry.status === "pending").length;
|
|
337
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
338
|
+
if (failed) return `${entries.length} actions \xB7 ${failed} failed`;
|
|
335
339
|
if ([...counts.keys()].every((key) => key === "read" || key === "search")) return `Explored ${entries.length} ${entries.length === 1 ? "item" : "items"}`;
|
|
336
|
-
|
|
337
|
-
return `Activity \xB7 ${Object.entries(labels).flatMap(([key, label]) => counts.has(key) ? [`${counts.get(key)} ${label}`] : []).join(" \xB7 ")}`;
|
|
340
|
+
return `${entries.length} actions`;
|
|
338
341
|
}
|
|
339
342
|
function canContinueHere(state) {
|
|
340
343
|
if (state.mode !== "mirror" || state.canSend) return false;
|
|
@@ -473,7 +476,7 @@ function Markdown({ value }) {
|
|
|
473
476
|
}
|
|
474
477
|
|
|
475
478
|
// src/conversation.jsx
|
|
476
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
479
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
477
480
|
function LoadingStatus({ state, compact = false }) {
|
|
478
481
|
const copy = {
|
|
479
482
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -521,6 +524,76 @@ function ContextDisclosure({ context }) {
|
|
|
521
524
|
] }, item.id ?? index)) })
|
|
522
525
|
] });
|
|
523
526
|
}
|
|
527
|
+
var TOOL_ICONS = {
|
|
528
|
+
read: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
529
|
+
/* @__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" }),
|
|
530
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
531
|
+
] }),
|
|
532
|
+
search: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
533
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
534
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.5 11.5 3 3" })
|
|
535
|
+
] }),
|
|
536
|
+
edit: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
537
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
538
|
+
/* @__PURE__ */ jsx3("path", { d: "m10 5 3 3" })
|
|
539
|
+
] }),
|
|
540
|
+
command: () => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
541
|
+
test: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
542
|
+
/* @__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" }),
|
|
543
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.5h8" })
|
|
544
|
+
] }),
|
|
545
|
+
web: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
546
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
547
|
+
/* @__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" })
|
|
548
|
+
] }),
|
|
549
|
+
agent: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
550
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
551
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
552
|
+
] }),
|
|
553
|
+
other: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
554
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
555
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
556
|
+
] })
|
|
557
|
+
};
|
|
558
|
+
function ToolIcon({ category }) {
|
|
559
|
+
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
560
|
+
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, {}) });
|
|
561
|
+
}
|
|
562
|
+
function toolAction(entry, category) {
|
|
563
|
+
const status = entry.status ?? "completed";
|
|
564
|
+
const actions = {
|
|
565
|
+
read: ["Reading", "Read", "Read failed"],
|
|
566
|
+
search: ["Searching", "Searched", "Search failed"],
|
|
567
|
+
edit: ["Editing", "Edited", "Edit failed"],
|
|
568
|
+
command: ["Running command", "Ran command", "Command failed"],
|
|
569
|
+
test: ["Running tests", "Ran tests", "Tests failed"],
|
|
570
|
+
web: ["Browsing", "Browsed", "Browser action failed"],
|
|
571
|
+
agent: ["Starting agent", "Started agent", "Agent failed"]
|
|
572
|
+
};
|
|
573
|
+
const position = status === "pending" ? 0 : status === "error" ? 2 : 1;
|
|
574
|
+
if (actions[category]) return actions[category][position];
|
|
575
|
+
const label = entry.label?.split(/__|\//).at(-1)?.replaceAll(/[_-]+/g, " ") || "Tool";
|
|
576
|
+
return status === "error" ? `${label} failed` : label;
|
|
577
|
+
}
|
|
578
|
+
function argumentLabel(key) {
|
|
579
|
+
const labels = { cmd: "Command", command: "Command", cwd: "Working directory", file_path: "File", target_file: "File", path: "Path", query: "Query", pattern: "Pattern", url: "URL" };
|
|
580
|
+
return labels[key] ?? key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase());
|
|
581
|
+
}
|
|
582
|
+
function argumentRows(argumentsText) {
|
|
583
|
+
if (!argumentsText) return [];
|
|
584
|
+
try {
|
|
585
|
+
const value = JSON.parse(argumentsText);
|
|
586
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
587
|
+
return Object.entries(value).map(([key, item]) => ({
|
|
588
|
+
key,
|
|
589
|
+
label: argumentLabel(key),
|
|
590
|
+
value: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
591
|
+
}));
|
|
592
|
+
}
|
|
593
|
+
} catch {
|
|
594
|
+
}
|
|
595
|
+
return [{ key: "arguments", label: "Details", value: argumentsText }];
|
|
596
|
+
}
|
|
524
597
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
525
598
|
if (entry.role === "request") return /* @__PURE__ */ jsx3(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
526
599
|
if (entry.role === "reasoning") {
|
|
@@ -537,35 +610,37 @@ function TranscriptEntry({ entry, state, adapter }) {
|
|
|
537
610
|
] });
|
|
538
611
|
}
|
|
539
612
|
function ToolRow({ entry, workspace }) {
|
|
540
|
-
const [open, setOpen] = useState2(entry.status === "pending");
|
|
541
|
-
const detailId = useId();
|
|
542
613
|
const target = compactToolTarget(toolTarget(entry.arguments), workspace);
|
|
543
614
|
const hasDetail = Boolean(entry.arguments || entry.resultText);
|
|
544
615
|
const category = toolCategory(entry);
|
|
545
|
-
|
|
546
|
-
/* @__PURE__ */
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
entry.
|
|
563
|
-
entry.
|
|
616
|
+
const summary = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
617
|
+
/* @__PURE__ */ jsx3(ToolIcon, { category }),
|
|
618
|
+
/* @__PURE__ */ jsx3("strong", { children: toolAction(entry, category) }),
|
|
619
|
+
target ? /* @__PURE__ */ jsx3("code", { class: "scui-tool-target", title: toolTarget(entry.arguments), children: target }) : null,
|
|
620
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
621
|
+
/* @__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" }),
|
|
622
|
+
hasDetail ? /* @__PURE__ */ jsx3("span", { class: "scui-tool-chevron", "aria-hidden": "true", children: "\u203A" }) : null
|
|
623
|
+
] });
|
|
624
|
+
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 }) });
|
|
625
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: [
|
|
626
|
+
/* @__PURE__ */ jsx3("summary", { class: "scui-tool-head", children: summary }),
|
|
627
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-tool-detail", children: [
|
|
628
|
+
entry.arguments ? /* @__PURE__ */ jsx3("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
629
|
+
/* @__PURE__ */ jsx3("dt", { children: row.label }),
|
|
630
|
+
/* @__PURE__ */ jsx3("dd", { children: /* @__PURE__ */ jsx3("pre", { children: row.value }) })
|
|
631
|
+
] }, row.key)) }) : null,
|
|
632
|
+
entry.resultText ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
633
|
+
/* @__PURE__ */ jsx3("strong", { children: entry.status === "error" ? "Error" : "Result" }),
|
|
634
|
+
/* @__PURE__ */ jsxs2("pre", { "data-error": entry.status === "error", children: [
|
|
635
|
+
entry.resultText,
|
|
636
|
+
entry.truncated ? "\n[truncated]" : ""
|
|
637
|
+
] })
|
|
564
638
|
] }) : null
|
|
565
|
-
] })
|
|
639
|
+
] })
|
|
566
640
|
] });
|
|
567
641
|
}
|
|
568
642
|
function ActivityGroup({ entries, state }) {
|
|
643
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx3("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx3(ToolRow, { entry: entries[0], workspace: state.workspace }) });
|
|
569
644
|
const active = entries.some((entry) => entry.status === "pending");
|
|
570
645
|
const [open, setOpen] = useState2(active);
|
|
571
646
|
const id = useId();
|
|
@@ -578,7 +653,7 @@ function ActivityGroup({ entries, state }) {
|
|
|
578
653
|
/* @__PURE__ */ jsx3("strong", { children: activitySummary(entries) }),
|
|
579
654
|
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
580
655
|
/* @__PURE__ */ jsxs2("small", { children: [
|
|
581
|
-
entries.filter((entry) => entry.status
|
|
656
|
+
entries.filter((entry) => entry.status !== "pending").length,
|
|
582
657
|
"/",
|
|
583
658
|
entries.length
|
|
584
659
|
] })
|
|
@@ -942,9 +1017,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
942
1017
|
}
|
|
943
1018
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels }) {
|
|
944
1019
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1020
|
+
const startableKey = startable.map((item) => item.id).join("\0");
|
|
945
1021
|
const [harness, setHarness] = useState4(startable[0]?.id ?? "");
|
|
946
1022
|
const [draft, setDraft] = useState4("");
|
|
947
1023
|
const [starting, setStarting] = useState4(false);
|
|
1024
|
+
useEffect4(() => {
|
|
1025
|
+
if (!startable.some((item) => item.id === harness)) setHarness(startable[0]?.id ?? "");
|
|
1026
|
+
}, [harness, startableKey]);
|
|
948
1027
|
useEffect4(() => {
|
|
949
1028
|
if (starting && (state.busy || state.transcript.length)) onStarted();
|
|
950
1029
|
}, [onStarted, starting, state.busy, state.transcript.length]);
|
package/messenger.mjs
CHANGED
|
@@ -329,9 +329,12 @@ function compactToolTarget(target, workspace) {
|
|
|
329
329
|
function activitySummary(entries) {
|
|
330
330
|
const counts = /* @__PURE__ */ new Map();
|
|
331
331
|
for (const entry of entries) counts.set(toolCategory(entry), (counts.get(toolCategory(entry)) ?? 0) + 1);
|
|
332
|
+
const failed = entries.filter((entry) => entry.status === "error").length;
|
|
333
|
+
const pending = entries.filter((entry) => entry.status === "pending").length;
|
|
334
|
+
if (pending) return `${entries.length} actions in progress`;
|
|
335
|
+
if (failed) return `${entries.length} actions \xB7 ${failed} failed`;
|
|
332
336
|
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 ")}`;
|
|
337
|
+
return `${entries.length} actions`;
|
|
335
338
|
}
|
|
336
339
|
function canContinueHere(state) {
|
|
337
340
|
if (state.mode !== "mirror" || state.canSend) return false;
|
|
@@ -470,7 +473,7 @@ function Markdown({ value }) {
|
|
|
470
473
|
}
|
|
471
474
|
|
|
472
475
|
// src/conversation.jsx
|
|
473
|
-
import { jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
476
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
474
477
|
function LoadingStatus({ state, compact = false }) {
|
|
475
478
|
const copy = {
|
|
476
479
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -518,6 +521,76 @@ function ContextDisclosure({ context }) {
|
|
|
518
521
|
] }, item.id ?? index)) })
|
|
519
522
|
] });
|
|
520
523
|
}
|
|
524
|
+
var TOOL_ICONS = {
|
|
525
|
+
read: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
526
|
+
/* @__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" }),
|
|
527
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
528
|
+
] }),
|
|
529
|
+
search: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
530
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
531
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.5 11.5 3 3" })
|
|
532
|
+
] }),
|
|
533
|
+
edit: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
534
|
+
/* @__PURE__ */ jsx3("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
535
|
+
/* @__PURE__ */ jsx3("path", { d: "m10 5 3 3" })
|
|
536
|
+
] }),
|
|
537
|
+
command: () => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
538
|
+
test: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
539
|
+
/* @__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" }),
|
|
540
|
+
/* @__PURE__ */ jsx3("path", { d: "M5 2.5h8" })
|
|
541
|
+
] }),
|
|
542
|
+
web: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
543
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
544
|
+
/* @__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" })
|
|
545
|
+
] }),
|
|
546
|
+
agent: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
547
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
548
|
+
/* @__PURE__ */ jsx3("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
549
|
+
] }),
|
|
550
|
+
other: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
551
|
+
/* @__PURE__ */ jsx3("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
552
|
+
/* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
553
|
+
] })
|
|
554
|
+
};
|
|
555
|
+
function ToolIcon({ category }) {
|
|
556
|
+
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
557
|
+
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, {}) });
|
|
558
|
+
}
|
|
559
|
+
function toolAction(entry, category) {
|
|
560
|
+
const status = entry.status ?? "completed";
|
|
561
|
+
const actions = {
|
|
562
|
+
read: ["Reading", "Read", "Read failed"],
|
|
563
|
+
search: ["Searching", "Searched", "Search failed"],
|
|
564
|
+
edit: ["Editing", "Edited", "Edit failed"],
|
|
565
|
+
command: ["Running command", "Ran command", "Command failed"],
|
|
566
|
+
test: ["Running tests", "Ran tests", "Tests failed"],
|
|
567
|
+
web: ["Browsing", "Browsed", "Browser action failed"],
|
|
568
|
+
agent: ["Starting agent", "Started agent", "Agent failed"]
|
|
569
|
+
};
|
|
570
|
+
const position = status === "pending" ? 0 : status === "error" ? 2 : 1;
|
|
571
|
+
if (actions[category]) return actions[category][position];
|
|
572
|
+
const label = entry.label?.split(/__|\//).at(-1)?.replaceAll(/[_-]+/g, " ") || "Tool";
|
|
573
|
+
return status === "error" ? `${label} failed` : label;
|
|
574
|
+
}
|
|
575
|
+
function argumentLabel(key) {
|
|
576
|
+
const labels = { cmd: "Command", command: "Command", cwd: "Working directory", file_path: "File", target_file: "File", path: "Path", query: "Query", pattern: "Pattern", url: "URL" };
|
|
577
|
+
return labels[key] ?? key.replaceAll(/[_-]+/g, " ").replace(/^./, (letter) => letter.toLocaleUpperCase());
|
|
578
|
+
}
|
|
579
|
+
function argumentRows(argumentsText) {
|
|
580
|
+
if (!argumentsText) return [];
|
|
581
|
+
try {
|
|
582
|
+
const value = JSON.parse(argumentsText);
|
|
583
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
584
|
+
return Object.entries(value).map(([key, item]) => ({
|
|
585
|
+
key,
|
|
586
|
+
label: argumentLabel(key),
|
|
587
|
+
value: typeof item === "string" ? item : JSON.stringify(item, null, 2)
|
|
588
|
+
}));
|
|
589
|
+
}
|
|
590
|
+
} catch {
|
|
591
|
+
}
|
|
592
|
+
return [{ key: "arguments", label: "Details", value: argumentsText }];
|
|
593
|
+
}
|
|
521
594
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
522
595
|
if (entry.role === "request") return /* @__PURE__ */ jsx3(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
523
596
|
if (entry.role === "reasoning") {
|
|
@@ -534,35 +607,37 @@ function TranscriptEntry({ entry, state, adapter }) {
|
|
|
534
607
|
] });
|
|
535
608
|
}
|
|
536
609
|
function ToolRow({ entry, workspace }) {
|
|
537
|
-
const [open, setOpen] = useState2(entry.status === "pending");
|
|
538
|
-
const detailId = useId();
|
|
539
610
|
const target = compactToolTarget(toolTarget(entry.arguments), workspace);
|
|
540
611
|
const hasDetail = Boolean(entry.arguments || entry.resultText);
|
|
541
612
|
const category = toolCategory(entry);
|
|
542
|
-
|
|
543
|
-
/* @__PURE__ */
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
entry.
|
|
560
|
-
entry.
|
|
613
|
+
const summary = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
614
|
+
/* @__PURE__ */ jsx3(ToolIcon, { category }),
|
|
615
|
+
/* @__PURE__ */ jsx3("strong", { children: toolAction(entry, category) }),
|
|
616
|
+
target ? /* @__PURE__ */ jsx3("code", { class: "scui-tool-target", title: toolTarget(entry.arguments), children: target }) : null,
|
|
617
|
+
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
618
|
+
/* @__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" }),
|
|
619
|
+
hasDetail ? /* @__PURE__ */ jsx3("span", { class: "scui-tool-chevron", "aria-hidden": "true", children: "\u203A" }) : null
|
|
620
|
+
] });
|
|
621
|
+
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 }) });
|
|
622
|
+
return /* @__PURE__ */ jsxs2("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: [
|
|
623
|
+
/* @__PURE__ */ jsx3("summary", { class: "scui-tool-head", children: summary }),
|
|
624
|
+
/* @__PURE__ */ jsxs2("div", { class: "scui-tool-detail", children: [
|
|
625
|
+
entry.arguments ? /* @__PURE__ */ jsx3("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs2("div", { children: [
|
|
626
|
+
/* @__PURE__ */ jsx3("dt", { children: row.label }),
|
|
627
|
+
/* @__PURE__ */ jsx3("dd", { children: /* @__PURE__ */ jsx3("pre", { children: row.value }) })
|
|
628
|
+
] }, row.key)) }) : null,
|
|
629
|
+
entry.resultText ? /* @__PURE__ */ jsxs2("section", { children: [
|
|
630
|
+
/* @__PURE__ */ jsx3("strong", { children: entry.status === "error" ? "Error" : "Result" }),
|
|
631
|
+
/* @__PURE__ */ jsxs2("pre", { "data-error": entry.status === "error", children: [
|
|
632
|
+
entry.resultText,
|
|
633
|
+
entry.truncated ? "\n[truncated]" : ""
|
|
634
|
+
] })
|
|
561
635
|
] }) : null
|
|
562
|
-
] })
|
|
636
|
+
] })
|
|
563
637
|
] });
|
|
564
638
|
}
|
|
565
639
|
function ActivityGroup({ entries, state }) {
|
|
640
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx3("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx3(ToolRow, { entry: entries[0], workspace: state.workspace }) });
|
|
566
641
|
const active = entries.some((entry) => entry.status === "pending");
|
|
567
642
|
const [open, setOpen] = useState2(active);
|
|
568
643
|
const id = useId();
|
|
@@ -575,7 +650,7 @@ function ActivityGroup({ entries, state }) {
|
|
|
575
650
|
/* @__PURE__ */ jsx3("strong", { children: activitySummary(entries) }),
|
|
576
651
|
/* @__PURE__ */ jsx3("span", { class: "scui-spacer" }),
|
|
577
652
|
/* @__PURE__ */ jsxs2("small", { children: [
|
|
578
|
-
entries.filter((entry) => entry.status
|
|
653
|
+
entries.filter((entry) => entry.status !== "pending").length,
|
|
579
654
|
"/",
|
|
580
655
|
entries.length
|
|
581
656
|
] })
|
|
@@ -939,9 +1014,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
939
1014
|
}
|
|
940
1015
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels }) {
|
|
941
1016
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1017
|
+
const startableKey = startable.map((item) => item.id).join("\0");
|
|
942
1018
|
const [harness, setHarness] = useState4(startable[0]?.id ?? "");
|
|
943
1019
|
const [draft, setDraft] = useState4("");
|
|
944
1020
|
const [starting, setStarting] = useState4(false);
|
|
1021
|
+
useEffect4(() => {
|
|
1022
|
+
if (!startable.some((item) => item.id === harness)) setHarness(startable[0]?.id ?? "");
|
|
1023
|
+
}, [harness, startableKey]);
|
|
945
1024
|
useEffect4(() => {
|
|
946
1025
|
if (starting && (state.busy || state.transcript.length)) onStarted();
|
|
947
1026
|
}, [onStarted, starting, state.busy, state.transcript.length]);
|
package/package.json
CHANGED
package/sessions.mjs
CHANGED
|
@@ -97,7 +97,7 @@ markdown.renderer.rules.link_open = (tokens, index, options, env, self) => {
|
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
// src/conversation.jsx
|
|
100
|
-
import { jsx as jsx2, jsxs } from "preact/jsx-runtime";
|
|
100
|
+
import { Fragment, jsx as jsx2, jsxs } from "preact/jsx-runtime";
|
|
101
101
|
function LoadingStatus({ state, compact = false }) {
|
|
102
102
|
const copy = {
|
|
103
103
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
package/styles.css
CHANGED
|
@@ -129,13 +129,16 @@
|
|
|
129
129
|
.scui-truncated { display:block; margin-top:5px; color:var(--scui-warning) }
|
|
130
130
|
.scui-notice { align-self:center; max-width:90%; padding:5px 8px; border-radius:7px; background:var(--scui-bg-raised); color:var(--scui-muted); font-size:10.5px; text-align:center }
|
|
131
131
|
|
|
132
|
-
.scui-activity {
|
|
133
|
-
.scui-activity-head,.scui-tool-head { display:flex; align-items:center; gap:6px; width:100%; min-height:
|
|
134
|
-
.scui-activity-head strong { font-size:
|
|
132
|
+
.scui-activity { min-width:0; color:var(--scui-muted) }
|
|
133
|
+
.scui-activity-head,.scui-tool-head { display:flex; align-items:center; gap:6px; box-sizing:border-box; width:100%; min-height:27px; padding:0 3px; border:0; background:transparent; color:inherit; text-align:left }
|
|
134
|
+
.scui-activity-head { cursor:pointer }.scui-activity-head strong { color:var(--scui-muted); font-size:10.5px; font-weight:600 }.scui-activity-head small { color:var(--scui-muted) }.scui-spacer { flex:1 }
|
|
135
135
|
.scui-fold { font-size:16px; transition:transform 120ms }.scui-fold[data-open="true"] { transform:rotate(90deg) }
|
|
136
|
-
.scui-
|
|
137
|
-
.scui-tool
|
|
138
|
-
.scui-tool-
|
|
136
|
+
.scui-activity:not([data-single="true"]) > div { margin-left:9px; padding-left:7px; border-left:1px solid var(--scui-border) }
|
|
137
|
+
.scui-tool { min-width:0 }.scui-tool summary { list-style:none }.scui-tool summary::-webkit-details-marker { display:none }.scui-tool-head { cursor:default }.scui-tool > summary.scui-tool-head { cursor:pointer }.scui-tool-icon { flex:0 0 14px; width:14px; height:14px; color:var(--scui-muted) }.scui-tool-head strong { flex:none; color:var(--scui-fg); font-size:10.5px; font-weight:600; white-space:nowrap }
|
|
138
|
+
.scui-tool-target { min-width:0; overflow:hidden; padding:0; background:transparent; color:var(--scui-muted); font:10px ui-monospace,SFMono-Regular,Menlo,monospace; text-overflow:ellipsis; white-space:nowrap }
|
|
139
|
+
.scui-tool-status { display:grid; flex:0 0 13px; width:13px; height:13px; place-items:center; color:var(--scui-success); font-size:10px }.scui-tool-status[data-status="pending"] { color:var(--scui-accent) }.scui-tool-status[data-status="error"] { color:var(--scui-danger); font-size:13px }.scui-tool-status i { box-sizing:border-box; width:11px; height:11px; border:1.5px solid currentColor; border-right-color:transparent; border-radius:50%; animation:scui-spin .75s linear infinite }
|
|
140
|
+
.scui-tool-chevron { flex:none; font-size:15px; line-height:1; transition:transform 120ms }.scui-tool[open] .scui-tool-chevron { transform:rotate(90deg) }
|
|
141
|
+
.scui-tool-detail { display:grid; gap:7px; max-height:220px; margin:2px 0 6px 20px; padding:8px; overflow:auto; border-left:1px solid var(--scui-border); background:var(--scui-bg-raised); font-size:10px }.scui-tool-detail dl,.scui-tool-detail section,.scui-tool-detail dl > div { display:grid; gap:3px; margin:0 }.scui-tool-detail dt,.scui-tool-detail section > strong { color:var(--scui-muted); font-weight:600 }.scui-tool-detail dd { min-width:0; margin:0 }.scui-tool-detail pre { margin:0; overflow-wrap:anywhere; color:var(--scui-fg); font:10px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace; white-space:pre-wrap }.scui-tool-detail pre[data-error="true"] { color:var(--scui-danger) }
|
|
139
142
|
.scui-request { padding:9px; border:1px solid var(--scui-warning); border-radius:9px; background:color-mix(in srgb,var(--scui-warning) 8%,var(--scui-bg)) }.scui-request-actions { display:flex; flex-wrap:wrap; gap:5px }.scui-request-actions button { padding:5px 8px; border:1px solid var(--scui-border-strong); border-radius:6px; background:var(--scui-bg); cursor:pointer }
|
|
140
143
|
.scui-request-done { color:var(--scui-muted); font-size:10.5px }
|
|
141
144
|
.scui-plan > summary { display:flex; justify-content:space-between; padding:6px 8px; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg-raised) }.scui-plan ol { display:grid; gap:4px; box-sizing:border-box; max-height:140px; margin:5px 0 0; padding:7px 8px 7px 25px; overflow:auto; border:1px solid var(--scui-border); border-radius:7px }.scui-plan li[data-status="completed"] { color:var(--scui-fg); text-decoration:line-through }
|