@volter-ai-dev/supercode-ui 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -2
- package/activity.d.ts +2 -0
- package/activity.mjs +941 -0
- package/components.d.ts +4 -0
- package/components.mjs +737 -485
- package/composer.mjs +82 -20
- package/controller.d.ts +4 -0
- package/controller.mjs +19 -0
- package/conversation.mjs +75 -64
- package/core.d.ts +2 -0
- package/core.mjs +85 -2
- package/embed.mjs +338 -149
- package/icon.mjs +1 -1
- package/index.d.ts +66 -2
- package/logo.mjs +11 -6
- package/messenger.mjs +338 -149
- package/package.json +53 -3
- package/react/activity.d.ts +4 -0
- package/react/activity.mjs +941 -0
- package/react/components.mjs +3081 -0
- package/react/composer.d.ts +2 -0
- package/react/composer.mjs +518 -0
- package/react/conversation.d.ts +2 -0
- package/react/conversation.mjs +1330 -0
- package/react/icon.d.ts +2 -0
- package/react/icon.mjs +51 -0
- package/react/index.d.ts +122 -0
- package/react/logo.d.ts +2 -0
- package/react/logo.mjs +92 -0
- package/react/messenger.d.ts +2 -0
- package/react/messenger.mjs +2974 -0
- package/react/sessions.d.ts +2 -0
- package/react/sessions.mjs +429 -0
- package/react/settings.d.ts +2 -0
- package/react/settings.mjs +319 -0
- package/sessions.mjs +48 -28
- package/settings.mjs +170 -69
- package/styles.css +9 -0
package/components.mjs
CHANGED
|
@@ -32,6 +32,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
32
32
|
mode: "none",
|
|
33
33
|
strategy: null,
|
|
34
34
|
canSend: false,
|
|
35
|
+
canSteer: false,
|
|
35
36
|
canResume: false,
|
|
36
37
|
continuationModes: Object.freeze([]),
|
|
37
38
|
canBranch: false,
|
|
@@ -719,6 +720,7 @@ function normalizeUiState(value) {
|
|
|
719
720
|
mode: MODES.has(raw.mode) ? raw.mode : "none",
|
|
720
721
|
strategy: STRATEGIES.has(raw.strategy) ? raw.strategy : null,
|
|
721
722
|
canSend: raw.canSend === true,
|
|
723
|
+
canSteer: raw.canSteer === true,
|
|
722
724
|
canResume,
|
|
723
725
|
continuationModes,
|
|
724
726
|
canBranch: raw.canBranch === true,
|
|
@@ -748,7 +750,29 @@ function normalizeUiState(value) {
|
|
|
748
750
|
const startable = item.startable === true;
|
|
749
751
|
const launchModes = Array.isArray(item.launchModes) ? [...new Set(item.launchModes.filter((mode) => mode === "headless" || mode === "terminal"))] : startable ? ["headless"] : [];
|
|
750
752
|
const preferredLaunchMode = launchModes.includes(item.preferredLaunchMode) ? item.preferredLaunchMode : launchModes[0] ?? null;
|
|
751
|
-
|
|
753
|
+
const capabilities = record(item.capabilities);
|
|
754
|
+
return [{
|
|
755
|
+
id: item.id,
|
|
756
|
+
label: string(item.label, harnessDisplayName(item.id)),
|
|
757
|
+
installed: item.installed === true,
|
|
758
|
+
startable,
|
|
759
|
+
reason: typeof item.reason === "string" ? boundedString(item.reason) : null,
|
|
760
|
+
auth: ["ready", "configured", "required", "unknown"].includes(item.auth) ? item.auth : "unknown",
|
|
761
|
+
runtime: ["ready", "degraded", "unavailable"].includes(item.runtime) ? item.runtime : startable ? "ready" : "unavailable",
|
|
762
|
+
protocol: boundedString(item.protocol, 100),
|
|
763
|
+
repair: typeof item.repair === "string" ? boundedString(item.repair, 4e3) : null,
|
|
764
|
+
capabilities: {
|
|
765
|
+
start: capabilities?.start === true,
|
|
766
|
+
resume: capabilities?.resume === true,
|
|
767
|
+
attach: capabilities?.attach === true,
|
|
768
|
+
send: capabilities?.send === true,
|
|
769
|
+
interrupt: capabilities?.interrupt === true,
|
|
770
|
+
steer: capabilities?.steer === true,
|
|
771
|
+
respond: capabilities?.respond === true
|
|
772
|
+
},
|
|
773
|
+
launchModes,
|
|
774
|
+
preferredLaunchMode
|
|
775
|
+
}];
|
|
752
776
|
}) : [],
|
|
753
777
|
history: { sessionLimit: number(history?.sessionLimit), hasMoreSessions: history?.hasMoreSessions === true, transcriptLimit: number(history?.transcriptLimit, 120), hasEarlier: history?.hasEarlier === true },
|
|
754
778
|
savedDraft: string(raw.savedDraft),
|
|
@@ -779,6 +803,56 @@ function sessionActivity(state, row) {
|
|
|
779
803
|
if (row.live || row.runtimeStatus === "idle") return "recent";
|
|
780
804
|
return "idle";
|
|
781
805
|
}
|
|
806
|
+
var ACTIVITY_PRIORITY = Object.freeze({
|
|
807
|
+
"needs-input": 70,
|
|
808
|
+
failed: 60,
|
|
809
|
+
working: 50,
|
|
810
|
+
unseen: 40,
|
|
811
|
+
finished: 30,
|
|
812
|
+
running: 20,
|
|
813
|
+
recent: 10,
|
|
814
|
+
idle: 0
|
|
815
|
+
});
|
|
816
|
+
function activityDetail(activity, preview, pill) {
|
|
817
|
+
if (preview) return preview;
|
|
818
|
+
if (activity === "needs-input") return "Needs input";
|
|
819
|
+
if (activity === "failed") return "Run failed";
|
|
820
|
+
if (activity === "working") return "Working\u2026";
|
|
821
|
+
if (activity === "finished") return "Finished";
|
|
822
|
+
if (activity === "unseen") return "New reply";
|
|
823
|
+
if (activity === "running") return "Session is running";
|
|
824
|
+
return pill || "Agent chats";
|
|
825
|
+
}
|
|
826
|
+
function projectAgentActivity(value) {
|
|
827
|
+
const state = normalizeUiState(value);
|
|
828
|
+
const attentionByKey = new Map(state.attention.map((item) => [item.key, item]));
|
|
829
|
+
const unreadCount = state.attention.reduce((total, item) => total + (item.unreadCount ?? 1), 0);
|
|
830
|
+
const ranked = state.sessions.map((row, index) => {
|
|
831
|
+
const activity2 = sessionActivity(state, row);
|
|
832
|
+
return {
|
|
833
|
+
row,
|
|
834
|
+
index,
|
|
835
|
+
activity: activity2,
|
|
836
|
+
priority: ACTIVITY_PRIORITY[activity2] ?? 0,
|
|
837
|
+
active: row.active || row.key === state.attached?.key || row.key === state.owned?.key,
|
|
838
|
+
updatedAt: row.previewUpdatedAt ?? row.updatedAt ?? 0
|
|
839
|
+
};
|
|
840
|
+
}).sort((left, right) => right.priority - left.priority || Number(right.active) - Number(left.active) || right.updatedAt - left.updatedAt || left.index - right.index);
|
|
841
|
+
const selected = ranked[0];
|
|
842
|
+
const fallback = state.attached ?? state.owned;
|
|
843
|
+
const harness = selected?.row.harness ?? fallback?.harness ?? state.harness;
|
|
844
|
+
const activity = selected?.activity ?? (state.needsInput ? "needs-input" : state.busy ? "working" : state.startup === "ready" ? "idle" : "recent");
|
|
845
|
+
const attention = selected ? attentionByKey.get(selected.row.key) : null;
|
|
846
|
+
const preview = selected?.row.preview || attention?.preview || "";
|
|
847
|
+
return {
|
|
848
|
+
harness,
|
|
849
|
+
sessionKey: selected?.row.key ?? fallback?.key ?? null,
|
|
850
|
+
title: selected ? sessionDisplayName(selected.row) : fallback ? sessionDisplayName(fallback) : "Agent chats",
|
|
851
|
+
detail: activityDetail(activity, preview, state.pill.label),
|
|
852
|
+
activity,
|
|
853
|
+
unreadCount
|
|
854
|
+
};
|
|
855
|
+
}
|
|
782
856
|
function filterSessions(rows, query) {
|
|
783
857
|
const needle = query.trim().toLocaleLowerCase();
|
|
784
858
|
if (!needle) return [...rows];
|
|
@@ -837,7 +911,7 @@ function canContinueHere(state) {
|
|
|
837
911
|
}
|
|
838
912
|
function operationLabel(operation) {
|
|
839
913
|
if (!operation) return "";
|
|
840
|
-
const labels = { discover: "Refreshing chats\u2026", observe: "Loading recent messages\u2026", attach: "Opening chat\u2026", start: "Starting new chat\u2026", resume: "Continuing here\u2026", join: "Joining live session\u2026", detach: "Detaching to read-only\u2026", branch: "Starting continuation\u2026", reduce: "Reducing context and verifying reversibility\u2026", terminal: "Preparing terminal handoff\u2026", export: "Exporting losslessly\u2026", interrupt: "Stopping agent\u2026", respond: "Sending response\u2026", configureHarness: "Updating harness settings\u2026", loadEarlier: "Loading earlier messages\u2026", loadSessions: "Loading more chats\u2026", refresh: "Retrying\u2026" };
|
|
914
|
+
const labels = { discover: "Refreshing chats\u2026", observe: "Loading recent messages\u2026", attach: "Opening chat\u2026", start: "Starting new chat\u2026", resume: "Continuing here\u2026", join: "Joining live session\u2026", detach: "Detaching to read-only\u2026", branch: "Starting continuation\u2026", reduce: "Reducing context and verifying reversibility\u2026", terminal: "Preparing terminal handoff\u2026", export: "Exporting losslessly\u2026", steer: "Steering agent\u2026", interrupt: "Stopping agent\u2026", respond: "Sending response\u2026", configureHarness: "Updating harness settings\u2026", loadEarlier: "Loading earlier messages\u2026", loadSessions: "Loading more chats\u2026", refresh: "Retrying\u2026" };
|
|
841
915
|
return labels[operation] ?? `${operation.replaceAll("_", " ")}\u2026`;
|
|
842
916
|
}
|
|
843
917
|
function terminalCommand(handoff) {
|
|
@@ -902,7 +976,7 @@ var ICONS = {
|
|
|
902
976
|
function UiIcon({ name, size = 16, class: className = "" }) {
|
|
903
977
|
const Glyph = ICONS[name];
|
|
904
978
|
if (!Glyph) return null;
|
|
905
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
979
|
+
return /* @__PURE__ */ jsx("svg", { className: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Glyph, {}) });
|
|
906
980
|
}
|
|
907
981
|
|
|
908
982
|
// src/context.jsx
|
|
@@ -976,6 +1050,39 @@ function partitionAttachments(value) {
|
|
|
976
1050
|
}
|
|
977
1051
|
return { context, images };
|
|
978
1052
|
}
|
|
1053
|
+
function normalizeAttachmentCandidates(value) {
|
|
1054
|
+
const candidates = [];
|
|
1055
|
+
for (const item of Array.isArray(value) ? value : []) {
|
|
1056
|
+
const context = normalizeContext(item)[0];
|
|
1057
|
+
if (context) {
|
|
1058
|
+
candidates.push(context);
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
const image = normalizeImages(item)[0];
|
|
1062
|
+
if (image) candidates.push(image);
|
|
1063
|
+
}
|
|
1064
|
+
return candidates.slice(0, MAX_CONTEXT_ITEMS + MAX_IMAGE_ITEMS);
|
|
1065
|
+
}
|
|
1066
|
+
function attachmentKey(item) {
|
|
1067
|
+
if (item.id) return `id:${item.id}`;
|
|
1068
|
+
return "detail" in item ? `context:${item.kind ?? ""}\0${item.label}\0${item.detail}` : `image:${item.url}`;
|
|
1069
|
+
}
|
|
1070
|
+
function ContextCandidate({ attachment, attached, onAttach }) {
|
|
1071
|
+
const image = "url" in attachment;
|
|
1072
|
+
return /* @__PURE__ */ jsxs2("button", { type: "button", disabled: attached, "aria-label": `${attached ? "Attached" : "Attach"} ${attachment.label}`, onClick: () => onAttach(attachment), children: [
|
|
1073
|
+
image ? /* @__PURE__ */ jsx2("img", { src: attachment.url, alt: "" }) : /* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 13 }),
|
|
1074
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1075
|
+
/* @__PURE__ */ jsx2("strong", { children: attachment.label }),
|
|
1076
|
+
/* @__PURE__ */ jsx2("small", { children: image ? "Image" : attachment.kind || "Context" })
|
|
1077
|
+
] }),
|
|
1078
|
+
attached ? /* @__PURE__ */ jsx2(UiIcon, { name: "check", size: 13 }) : /* @__PURE__ */ jsx2(UiIcon, { name: "plus", size: 13 })
|
|
1079
|
+
] });
|
|
1080
|
+
}
|
|
1081
|
+
function ContextCandidates({ items, context, images, state, adapter, onAttach, component: Candidate = ContextCandidate }) {
|
|
1082
|
+
if (!items.length) return null;
|
|
1083
|
+
const attached = new Set([...context, ...images].map(attachmentKey));
|
|
1084
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-context-candidates", "aria-label": "Available context", children: items.map((attachment, index) => /* @__PURE__ */ jsx2(Candidate, { value: attachment, attachment, attached: attached.has(attachmentKey(attachment)), state, adapter, onAttach, index }, attachmentKey(attachment))) });
|
|
1085
|
+
}
|
|
979
1086
|
async function imageAttachmentsFromFiles(value) {
|
|
980
1087
|
const files = Array.from(value ?? []).filter((file) => file?.type?.startsWith("image/"));
|
|
981
1088
|
if (files.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images at a time.`);
|
|
@@ -993,7 +1100,7 @@ async function imageAttachmentsFromFiles(value) {
|
|
|
993
1100
|
}
|
|
994
1101
|
function ContextTray({ items, onRemove }) {
|
|
995
1102
|
if (!items.length) return null;
|
|
996
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1103
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
997
1104
|
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
998
1105
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
999
1106
|
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
@@ -1001,7 +1108,7 @@ function ContextTray({ items, onRemove }) {
|
|
|
1001
1108
|
}
|
|
1002
1109
|
function ImageTray({ items, onRemove }) {
|
|
1003
1110
|
if (!items.length) return null;
|
|
1004
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1111
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-images", "aria-label": "Attached images", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
1005
1112
|
/* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }),
|
|
1006
1113
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
1007
1114
|
onRemove ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove image ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) }) : null
|
|
@@ -1079,7 +1186,7 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1079
1186
|
"dialog",
|
|
1080
1187
|
{
|
|
1081
1188
|
ref: dialog,
|
|
1082
|
-
|
|
1189
|
+
className: "scui-image-viewer",
|
|
1083
1190
|
"aria-label": `Image preview: ${item.label}`,
|
|
1084
1191
|
onClose,
|
|
1085
1192
|
onClick: (event) => {
|
|
@@ -1107,19 +1214,19 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1107
1214
|
] })
|
|
1108
1215
|
] }),
|
|
1109
1216
|
/* @__PURE__ */ jsxs2("figure", { children: [
|
|
1110
|
-
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", {
|
|
1217
|
+
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "alert", children: [
|
|
1111
1218
|
/* @__PURE__ */ jsx2(UiIcon, { name: "image", size: 28 }),
|
|
1112
1219
|
/* @__PURE__ */ jsx2("strong", { children: "Could not load image" }),
|
|
1113
1220
|
/* @__PURE__ */ jsx2("small", { children: resolution.message }),
|
|
1114
1221
|
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => resolve(item, true), children: "Retry" })
|
|
1115
|
-
] }) : /* @__PURE__ */ jsxs2("div", {
|
|
1116
|
-
/* @__PURE__ */ jsx2("i", {
|
|
1222
|
+
] }) : /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "status", children: [
|
|
1223
|
+
/* @__PURE__ */ jsx2("i", { className: "scui-control-spinner" }),
|
|
1117
1224
|
/* @__PURE__ */ jsx2("strong", { children: "Loading image\u2026" }),
|
|
1118
1225
|
/* @__PURE__ */ jsx2("small", { children: "The original stays out of the transcript payload." })
|
|
1119
1226
|
] }),
|
|
1120
1227
|
items.length > 1 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1121
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1122
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1228
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-previous", "aria-label": "Previous image", onClick: () => move(-1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) }),
|
|
1229
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-next", "aria-label": "Next image", onClick: () => move(1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) })
|
|
1123
1230
|
] }) : null
|
|
1124
1231
|
] })
|
|
1125
1232
|
]
|
|
@@ -1136,7 +1243,7 @@ function MessageImages({ items, adapter }) {
|
|
|
1136
1243
|
requestAnimationFrame(() => opener.current?.focus({ preventScroll: true }));
|
|
1137
1244
|
};
|
|
1138
1245
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1139
|
-
/* @__PURE__ */ jsx2("div", {
|
|
1246
|
+
/* @__PURE__ */ jsx2("div", { className: "scui-message-images", "aria-label": "Message images", children: items.map((item, index) => item.url ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `View image ${item.label}`, onClick: (event) => {
|
|
1140
1247
|
opener.current = event.currentTarget;
|
|
1141
1248
|
setActive(viewable.indexOf(item));
|
|
1142
1249
|
}, children: /* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }) }, item.id ?? `${item.label}:${index}`) : item.reference && adapter?.resolveImage ? /* @__PURE__ */ jsxs2("button", { type: "button", "data-lazy": "true", "aria-label": `Load image ${item.label}`, onClick: (event) => {
|
|
@@ -1159,6 +1266,16 @@ function MessageImages({ items, adapter }) {
|
|
|
1159
1266
|
] });
|
|
1160
1267
|
}
|
|
1161
1268
|
|
|
1269
|
+
// src/intent.js
|
|
1270
|
+
var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
|
|
1271
|
+
async function dispatchConfirmedIntent(adapter, intent) {
|
|
1272
|
+
if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
|
|
1273
|
+
const confirmed = await adapter.confirmIntent(intent);
|
|
1274
|
+
if (!confirmed) return;
|
|
1275
|
+
}
|
|
1276
|
+
return adapter.onIntent(intent);
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1162
1279
|
// src/textarea.js
|
|
1163
1280
|
import { useLayoutEffect } from "preact/hooks";
|
|
1164
1281
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -1185,28 +1302,29 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
1185
1302
|
const terminal = resume && state.continuationModes?.includes("terminal");
|
|
1186
1303
|
const join = state.canAttach;
|
|
1187
1304
|
const branch = state.canBranch;
|
|
1188
|
-
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", {
|
|
1305
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { className: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
1189
1306
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1190
1307
|
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
1191
1308
|
] }) });
|
|
1192
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1309
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-continuation", children: [
|
|
1193
1310
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1194
1311
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1195
1312
|
/* @__PURE__ */ jsx3("small", { children: join ? "Join the proven live runtime without taking it over." : resume ? `Resume this ${harnessDisplayName(state.harness)} session here.` : "Start an independent continuation." })
|
|
1196
1313
|
] }),
|
|
1197
|
-
/* @__PURE__ */ jsxs3("span", {
|
|
1198
|
-
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => adapter
|
|
1199
|
-
terminal ? /* @__PURE__ */ jsx3("button", { type: "button",
|
|
1314
|
+
/* @__PURE__ */ jsxs3("span", { className: "scui-continuation-actions", children: [
|
|
1315
|
+
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => dispatchConfirmedIntent(adapter, join ? { action: "join" } : resume ? { action: "resume", mode: "headless" } : { action: "branch" }), children: join ? labels.joinLive : resume ? labels.continueHere : labels.forkHere }),
|
|
1316
|
+
terminal ? /* @__PURE__ */ jsx3("button", { type: "button", className: "scui-secondary", disabled: Boolean(state.operation), onClick: () => dispatchConfirmedIntent(adapter, { action: "resume", mode: "terminal" }), children: labels.continueWithTerminal ?? DEFAULT_LABELS.continueWithTerminal }) : null
|
|
1200
1317
|
] })
|
|
1201
1318
|
] });
|
|
1202
1319
|
}
|
|
1203
|
-
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
1320
|
+
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, contextCandidates = [], components = {}, onPending, onDraftRestored }) {
|
|
1204
1321
|
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
1205
1322
|
const [draft, setDraft] = useState2(remembered.draft);
|
|
1206
1323
|
const [context, setContext] = useState2(remembered.context ?? []);
|
|
1207
1324
|
const [images, setImages] = useState2(remembered.images ?? []);
|
|
1208
1325
|
const [queue, setQueue] = useState2((remembered.queue ?? []).map((item) => ({ ...item, context: item.context ?? [], images: item.images ?? [] })));
|
|
1209
1326
|
const [dispatching, setDispatching] = useState2(false);
|
|
1327
|
+
const [steering, setSteering] = useState2(false);
|
|
1210
1328
|
const [picking, setPicking] = useState2(false);
|
|
1211
1329
|
const [dragging, setDragging] = useState2(false);
|
|
1212
1330
|
const [pickerError, setPickerError] = useState2(null);
|
|
@@ -1221,8 +1339,10 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1221
1339
|
remember(draft, context, images, next);
|
|
1222
1340
|
return next;
|
|
1223
1341
|
});
|
|
1224
|
-
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
1225
|
-
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching;
|
|
1342
|
+
const queueBlocked = state.busy || pendingStatus !== null || dispatching || steering;
|
|
1343
|
+
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching || steering;
|
|
1344
|
+
const steerAvailable = state.busy && state.canSteer && !steering && pendingStatus === null;
|
|
1345
|
+
const canSteerDraft = steerAvailable && Boolean(draft.trim()) && context.length === 0 && images.length === 0;
|
|
1226
1346
|
useEffect2(() => {
|
|
1227
1347
|
if (!queueBlocked && state.canSend && queue.length) {
|
|
1228
1348
|
const [next, ...rest] = queue;
|
|
@@ -1274,6 +1394,14 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1274
1394
|
});
|
|
1275
1395
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
1276
1396
|
};
|
|
1397
|
+
const attachCandidate = (picked) => {
|
|
1398
|
+
const attachments = partitionAttachments(picked);
|
|
1399
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
1400
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
1401
|
+
setContext(nextContext);
|
|
1402
|
+
setImages(nextImages);
|
|
1403
|
+
remember(draft, nextContext, nextImages, queue);
|
|
1404
|
+
};
|
|
1277
1405
|
const addImageFiles = (value, source) => {
|
|
1278
1406
|
const allFiles = Array.from(value ?? []);
|
|
1279
1407
|
if (!allFiles.length) return false;
|
|
@@ -1302,9 +1430,17 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1302
1430
|
setDragging(false);
|
|
1303
1431
|
if (addImageFiles(event.dataTransfer?.files, "drop")) event.preventDefault();
|
|
1304
1432
|
};
|
|
1305
|
-
const send = () => {
|
|
1433
|
+
const send = (forceQueue = false) => {
|
|
1306
1434
|
const text = draft.trim();
|
|
1307
1435
|
if (!text && !images.length) return;
|
|
1436
|
+
if (canSteerDraft && !forceQueue) {
|
|
1437
|
+
setSteering(true);
|
|
1438
|
+
Promise.resolve(adapter.onIntent({ action: "steer", text })).then(() => {
|
|
1439
|
+
setDraft("");
|
|
1440
|
+
remember("", context, images, queue);
|
|
1441
|
+
}, (error) => setPickerError(error instanceof Error ? error.message : "Could not steer the active turn.")).finally(() => setSteering(false));
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1308
1444
|
const message = { text, context, images };
|
|
1309
1445
|
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
1310
1446
|
else if (state.canSend) {
|
|
@@ -1317,8 +1453,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1317
1453
|
setImages([]);
|
|
1318
1454
|
remember("", [], [], queuesNewMessage ? [...queue, message] : queue);
|
|
1319
1455
|
};
|
|
1320
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1321
|
-
queue.length ? /* @__PURE__ */ jsxs3("div", {
|
|
1456
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-compose", children: [
|
|
1457
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { className: "scui-queue", children: [
|
|
1322
1458
|
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
1323
1459
|
queue.length,
|
|
1324
1460
|
" queued"
|
|
@@ -1334,6 +1470,7 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1334
1470
|
/* @__PURE__ */ jsx3("button", { type: "button", "aria-label": `Remove queued message ${index + 1}`, onClick: () => updateQueue((items) => items.filter((_, itemIndex) => itemIndex !== index)), children: /* @__PURE__ */ jsx3(UiIcon, { name: "close", size: 13 }) })
|
|
1335
1471
|
] }, `${index}:${item.text}`))
|
|
1336
1472
|
] }) : null,
|
|
1473
|
+
/* @__PURE__ */ jsx3(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }),
|
|
1337
1474
|
/* @__PURE__ */ jsx3(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
1338
1475
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1339
1476
|
remember(draft, context, next, queue);
|
|
@@ -1344,8 +1481,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1344
1481
|
remember(draft, next, images, queue);
|
|
1345
1482
|
return next;
|
|
1346
1483
|
}) }),
|
|
1347
|
-
pickerError ? /* @__PURE__ */ jsx3("small", {
|
|
1348
|
-
/* @__PURE__ */ jsxs3("div", {
|
|
1484
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
1485
|
+
/* @__PURE__ */ jsxs3("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
1349
1486
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
1350
1487
|
event.preventDefault();
|
|
1351
1488
|
setDragging(true);
|
|
@@ -1355,8 +1492,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1355
1492
|
}, onDragLeave: (event) => {
|
|
1356
1493
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
1357
1494
|
}, onDrop: dropImages, children: [
|
|
1358
|
-
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", {
|
|
1359
|
-
/* @__PURE__ */ jsx3("textarea", { ref: textarea, rows: 1, "aria-label": `Message ${harnessDisplayName(state.harness) || "agent"}`, placeholder: state.startup !== "ready" ? "Connecting\u2026" : pendingStatus === "failed" ? "Retry or edit the unsent message\u2026" : pendingStatus === "editing" ? "Edit and resend\u2026" : queueBlocked ? "Queue a follow-up\u2026" : labels.askAgent, value: draft, disabled: state.mode !== "control" && !state.canSend, onPaste: pasteImages, onInput: (event) => {
|
|
1495
|
+
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", { className: "scui-attach", type: "button", "aria-label": "Attach files or images", disabled: picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS, onClick: pickContext, children: picking ? /* @__PURE__ */ jsx3("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx3(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
1496
|
+
/* @__PURE__ */ jsx3("textarea", { ref: textarea, rows: 1, "aria-label": `Message ${harnessDisplayName(state.harness) || "agent"}`, placeholder: state.startup !== "ready" ? "Connecting\u2026" : pendingStatus === "failed" ? "Retry or edit the unsent message\u2026" : pendingStatus === "editing" ? "Edit and resend\u2026" : steerAvailable && context.length === 0 && images.length === 0 ? "Redirect the current turn\u2026" : queueBlocked ? "Queue a follow-up\u2026" : labels.askAgent, value: draft, disabled: state.mode !== "control" && !state.canSend, onPaste: pasteImages, onInput: (event) => {
|
|
1360
1497
|
const value = event.currentTarget.value;
|
|
1361
1498
|
setDraft(value);
|
|
1362
1499
|
remember(value, context, images, queue);
|
|
@@ -1367,21 +1504,129 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1367
1504
|
}
|
|
1368
1505
|
} }),
|
|
1369
1506
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1370
|
-
state.busy ? /* @__PURE__ */ jsx3("button", {
|
|
1371
|
-
/* @__PURE__ */ jsx3("button", {
|
|
1507
|
+
state.busy ? /* @__PURE__ */ jsx3("button", { className: "scui-stop", type: "button", "aria-label": "Stop agent", disabled: !state.canInterrupt, onClick: () => adapter.onIntent({ action: "interrupt" }), children: /* @__PURE__ */ jsx3(UiIcon, { name: "stop", size: 15 }) }) : null,
|
|
1508
|
+
canSteerDraft ? /* @__PURE__ */ jsx3("button", { className: "scui-queue-send", type: "button", "aria-label": "Queue follow-up instead", onClick: () => send(true), children: /* @__PURE__ */ jsx3(UiIcon, { name: "plus", size: 15 }) }) : null,
|
|
1509
|
+
/* @__PURE__ */ jsx3("button", { className: "scui-send", type: "button", "aria-label": canSteerDraft ? "Steer current turn" : queuesNewMessage ? "Queue message" : "Send message", disabled: steering || !draft.trim() && !images.length || !queuesNewMessage && !state.canSend, onClick: () => send(), children: steering ? /* @__PURE__ */ jsx3("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx3(UiIcon, { name: canSteerDraft ? "send" : queuesNewMessage ? "plus" : "send", size: 17 }) })
|
|
1372
1510
|
] })
|
|
1373
1511
|
] })
|
|
1374
1512
|
] });
|
|
1375
1513
|
}
|
|
1376
1514
|
|
|
1515
|
+
// src/logo.jsx
|
|
1516
|
+
import { useEffect as useEffect3 } from "preact/hooks";
|
|
1517
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
1518
|
+
var LOGOS = {
|
|
1519
|
+
"claude-code": {
|
|
1520
|
+
viewBox: "-1 3.5 26 18",
|
|
1521
|
+
paths: [
|
|
1522
|
+
["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z" }]
|
|
1523
|
+
]
|
|
1524
|
+
},
|
|
1525
|
+
codex: {
|
|
1526
|
+
viewBox: "-1 -1 26 26",
|
|
1527
|
+
paths: [
|
|
1528
|
+
["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z" }]
|
|
1529
|
+
]
|
|
1530
|
+
},
|
|
1531
|
+
gemini: {
|
|
1532
|
+
viewBox: "0 0 24 24",
|
|
1533
|
+
paths: [["path", { d: "M12 24C12 17.373 6.627 12 0 12 6.627 12 12 6.627 12 0c0 6.627 5.373 12 12 12-6.627 0-12 5.373-12 12z" }]]
|
|
1534
|
+
},
|
|
1535
|
+
grok: {
|
|
1536
|
+
viewBox: "-1 -1 26 26",
|
|
1537
|
+
paths: [["path", { d: "M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815" }]]
|
|
1538
|
+
},
|
|
1539
|
+
// Canonical mark from block/goose's documentation/static/img/goose.svg.
|
|
1540
|
+
goose: {
|
|
1541
|
+
viewBox: "0 0 45 45",
|
|
1542
|
+
paths: [["path", { d: "M43.2098 39.2492L39.8118 36.4522C37.9646 34.9318 36.3923 33.1051 35.1631 31.0529C33.4647 28.2172 31.1178 25.8243 28.3164 24.071L26.9482 23.2744C26.4794 22.9485 26.1525 22.4405 26.106 21.8675C26.0762 21.4981 26.1647 21.1678 26.3712 20.8771C27.0837 19.873 30.9617 15.6995 31.6365 15.1411C32.5056 14.4228 33.4739 13.8253 34.3724 13.1412C34.5001 13.0438 34.6283 12.9469 34.7545 12.8481C35.0574 12.6088 35.3295 12.3671 35.5458 12.0803C36.5993 10.8604 36.5783 9.82938 36.5783 9.82938C36.4677 9.5534 36.0645 8.69902 35.2449 8.29825C35.9696 8.28406 36.7872 8.55564 37.1582 8.91873C37.6039 8.21947 37.8922 7.76585 38.3404 7.00347C38.4471 6.82241 38.5038 6.48771 38.2998 6.30029C38.1114 6.11287 37.6416 6.01697 37.4606 6.12364C36.4692 6.70693 35.5047 7.33475 34.6351 7.88525C34.6351 7.88525 33.6046 7.86372 32.3842 8.91775C32.097 9.13452 31.8552 9.4066 31.6282 9.69433C31.5171 9.83476 31.4202 9.96297 31.3233 10.0912C30.6387 10.9901 30.0417 11.958 29.3234 12.8271C28.7656 13.5023 24.5915 17.3798 23.5874 18.0923C23.2967 18.2988 22.9669 18.3879 22.597 18.3575C22.0245 18.3115 21.5161 17.9842 21.1902 17.5154L20.3935 16.1472C18.6402 13.3448 16.2474 10.9989 13.4117 9.30041C11.3594 8.0712 9.5332 6.49847 8.01234 4.65172L5.2153 1.25377C5.0773 1.08642 4.81306 1.11382 4.71422 1.30662C4.39615 1.92612 3.78888 3.23411 3.32353 4.99327C3.92786 5.81095 5.26717 7.35089 6.8624 8.65351C6.97348 8.74403 6.88246 8.92313 6.74447 8.88496C5.36846 8.51013 4.03062 7.90825 3.02944 7.39542C2.94772 7.35383 2.84887 7.4057 2.83713 7.49672C2.68152 8.74354 2.64139 10.1127 2.80581 11.5562C4.02572 12.1596 5.85143 12.8804 7.76816 13.3389C7.90713 13.3722 7.90273 13.5723 7.76229 13.5992C6.26982 13.8801 4.70688 13.9427 3.43656 13.9261C3.3475 13.9251 3.28193 14.0093 3.30591 14.0949C3.56085 14.9958 3.90632 15.9118 4.3619 16.8342C4.55029 17.2487 4.75532 17.6553 4.97504 18.0532C6.21207 18.107 7.47946 17.9964 8.75369 17.7713C8.97095 17.7331 9.08741 18.0189 8.90391 18.1417C8.03877 18.7201 7.11588 19.2183 6.25758 19.6283C6.14259 19.6836 6.1054 19.8304 6.18125 19.9327C6.69114 20.6236 7.25191 21.2774 7.86114 21.8866C7.86114 21.8866 10.8608 24.9763 10.9425 25.2185C12.6928 23.4261 15.5701 21.4394 18.7474 19.7047C14.4921 23.1672 12.1198 25.7235 10.9258 27.1758L10.0935 28.3439C9.66091 28.9507 9.2856 29.5951 8.97193 30.2709C7.92231 32.5292 6.19201 37.0966 6.19201 37.0966C6.0594 37.4543 6.16755 37.8072 6.39753 38.0371C6.66031 38.2999 7.01263 38.4076 7.37033 38.275C7.37033 38.275 11.9368 36.5447 14.1961 35.495C14.8719 35.1814 15.5168 34.8056 16.1231 34.3735L17.4095 33.457C18.0907 32.9715 19.0234 33.0489 19.615 33.6405L22.5804 36.6058C23.1896 37.2151 23.8433 37.7758 24.5343 38.2857C24.637 38.3611 24.7833 38.3244 24.8386 38.2094C25.2492 37.3516 25.7473 36.4277 26.3252 35.5631C26.4481 35.3796 26.7343 35.4965 26.6957 35.7133C26.4701 36.988 26.3605 38.2554 26.3086 39.3035C27.2178 39.9172 28.5551 40.5606 30.3721 41.1611C30.4577 41.185 30.5419 41.1195 30.5409 41.0304C30.5237 39.7596 30.5864 38.1967 30.8677 36.7047C30.8942 36.5638 31.0943 36.5593 31.1281 36.6988C31.5861 38.616 32.3069 40.4417 32.8041 41.5829C34.3543 41.8256 35.7234 41.7855 36.9703 41.6298C37.0618 41.6186 37.1136 41.5197 37.0715 41.4375C36.5587 40.4364 35.9568 39.0975 35.582 37.7225C35.5443 37.584 35.7229 37.4935 35.8135 37.6046C37.1161 39.1998 38.656 40.5391 39.3548 41.1175C41.2333 40.6786 42.5413 40.0713 43.1604 39.7528C43.3532 39.6539 43.3806 39.3897 43.2132 39.2517Z" }]]
|
|
1543
|
+
},
|
|
1544
|
+
opencode: { viewBox: "2.5 0 19 24", paths: [["path", { d: "M16 6H8v12h8V6zm4 16H4V2h16v20z" }]] },
|
|
1545
|
+
pi: {
|
|
1546
|
+
viewBox: "0 0 24 24",
|
|
1547
|
+
paths: [
|
|
1548
|
+
["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
|
|
1549
|
+
["path", { d: "M17.5 12H23v11h-5.5V12z" }]
|
|
1550
|
+
]
|
|
1551
|
+
},
|
|
1552
|
+
// Product mark shared with the first-party browser frontend favicon.
|
|
1553
|
+
supercode: {
|
|
1554
|
+
viewBox: "0 0 64 64",
|
|
1555
|
+
paths: [
|
|
1556
|
+
["rect", { width: "64", height: "64", rx: "14", fill: "#111923" }],
|
|
1557
|
+
["path", { d: "M18 21h28v6H18zm0 13h18v6H18z", fill: "#5f8fff" }],
|
|
1558
|
+
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", strokeWidth: "4" }]
|
|
1559
|
+
]
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
function hasHarnessLogo(id) {
|
|
1563
|
+
return Object.hasOwn(LOGOS, id);
|
|
1564
|
+
}
|
|
1565
|
+
var LOGO_CHROME = {
|
|
1566
|
+
codex: { background: "#f7f7f5", color: "#111" },
|
|
1567
|
+
gemini: { background: "#f7f7f5", color: "#6e79dc" },
|
|
1568
|
+
goose: { background: "#f7f7f5", color: "#101010" },
|
|
1569
|
+
pi: { background: "#efefeb", color: "#111" },
|
|
1570
|
+
supercode: { background: "#111923", color: "#f7f7f5" }
|
|
1571
|
+
};
|
|
1572
|
+
function escapeSvgAttribute(value) {
|
|
1573
|
+
return String(value).replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
1574
|
+
}
|
|
1575
|
+
var SVG_ATTRIBUTE_NAMES = Object.freeze({
|
|
1576
|
+
clipRule: "clip-rule",
|
|
1577
|
+
fillRule: "fill-rule",
|
|
1578
|
+
strokeWidth: "stroke-width"
|
|
1579
|
+
});
|
|
1580
|
+
function harnessLogoDataUrl(id) {
|
|
1581
|
+
const logo = LOGOS[id];
|
|
1582
|
+
if (!logo) return null;
|
|
1583
|
+
const chrome = LOGO_CHROME[id] ?? { background: "#111", color: id === "claude-code" ? "#d97757" : "#f7f7f5" };
|
|
1584
|
+
const glyph = logo.paths.map(([tag, attributes]) => {
|
|
1585
|
+
const serialized = Object.entries(attributes).map(([name, value]) => `${SVG_ATTRIBUTE_NAMES[name] ?? name}="${escapeSvgAttribute(value)}"`).join(" ");
|
|
1586
|
+
return `<${tag} ${serialized}/>`;
|
|
1587
|
+
}).join("");
|
|
1588
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle cx="20" cy="20" r="19" fill="${chrome.background}" stroke="#383a42"/><svg x="7" y="7" width="26" height="26" viewBox="${logo.viewBox}" color="${chrome.color}" fill="currentColor" preserveAspectRatio="xMidYMid meet">${glyph}</svg></svg>`;
|
|
1589
|
+
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
1590
|
+
}
|
|
1591
|
+
function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
1592
|
+
const logo = LOGOS[id];
|
|
1593
|
+
useEffect3(() => {
|
|
1594
|
+
if (!logo) onMissingLogo?.(id);
|
|
1595
|
+
}, [id, logo, onMissingLogo]);
|
|
1596
|
+
if (!logo) return null;
|
|
1597
|
+
return /* @__PURE__ */ jsxs4("span", { className: "scui-logo", "data-harness": id, "data-activity": activity, style: { "--scui-logo-size": `${size}px` }, "aria-hidden": "true", children: [
|
|
1598
|
+
/* @__PURE__ */ jsx4("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx4(Tag, { ...props }, index)) }),
|
|
1599
|
+
activity && activity !== "idle" ? /* @__PURE__ */ jsx4("i", {}) : null
|
|
1600
|
+
] });
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
// src/activity.jsx
|
|
1604
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
1605
|
+
function AgentActivityLauncher({ state, onOpen, class: className = "", showSummary = false, components = {} }) {
|
|
1606
|
+
const value = projectAgentActivity(state);
|
|
1607
|
+
const Logo = components.HarnessLogo ?? HarnessLogo;
|
|
1608
|
+
const badge = value.unreadCount > 99 ? "99+" : String(value.unreadCount);
|
|
1609
|
+
const label = [value.title, value.detail, value.unreadCount ? `${value.unreadCount} unread` : ""].filter(Boolean).join(" \xB7 ");
|
|
1610
|
+
return /* @__PURE__ */ jsxs5("button", { className: `scui-launcher ${className}`, "data-activity": value.activity, type: "button", "aria-label": `Open ${label}`, onClick: () => onOpen?.(value), children: [
|
|
1611
|
+
/* @__PURE__ */ jsxs5("span", { className: "scui-launcher-logo", children: [
|
|
1612
|
+
/* @__PURE__ */ jsx5(Logo, { id: value.harness || "supercode", activity: value.activity, size: 36 }),
|
|
1613
|
+
value.unreadCount ? /* @__PURE__ */ jsx5("b", { "aria-hidden": "true", children: badge }) : null
|
|
1614
|
+
] }),
|
|
1615
|
+
showSummary ? /* @__PURE__ */ jsxs5("span", { className: "scui-launcher-copy", children: [
|
|
1616
|
+
/* @__PURE__ */ jsx5("strong", { children: value.title }),
|
|
1617
|
+
/* @__PURE__ */ jsx5("small", { children: value.detail })
|
|
1618
|
+
] }) : null
|
|
1619
|
+
] });
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1377
1622
|
// src/conversation.jsx
|
|
1378
1623
|
import { Fragment as Fragment3 } from "preact";
|
|
1379
|
-
import { useEffect as
|
|
1624
|
+
import { useEffect as useEffect5, useId, useLayoutEffect as useLayoutEffect2, useRef as useRef4, useState as useState3 } from "preact/hooks";
|
|
1380
1625
|
|
|
1381
1626
|
// src/markdown.jsx
|
|
1382
1627
|
import MarkdownIt from "markdown-it";
|
|
1383
|
-
import { useEffect as
|
|
1384
|
-
import { jsx as
|
|
1628
|
+
import { useEffect as useEffect4, useMemo, useRef as useRef3 } from "preact/hooks";
|
|
1629
|
+
import { jsx as jsx6 } from "preact/jsx-runtime";
|
|
1385
1630
|
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
1386
1631
|
var LANGUAGE_LABELS = {
|
|
1387
1632
|
bash: "Shell",
|
|
@@ -1443,7 +1688,7 @@ function setCopyState(button, status) {
|
|
|
1443
1688
|
function Markdown({ value, copyText }) {
|
|
1444
1689
|
const html = useMemo(() => markdown.render(value), [value]);
|
|
1445
1690
|
const resets = useRef3(/* @__PURE__ */ new Map());
|
|
1446
|
-
|
|
1691
|
+
useEffect4(() => () => {
|
|
1447
1692
|
for (const timer of resets.current.values()) clearTimeout(timer);
|
|
1448
1693
|
resets.current.clear();
|
|
1449
1694
|
}, []);
|
|
@@ -1468,11 +1713,11 @@ function Markdown({ value, copyText }) {
|
|
|
1468
1713
|
}, 1500);
|
|
1469
1714
|
resets.current.set(button, timer);
|
|
1470
1715
|
};
|
|
1471
|
-
return /* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ jsx6("div", { className: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1472
1717
|
}
|
|
1473
1718
|
|
|
1474
1719
|
// src/conversation.jsx
|
|
1475
|
-
import { Fragment as Fragment4, jsx as
|
|
1720
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
1476
1721
|
function LoadingStatus({ state, compact = false }) {
|
|
1477
1722
|
const copy = {
|
|
1478
1723
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -1480,50 +1725,50 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1480
1725
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1481
1726
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1482
1727
|
}[state.startup];
|
|
1483
|
-
return /* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__PURE__ */
|
|
1487
|
-
/* @__PURE__ */
|
|
1728
|
+
return /* @__PURE__ */ jsxs6("div", { className: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1729
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx7("i", {}) }),
|
|
1730
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-loading-copy", children: [
|
|
1731
|
+
/* @__PURE__ */ jsx7("strong", { children: copy[0] }),
|
|
1732
|
+
/* @__PURE__ */ jsx7("small", { children: copy[1] })
|
|
1488
1733
|
] }),
|
|
1489
|
-
/* @__PURE__ */
|
|
1734
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx7("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
|
|
1490
1735
|
] });
|
|
1491
1736
|
}
|
|
1492
1737
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1493
1738
|
const request = entry.request;
|
|
1494
1739
|
if (!request) return null;
|
|
1495
1740
|
if (request.status === "responded") {
|
|
1496
|
-
return /* @__PURE__ */
|
|
1741
|
+
return /* @__PURE__ */ jsxs6("div", { className: "scui-request-done", children: [
|
|
1497
1742
|
"\u2713 Request answered \xB7 ",
|
|
1498
1743
|
request.resolution?.name ?? request.requestKind
|
|
1499
1744
|
] });
|
|
1500
1745
|
}
|
|
1501
|
-
return /* @__PURE__ */
|
|
1502
|
-
/* @__PURE__ */
|
|
1503
|
-
/* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1505
|
-
request.options.map((option) => /* @__PURE__ */
|
|
1506
|
-
request.cancellable ? /* @__PURE__ */
|
|
1746
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1747
|
+
/* @__PURE__ */ jsx7("strong", { children: "Agent needs input" }),
|
|
1748
|
+
/* @__PURE__ */ jsx7(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1749
|
+
/* @__PURE__ */ jsxs6("div", { className: "scui-request-actions", children: [
|
|
1750
|
+
request.options.map((option) => /* @__PURE__ */ jsx7("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: option.optionId }), children: option.name }, option.optionId)),
|
|
1751
|
+
request.cancellable ? /* @__PURE__ */ jsx7("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1507
1752
|
] })
|
|
1508
1753
|
] });
|
|
1509
1754
|
}
|
|
1510
1755
|
function ContextDisclosure({ context }) {
|
|
1511
1756
|
if (!context?.length) return null;
|
|
1512
|
-
return /* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1757
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-context", children: [
|
|
1758
|
+
/* @__PURE__ */ jsxs6("summary", { children: [
|
|
1514
1759
|
"Context \xB7 ",
|
|
1515
1760
|
context.length
|
|
1516
1761
|
] }),
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1762
|
+
/* @__PURE__ */ jsx7("div", { children: context.map((item, index) => /* @__PURE__ */ jsxs6("p", { children: [
|
|
1763
|
+
/* @__PURE__ */ jsx7("strong", { children: item.label }),
|
|
1764
|
+
/* @__PURE__ */ jsx7("span", { children: item.detail })
|
|
1520
1765
|
] }, item.id ?? index)) })
|
|
1521
1766
|
] });
|
|
1522
1767
|
}
|
|
1523
1768
|
function MessageMeta({ entry, adapter }) {
|
|
1524
1769
|
const [copyState, setCopyState2] = useState3("idle");
|
|
1525
1770
|
const reset = useRef4(null);
|
|
1526
|
-
|
|
1771
|
+
useEffect5(() => () => clearTimeout(reset.current), []);
|
|
1527
1772
|
const date = entry.ts === null ? null : new Date(entry.ts);
|
|
1528
1773
|
const validDate = date && Number.isFinite(date.valueOf()) ? date : null;
|
|
1529
1774
|
if (!validDate && (!adapter?.copyText || !entry.text)) return null;
|
|
@@ -1538,46 +1783,46 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1538
1783
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1539
1784
|
};
|
|
1540
1785
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1541
|
-
return /* @__PURE__ */
|
|
1542
|
-
validDate ? /* @__PURE__ */
|
|
1543
|
-
adapter?.copyText && entry.text ? /* @__PURE__ */
|
|
1786
|
+
return /* @__PURE__ */ jsxs6("footer", { className: "scui-message-meta", children: [
|
|
1787
|
+
validDate ? /* @__PURE__ */ jsx7("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1788
|
+
adapter?.copyText && entry.text ? /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": copyLabel, title: copyLabel, onClick: copy, "data-status": copyState, children: /* @__PURE__ */ jsx7(UiIcon, { name: "copy", size: 13 }) }) : null
|
|
1544
1789
|
] });
|
|
1545
1790
|
}
|
|
1546
1791
|
var TOOL_ICONS = {
|
|
1547
|
-
read: () => /* @__PURE__ */
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1792
|
+
read: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1793
|
+
/* @__PURE__ */ jsx7("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" }),
|
|
1794
|
+
/* @__PURE__ */ jsx7("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
1550
1795
|
] }),
|
|
1551
|
-
search: () => /* @__PURE__ */
|
|
1552
|
-
/* @__PURE__ */
|
|
1553
|
-
/* @__PURE__ */
|
|
1796
|
+
search: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1797
|
+
/* @__PURE__ */ jsx7("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
1798
|
+
/* @__PURE__ */ jsx7("path", { d: "m11.5 11.5 3 3" })
|
|
1554
1799
|
] }),
|
|
1555
|
-
edit: () => /* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1800
|
+
edit: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1801
|
+
/* @__PURE__ */ jsx7("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
1802
|
+
/* @__PURE__ */ jsx7("path", { d: "m10 5 3 3" })
|
|
1558
1803
|
] }),
|
|
1559
|
-
command: () => /* @__PURE__ */
|
|
1560
|
-
test: () => /* @__PURE__ */
|
|
1561
|
-
/* @__PURE__ */
|
|
1562
|
-
/* @__PURE__ */
|
|
1804
|
+
command: () => /* @__PURE__ */ jsx7(Fragment4, { children: /* @__PURE__ */ jsx7("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
1805
|
+
test: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1806
|
+
/* @__PURE__ */ jsx7("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" }),
|
|
1807
|
+
/* @__PURE__ */ jsx7("path", { d: "M5 2.5h8" })
|
|
1563
1808
|
] }),
|
|
1564
|
-
web: () => /* @__PURE__ */
|
|
1565
|
-
/* @__PURE__ */
|
|
1566
|
-
/* @__PURE__ */
|
|
1809
|
+
web: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1810
|
+
/* @__PURE__ */ jsx7("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
1811
|
+
/* @__PURE__ */ jsx7("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" })
|
|
1567
1812
|
] }),
|
|
1568
|
-
agent: () => /* @__PURE__ */
|
|
1569
|
-
/* @__PURE__ */
|
|
1570
|
-
/* @__PURE__ */
|
|
1813
|
+
agent: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1814
|
+
/* @__PURE__ */ jsx7("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
1815
|
+
/* @__PURE__ */ jsx7("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
1571
1816
|
] }),
|
|
1572
|
-
plan: () => /* @__PURE__ */
|
|
1573
|
-
other: () => /* @__PURE__ */
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1817
|
+
plan: () => /* @__PURE__ */ jsx7(Fragment4, { children: /* @__PURE__ */ jsx7("path", { d: "m3 5 1 1 2-2M3 9l1 1 2-2M3 13l1 1 2-2M8 5h7M8 9h7M8 13h7" }) }),
|
|
1818
|
+
other: () => /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1819
|
+
/* @__PURE__ */ jsx7("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
1820
|
+
/* @__PURE__ */ jsx7("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
1576
1821
|
] })
|
|
1577
1822
|
};
|
|
1578
1823
|
function ToolIcon({ category }) {
|
|
1579
1824
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1580
|
-
return /* @__PURE__ */
|
|
1825
|
+
return /* @__PURE__ */ jsx7("svg", { className: "scui-tool-icon", viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: "1.35", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx7(Glyph, {}) });
|
|
1581
1826
|
}
|
|
1582
1827
|
function toolAction2(entry, category, presentation) {
|
|
1583
1828
|
if (presentation?.action) return presentation.action;
|
|
@@ -1632,89 +1877,89 @@ function ToolMetrics({ presentation }) {
|
|
|
1632
1877
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1633
1878
|
formatDuration(presentation.durationMs)
|
|
1634
1879
|
].filter(Boolean);
|
|
1635
|
-
return metrics.length ? /* @__PURE__ */
|
|
1880
|
+
return metrics.length ? /* @__PURE__ */ jsx7("div", { className: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx7("span", { children: metric }, metric)) }) : null;
|
|
1636
1881
|
}
|
|
1637
1882
|
function PendingElapsed({ now }) {
|
|
1638
1883
|
const clock = now ?? Date.now;
|
|
1639
1884
|
const started = useRef4(clock());
|
|
1640
1885
|
const [elapsed, setElapsed] = useState3(0);
|
|
1641
|
-
|
|
1886
|
+
useEffect5(() => {
|
|
1642
1887
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1643
1888
|
return () => clearInterval(timer);
|
|
1644
1889
|
}, [clock]);
|
|
1645
|
-
return /* @__PURE__ */
|
|
1890
|
+
return /* @__PURE__ */ jsx7("small", { className: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1646
1891
|
}
|
|
1647
1892
|
function LinePreview({ value, kind }) {
|
|
1648
1893
|
if (!value) return null;
|
|
1649
|
-
return /* @__PURE__ */
|
|
1894
|
+
return /* @__PURE__ */ jsx7("ol", { className: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1650
1895
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1651
|
-
return /* @__PURE__ */
|
|
1652
|
-
/* @__PURE__ */
|
|
1653
|
-
/* @__PURE__ */
|
|
1896
|
+
return /* @__PURE__ */ jsxs6("li", { "data-tone": tone, children: [
|
|
1897
|
+
/* @__PURE__ */ jsx7("span", { children: index + 1 }),
|
|
1898
|
+
/* @__PURE__ */ jsx7("code", { children: line || " " })
|
|
1654
1899
|
] }, index);
|
|
1655
1900
|
}) });
|
|
1656
1901
|
}
|
|
1657
1902
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1658
|
-
return /* @__PURE__ */
|
|
1659
|
-
/* @__PURE__ */
|
|
1660
|
-
/* @__PURE__ */
|
|
1661
|
-
/* @__PURE__ */
|
|
1662
|
-
/* @__PURE__ */
|
|
1663
|
-
/* @__PURE__ */
|
|
1903
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-terminal", children: [
|
|
1904
|
+
/* @__PURE__ */ jsxs6("header", { children: [
|
|
1905
|
+
/* @__PURE__ */ jsxs6("span", { "aria-hidden": "true", children: [
|
|
1906
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
1907
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
1908
|
+
/* @__PURE__ */ jsx7("i", {})
|
|
1664
1909
|
] }),
|
|
1665
|
-
/* @__PURE__ */
|
|
1910
|
+
/* @__PURE__ */ jsx7("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1666
1911
|
] }),
|
|
1667
|
-
presentation.preview ? /* @__PURE__ */
|
|
1668
|
-
/* @__PURE__ */
|
|
1912
|
+
presentation.preview ? /* @__PURE__ */ jsx7("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs6("div", { className: "scui-terminal-wait", children: [
|
|
1913
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
1669
1914
|
" Waiting for output"
|
|
1670
|
-
] }) : /* @__PURE__ */
|
|
1915
|
+
] }) : /* @__PURE__ */ jsx7("div", { className: "scui-terminal-empty", children: "No output" })
|
|
1671
1916
|
] });
|
|
1672
1917
|
}
|
|
1673
1918
|
function SearchPreview({ presentation }) {
|
|
1674
1919
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1675
|
-
return /* @__PURE__ */
|
|
1676
|
-
presentation.query ? /* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1920
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-search-preview", children: [
|
|
1921
|
+
presentation.query ? /* @__PURE__ */ jsxs6("header", { children: [
|
|
1922
|
+
/* @__PURE__ */ jsx7("span", { children: "Search" }),
|
|
1923
|
+
/* @__PURE__ */ jsx7("code", { children: presentation.query })
|
|
1679
1924
|
] }) : null,
|
|
1680
|
-
lines.length ? /* @__PURE__ */
|
|
1925
|
+
lines.length ? /* @__PURE__ */ jsx7("ol", { children: lines.map((line, index) => {
|
|
1681
1926
|
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
1682
|
-
return /* @__PURE__ */
|
|
1683
|
-
/* @__PURE__ */
|
|
1684
|
-
/* @__PURE__ */
|
|
1927
|
+
return /* @__PURE__ */ jsx7("li", { children: match ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1928
|
+
/* @__PURE__ */ jsx7("code", { children: match[1] }),
|
|
1929
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1685
1930
|
match[2],
|
|
1686
1931
|
match[3] ? `:${match[3]}` : ""
|
|
1687
1932
|
] }),
|
|
1688
|
-
/* @__PURE__ */
|
|
1689
|
-
] }) : /* @__PURE__ */
|
|
1690
|
-
}) }) : /* @__PURE__ */
|
|
1933
|
+
/* @__PURE__ */ jsx7("span", { children: match[4] })
|
|
1934
|
+
] }) : /* @__PURE__ */ jsx7("span", { children: line }) }, index);
|
|
1935
|
+
}) }) : /* @__PURE__ */ jsx7("p", { children: "No textual results" })
|
|
1691
1936
|
] });
|
|
1692
1937
|
}
|
|
1693
1938
|
function ToolPreview({ presentation, entry }) {
|
|
1694
1939
|
const pending = entry.status === "pending";
|
|
1695
1940
|
const failed = entry.status === "error";
|
|
1696
|
-
if (presentation.detail === "terminal") return /* @__PURE__ */
|
|
1697
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */
|
|
1698
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */
|
|
1699
|
-
if (presentation.detail === "matches") return /* @__PURE__ */
|
|
1700
|
-
if (presentation.detail === "web") return /* @__PURE__ */
|
|
1701
|
-
presentation.url ? /* @__PURE__ */
|
|
1702
|
-
presentation.preview ? /* @__PURE__ */
|
|
1941
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx7(TerminalPreview, { presentation, pending, failed });
|
|
1942
|
+
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx7(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx7("div", { className: "scui-tool-empty", children: "Edit completed without a textual diff" });
|
|
1943
|
+
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx7(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx7("div", { className: "scui-tool-empty", children: "File contents were not included in this event" });
|
|
1944
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx7(SearchPreview, { presentation });
|
|
1945
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs6("section", { className: "scui-web-preview", children: [
|
|
1946
|
+
presentation.url ? /* @__PURE__ */ jsx7("code", { children: presentation.url }) : null,
|
|
1947
|
+
presentation.preview ? /* @__PURE__ */ jsx7("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx7("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1703
1948
|
] });
|
|
1704
|
-
if (presentation.detail === "agent") return /* @__PURE__ */
|
|
1705
|
-
/* @__PURE__ */
|
|
1706
|
-
/* @__PURE__ */
|
|
1707
|
-
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */
|
|
1708
|
-
if (presentation.detail === "plan") return /* @__PURE__ */
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1949
|
+
if (presentation.detail === "agent") return /* @__PURE__ */ jsx7("section", { className: "scui-agent-preview", children: presentation.items?.length ? /* @__PURE__ */ jsx7("ol", { className: "scui-agent-roster", children: presentation.items.map((item, index) => /* @__PURE__ */ jsxs6("li", { children: [
|
|
1950
|
+
/* @__PURE__ */ jsx7("strong", { children: item.label }),
|
|
1951
|
+
/* @__PURE__ */ jsx7("small", { children: item.status })
|
|
1952
|
+
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx7("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx7("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1953
|
+
if (presentation.detail === "plan") return /* @__PURE__ */ jsx7("ol", { className: "scui-plan-preview", children: presentation.items?.map((item, index) => /* @__PURE__ */ jsxs6("li", { "data-status": item.status, children: [
|
|
1954
|
+
/* @__PURE__ */ jsx7("i", { "aria-hidden": "true" }),
|
|
1955
|
+
/* @__PURE__ */ jsx7("span", { children: item.label })
|
|
1711
1956
|
] }, `${item.label}:${index}`)) });
|
|
1712
|
-
return presentation.preview ? /* @__PURE__ */
|
|
1957
|
+
return presentation.preview ? /* @__PURE__ */ jsx7("pre", { className: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1713
1958
|
}
|
|
1714
1959
|
function ToolActions({ presentation, adapter }) {
|
|
1715
1960
|
const [copied, setCopied] = useState3(false);
|
|
1716
1961
|
const reset = useRef4(null);
|
|
1717
|
-
|
|
1962
|
+
useEffect5(() => () => clearTimeout(reset.current), []);
|
|
1718
1963
|
if (!adapter?.copyText) return null;
|
|
1719
1964
|
const action = presentation.command ? ["Copy command", presentation.command] : presentation.path ? ["Copy path", presentation.path] : presentation.url ? ["Copy URL", presentation.url] : presentation.query ? ["Copy query", presentation.query] : null;
|
|
1720
1965
|
const copy = async () => {
|
|
@@ -1723,27 +1968,27 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1723
1968
|
clearTimeout(reset.current);
|
|
1724
1969
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1725
1970
|
};
|
|
1726
|
-
return action ? /* @__PURE__ */
|
|
1971
|
+
return action ? /* @__PURE__ */ jsx7("div", { className: "scui-tool-actions", children: /* @__PURE__ */ jsx7("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1727
1972
|
}
|
|
1728
1973
|
function ToolStack({ tools }) {
|
|
1729
1974
|
if (tools.length < 2) return null;
|
|
1730
|
-
return /* @__PURE__ */
|
|
1975
|
+
return /* @__PURE__ */ jsx7("div", { className: "scui-tool-stack", "aria-label": "Coordinated tools", children: tools.map((tool) => /* @__PURE__ */ jsx7("span", { children: tool.replaceAll("__", " \xB7 ").replaceAll("_", " ") }, tool)) });
|
|
1731
1976
|
}
|
|
1732
1977
|
function TechnicalDetails({ entry }) {
|
|
1733
1978
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1734
|
-
return /* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
entry.arguments ? /* @__PURE__ */
|
|
1738
|
-
/* @__PURE__ */
|
|
1739
|
-
/* @__PURE__ */
|
|
1740
|
-
/* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
1979
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-tool-technical", children: [
|
|
1980
|
+
/* @__PURE__ */ jsx7("summary", { children: "Technical details" }),
|
|
1981
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
1982
|
+
entry.arguments ? /* @__PURE__ */ jsxs6("section", { children: [
|
|
1983
|
+
/* @__PURE__ */ jsx7("strong", { children: "Native arguments" }),
|
|
1984
|
+
/* @__PURE__ */ jsx7("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
1985
|
+
/* @__PURE__ */ jsx7("dt", { children: row.label }),
|
|
1986
|
+
/* @__PURE__ */ jsx7("dd", { children: /* @__PURE__ */ jsx7("pre", { children: row.value }) })
|
|
1742
1987
|
] }, row.key)) })
|
|
1743
1988
|
] }) : null,
|
|
1744
|
-
entry.resultText ? /* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
/* @__PURE__ */
|
|
1989
|
+
entry.resultText ? /* @__PURE__ */ jsxs6("section", { children: [
|
|
1990
|
+
/* @__PURE__ */ jsx7("strong", { children: "Native result" }),
|
|
1991
|
+
/* @__PURE__ */ jsxs6("pre", { "data-error": entry.status === "error", children: [
|
|
1747
1992
|
entry.resultText,
|
|
1748
1993
|
entry.truncated ? "\n[truncated]" : ""
|
|
1749
1994
|
] })
|
|
@@ -1752,127 +1997,127 @@ function TechnicalDetails({ entry }) {
|
|
|
1752
1997
|
] });
|
|
1753
1998
|
}
|
|
1754
1999
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1755
|
-
if (entry.role === "request") return /* @__PURE__ */
|
|
2000
|
+
if (entry.role === "request") return /* @__PURE__ */ jsx7(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1756
2001
|
if (entry.role === "reasoning") {
|
|
1757
|
-
return /* @__PURE__ */
|
|
1758
|
-
/* @__PURE__ */
|
|
1759
|
-
/* @__PURE__ */
|
|
2002
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-reasoning", open: entry.streaming, children: [
|
|
2003
|
+
/* @__PURE__ */ jsx7("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
2004
|
+
/* @__PURE__ */ jsx7(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1760
2005
|
] });
|
|
1761
2006
|
}
|
|
1762
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */
|
|
1763
|
-
return /* @__PURE__ */
|
|
1764
|
-
/* @__PURE__ */
|
|
1765
|
-
/* @__PURE__ */
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
entry.truncated ? /* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
2007
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx7("div", { className: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
2008
|
+
return /* @__PURE__ */ jsxs6("article", { className: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
2009
|
+
/* @__PURE__ */ jsx7(MessageImages, { items: entry.images, adapter }),
|
|
2010
|
+
/* @__PURE__ */ jsx7(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
2011
|
+
/* @__PURE__ */ jsx7(ContextDisclosure, { context: entry.context }),
|
|
2012
|
+
entry.truncated ? /* @__PURE__ */ jsx7("small", { className: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
2013
|
+
/* @__PURE__ */ jsx7(MessageMeta, { entry, adapter })
|
|
1769
2014
|
] });
|
|
1770
2015
|
}
|
|
1771
2016
|
function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
1772
2017
|
const presentation = entry.presentation ?? createToolPresentation(entry);
|
|
1773
2018
|
const [expanded, setExpanded] = useState3(open || entry.status === "pending");
|
|
1774
|
-
|
|
2019
|
+
useEffect5(() => {
|
|
1775
2020
|
if (entry.status === "pending") setExpanded(true);
|
|
1776
2021
|
}, [entry.status]);
|
|
1777
2022
|
const target = compactToolTarget(presentation.target, workspace);
|
|
1778
2023
|
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
1779
2024
|
const category = presentation.category ?? toolCategory(entry);
|
|
1780
|
-
const summary = /* @__PURE__ */
|
|
1781
|
-
/* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
target ? /* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
1785
|
-
entry.status === "pending" ? /* @__PURE__ */
|
|
1786
|
-
/* @__PURE__ */
|
|
1787
|
-
hasDetail ? /* @__PURE__ */
|
|
2025
|
+
const summary = /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2026
|
+
/* @__PURE__ */ jsx7(ToolIcon, { category }),
|
|
2027
|
+
/* @__PURE__ */ jsx7("strong", { children: toolAction2(entry, category, presentation) }),
|
|
2028
|
+
target ? /* @__PURE__ */ jsx7("code", { className: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
2029
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-spacer" }),
|
|
2030
|
+
entry.status === "pending" ? /* @__PURE__ */ jsx7(PendingElapsed, { now: adapter?.now }) : null,
|
|
2031
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-tool-status", role: "status", "data-status": entry.status ?? "completed", "aria-label": entry.status ?? "completed", children: entry.status === "pending" ? /* @__PURE__ */ jsx7("i", {}) : /* @__PURE__ */ jsx7(UiIcon, { name: entry.status === "error" ? "close" : "check", size: 12 }) }),
|
|
2032
|
+
hasDetail ? /* @__PURE__ */ jsx7(UiIcon, { name: "chevron", size: 14, className: "scui-tool-chevron" }) : null
|
|
1788
2033
|
] });
|
|
1789
|
-
if (!hasDetail) return /* @__PURE__ */
|
|
1790
|
-
return /* @__PURE__ */
|
|
1791
|
-
/* @__PURE__ */
|
|
1792
|
-
/* @__PURE__ */
|
|
1793
|
-
/* @__PURE__ */
|
|
1794
|
-
/* @__PURE__ */
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
presentation.fields.length ? /* @__PURE__ */
|
|
1797
|
-
/* @__PURE__ */
|
|
1798
|
-
/* @__PURE__ */
|
|
2034
|
+
if (!hasDetail) return /* @__PURE__ */ jsx7("div", { className: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx7("div", { className: "scui-tool-head", children: summary }) });
|
|
2035
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
2036
|
+
/* @__PURE__ */ jsx7("summary", { className: "scui-tool-head", children: summary }),
|
|
2037
|
+
/* @__PURE__ */ jsxs6("div", { className: "scui-tool-detail", children: [
|
|
2038
|
+
/* @__PURE__ */ jsx7(ToolMetrics, { presentation }),
|
|
2039
|
+
/* @__PURE__ */ jsx7(ToolStack, { tools: presentation.tools ?? [] }),
|
|
2040
|
+
/* @__PURE__ */ jsx7(ToolPreview, { presentation, entry }),
|
|
2041
|
+
presentation.fields.length ? /* @__PURE__ */ jsx7("dl", { className: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs6("div", { children: [
|
|
2042
|
+
/* @__PURE__ */ jsx7("dt", { children: field.label }),
|
|
2043
|
+
/* @__PURE__ */ jsx7("dd", { children: field.value })
|
|
1799
2044
|
] }, field.label)) }) : null,
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
2045
|
+
/* @__PURE__ */ jsx7(ToolActions, { presentation, adapter }),
|
|
2046
|
+
/* @__PURE__ */ jsx7(TechnicalDetails, { entry })
|
|
1802
2047
|
] })
|
|
1803
2048
|
] });
|
|
1804
2049
|
}
|
|
1805
2050
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1806
|
-
if (entries.length === 1) return /* @__PURE__ */
|
|
2051
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx7("section", { className: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx7(ToolRow, { entry: entries[0], workspace: state.workspace, adapter }) });
|
|
1807
2052
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1808
2053
|
const [open, setOpen] = useState3(active);
|
|
1809
2054
|
const id = useId();
|
|
1810
|
-
|
|
2055
|
+
useEffect5(() => {
|
|
1811
2056
|
if (active) setOpen(true);
|
|
1812
2057
|
}, [active]);
|
|
1813
|
-
return /* @__PURE__ */
|
|
1814
|
-
/* @__PURE__ */
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__PURE__ */
|
|
1818
|
-
/* @__PURE__ */
|
|
2058
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-activity", children: [
|
|
2059
|
+
/* @__PURE__ */ jsxs6("button", { className: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
2060
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx7(UiIcon, { name: "chevron", size: 14 }) }),
|
|
2061
|
+
/* @__PURE__ */ jsx7("strong", { children: activitySummary(entries) }),
|
|
2062
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-spacer" }),
|
|
2063
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1819
2064
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1820
2065
|
"/",
|
|
1821
2066
|
entries.length
|
|
1822
2067
|
] })
|
|
1823
2068
|
] }),
|
|
1824
|
-
open ? /* @__PURE__ */
|
|
2069
|
+
open ? /* @__PURE__ */ jsx7("div", { id, children: entries.map((entry) => /* @__PURE__ */ jsx7(ToolRow, { entry, workspace: state.workspace, adapter }, entry.id)) }) : null
|
|
1825
2070
|
] });
|
|
1826
2071
|
}
|
|
1827
2072
|
function TaskPlan({ plan }) {
|
|
1828
2073
|
if (!plan.items.length) return null;
|
|
1829
2074
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1830
|
-
return /* @__PURE__ */
|
|
1831
|
-
/* @__PURE__ */
|
|
1832
|
-
/* @__PURE__ */
|
|
1833
|
-
/* @__PURE__ */
|
|
2075
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-plan", children: [
|
|
2076
|
+
/* @__PURE__ */ jsxs6("summary", { children: [
|
|
2077
|
+
/* @__PURE__ */ jsx7("span", { children: "Plan" }),
|
|
2078
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1834
2079
|
complete,
|
|
1835
2080
|
"/",
|
|
1836
2081
|
plan.items.length
|
|
1837
2082
|
] })
|
|
1838
2083
|
] }),
|
|
1839
|
-
/* @__PURE__ */
|
|
1840
|
-
/* @__PURE__ */
|
|
2084
|
+
/* @__PURE__ */ jsx7("ol", { tabIndex: 0, "aria-label": "Task plan steps", children: plan.items.map((item) => /* @__PURE__ */ jsxs6("li", { "data-status": item.status, children: [
|
|
2085
|
+
/* @__PURE__ */ jsx7("i", { "aria-hidden": "true" }),
|
|
1841
2086
|
" ",
|
|
1842
|
-
/* @__PURE__ */
|
|
2087
|
+
/* @__PURE__ */ jsx7("span", { children: item.title })
|
|
1843
2088
|
] }, item.id)) })
|
|
1844
2089
|
] });
|
|
1845
2090
|
}
|
|
1846
2091
|
function SessionDetails({ semantics }) {
|
|
1847
2092
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1848
|
-
return /* @__PURE__ */
|
|
1849
|
-
/* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
1851
|
-
semantics.fidelity ? /* @__PURE__ */
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
2093
|
+
return /* @__PURE__ */ jsxs6("details", { className: "scui-details", children: [
|
|
2094
|
+
/* @__PURE__ */ jsx7("summary", { children: "Session details" }),
|
|
2095
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
2096
|
+
semantics.fidelity ? /* @__PURE__ */ jsxs6("p", { children: [
|
|
2097
|
+
/* @__PURE__ */ jsx7("strong", { children: "Fidelity" }),
|
|
2098
|
+
/* @__PURE__ */ jsx7("span", { children: semantics.fidelity.replaceAll("_", " ") })
|
|
1854
2099
|
] }) : null,
|
|
1855
|
-
/* @__PURE__ */
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
2100
|
+
/* @__PURE__ */ jsxs6("p", { children: [
|
|
2101
|
+
/* @__PURE__ */ jsx7("strong", { children: "Native records" }),
|
|
2102
|
+
/* @__PURE__ */ jsx7("span", { children: semantics.rawRecords })
|
|
1858
2103
|
] }),
|
|
1859
|
-
semantics.residueCount ? /* @__PURE__ */
|
|
1860
|
-
/* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
2104
|
+
semantics.residueCount ? /* @__PURE__ */ jsxs6("p", { children: [
|
|
2105
|
+
/* @__PURE__ */ jsx7("strong", { children: "Residue" }),
|
|
2106
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
1862
2107
|
semantics.residueCount,
|
|
1863
2108
|
" retained"
|
|
1864
2109
|
] })
|
|
1865
2110
|
] }) : null,
|
|
1866
|
-
semantics.parseErrors ? /* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
1868
|
-
/* @__PURE__ */
|
|
2111
|
+
semantics.parseErrors ? /* @__PURE__ */ jsxs6("p", { children: [
|
|
2112
|
+
/* @__PURE__ */ jsx7("strong", { children: "Parse diagnostics" }),
|
|
2113
|
+
/* @__PURE__ */ jsx7("span", { children: semantics.parseErrors })
|
|
1869
2114
|
] }) : null,
|
|
1870
|
-
semantics.subagents.map((agent) => /* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
2115
|
+
semantics.subagents.map((agent) => /* @__PURE__ */ jsxs6("p", { children: [
|
|
2116
|
+
/* @__PURE__ */ jsxs6("strong", { children: [
|
|
1872
2117
|
agent.source,
|
|
1873
2118
|
" subagent"
|
|
1874
2119
|
] }),
|
|
1875
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
1876
2121
|
agent.messages,
|
|
1877
2122
|
" messages \xB7 ",
|
|
1878
2123
|
agent.fidelity.replaceAll("_", " ")
|
|
@@ -1885,13 +2130,13 @@ var conversationMemory = /* @__PURE__ */ new Map();
|
|
|
1885
2130
|
function ConversationAnnouncements({ state }) {
|
|
1886
2131
|
const previousBusy = useRef4(state.busy);
|
|
1887
2132
|
const [announcement, setAnnouncement] = useState3("");
|
|
1888
|
-
|
|
2133
|
+
useEffect5(() => {
|
|
1889
2134
|
if (previousBusy.current && !state.busy && !state.error) {
|
|
1890
2135
|
setAnnouncement(`${harnessDisplayName(state.harness) || "Coding agent"} finished working`);
|
|
1891
2136
|
}
|
|
1892
2137
|
previousBusy.current = state.busy;
|
|
1893
2138
|
}, [state.busy, state.error, state.harness]);
|
|
1894
|
-
return /* @__PURE__ */
|
|
2139
|
+
return /* @__PURE__ */ jsx7("span", { className: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1895
2140
|
}
|
|
1896
2141
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1897
2142
|
const scroller = useRef4(null);
|
|
@@ -1940,149 +2185,66 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1940
2185
|
else pin();
|
|
1941
2186
|
} else if (atBottom) pin();
|
|
1942
2187
|
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1943
|
-
return /* @__PURE__ */
|
|
1944
|
-
/* @__PURE__ */
|
|
1945
|
-
/* @__PURE__ */
|
|
2188
|
+
return /* @__PURE__ */ jsxs6("div", { className: "scui-conversation-wrap", children: [
|
|
2189
|
+
/* @__PURE__ */ jsx7(ConversationAnnouncements, { state }),
|
|
2190
|
+
/* @__PURE__ */ jsx7("div", { className: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1946
2191
|
const element = event.currentTarget;
|
|
1947
2192
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1948
2193
|
setAtBottom(bottom);
|
|
1949
2194
|
remember({ top: element.scrollTop, atBottom: bottom });
|
|
1950
|
-
}, children: /* @__PURE__ */
|
|
1951
|
-
Before ? /* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
1953
|
-
/* @__PURE__ */
|
|
1954
|
-
state.history.hasEarlier ? /* @__PURE__ */
|
|
2195
|
+
}, children: /* @__PURE__ */ jsxs6("div", { children: [
|
|
2196
|
+
Before ? /* @__PURE__ */ jsx7(Before, { state, adapter, value: null }) : null,
|
|
2197
|
+
/* @__PURE__ */ jsx7(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
2198
|
+
/* @__PURE__ */ jsx7(SessionDetails, { semantics: state.semantics }),
|
|
2199
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx7("button", { className: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1955
2200
|
const element = scroller.current;
|
|
1956
2201
|
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1957
2202
|
setAtBottom(false);
|
|
1958
2203
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1959
2204
|
}, children: "Load earlier messages" }) : null,
|
|
1960
|
-
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */
|
|
1961
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */
|
|
1962
|
-
blocks.map((block, index) => /* @__PURE__ */
|
|
1963
|
-
index === unreadBlock ? /* @__PURE__ */
|
|
1964
|
-
block.kind === "activity" ? /* @__PURE__ */
|
|
2205
|
+
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx7(LoadingStatus, { state }) : null,
|
|
2206
|
+
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx7(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx7("div", { className: "scui-empty", children: state.error ?? (state.harness ? `${harnessDisplayName(state.harness)} is listening. Say something.` : "No transcript yet.") }) : null,
|
|
2207
|
+
blocks.map((block, index) => /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
2208
|
+
index === unreadBlock ? /* @__PURE__ */ jsx7("div", { className: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx7("span", { children: "New" }) }) : null,
|
|
2209
|
+
block.kind === "activity" ? /* @__PURE__ */ jsx7(Group, { value: block.entries, entries: block.entries, state, adapter }) : /* @__PURE__ */ jsx7(Entry, { value: block.entry, entry: block.entry, state, adapter })
|
|
1965
2210
|
] }, block.id)),
|
|
1966
|
-
pendingMessage ? /* @__PURE__ */
|
|
1967
|
-
/* @__PURE__ */
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
/* @__PURE__ */
|
|
1971
|
-
/* @__PURE__ */
|
|
1972
|
-
pendingMessage.status === "failed" ? /* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
2211
|
+
pendingMessage ? /* @__PURE__ */ jsxs6("article", { className: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
2212
|
+
/* @__PURE__ */ jsx7(MessageImages, { items: pendingMessage.images, adapter }),
|
|
2213
|
+
/* @__PURE__ */ jsx7(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
2214
|
+
/* @__PURE__ */ jsx7(ContextDisclosure, { context: pendingMessage.context }),
|
|
2215
|
+
/* @__PURE__ */ jsxs6("footer", { children: [
|
|
2216
|
+
/* @__PURE__ */ jsx7("small", { children: pendingMessage.status === "failed" ? "Not sent" : "Sending\u2026" }),
|
|
2217
|
+
pendingMessage.status === "failed" ? /* @__PURE__ */ jsxs6("span", { children: [
|
|
2218
|
+
/* @__PURE__ */ jsx7("button", { type: "button", onClick: pendingMessage.onRetry, children: "Retry" }),
|
|
2219
|
+
/* @__PURE__ */ jsx7("button", { type: "button", onClick: pendingMessage.onEdit, children: "Edit" })
|
|
1975
2220
|
] }) : null
|
|
1976
2221
|
] })
|
|
1977
2222
|
] }) : null,
|
|
1978
|
-
state.busy ? /* @__PURE__ */
|
|
1979
|
-
/* @__PURE__ */
|
|
1980
|
-
/* @__PURE__ */
|
|
1981
|
-
/* @__PURE__ */
|
|
1982
|
-
/* @__PURE__ */
|
|
1983
|
-
/* @__PURE__ */
|
|
2223
|
+
state.busy ? /* @__PURE__ */ jsxs6("div", { className: "scui-working", role: "status", children: [
|
|
2224
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2225
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
2226
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
2227
|
+
/* @__PURE__ */ jsx7("i", {}),
|
|
2228
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1984
2229
|
harnessDisplayName(state.harness),
|
|
1985
2230
|
" is working"
|
|
1986
2231
|
] })
|
|
1987
2232
|
] }) : null,
|
|
1988
|
-
After ? /* @__PURE__ */
|
|
2233
|
+
After ? /* @__PURE__ */ jsx7(After, { state, adapter, value: null }) : null
|
|
1989
2234
|
] }) }),
|
|
1990
|
-
!atBottom ? /* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
2235
|
+
!atBottom ? /* @__PURE__ */ jsxs6("button", { className: "scui-latest", type: "button", onClick: pin, children: [
|
|
2236
|
+
/* @__PURE__ */ jsx7(UiIcon, { name: "down", size: 13 }),
|
|
1992
2237
|
" Latest"
|
|
1993
2238
|
] }) : null
|
|
1994
2239
|
] });
|
|
1995
2240
|
}
|
|
1996
2241
|
|
|
1997
|
-
// src/logo.jsx
|
|
1998
|
-
import { useEffect as useEffect5 } from "preact/hooks";
|
|
1999
|
-
import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
2000
|
-
var LOGOS = {
|
|
2001
|
-
"claude-code": {
|
|
2002
|
-
viewBox: "-1 3.5 26 18",
|
|
2003
|
-
paths: [
|
|
2004
|
-
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z" }]
|
|
2005
|
-
]
|
|
2006
|
-
},
|
|
2007
|
-
codex: {
|
|
2008
|
-
viewBox: "-1 -1 26 26",
|
|
2009
|
-
paths: [
|
|
2010
|
-
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z" }]
|
|
2011
|
-
]
|
|
2012
|
-
},
|
|
2013
|
-
gemini: {
|
|
2014
|
-
viewBox: "0 0 24 24",
|
|
2015
|
-
paths: [["path", { d: "M12 24C12 17.373 6.627 12 0 12 6.627 12 12 6.627 12 0c0 6.627 5.373 12 12 12-6.627 0-12 5.373-12 12z" }]]
|
|
2016
|
-
},
|
|
2017
|
-
grok: {
|
|
2018
|
-
viewBox: "-1 -1 26 26",
|
|
2019
|
-
paths: [["path", { d: "M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815" }]]
|
|
2020
|
-
},
|
|
2021
|
-
// Canonical mark from block/goose's documentation/static/img/goose.svg.
|
|
2022
|
-
goose: {
|
|
2023
|
-
viewBox: "0 0 45 45",
|
|
2024
|
-
paths: [["path", { d: "M43.2098 39.2492L39.8118 36.4522C37.9646 34.9318 36.3923 33.1051 35.1631 31.0529C33.4647 28.2172 31.1178 25.8243 28.3164 24.071L26.9482 23.2744C26.4794 22.9485 26.1525 22.4405 26.106 21.8675C26.0762 21.4981 26.1647 21.1678 26.3712 20.8771C27.0837 19.873 30.9617 15.6995 31.6365 15.1411C32.5056 14.4228 33.4739 13.8253 34.3724 13.1412C34.5001 13.0438 34.6283 12.9469 34.7545 12.8481C35.0574 12.6088 35.3295 12.3671 35.5458 12.0803C36.5993 10.8604 36.5783 9.82938 36.5783 9.82938C36.4677 9.5534 36.0645 8.69902 35.2449 8.29825C35.9696 8.28406 36.7872 8.55564 37.1582 8.91873C37.6039 8.21947 37.8922 7.76585 38.3404 7.00347C38.4471 6.82241 38.5038 6.48771 38.2998 6.30029C38.1114 6.11287 37.6416 6.01697 37.4606 6.12364C36.4692 6.70693 35.5047 7.33475 34.6351 7.88525C34.6351 7.88525 33.6046 7.86372 32.3842 8.91775C32.097 9.13452 31.8552 9.4066 31.6282 9.69433C31.5171 9.83476 31.4202 9.96297 31.3233 10.0912C30.6387 10.9901 30.0417 11.958 29.3234 12.8271C28.7656 13.5023 24.5915 17.3798 23.5874 18.0923C23.2967 18.2988 22.9669 18.3879 22.597 18.3575C22.0245 18.3115 21.5161 17.9842 21.1902 17.5154L20.3935 16.1472C18.6402 13.3448 16.2474 10.9989 13.4117 9.30041C11.3594 8.0712 9.5332 6.49847 8.01234 4.65172L5.2153 1.25377C5.0773 1.08642 4.81306 1.11382 4.71422 1.30662C4.39615 1.92612 3.78888 3.23411 3.32353 4.99327C3.92786 5.81095 5.26717 7.35089 6.8624 8.65351C6.97348 8.74403 6.88246 8.92313 6.74447 8.88496C5.36846 8.51013 4.03062 7.90825 3.02944 7.39542C2.94772 7.35383 2.84887 7.4057 2.83713 7.49672C2.68152 8.74354 2.64139 10.1127 2.80581 11.5562C4.02572 12.1596 5.85143 12.8804 7.76816 13.3389C7.90713 13.3722 7.90273 13.5723 7.76229 13.5992C6.26982 13.8801 4.70688 13.9427 3.43656 13.9261C3.3475 13.9251 3.28193 14.0093 3.30591 14.0949C3.56085 14.9958 3.90632 15.9118 4.3619 16.8342C4.55029 17.2487 4.75532 17.6553 4.97504 18.0532C6.21207 18.107 7.47946 17.9964 8.75369 17.7713C8.97095 17.7331 9.08741 18.0189 8.90391 18.1417C8.03877 18.7201 7.11588 19.2183 6.25758 19.6283C6.14259 19.6836 6.1054 19.8304 6.18125 19.9327C6.69114 20.6236 7.25191 21.2774 7.86114 21.8866C7.86114 21.8866 10.8608 24.9763 10.9425 25.2185C12.6928 23.4261 15.5701 21.4394 18.7474 19.7047C14.4921 23.1672 12.1198 25.7235 10.9258 27.1758L10.0935 28.3439C9.66091 28.9507 9.2856 29.5951 8.97193 30.2709C7.92231 32.5292 6.19201 37.0966 6.19201 37.0966C6.0594 37.4543 6.16755 37.8072 6.39753 38.0371C6.66031 38.2999 7.01263 38.4076 7.37033 38.275C7.37033 38.275 11.9368 36.5447 14.1961 35.495C14.8719 35.1814 15.5168 34.8056 16.1231 34.3735L17.4095 33.457C18.0907 32.9715 19.0234 33.0489 19.615 33.6405L22.5804 36.6058C23.1896 37.2151 23.8433 37.7758 24.5343 38.2857C24.637 38.3611 24.7833 38.3244 24.8386 38.2094C25.2492 37.3516 25.7473 36.4277 26.3252 35.5631C26.4481 35.3796 26.7343 35.4965 26.6957 35.7133C26.4701 36.988 26.3605 38.2554 26.3086 39.3035C27.2178 39.9172 28.5551 40.5606 30.3721 41.1611C30.4577 41.185 30.5419 41.1195 30.5409 41.0304C30.5237 39.7596 30.5864 38.1967 30.8677 36.7047C30.8942 36.5638 31.0943 36.5593 31.1281 36.6988C31.5861 38.616 32.3069 40.4417 32.8041 41.5829C34.3543 41.8256 35.7234 41.7855 36.9703 41.6298C37.0618 41.6186 37.1136 41.5197 37.0715 41.4375C36.5587 40.4364 35.9568 39.0975 35.582 37.7225C35.5443 37.584 35.7229 37.4935 35.8135 37.6046C37.1161 39.1998 38.656 40.5391 39.3548 41.1175C41.2333 40.6786 42.5413 40.0713 43.1604 39.7528C43.3532 39.6539 43.3806 39.3897 43.2132 39.2517Z" }]]
|
|
2025
|
-
},
|
|
2026
|
-
opencode: { viewBox: "2.5 0 19 24", paths: [["path", { d: "M16 6H8v12h8V6zm4 16H4V2h16v20z" }]] },
|
|
2027
|
-
pi: {
|
|
2028
|
-
viewBox: "0 0 24 24",
|
|
2029
|
-
paths: [
|
|
2030
|
-
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
|
|
2031
|
-
["path", { d: "M17.5 12H23v11h-5.5V12z" }]
|
|
2032
|
-
]
|
|
2033
|
-
},
|
|
2034
|
-
// Product mark shared with the first-party browser frontend favicon.
|
|
2035
|
-
supercode: {
|
|
2036
|
-
viewBox: "0 0 64 64",
|
|
2037
|
-
paths: [
|
|
2038
|
-
["rect", { width: "64", height: "64", rx: "14", fill: "#111923" }],
|
|
2039
|
-
["path", { d: "M18 21h28v6H18zm0 13h18v6H18z", fill: "#5f8fff" }],
|
|
2040
|
-
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", "stroke-width": "4" }]
|
|
2041
|
-
]
|
|
2042
|
-
}
|
|
2043
|
-
};
|
|
2044
|
-
function hasHarnessLogo(id) {
|
|
2045
|
-
return Object.hasOwn(LOGOS, id);
|
|
2046
|
-
}
|
|
2047
|
-
var LOGO_CHROME = {
|
|
2048
|
-
codex: { background: "#f7f7f5", color: "#111" },
|
|
2049
|
-
gemini: { background: "#f7f7f5", color: "#6e79dc" },
|
|
2050
|
-
goose: { background: "#f7f7f5", color: "#101010" },
|
|
2051
|
-
pi: { background: "#efefeb", color: "#111" },
|
|
2052
|
-
supercode: { background: "#111923", color: "#f7f7f5" }
|
|
2053
|
-
};
|
|
2054
|
-
function escapeSvgAttribute(value) {
|
|
2055
|
-
return String(value).replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
2056
|
-
}
|
|
2057
|
-
function harnessLogoDataUrl(id) {
|
|
2058
|
-
const logo = LOGOS[id];
|
|
2059
|
-
if (!logo) return null;
|
|
2060
|
-
const chrome = LOGO_CHROME[id] ?? { background: "#111", color: id === "claude-code" ? "#d97757" : "#f7f7f5" };
|
|
2061
|
-
const glyph = logo.paths.map(([tag, attributes]) => {
|
|
2062
|
-
const serialized = Object.entries(attributes).map(([name, value]) => `${name}="${escapeSvgAttribute(value)}"`).join(" ");
|
|
2063
|
-
return `<${tag} ${serialized}/>`;
|
|
2064
|
-
}).join("");
|
|
2065
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle cx="20" cy="20" r="19" fill="${chrome.background}" stroke="#383a42"/><svg x="7" y="7" width="26" height="26" viewBox="${logo.viewBox}" color="${chrome.color}" fill="currentColor" preserveAspectRatio="xMidYMid meet">${glyph}</svg></svg>`;
|
|
2066
|
-
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
2067
|
-
}
|
|
2068
|
-
function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
2069
|
-
const logo = LOGOS[id];
|
|
2070
|
-
useEffect5(() => {
|
|
2071
|
-
if (!logo) onMissingLogo?.(id);
|
|
2072
|
-
}, [id, logo, onMissingLogo]);
|
|
2073
|
-
if (!logo) return null;
|
|
2074
|
-
return /* @__PURE__ */ jsxs5("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
|
|
2075
|
-
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
2076
|
-
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
2077
|
-
] });
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
2242
|
// src/messenger.jsx
|
|
2081
2243
|
import { useEffect as useEffect8, useId as useId3, useMemo as useMemo3, useRef as useRef7, useState as useState6 } from "preact/hooks";
|
|
2082
2244
|
|
|
2083
2245
|
// src/sessions.jsx
|
|
2084
2246
|
import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect3, useRef as useRef5, useState as useState4 } from "preact/hooks";
|
|
2085
|
-
import { jsx as
|
|
2247
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
2086
2248
|
var sessionListMemory = /* @__PURE__ */ new Map();
|
|
2087
2249
|
function sessionPathParts(value) {
|
|
2088
2250
|
const complete = String(value ?? "").replaceAll("\\", "/");
|
|
@@ -2105,32 +2267,32 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2105
2267
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2106
2268
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2107
2269
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2108
|
-
return /* @__PURE__ */
|
|
2109
|
-
/* @__PURE__ */
|
|
2110
|
-
/* @__PURE__ */
|
|
2111
|
-
/* @__PURE__ */
|
|
2112
|
-
/* @__PURE__ */
|
|
2113
|
-
/* @__PURE__ */
|
|
2270
|
+
return /* @__PURE__ */ jsxs7("button", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
2271
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2272
|
+
/* @__PURE__ */ jsxs7("span", { className: "scui-session-copy", children: [
|
|
2273
|
+
/* @__PURE__ */ jsxs7("span", { className: "scui-session-title", children: [
|
|
2274
|
+
/* @__PURE__ */ jsx8("strong", { children: title }),
|
|
2275
|
+
/* @__PURE__ */ jsx8("span", { className: "scui-session-meta", children: age ? /* @__PURE__ */ jsx8("time", { children: age }) : null })
|
|
2114
2276
|
] }),
|
|
2115
|
-
path.complete ? /* @__PURE__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
2117
|
-
path.separator ? /* @__PURE__ */
|
|
2118
|
-
path.trailing ? /* @__PURE__ */
|
|
2277
|
+
path.complete ? /* @__PURE__ */ jsxs7("small", { className: "scui-session-path", title: row.cwd, children: [
|
|
2278
|
+
/* @__PURE__ */ jsx8("span", { className: "scui-session-path-leading", children: path.leading }),
|
|
2279
|
+
path.separator ? /* @__PURE__ */ jsx8("span", { className: "scui-session-path-separator", children: path.separator }) : null,
|
|
2280
|
+
path.trailing ? /* @__PURE__ */ jsx8("span", { className: "scui-session-path-trailing", children: path.trailing }) : null
|
|
2119
2281
|
] }) : null,
|
|
2120
|
-
working || preview || unreadCount ? /* @__PURE__ */
|
|
2121
|
-
working ? /* @__PURE__ */
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
2282
|
+
working || preview || unreadCount ? /* @__PURE__ */ jsxs7("span", { className: "scui-session-preview", children: [
|
|
2283
|
+
working ? /* @__PURE__ */ jsxs7("span", { className: "scui-session-working", "aria-hidden": "true", children: [
|
|
2284
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
2285
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
2286
|
+
/* @__PURE__ */ jsx8("i", {})
|
|
2125
2287
|
] }) : null,
|
|
2126
|
-
preview || working ? /* @__PURE__ */
|
|
2127
|
-
unreadCount ? /* @__PURE__ */
|
|
2288
|
+
preview || working ? /* @__PURE__ */ jsx8("small", { children: preview || "Working\u2026" }) : null,
|
|
2289
|
+
unreadCount ? /* @__PURE__ */ jsx8("b", { "aria-label": `${unreadCount} unread messages`, children: unreadLabel }) : null
|
|
2128
2290
|
] }) : null,
|
|
2129
|
-
state.attachError?.key === row.key ? /* @__PURE__ */
|
|
2291
|
+
state.attachError?.key === row.key ? /* @__PURE__ */ jsx8("em", { children: state.attachError.message }) : null
|
|
2130
2292
|
] })
|
|
2131
2293
|
] });
|
|
2132
2294
|
}
|
|
2133
|
-
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2295
|
+
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, slots = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2134
2296
|
const remembered = sessionListMemory.get(memoryKey) ?? { query: "", top: 0 };
|
|
2135
2297
|
const [query, setQuery] = useState4(remembered.query);
|
|
2136
2298
|
const [loadingMore, setLoadingMore] = useState4(false);
|
|
@@ -2139,6 +2301,8 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2139
2301
|
const rowScroller = useRef5(null);
|
|
2140
2302
|
const rows = filterSessions(state.sessions, query);
|
|
2141
2303
|
const Row = components.SessionRow ?? SessionRow;
|
|
2304
|
+
const BeforeSessions = slots.beforeSessions;
|
|
2305
|
+
const AfterSessions = slots.afterSessions;
|
|
2142
2306
|
useLayoutEffect3(() => {
|
|
2143
2307
|
if (rowScroller.current) rowScroller.current.scrollTop = remembered.top;
|
|
2144
2308
|
}, [memoryKey]);
|
|
@@ -2162,51 +2326,53 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2162
2326
|
Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
|
|
2163
2327
|
}
|
|
2164
2328
|
};
|
|
2165
|
-
return /* @__PURE__ */
|
|
2166
|
-
/* @__PURE__ */
|
|
2167
|
-
/* @__PURE__ */
|
|
2168
|
-
/* @__PURE__ */
|
|
2169
|
-
/* @__PURE__ */
|
|
2329
|
+
return /* @__PURE__ */ jsxs7("section", { className: "scui-list", ref: root, children: [
|
|
2330
|
+
/* @__PURE__ */ jsxs7("header", { className: "scui-head", children: [
|
|
2331
|
+
/* @__PURE__ */ jsxs7("span", { className: "scui-head-copy", children: [
|
|
2332
|
+
/* @__PURE__ */ jsx8("strong", { children: labels.chats }),
|
|
2333
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
2170
2334
|
state.sessions.length,
|
|
2171
2335
|
" recent conversations"
|
|
2172
2336
|
] })
|
|
2173
2337
|
] }),
|
|
2174
|
-
HeaderActions ? /* @__PURE__ */
|
|
2175
|
-
/* @__PURE__ */
|
|
2176
|
-
onClose ? /* @__PURE__ */
|
|
2338
|
+
HeaderActions ? /* @__PURE__ */ jsx8(HeaderActions, { state, adapter, value: "list" }) : null,
|
|
2339
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "data-list-focus": "new", "aria-label": labels.newChat, disabled: !state.harnesses.some((item) => item.startable), onClick: onNew, children: /* @__PURE__ */ jsx8(UiIcon, { name: "plus", size: 18 }) }),
|
|
2340
|
+
onClose ? /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2177
2341
|
] }),
|
|
2178
|
-
state.startup !== "ready" ? /* @__PURE__ */
|
|
2179
|
-
state.sessions.length > 4 ? /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2342
|
+
state.startup !== "ready" ? /* @__PURE__ */ jsx8(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
2343
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs7("label", { className: "scui-search", children: [
|
|
2344
|
+
/* @__PURE__ */ jsx8(UiIcon, { name: "search", size: 15 }),
|
|
2345
|
+
/* @__PURE__ */ jsx8("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
|
|
2182
2346
|
const value = event.currentTarget.value;
|
|
2183
2347
|
setQuery(value);
|
|
2184
2348
|
boundedSet(sessionListMemory, memoryKey, { query: value, top: 0 });
|
|
2185
2349
|
if (rowScroller.current) rowScroller.current.scrollTop = 0;
|
|
2186
2350
|
} }),
|
|
2187
|
-
/* @__PURE__ */
|
|
2351
|
+
/* @__PURE__ */ jsx8("small", { children: rows.length })
|
|
2188
2352
|
] }) : null,
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
|
|
2191
|
-
rows.
|
|
2192
|
-
|
|
2353
|
+
/* @__PURE__ */ jsxs7("div", { className: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
|
|
2354
|
+
BeforeSessions ? /* @__PURE__ */ jsx8(BeforeSessions, { state, adapter, value: { query, rows } }) : null,
|
|
2355
|
+
!rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx8("div", { className: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
|
|
2356
|
+
rows.map((row) => /* @__PURE__ */ jsx8(Row, { value: row, row, state, adapter, onOpen, now }, row.key)),
|
|
2357
|
+
state.history.hasMoreSessions ? /* @__PURE__ */ jsx8("button", { className: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null,
|
|
2358
|
+
AfterSessions ? /* @__PURE__ */ jsx8(AfterSessions, { state, adapter, value: { query, rows } }) : null
|
|
2193
2359
|
] })
|
|
2194
2360
|
] });
|
|
2195
2361
|
}
|
|
2196
2362
|
|
|
2197
2363
|
// src/settings.jsx
|
|
2198
2364
|
import { useEffect as useEffect7, useId as useId2, useMemo as useMemo2, useRef as useRef6, useState as useState5 } from "preact/hooks";
|
|
2199
|
-
import { jsx as
|
|
2365
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
2200
2366
|
function HarnessAdvisory({ state, onReview }) {
|
|
2201
2367
|
const advisory = state.interopSettings?.advisories[0];
|
|
2202
2368
|
if (!advisory && !state.interopSettingsError) return null;
|
|
2203
|
-
return /* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2369
|
+
return /* @__PURE__ */ jsxs8("div", { className: "scui-advisory", "data-severity": advisory?.severity ?? "error", role: advisory?.severity === "error" || !advisory ? "alert" : "status", children: [
|
|
2370
|
+
/* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: "!" }),
|
|
2371
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2372
|
+
/* @__PURE__ */ jsx9("strong", { children: advisory?.title ?? "Could not inspect harness settings" }),
|
|
2373
|
+
/* @__PURE__ */ jsx9("small", { children: advisory?.message ?? state.interopSettingsError })
|
|
2208
2374
|
] }),
|
|
2209
|
-
advisory && state.canConfigureSettings ? /* @__PURE__ */
|
|
2375
|
+
advisory && state.canConfigureSettings ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => onReview(advisory.recommendation.change), children: "Review" }) : null
|
|
2210
2376
|
] });
|
|
2211
2377
|
}
|
|
2212
2378
|
function initialValues(report, recommendedChange) {
|
|
@@ -2234,11 +2400,11 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2234
2400
|
document.addEventListener("keydown", dismiss);
|
|
2235
2401
|
return () => document.removeEventListener("keydown", dismiss);
|
|
2236
2402
|
}, [onClose]);
|
|
2237
|
-
if (!report) return /* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2240
|
-
/* @__PURE__ */
|
|
2241
|
-
/* @__PURE__ */
|
|
2403
|
+
if (!report) return /* @__PURE__ */ jsx9("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: /* @__PURE__ */ jsxs8("header", { children: [
|
|
2404
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }),
|
|
2405
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2406
|
+
/* @__PURE__ */ jsx9("strong", { id: titleId, children: "Harness settings" }),
|
|
2407
|
+
/* @__PURE__ */ jsx9("small", { children: state.interopSettingsError ?? "No interoperability controls are available." })
|
|
2242
2408
|
] })
|
|
2243
2409
|
] }) });
|
|
2244
2410
|
const changed = report.controls.flatMap((control) => values[control.key] !== (control.configuredValue ?? control.effectiveValue ?? control.choices[0]?.value ?? null) ? [{ key: control.key, value: values[control.key] ?? null }] : []);
|
|
@@ -2247,61 +2413,86 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2247
2413
|
if (!changed.length || !state.canConfigureSettings) return;
|
|
2248
2414
|
adapter.onIntent({ action: "configureHarness", harness: report.harness, changes: changed, expectedRevision: report.revision });
|
|
2249
2415
|
};
|
|
2250
|
-
return /* @__PURE__ */
|
|
2251
|
-
/* @__PURE__ */
|
|
2252
|
-
/* @__PURE__ */
|
|
2253
|
-
/* @__PURE__ */
|
|
2254
|
-
/* @__PURE__ */
|
|
2416
|
+
return /* @__PURE__ */ jsxs8("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [
|
|
2417
|
+
/* @__PURE__ */ jsxs8("header", { children: [
|
|
2418
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }),
|
|
2419
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2420
|
+
/* @__PURE__ */ jsxs8("strong", { id: titleId, children: [
|
|
2255
2421
|
harnessDisplayName(report.harness),
|
|
2256
2422
|
" interoperability"
|
|
2257
2423
|
] }),
|
|
2258
|
-
/* @__PURE__ */
|
|
2424
|
+
/* @__PURE__ */ jsx9("small", { children: "Native harness settings used by Supercode" })
|
|
2259
2425
|
] })
|
|
2260
2426
|
] }),
|
|
2261
|
-
/* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsxs8("form", { onSubmit: submit, children: [
|
|
2262
2428
|
report.controls.map((control) => {
|
|
2263
2429
|
const choice = control.choices.find((item) => item.value === values[control.key]);
|
|
2264
2430
|
const recommendation = report.advisories.map((advisory) => advisory.recommendation).find((item) => item.change.key === control.key && item.change.value === values[control.key]);
|
|
2265
2431
|
const consequence = choice?.risk ?? recommendation?.consequence;
|
|
2266
|
-
return /* @__PURE__ */
|
|
2267
|
-
/* @__PURE__ */
|
|
2268
|
-
/* @__PURE__ */
|
|
2269
|
-
/* @__PURE__ */
|
|
2432
|
+
return /* @__PURE__ */ jsxs8("fieldset", { disabled: !control.writable || Boolean(state.operation), children: [
|
|
2433
|
+
/* @__PURE__ */ jsxs8("label", { htmlFor: `scui-setting-${control.key}`, children: [
|
|
2434
|
+
/* @__PURE__ */ jsx9("strong", { children: control.label }),
|
|
2435
|
+
/* @__PURE__ */ jsx9("small", { children: control.description })
|
|
2270
2436
|
] }),
|
|
2271
|
-
/* @__PURE__ */
|
|
2272
|
-
control.resettable ? /* @__PURE__ */
|
|
2273
|
-
control.choices.map((item) => /* @__PURE__ */
|
|
2437
|
+
/* @__PURE__ */ jsxs8("select", { id: `scui-setting-${control.key}`, value: values[control.key] ?? "@default", onChange: (event) => setValues((current) => ({ ...current, [control.key]: event.currentTarget.value === "@default" ? null : event.currentTarget.value })), children: [
|
|
2438
|
+
control.resettable ? /* @__PURE__ */ jsx9("option", { value: "@default", children: "Use harness default" }) : null,
|
|
2439
|
+
control.choices.map((item) => /* @__PURE__ */ jsx9("option", { value: item.value, children: item.label }, item.value))
|
|
2274
2440
|
] }),
|
|
2275
|
-
choice ? /* @__PURE__ */
|
|
2276
|
-
consequence ? /* @__PURE__ */
|
|
2277
|
-
/* @__PURE__ */
|
|
2441
|
+
choice ? /* @__PURE__ */ jsx9("p", { children: choice.description }) : null,
|
|
2442
|
+
consequence ? /* @__PURE__ */ jsxs8("p", { className: "scui-setting-risk", children: [
|
|
2443
|
+
/* @__PURE__ */ jsx9("strong", { children: "Security consequence" }),
|
|
2278
2444
|
consequence
|
|
2279
2445
|
] }) : null,
|
|
2280
|
-
/* @__PURE__ */
|
|
2446
|
+
/* @__PURE__ */ jsxs8("small", { className: "scui-setting-source", children: [
|
|
2281
2447
|
control.effectiveNote,
|
|
2282
2448
|
control.sourcePath ? ` Source: ${control.sourcePath}` : ""
|
|
2283
2449
|
] })
|
|
2284
2450
|
] }, control.key);
|
|
2285
2451
|
}),
|
|
2286
|
-
/* @__PURE__ */
|
|
2287
|
-
/* @__PURE__ */
|
|
2288
|
-
/* @__PURE__ */
|
|
2452
|
+
/* @__PURE__ */ jsxs8("footer", { children: [
|
|
2453
|
+
/* @__PURE__ */ jsx9("button", { type: "button", onClick: onClose, children: "Cancel" }),
|
|
2454
|
+
/* @__PURE__ */ jsx9("button", { type: "submit", disabled: !changed.length || !state.canConfigureSettings || Boolean(state.operation), children: state.operation === "configureHarness" ? "Applying\u2026" : "Apply changes" })
|
|
2289
2455
|
] })
|
|
2290
2456
|
] })
|
|
2291
2457
|
] });
|
|
2292
2458
|
}
|
|
2459
|
+
function HarnessReadiness({ harnesses, adapter }) {
|
|
2460
|
+
const blocked = harnesses.filter((item) => !item.startable);
|
|
2461
|
+
if (!blocked.length) return null;
|
|
2462
|
+
return /* @__PURE__ */ jsxs8("details", { className: "scui-readiness", open: !harnesses.some((item) => item.startable), children: [
|
|
2463
|
+
/* @__PURE__ */ jsxs8("summary", { children: [
|
|
2464
|
+
blocked.length,
|
|
2465
|
+
" ",
|
|
2466
|
+
blocked.length === 1 ? "harness needs" : "harnesses need",
|
|
2467
|
+
" setup"
|
|
2468
|
+
] }),
|
|
2469
|
+
/* @__PURE__ */ jsx9("div", { children: blocked.map((item) => /* @__PURE__ */ jsxs8("section", { children: [
|
|
2470
|
+
/* @__PURE__ */ jsx9(HarnessLogo, { id: item.id, size: 25 }),
|
|
2471
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2472
|
+
/* @__PURE__ */ jsx9("strong", { children: item.label }),
|
|
2473
|
+
/* @__PURE__ */ jsx9("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") }),
|
|
2474
|
+
item.protocol ? /* @__PURE__ */ jsxs8("em", { children: [
|
|
2475
|
+
item.protocol,
|
|
2476
|
+
" \xB7 ",
|
|
2477
|
+
item.runtime
|
|
2478
|
+
] }) : null
|
|
2479
|
+
] }),
|
|
2480
|
+
item.repair ? /* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2481
|
+
] }, item.id)) })
|
|
2482
|
+
] });
|
|
2483
|
+
}
|
|
2293
2484
|
|
|
2294
2485
|
// src/messenger.jsx
|
|
2295
|
-
import { jsx as
|
|
2486
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
2296
2487
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
2297
2488
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
2298
2489
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
2299
|
-
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2490
|
+
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "steer", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2300
2491
|
function Receipt({ state, adapter }) {
|
|
2301
2492
|
const receipt = state.reductionReceipt;
|
|
2302
|
-
if (receipt) return /* @__PURE__ */
|
|
2303
|
-
/* @__PURE__ */
|
|
2304
|
-
/* @__PURE__ */
|
|
2493
|
+
if (receipt) return /* @__PURE__ */ jsx10("div", { className: "scui-receipt", children: /* @__PURE__ */ jsxs9("span", { children: [
|
|
2494
|
+
/* @__PURE__ */ jsx10("strong", { children: "Reduced and verified" }),
|
|
2495
|
+
/* @__PURE__ */ jsxs9("small", { children: [
|
|
2305
2496
|
receipt.sourceTokens.toLocaleString(),
|
|
2306
2497
|
" \u2192 ",
|
|
2307
2498
|
receipt.reducedTokens.toLocaleString(),
|
|
@@ -2310,27 +2501,27 @@ function Receipt({ state, adapter }) {
|
|
|
2310
2501
|
"\xD7 \xB7 reversible"
|
|
2311
2502
|
] })
|
|
2312
2503
|
] }) });
|
|
2313
|
-
if (state.exportReceipt) return /* @__PURE__ */
|
|
2314
|
-
/* @__PURE__ */
|
|
2315
|
-
/* @__PURE__ */
|
|
2504
|
+
if (state.exportReceipt) return /* @__PURE__ */ jsxs9("div", { className: "scui-receipt", children: [
|
|
2505
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2506
|
+
/* @__PURE__ */ jsxs9("strong", { children: [
|
|
2316
2507
|
"Lossless export ready \xB7 ",
|
|
2317
2508
|
harnessDisplayName(state.exportReceipt.targetHarness)
|
|
2318
2509
|
] }),
|
|
2319
|
-
/* @__PURE__ */
|
|
2510
|
+
/* @__PURE__ */ jsxs9("small", { children: [
|
|
2320
2511
|
state.exportReceipt.path,
|
|
2321
2512
|
" \xB7 ",
|
|
2322
2513
|
state.exportReceipt.files,
|
|
2323
2514
|
" files"
|
|
2324
2515
|
] })
|
|
2325
2516
|
] }),
|
|
2326
|
-
/* @__PURE__ */
|
|
2517
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter.copyText?.(state.exportReceipt.path), children: "Copy path" })
|
|
2327
2518
|
] });
|
|
2328
|
-
if (state.terminalHandoff) return /* @__PURE__ */
|
|
2329
|
-
/* @__PURE__ */
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
/* @__PURE__ */
|
|
2519
|
+
if (state.terminalHandoff) return /* @__PURE__ */ jsxs9("div", { className: "scui-receipt", children: [
|
|
2520
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2521
|
+
/* @__PURE__ */ jsx10("strong", { children: "Terminal handoff ready" }),
|
|
2522
|
+
/* @__PURE__ */ jsx10("small", { children: state.terminalHandoff.cwd })
|
|
2332
2523
|
] }),
|
|
2333
|
-
/* @__PURE__ */
|
|
2524
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter.copyText?.(terminalCommand(state.terminalHandoff)), children: "Copy command" })
|
|
2334
2525
|
] });
|
|
2335
2526
|
return null;
|
|
2336
2527
|
}
|
|
@@ -2382,7 +2573,7 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2382
2573
|
const dispatch = (item) => {
|
|
2383
2574
|
setOpen(false);
|
|
2384
2575
|
if (item.onSelect) item.onSelect();
|
|
2385
|
-
else adapter
|
|
2576
|
+
else dispatchConfirmedIntent(adapter, item.intent);
|
|
2386
2577
|
};
|
|
2387
2578
|
const navigate = (event) => {
|
|
2388
2579
|
if (event.key === "Escape") {
|
|
@@ -2400,13 +2591,13 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2400
2591
|
const index = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : (current <= 0 ? items.length : current) - 1;
|
|
2401
2592
|
items[index].focus({ preventScroll: true });
|
|
2402
2593
|
};
|
|
2403
|
-
return /* @__PURE__ */
|
|
2594
|
+
return /* @__PURE__ */ jsxs9("div", { className: "scui-menu", ref: root, onBlur: (event) => {
|
|
2404
2595
|
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
2405
2596
|
}, children: [
|
|
2406
|
-
/* @__PURE__ */
|
|
2407
|
-
open ? /* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2409
|
-
group.items.map((item) => /* @__PURE__ */
|
|
2597
|
+
/* @__PURE__ */ jsx10("button", { ref: trigger, className: "scui-menu-trigger", type: "button", "aria-label": "Conversation actions", "aria-haspopup": "menu", "aria-expanded": open, "aria-controls": open ? menuId : void 0, onClick: () => setOpen((value) => !value), children: /* @__PURE__ */ jsx10(UiIcon, { name: "menu", size: 18 }) }),
|
|
2598
|
+
open ? /* @__PURE__ */ jsx10("div", { ref: panel, id: menuId, className: "scui-menu-panel", role: "menu", "aria-label": "Conversation actions", onKeyDown: navigate, children: groups.map((group) => /* @__PURE__ */ jsxs9("section", { role: "group", "aria-label": group.label, children: [
|
|
2599
|
+
/* @__PURE__ */ jsx10("strong", { children: group.label }),
|
|
2600
|
+
group.items.map((item) => /* @__PURE__ */ jsx10("button", { role: "menuitem", type: "button", disabled: actionPending, onClick: () => dispatch(item), children: item.label }, item.key))
|
|
2410
2601
|
] }, group.label)) }) : null
|
|
2411
2602
|
] });
|
|
2412
2603
|
}
|
|
@@ -2419,24 +2610,24 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2419
2610
|
useEffect8(() => {
|
|
2420
2611
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
2421
2612
|
}, []);
|
|
2422
|
-
return /* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__PURE__ */
|
|
2425
|
-
/* @__PURE__ */
|
|
2426
|
-
/* @__PURE__ */
|
|
2427
|
-
/* @__PURE__ */
|
|
2613
|
+
return /* @__PURE__ */ jsxs9("header", { className: "scui-head scui-chat-head", children: [
|
|
2614
|
+
/* @__PURE__ */ jsx10("button", { ref: back, type: "button", "aria-label": "Back to chats", onClick: onBack, children: /* @__PURE__ */ jsx10(UiIcon, { name: "back", size: 18 }) }),
|
|
2615
|
+
/* @__PURE__ */ jsx10(HarnessLogo, { id: harness, size: 28 }),
|
|
2616
|
+
/* @__PURE__ */ jsxs9("span", { className: "scui-head-copy", children: [
|
|
2617
|
+
/* @__PURE__ */ jsx10("strong", { children: title }),
|
|
2618
|
+
/* @__PURE__ */ jsxs9("small", { children: [
|
|
2428
2619
|
harnessDisplayName(harness),
|
|
2429
2620
|
" \xB7 ",
|
|
2430
2621
|
status
|
|
2431
2622
|
] })
|
|
2432
2623
|
] }),
|
|
2433
|
-
HeaderActions ? /* @__PURE__ */
|
|
2434
|
-
menu ? /* @__PURE__ */
|
|
2435
|
-
/* @__PURE__ */
|
|
2436
|
-
onClose ? /* @__PURE__ */
|
|
2624
|
+
HeaderActions ? /* @__PURE__ */ jsx10(HeaderActions, { state, adapter, value: "chat" }) : null,
|
|
2625
|
+
menu ? /* @__PURE__ */ jsx10(ConversationActions, { state, adapter, actionPending, onSettings }) : null,
|
|
2626
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ jsx10(UiIcon, { name: "plus", size: 18 }) }),
|
|
2627
|
+
onClose ? /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx10(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2437
2628
|
] });
|
|
2438
2629
|
}
|
|
2439
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels }) {
|
|
2630
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2440
2631
|
const Header = slots.header;
|
|
2441
2632
|
const HeaderActions = slots.headerActions;
|
|
2442
2633
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2533,29 +2724,29 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2533
2724
|
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, context: pending.context, images: pending.images, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
2534
2725
|
const action = state.operation || pendingAction?.action || null;
|
|
2535
2726
|
const actionLabel = operationLabel(action);
|
|
2536
|
-
const actionState = action ? { ...state, operation: action, canInterrupt: false, canRespond: false } : state;
|
|
2727
|
+
const actionState = action ? { ...state, operation: action, canSteer: false, canInterrupt: false, canRespond: false } : state;
|
|
2537
2728
|
const unreadAfterMessages = state.attention.find((item) => item.key === state.attached?.key)?.afterMessages ?? null;
|
|
2538
2729
|
const Advisory = components.HarnessAdvisory ?? HarnessAdvisory;
|
|
2539
2730
|
const SettingsPanel = components.HarnessSettingsPanel ?? HarnessSettingsPanel;
|
|
2540
|
-
return /* @__PURE__ */
|
|
2541
|
-
Header ? /* @__PURE__ */
|
|
2542
|
-
actionLabel ? /* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2731
|
+
return /* @__PURE__ */ jsxs9("section", { className: "scui-chat", children: [
|
|
2732
|
+
Header ? /* @__PURE__ */ jsx10(Header, { state: actionState, adapter: trackedAdapter, value: null }) : /* @__PURE__ */ jsx10(ChatHeader, { state: actionState, adapter: trackedAdapter, pendingStatus: pending?.status ?? null, actionPending: Boolean(action), onBack, onNew, onClose, onSettings: () => setSettings({ recommendedChange: null }), headerActions: HeaderActions }),
|
|
2733
|
+
actionLabel ? /* @__PURE__ */ jsxs9("div", { className: "scui-operation", role: "status", children: [
|
|
2734
|
+
/* @__PURE__ */ jsx10("i", {}),
|
|
2544
2735
|
actionLabel
|
|
2545
2736
|
] }) : null,
|
|
2546
|
-
state.error ? /* @__PURE__ */
|
|
2547
|
-
/* @__PURE__ */
|
|
2548
|
-
state.recoverable ? /* @__PURE__ */
|
|
2737
|
+
state.error ? /* @__PURE__ */ jsxs9("div", { className: "scui-error", role: "alert", children: [
|
|
2738
|
+
/* @__PURE__ */ jsx10("span", { children: state.error }),
|
|
2739
|
+
state.recoverable ? /* @__PURE__ */ jsx10("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
|
|
2549
2740
|
] }) : null,
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
2552
|
-
/* @__PURE__ */
|
|
2553
|
-
/* @__PURE__ */
|
|
2554
|
-
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */
|
|
2555
|
-
settings ? /* @__PURE__ */
|
|
2741
|
+
/* @__PURE__ */ jsx10(Receipt, { state, adapter }),
|
|
2742
|
+
/* @__PURE__ */ jsx10(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2743
|
+
/* @__PURE__ */ jsx10(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2744
|
+
/* @__PURE__ */ jsx10(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
|
|
2745
|
+
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx10(Composer, { state: actionState, adapter: trackedAdapter, labels, memoryKey, pendingStatus: pending?.status ?? null, restoreDraft, contextCandidates, components, onDraftRestored: (id) => setRestoreDraft((value) => value?.id === id ? null : value), onPending: beginPending }, memoryKey) : null,
|
|
2746
|
+
settings ? /* @__PURE__ */ jsx10(SettingsPanel, { state: actionState, adapter: trackedAdapter, value: state.interopSettings, recommendedChange: settings.recommendedChange, onClose: () => setSettings(null) }) : null
|
|
2556
2747
|
] });
|
|
2557
2748
|
}
|
|
2558
|
-
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions }) {
|
|
2749
|
+
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation }) {
|
|
2559
2750
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
2560
2751
|
const startableKey = startable.map((item) => `${item.id}:${item.launchModes?.join(",")}:${item.preferredLaunchMode ?? ""}`).join("\0");
|
|
2561
2752
|
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [], modes: {} };
|
|
@@ -2571,6 +2762,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2571
2762
|
const startSequence = useRef7(0);
|
|
2572
2763
|
const textarea = useRef7(null);
|
|
2573
2764
|
const selectedHarness = startable.find((item) => item.id === harness) ?? null;
|
|
2765
|
+
const Readiness = components.HarnessReadiness ?? HarnessReadiness;
|
|
2574
2766
|
const launchModes = selectedHarness?.launchModes?.length ? selectedHarness.launchModes : ["headless"];
|
|
2575
2767
|
const rememberedMode = modes[harness];
|
|
2576
2768
|
const mode = launchModes.includes(rememberedMode) ? rememberedMode : launchModes.includes(selectedHarness?.preferredLaunchMode) ? selectedHarness.preferredLaunchMode : launchModes[0];
|
|
@@ -2597,6 +2789,19 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2597
2789
|
useEffect8(() => {
|
|
2598
2790
|
textarea.current?.focus({ preventScroll: true });
|
|
2599
2791
|
}, []);
|
|
2792
|
+
useEffect8(() => {
|
|
2793
|
+
if (!navigation) return;
|
|
2794
|
+
const nextHarness = startable.some((item) => item.id === navigation.harness) ? navigation.harness : harness;
|
|
2795
|
+
const nextDraft = typeof navigation.draft === "string" ? navigation.draft : draft;
|
|
2796
|
+
const nextContext = mergeContext([], navigation.context ?? []);
|
|
2797
|
+
const nextImages = mergeImages([], navigation.images ?? []);
|
|
2798
|
+
setHarness(nextHarness);
|
|
2799
|
+
setDraft(nextDraft);
|
|
2800
|
+
setContext(nextContext);
|
|
2801
|
+
setImages(nextImages);
|
|
2802
|
+
remember({ harness: nextHarness, draft: nextDraft, context: nextContext, images: nextImages });
|
|
2803
|
+
textarea.current?.focus({ preventScroll: true });
|
|
2804
|
+
}, [navigation?.id]);
|
|
2600
2805
|
const pickContext = () => {
|
|
2601
2806
|
if (mode === "terminal" || !adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
2602
2807
|
setPicking(true);
|
|
@@ -2617,6 +2822,15 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2617
2822
|
});
|
|
2618
2823
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
2619
2824
|
};
|
|
2825
|
+
const attachCandidate = (picked) => {
|
|
2826
|
+
if (mode === "terminal") return;
|
|
2827
|
+
const attachments = partitionAttachments(picked);
|
|
2828
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
2829
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
2830
|
+
setContext(nextContext);
|
|
2831
|
+
setImages(nextImages);
|
|
2832
|
+
remember({ context: nextContext, images: nextImages });
|
|
2833
|
+
};
|
|
2620
2834
|
const addImageFiles = (value, source) => {
|
|
2621
2835
|
const allFiles = Array.from(value ?? []);
|
|
2622
2836
|
if (!allFiles.length) return false;
|
|
@@ -2665,65 +2879,67 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2665
2879
|
Promise.resolve(result).catch(() => setStarting((current) => current?.id === id ? null : current));
|
|
2666
2880
|
}
|
|
2667
2881
|
};
|
|
2668
|
-
return /* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
2670
|
-
/* @__PURE__ */
|
|
2671
|
-
/* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
/* @__PURE__ */
|
|
2882
|
+
return /* @__PURE__ */ jsxs9("section", { className: "scui-chat", children: [
|
|
2883
|
+
/* @__PURE__ */ jsxs9("header", { className: "scui-head", children: [
|
|
2884
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Back", onClick: onBack, children: /* @__PURE__ */ jsx10(UiIcon, { name: "back", size: 18 }) }),
|
|
2885
|
+
/* @__PURE__ */ jsxs9("span", { className: "scui-head-copy", children: [
|
|
2886
|
+
/* @__PURE__ */ jsx10("strong", { children: labels.newChat }),
|
|
2887
|
+
/* @__PURE__ */ jsx10("small", { children: "No session is created until you send" })
|
|
2674
2888
|
] }),
|
|
2675
|
-
HeaderActions ? /* @__PURE__ */
|
|
2676
|
-
onClose ? /* @__PURE__ */
|
|
2889
|
+
HeaderActions ? /* @__PURE__ */ jsx10(HeaderActions, { state, adapter, value: "new" }) : null,
|
|
2890
|
+
onClose ? /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx10(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2677
2891
|
] }),
|
|
2678
|
-
starting ? /* @__PURE__ */
|
|
2679
|
-
/* @__PURE__ */
|
|
2892
|
+
starting ? /* @__PURE__ */ jsxs9("div", { className: "scui-operation", role: "status", children: [
|
|
2893
|
+
/* @__PURE__ */ jsx10("i", {}),
|
|
2680
2894
|
mode === "terminal" ? "Opening terminal\u2026" : operationLabel("start")
|
|
2681
2895
|
] }) : null,
|
|
2682
|
-
/* @__PURE__ */
|
|
2683
|
-
/* @__PURE__ */
|
|
2684
|
-
/* @__PURE__ */
|
|
2685
|
-
/* @__PURE__ */
|
|
2896
|
+
/* @__PURE__ */ jsxs9("div", { className: "scui-new", children: [
|
|
2897
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2898
|
+
/* @__PURE__ */ jsx10("strong", { children: "What should the agent build or fix?" }),
|
|
2899
|
+
/* @__PURE__ */ jsx10("small", { children: "Choose a coding harness and send the first message." })
|
|
2686
2900
|
] }),
|
|
2687
|
-
/* @__PURE__ */
|
|
2688
|
-
/* @__PURE__ */
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
2901
|
+
/* @__PURE__ */ jsxs9("div", { className: "scui-compose", children: [
|
|
2902
|
+
/* @__PURE__ */ jsxs9("label", { className: "scui-harness-picker", children: [
|
|
2903
|
+
/* @__PURE__ */ jsx10(HarnessLogo, { id: harness, size: 24 }),
|
|
2904
|
+
/* @__PURE__ */ jsx10("span", { children: "Coding harness" }),
|
|
2905
|
+
/* @__PURE__ */ jsx10("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
2692
2906
|
const value = event.currentTarget.value;
|
|
2693
2907
|
setHarness(value);
|
|
2694
2908
|
remember({ harness: value });
|
|
2695
|
-
}, children: state.harnesses.map((item) => /* @__PURE__ */
|
|
2909
|
+
}, children: state.harnesses.map((item) => /* @__PURE__ */ jsxs9("option", { value: item.id, disabled: !item.startable, children: [
|
|
2696
2910
|
item.label,
|
|
2697
2911
|
item.startable ? "" : " \xB7 unavailable"
|
|
2698
2912
|
] }, item.id)) })
|
|
2699
2913
|
] }),
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2914
|
+
/* @__PURE__ */ jsx10(Readiness, { harnesses: state.harnesses, state, adapter }),
|
|
2915
|
+
launchModes.length > 1 ? /* @__PURE__ */ jsxs9("fieldset", { className: "scui-launch-modes", disabled: Boolean(starting), children: [
|
|
2916
|
+
/* @__PURE__ */ jsx10("legend", { children: "Run as" }),
|
|
2917
|
+
launchModes.map((item) => /* @__PURE__ */ jsxs9("label", { children: [
|
|
2918
|
+
/* @__PURE__ */ jsx10("input", { type: "radio", name: `launch-mode-${memoryKey}`, value: item, checked: mode === item, onChange: () => {
|
|
2704
2919
|
const next = { ...modes, [harness]: item };
|
|
2705
2920
|
setModes(next);
|
|
2706
2921
|
setPickerError(null);
|
|
2707
2922
|
remember({ modes: next });
|
|
2708
2923
|
} }),
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
/* @__PURE__ */
|
|
2924
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2925
|
+
/* @__PURE__ */ jsx10("strong", { children: item === "terminal" ? "Terminal" : "Chat" }),
|
|
2926
|
+
/* @__PURE__ */ jsx10("small", { children: item === "terminal" ? "Interactive tmux session" : "Managed here" })
|
|
2712
2927
|
] })
|
|
2713
2928
|
] }, item))
|
|
2714
2929
|
] }) : null,
|
|
2715
|
-
/* @__PURE__ */
|
|
2930
|
+
mode !== "terminal" ? /* @__PURE__ */ jsx10(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }) : null,
|
|
2931
|
+
/* @__PURE__ */ jsx10(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
2716
2932
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2717
2933
|
remember({ images: next });
|
|
2718
2934
|
return next;
|
|
2719
2935
|
}) }),
|
|
2720
|
-
/* @__PURE__ */
|
|
2936
|
+
/* @__PURE__ */ jsx10(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
2721
2937
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2722
2938
|
remember({ context: next });
|
|
2723
2939
|
return next;
|
|
2724
2940
|
}) }),
|
|
2725
|
-
terminalAttachments ? /* @__PURE__ */
|
|
2726
|
-
/* @__PURE__ */
|
|
2941
|
+
terminalAttachments ? /* @__PURE__ */ jsx10("small", { className: "scui-context-error", role: "alert", children: "Terminal starts currently accept text only. Remove attachments or choose Chat." }) : pickerError ? /* @__PURE__ */ jsx10("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
2942
|
+
/* @__PURE__ */ jsxs9("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
2727
2943
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
2728
2944
|
event.preventDefault();
|
|
2729
2945
|
setDragging(true);
|
|
@@ -2733,8 +2949,8 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2733
2949
|
}, onDragLeave: (event) => {
|
|
2734
2950
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
2735
2951
|
}, onDrop: dropImages, children: [
|
|
2736
|
-
adapter.pickContext ? /* @__PURE__ */
|
|
2737
|
-
/* @__PURE__ */
|
|
2952
|
+
adapter.pickContext ? /* @__PURE__ */ jsx10("button", { className: "scui-attach", type: "button", "aria-label": "Attach files or images", disabled: mode === "terminal" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx10("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx10(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2953
|
+
/* @__PURE__ */ jsx10("textarea", { ref: textarea, rows: 3, "aria-label": "Message coding agent", placeholder: startable.length ? "What should the agent do?" : "No coding harness is available", value: draft, disabled: !startable.length || Boolean(starting), onPaste: pasteImages, onInput: (event) => {
|
|
2738
2954
|
const value = event.currentTarget.value;
|
|
2739
2955
|
setDraft(value);
|
|
2740
2956
|
remember({ draft: value });
|
|
@@ -2744,22 +2960,52 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2744
2960
|
send();
|
|
2745
2961
|
}
|
|
2746
2962
|
} }),
|
|
2747
|
-
/* @__PURE__ */
|
|
2963
|
+
/* @__PURE__ */ jsx10("span", { children: /* @__PURE__ */ jsx10("button", { type: "button", className: "scui-send", "aria-label": mode === "terminal" ? "Start terminal session" : "Start chat", disabled: !draft.trim() && !images.length || !harness || Boolean(starting) || terminalAttachments || mode === "terminal" && !draft.trim(), onClick: send, children: starting ? /* @__PURE__ */ jsx10("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx10(UiIcon, { name: "send", size: 17 }) }) })
|
|
2748
2964
|
] })
|
|
2749
2965
|
] })
|
|
2750
2966
|
] });
|
|
2751
2967
|
}
|
|
2752
|
-
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, labels, components = {}, slots = {} }) {
|
|
2968
|
+
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, navigation = null, onViewChange, contextCandidates: candidatesInput = [], labels, components = {}, slots = {} }) {
|
|
2753
2969
|
const state = useMemo3(() => normalizeUiState(stateInput), [stateInput]);
|
|
2970
|
+
const contextCandidates = useMemo3(() => normalizeAttachmentCandidates(candidatesInput), [candidatesInput]);
|
|
2754
2971
|
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
2755
2972
|
const memoryKey = state.workspace || "@default";
|
|
2756
2973
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2757
2974
|
const [opening, setOpening] = useState6(null);
|
|
2975
|
+
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2758
2976
|
const [listFocus, setListFocus] = useState6(null);
|
|
2977
|
+
const lastNavigation = useRef7(null);
|
|
2759
2978
|
const setView = (next) => {
|
|
2760
2979
|
boundedSet(messengerViewMemory, memoryKey, next);
|
|
2761
2980
|
setViewState(next);
|
|
2981
|
+
onViewChange?.(next);
|
|
2762
2982
|
};
|
|
2983
|
+
useEffect8(() => {
|
|
2984
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2985
|
+
lastNavigation.current = navigation.id;
|
|
2986
|
+
if (navigation.view === "list") {
|
|
2987
|
+
setOpening(null);
|
|
2988
|
+
setView("list");
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2991
|
+
if (navigation.view === "new") {
|
|
2992
|
+
setListFocus("@new");
|
|
2993
|
+
setNewNavigation(navigation);
|
|
2994
|
+
setView("new");
|
|
2995
|
+
return;
|
|
2996
|
+
}
|
|
2997
|
+
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2998
|
+
setListFocus(navigation.sessionKey);
|
|
2999
|
+
if (state.attached?.key === navigation.sessionKey) {
|
|
3000
|
+
setOpening(null);
|
|
3001
|
+
setView("chat");
|
|
3002
|
+
return;
|
|
3003
|
+
}
|
|
3004
|
+
const row = state.sessions.find((item) => item.key === navigation.sessionKey);
|
|
3005
|
+
setOpening(row ?? { key: navigation.sessionKey, harness: "supercode", name: "Chat", title: "Chat" });
|
|
3006
|
+
adapter.onIntent({ action: "attach", key: navigation.sessionKey });
|
|
3007
|
+
}
|
|
3008
|
+
}, [adapter, navigation, state.attached?.key, state.sessions]);
|
|
2763
3009
|
useEffect8(() => {
|
|
2764
3010
|
if (!opening) return;
|
|
2765
3011
|
if (state.attached?.key === opening.key) {
|
|
@@ -2777,40 +3023,46 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2777
3023
|
const close = () => adapter.onClose?.();
|
|
2778
3024
|
const Footer = slots.footer;
|
|
2779
3025
|
const HeaderActions = slots.headerActions;
|
|
2780
|
-
return /* @__PURE__ */
|
|
2781
|
-
view === "list" ? /* @__PURE__ */
|
|
3026
|
+
return /* @__PURE__ */ jsxs9("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
3027
|
+
view === "list" ? /* @__PURE__ */ jsx10(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2782
3028
|
setListFocus("@new");
|
|
3029
|
+
setNewNavigation(null);
|
|
2783
3030
|
setView("new");
|
|
2784
|
-
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, headerActions: HeaderActions }) : null,
|
|
2785
|
-
view === "new" ? /* @__PURE__ */
|
|
2786
|
-
view === "chat" ? /* @__PURE__ */
|
|
3031
|
+
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
3032
|
+
view === "new" ? /* @__PURE__ */ jsx10(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: (mode) => setView(mode === "terminal" ? "list" : "chat"), labels: copy, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation: newNavigation }) : null,
|
|
3033
|
+
view === "chat" ? /* @__PURE__ */ jsx10(Chat, { state, adapter, onBack: () => {
|
|
2787
3034
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2788
3035
|
setView("list");
|
|
2789
3036
|
}, onNew: () => {
|
|
2790
3037
|
setListFocus("@new");
|
|
3038
|
+
setNewNavigation(null);
|
|
2791
3039
|
setView("new");
|
|
2792
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy }) : null,
|
|
2793
|
-
opening ? /* @__PURE__ */
|
|
2794
|
-
/* @__PURE__ */
|
|
2795
|
-
/* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
3040
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
3041
|
+
opening ? /* @__PURE__ */ jsxs9("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
3042
|
+
/* @__PURE__ */ jsx10(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
3043
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
3044
|
+
/* @__PURE__ */ jsxs9("strong", { children: [
|
|
2797
3045
|
"Opening ",
|
|
2798
3046
|
sessionDisplayName(opening)
|
|
2799
3047
|
] }),
|
|
2800
|
-
/* @__PURE__ */
|
|
3048
|
+
/* @__PURE__ */ jsx10("small", { children: "Loading the latest transcript window\u2026" })
|
|
2801
3049
|
] }),
|
|
2802
|
-
/* @__PURE__ */
|
|
3050
|
+
/* @__PURE__ */ jsx10("i", {})
|
|
2803
3051
|
] }) : null,
|
|
2804
|
-
Footer ? /* @__PURE__ */
|
|
3052
|
+
Footer ? /* @__PURE__ */ jsx10(Footer, { state, adapter, value: copy }) : null
|
|
2805
3053
|
] });
|
|
2806
3054
|
}
|
|
2807
3055
|
export {
|
|
2808
3056
|
ActivityGroup,
|
|
3057
|
+
AgentActivityLauncher,
|
|
2809
3058
|
Composer,
|
|
3059
|
+
ContextCandidate,
|
|
3060
|
+
ContextCandidates,
|
|
2810
3061
|
ContinuationBar,
|
|
2811
3062
|
Conversation,
|
|
2812
3063
|
HarnessAdvisory,
|
|
2813
3064
|
HarnessLogo,
|
|
3065
|
+
HarnessReadiness,
|
|
2814
3066
|
HarnessSettingsPanel,
|
|
2815
3067
|
ImageViewer,
|
|
2816
3068
|
LoadingStatus,
|