@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/embed.mjs
CHANGED
|
@@ -35,6 +35,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
35
35
|
mode: "none",
|
|
36
36
|
strategy: null,
|
|
37
37
|
canSend: false,
|
|
38
|
+
canSteer: false,
|
|
38
39
|
canResume: false,
|
|
39
40
|
continuationModes: Object.freeze([]),
|
|
40
41
|
canBranch: false,
|
|
@@ -722,6 +723,7 @@ function normalizeUiState(value) {
|
|
|
722
723
|
mode: MODES.has(raw.mode) ? raw.mode : "none",
|
|
723
724
|
strategy: STRATEGIES.has(raw.strategy) ? raw.strategy : null,
|
|
724
725
|
canSend: raw.canSend === true,
|
|
726
|
+
canSteer: raw.canSteer === true,
|
|
725
727
|
canResume,
|
|
726
728
|
continuationModes,
|
|
727
729
|
canBranch: raw.canBranch === true,
|
|
@@ -751,7 +753,29 @@ function normalizeUiState(value) {
|
|
|
751
753
|
const startable = item.startable === true;
|
|
752
754
|
const launchModes = Array.isArray(item.launchModes) ? [...new Set(item.launchModes.filter((mode) => mode === "headless" || mode === "terminal"))] : startable ? ["headless"] : [];
|
|
753
755
|
const preferredLaunchMode = launchModes.includes(item.preferredLaunchMode) ? item.preferredLaunchMode : launchModes[0] ?? null;
|
|
754
|
-
|
|
756
|
+
const capabilities = record(item.capabilities);
|
|
757
|
+
return [{
|
|
758
|
+
id: item.id,
|
|
759
|
+
label: string(item.label, harnessDisplayName(item.id)),
|
|
760
|
+
installed: item.installed === true,
|
|
761
|
+
startable,
|
|
762
|
+
reason: typeof item.reason === "string" ? boundedString(item.reason) : null,
|
|
763
|
+
auth: ["ready", "configured", "required", "unknown"].includes(item.auth) ? item.auth : "unknown",
|
|
764
|
+
runtime: ["ready", "degraded", "unavailable"].includes(item.runtime) ? item.runtime : startable ? "ready" : "unavailable",
|
|
765
|
+
protocol: boundedString(item.protocol, 100),
|
|
766
|
+
repair: typeof item.repair === "string" ? boundedString(item.repair, 4e3) : null,
|
|
767
|
+
capabilities: {
|
|
768
|
+
start: capabilities?.start === true,
|
|
769
|
+
resume: capabilities?.resume === true,
|
|
770
|
+
attach: capabilities?.attach === true,
|
|
771
|
+
send: capabilities?.send === true,
|
|
772
|
+
interrupt: capabilities?.interrupt === true,
|
|
773
|
+
steer: capabilities?.steer === true,
|
|
774
|
+
respond: capabilities?.respond === true
|
|
775
|
+
},
|
|
776
|
+
launchModes,
|
|
777
|
+
preferredLaunchMode
|
|
778
|
+
}];
|
|
755
779
|
}) : [],
|
|
756
780
|
history: { sessionLimit: number(history?.sessionLimit), hasMoreSessions: history?.hasMoreSessions === true, transcriptLimit: number(history?.transcriptLimit, 120), hasEarlier: history?.hasEarlier === true },
|
|
757
781
|
savedDraft: string(raw.savedDraft),
|
|
@@ -782,6 +806,16 @@ function sessionActivity(state, row) {
|
|
|
782
806
|
if (row.live || row.runtimeStatus === "idle") return "recent";
|
|
783
807
|
return "idle";
|
|
784
808
|
}
|
|
809
|
+
var ACTIVITY_PRIORITY = Object.freeze({
|
|
810
|
+
"needs-input": 70,
|
|
811
|
+
failed: 60,
|
|
812
|
+
working: 50,
|
|
813
|
+
unseen: 40,
|
|
814
|
+
finished: 30,
|
|
815
|
+
running: 20,
|
|
816
|
+
recent: 10,
|
|
817
|
+
idle: 0
|
|
818
|
+
});
|
|
785
819
|
function filterSessions(rows, query) {
|
|
786
820
|
const needle = query.trim().toLocaleLowerCase();
|
|
787
821
|
if (!needle) return [...rows];
|
|
@@ -840,7 +874,7 @@ function canContinueHere(state) {
|
|
|
840
874
|
}
|
|
841
875
|
function operationLabel(operation) {
|
|
842
876
|
if (!operation) return "";
|
|
843
|
-
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" };
|
|
877
|
+
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" };
|
|
844
878
|
return labels[operation] ?? `${operation.replaceAll("_", " ")}\u2026`;
|
|
845
879
|
}
|
|
846
880
|
function terminalCommand(handoff) {
|
|
@@ -908,7 +942,7 @@ var ICONS = {
|
|
|
908
942
|
function UiIcon({ name, size = 16, class: className = "" }) {
|
|
909
943
|
const Glyph = ICONS[name];
|
|
910
944
|
if (!Glyph) return null;
|
|
911
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
945
|
+
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, {}) });
|
|
912
946
|
}
|
|
913
947
|
|
|
914
948
|
// src/context.jsx
|
|
@@ -982,6 +1016,39 @@ function partitionAttachments(value) {
|
|
|
982
1016
|
}
|
|
983
1017
|
return { context, images };
|
|
984
1018
|
}
|
|
1019
|
+
function normalizeAttachmentCandidates(value) {
|
|
1020
|
+
const candidates = [];
|
|
1021
|
+
for (const item of Array.isArray(value) ? value : []) {
|
|
1022
|
+
const context = normalizeContext(item)[0];
|
|
1023
|
+
if (context) {
|
|
1024
|
+
candidates.push(context);
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
const image = normalizeImages(item)[0];
|
|
1028
|
+
if (image) candidates.push(image);
|
|
1029
|
+
}
|
|
1030
|
+
return candidates.slice(0, MAX_CONTEXT_ITEMS + MAX_IMAGE_ITEMS);
|
|
1031
|
+
}
|
|
1032
|
+
function attachmentKey(item) {
|
|
1033
|
+
if (item.id) return `id:${item.id}`;
|
|
1034
|
+
return "detail" in item ? `context:${item.kind ?? ""}\0${item.label}\0${item.detail}` : `image:${item.url}`;
|
|
1035
|
+
}
|
|
1036
|
+
function ContextCandidate({ attachment, attached, onAttach }) {
|
|
1037
|
+
const image = "url" in attachment;
|
|
1038
|
+
return /* @__PURE__ */ jsxs2("button", { type: "button", disabled: attached, "aria-label": `${attached ? "Attached" : "Attach"} ${attachment.label}`, onClick: () => onAttach(attachment), children: [
|
|
1039
|
+
image ? /* @__PURE__ */ jsx2("img", { src: attachment.url, alt: "" }) : /* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 13 }),
|
|
1040
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1041
|
+
/* @__PURE__ */ jsx2("strong", { children: attachment.label }),
|
|
1042
|
+
/* @__PURE__ */ jsx2("small", { children: image ? "Image" : attachment.kind || "Context" })
|
|
1043
|
+
] }),
|
|
1044
|
+
attached ? /* @__PURE__ */ jsx2(UiIcon, { name: "check", size: 13 }) : /* @__PURE__ */ jsx2(UiIcon, { name: "plus", size: 13 })
|
|
1045
|
+
] });
|
|
1046
|
+
}
|
|
1047
|
+
function ContextCandidates({ items, context, images, state, adapter, onAttach, component: Candidate = ContextCandidate }) {
|
|
1048
|
+
if (!items.length) return null;
|
|
1049
|
+
const attached = new Set([...context, ...images].map(attachmentKey));
|
|
1050
|
+
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))) });
|
|
1051
|
+
}
|
|
985
1052
|
async function imageAttachmentsFromFiles(value) {
|
|
986
1053
|
const files = Array.from(value ?? []).filter((file) => file?.type?.startsWith("image/"));
|
|
987
1054
|
if (files.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images at a time.`);
|
|
@@ -999,7 +1066,7 @@ async function imageAttachmentsFromFiles(value) {
|
|
|
999
1066
|
}
|
|
1000
1067
|
function ContextTray({ items, onRemove }) {
|
|
1001
1068
|
if (!items.length) return null;
|
|
1002
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1069
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
1003
1070
|
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
1004
1071
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
1005
1072
|
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
@@ -1007,7 +1074,7 @@ function ContextTray({ items, onRemove }) {
|
|
|
1007
1074
|
}
|
|
1008
1075
|
function ImageTray({ items, onRemove }) {
|
|
1009
1076
|
if (!items.length) return null;
|
|
1010
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1077
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-images", "aria-label": "Attached images", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
1011
1078
|
/* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }),
|
|
1012
1079
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
1013
1080
|
onRemove ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove image ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) }) : null
|
|
@@ -1085,7 +1152,7 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1085
1152
|
"dialog",
|
|
1086
1153
|
{
|
|
1087
1154
|
ref: dialog,
|
|
1088
|
-
|
|
1155
|
+
className: "scui-image-viewer",
|
|
1089
1156
|
"aria-label": `Image preview: ${item.label}`,
|
|
1090
1157
|
onClose,
|
|
1091
1158
|
onClick: (event) => {
|
|
@@ -1113,19 +1180,19 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1113
1180
|
] })
|
|
1114
1181
|
] }),
|
|
1115
1182
|
/* @__PURE__ */ jsxs2("figure", { children: [
|
|
1116
|
-
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", {
|
|
1183
|
+
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "alert", children: [
|
|
1117
1184
|
/* @__PURE__ */ jsx2(UiIcon, { name: "image", size: 28 }),
|
|
1118
1185
|
/* @__PURE__ */ jsx2("strong", { children: "Could not load image" }),
|
|
1119
1186
|
/* @__PURE__ */ jsx2("small", { children: resolution.message }),
|
|
1120
1187
|
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => resolve(item, true), children: "Retry" })
|
|
1121
|
-
] }) : /* @__PURE__ */ jsxs2("div", {
|
|
1122
|
-
/* @__PURE__ */ jsx2("i", {
|
|
1188
|
+
] }) : /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "status", children: [
|
|
1189
|
+
/* @__PURE__ */ jsx2("i", { className: "scui-control-spinner" }),
|
|
1123
1190
|
/* @__PURE__ */ jsx2("strong", { children: "Loading image\u2026" }),
|
|
1124
1191
|
/* @__PURE__ */ jsx2("small", { children: "The original stays out of the transcript payload." })
|
|
1125
1192
|
] }),
|
|
1126
1193
|
items.length > 1 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1127
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1128
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1194
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-previous", "aria-label": "Previous image", onClick: () => move(-1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) }),
|
|
1195
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-next", "aria-label": "Next image", onClick: () => move(1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) })
|
|
1129
1196
|
] }) : null
|
|
1130
1197
|
] })
|
|
1131
1198
|
]
|
|
@@ -1142,7 +1209,7 @@ function MessageImages({ items, adapter }) {
|
|
|
1142
1209
|
requestAnimationFrame(() => opener.current?.focus({ preventScroll: true }));
|
|
1143
1210
|
};
|
|
1144
1211
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1145
|
-
/* @__PURE__ */ jsx2("div", {
|
|
1212
|
+
/* @__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) => {
|
|
1146
1213
|
opener.current = event.currentTarget;
|
|
1147
1214
|
setActive(viewable.indexOf(item));
|
|
1148
1215
|
}, 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) => {
|
|
@@ -1165,6 +1232,16 @@ function MessageImages({ items, adapter }) {
|
|
|
1165
1232
|
] });
|
|
1166
1233
|
}
|
|
1167
1234
|
|
|
1235
|
+
// src/intent.js
|
|
1236
|
+
var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
|
|
1237
|
+
async function dispatchConfirmedIntent(adapter, intent) {
|
|
1238
|
+
if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
|
|
1239
|
+
const confirmed = await adapter.confirmIntent(intent);
|
|
1240
|
+
if (!confirmed) return;
|
|
1241
|
+
}
|
|
1242
|
+
return adapter.onIntent(intent);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1168
1245
|
// src/textarea.js
|
|
1169
1246
|
import { useLayoutEffect } from "preact/hooks";
|
|
1170
1247
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -1191,28 +1268,29 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
1191
1268
|
const terminal = resume && state.continuationModes?.includes("terminal");
|
|
1192
1269
|
const join = state.canAttach;
|
|
1193
1270
|
const branch = state.canBranch;
|
|
1194
|
-
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", {
|
|
1271
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { className: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
1195
1272
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1196
1273
|
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
1197
1274
|
] }) });
|
|
1198
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1275
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-continuation", children: [
|
|
1199
1276
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1200
1277
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1201
1278
|
/* @__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." })
|
|
1202
1279
|
] }),
|
|
1203
|
-
/* @__PURE__ */ jsxs3("span", {
|
|
1204
|
-
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => adapter
|
|
1205
|
-
terminal ? /* @__PURE__ */ jsx3("button", { type: "button",
|
|
1280
|
+
/* @__PURE__ */ jsxs3("span", { className: "scui-continuation-actions", children: [
|
|
1281
|
+
/* @__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 }),
|
|
1282
|
+
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
|
|
1206
1283
|
] })
|
|
1207
1284
|
] });
|
|
1208
1285
|
}
|
|
1209
|
-
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
1286
|
+
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, contextCandidates = [], components = {}, onPending, onDraftRestored }) {
|
|
1210
1287
|
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
1211
1288
|
const [draft, setDraft] = useState2(remembered.draft);
|
|
1212
1289
|
const [context, setContext] = useState2(remembered.context ?? []);
|
|
1213
1290
|
const [images, setImages] = useState2(remembered.images ?? []);
|
|
1214
1291
|
const [queue, setQueue] = useState2((remembered.queue ?? []).map((item) => ({ ...item, context: item.context ?? [], images: item.images ?? [] })));
|
|
1215
1292
|
const [dispatching, setDispatching] = useState2(false);
|
|
1293
|
+
const [steering, setSteering] = useState2(false);
|
|
1216
1294
|
const [picking, setPicking] = useState2(false);
|
|
1217
1295
|
const [dragging, setDragging] = useState2(false);
|
|
1218
1296
|
const [pickerError, setPickerError] = useState2(null);
|
|
@@ -1227,8 +1305,10 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1227
1305
|
remember(draft, context, images, next);
|
|
1228
1306
|
return next;
|
|
1229
1307
|
});
|
|
1230
|
-
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
1231
|
-
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching;
|
|
1308
|
+
const queueBlocked = state.busy || pendingStatus !== null || dispatching || steering;
|
|
1309
|
+
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching || steering;
|
|
1310
|
+
const steerAvailable = state.busy && state.canSteer && !steering && pendingStatus === null;
|
|
1311
|
+
const canSteerDraft = steerAvailable && Boolean(draft.trim()) && context.length === 0 && images.length === 0;
|
|
1232
1312
|
useEffect2(() => {
|
|
1233
1313
|
if (!queueBlocked && state.canSend && queue.length) {
|
|
1234
1314
|
const [next, ...rest] = queue;
|
|
@@ -1280,6 +1360,14 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1280
1360
|
});
|
|
1281
1361
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
1282
1362
|
};
|
|
1363
|
+
const attachCandidate = (picked) => {
|
|
1364
|
+
const attachments = partitionAttachments(picked);
|
|
1365
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
1366
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
1367
|
+
setContext(nextContext);
|
|
1368
|
+
setImages(nextImages);
|
|
1369
|
+
remember(draft, nextContext, nextImages, queue);
|
|
1370
|
+
};
|
|
1283
1371
|
const addImageFiles = (value, source) => {
|
|
1284
1372
|
const allFiles = Array.from(value ?? []);
|
|
1285
1373
|
if (!allFiles.length) return false;
|
|
@@ -1308,9 +1396,17 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1308
1396
|
setDragging(false);
|
|
1309
1397
|
if (addImageFiles(event.dataTransfer?.files, "drop")) event.preventDefault();
|
|
1310
1398
|
};
|
|
1311
|
-
const send = () => {
|
|
1399
|
+
const send = (forceQueue = false) => {
|
|
1312
1400
|
const text = draft.trim();
|
|
1313
1401
|
if (!text && !images.length) return;
|
|
1402
|
+
if (canSteerDraft && !forceQueue) {
|
|
1403
|
+
setSteering(true);
|
|
1404
|
+
Promise.resolve(adapter.onIntent({ action: "steer", text })).then(() => {
|
|
1405
|
+
setDraft("");
|
|
1406
|
+
remember("", context, images, queue);
|
|
1407
|
+
}, (error) => setPickerError(error instanceof Error ? error.message : "Could not steer the active turn.")).finally(() => setSteering(false));
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1314
1410
|
const message = { text, context, images };
|
|
1315
1411
|
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
1316
1412
|
else if (state.canSend) {
|
|
@@ -1323,8 +1419,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1323
1419
|
setImages([]);
|
|
1324
1420
|
remember("", [], [], queuesNewMessage ? [...queue, message] : queue);
|
|
1325
1421
|
};
|
|
1326
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1327
|
-
queue.length ? /* @__PURE__ */ jsxs3("div", {
|
|
1422
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-compose", children: [
|
|
1423
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { className: "scui-queue", children: [
|
|
1328
1424
|
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
1329
1425
|
queue.length,
|
|
1330
1426
|
" queued"
|
|
@@ -1340,6 +1436,7 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1340
1436
|
/* @__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 }) })
|
|
1341
1437
|
] }, `${index}:${item.text}`))
|
|
1342
1438
|
] }) : null,
|
|
1439
|
+
/* @__PURE__ */ jsx3(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }),
|
|
1343
1440
|
/* @__PURE__ */ jsx3(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
1344
1441
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1345
1442
|
remember(draft, context, next, queue);
|
|
@@ -1350,8 +1447,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1350
1447
|
remember(draft, next, images, queue);
|
|
1351
1448
|
return next;
|
|
1352
1449
|
}) }),
|
|
1353
|
-
pickerError ? /* @__PURE__ */ jsx3("small", {
|
|
1354
|
-
/* @__PURE__ */ jsxs3("div", {
|
|
1450
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
1451
|
+
/* @__PURE__ */ jsxs3("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
1355
1452
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
1356
1453
|
event.preventDefault();
|
|
1357
1454
|
setDragging(true);
|
|
@@ -1361,8 +1458,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1361
1458
|
}, onDragLeave: (event) => {
|
|
1362
1459
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
1363
1460
|
}, onDrop: dropImages, children: [
|
|
1364
|
-
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", {
|
|
1365
|
-
/* @__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) => {
|
|
1461
|
+
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,
|
|
1462
|
+
/* @__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) => {
|
|
1366
1463
|
const value = event.currentTarget.value;
|
|
1367
1464
|
setDraft(value);
|
|
1368
1465
|
remember(value, context, images, queue);
|
|
@@ -1373,8 +1470,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1373
1470
|
}
|
|
1374
1471
|
} }),
|
|
1375
1472
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1376
|
-
state.busy ? /* @__PURE__ */ jsx3("button", {
|
|
1377
|
-
/* @__PURE__ */ jsx3("button", {
|
|
1473
|
+
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,
|
|
1474
|
+
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,
|
|
1475
|
+
/* @__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 }) })
|
|
1378
1476
|
] })
|
|
1379
1477
|
] })
|
|
1380
1478
|
] });
|
|
@@ -1474,7 +1572,7 @@ function Markdown({ value, copyText }) {
|
|
|
1474
1572
|
}, 1500);
|
|
1475
1573
|
resets.current.set(button, timer);
|
|
1476
1574
|
};
|
|
1477
|
-
return /* @__PURE__ */ jsx4("div", {
|
|
1575
|
+
return /* @__PURE__ */ jsx4("div", { className: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1478
1576
|
}
|
|
1479
1577
|
|
|
1480
1578
|
// src/conversation.jsx
|
|
@@ -1486,28 +1584,28 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1486
1584
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1487
1585
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1488
1586
|
}[state.startup];
|
|
1489
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
1490
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1491
|
-
/* @__PURE__ */ jsxs4("span", {
|
|
1587
|
+
return /* @__PURE__ */ jsxs4("div", { className: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1588
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("i", {}) }),
|
|
1589
|
+
/* @__PURE__ */ jsxs4("span", { className: "scui-loading-copy", children: [
|
|
1492
1590
|
/* @__PURE__ */ jsx5("strong", { children: copy[0] }),
|
|
1493
1591
|
/* @__PURE__ */ jsx5("small", { children: copy[1] })
|
|
1494
1592
|
] }),
|
|
1495
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1593
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx5("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
|
|
1496
1594
|
] });
|
|
1497
1595
|
}
|
|
1498
1596
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1499
1597
|
const request = entry.request;
|
|
1500
1598
|
if (!request) return null;
|
|
1501
1599
|
if (request.status === "responded") {
|
|
1502
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
1600
|
+
return /* @__PURE__ */ jsxs4("div", { className: "scui-request-done", children: [
|
|
1503
1601
|
"\u2713 Request answered \xB7 ",
|
|
1504
1602
|
request.resolution?.name ?? request.requestKind
|
|
1505
1603
|
] });
|
|
1506
1604
|
}
|
|
1507
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1605
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1508
1606
|
/* @__PURE__ */ jsx5("strong", { children: "Agent needs input" }),
|
|
1509
1607
|
/* @__PURE__ */ jsx5(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1510
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
1608
|
+
/* @__PURE__ */ jsxs4("div", { className: "scui-request-actions", children: [
|
|
1511
1609
|
request.options.map((option) => /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: option.optionId }), children: option.name }, option.optionId)),
|
|
1512
1610
|
request.cancellable ? /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1513
1611
|
] })
|
|
@@ -1515,7 +1613,7 @@ function RequestCard({ entry, adapter, canRespond }) {
|
|
|
1515
1613
|
}
|
|
1516
1614
|
function ContextDisclosure({ context }) {
|
|
1517
1615
|
if (!context?.length) return null;
|
|
1518
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1616
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-context", children: [
|
|
1519
1617
|
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1520
1618
|
"Context \xB7 ",
|
|
1521
1619
|
context.length
|
|
@@ -1544,7 +1642,7 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1544
1642
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1545
1643
|
};
|
|
1546
1644
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1547
|
-
return /* @__PURE__ */ jsxs4("footer", {
|
|
1645
|
+
return /* @__PURE__ */ jsxs4("footer", { className: "scui-message-meta", children: [
|
|
1548
1646
|
validDate ? /* @__PURE__ */ jsx5("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1549
1647
|
adapter?.copyText && entry.text ? /* @__PURE__ */ jsx5("button", { type: "button", "aria-label": copyLabel, title: copyLabel, onClick: copy, "data-status": copyState, children: /* @__PURE__ */ jsx5(UiIcon, { name: "copy", size: 13 }) }) : null
|
|
1550
1648
|
] });
|
|
@@ -1583,7 +1681,7 @@ var TOOL_ICONS = {
|
|
|
1583
1681
|
};
|
|
1584
1682
|
function ToolIcon({ category }) {
|
|
1585
1683
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1586
|
-
return /* @__PURE__ */ jsx5("svg", {
|
|
1684
|
+
return /* @__PURE__ */ jsx5("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__ */ jsx5(Glyph, {}) });
|
|
1587
1685
|
}
|
|
1588
1686
|
function toolAction2(entry, category, presentation) {
|
|
1589
1687
|
if (presentation?.action) return presentation.action;
|
|
@@ -1638,7 +1736,7 @@ function ToolMetrics({ presentation }) {
|
|
|
1638
1736
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1639
1737
|
formatDuration(presentation.durationMs)
|
|
1640
1738
|
].filter(Boolean);
|
|
1641
|
-
return metrics.length ? /* @__PURE__ */ jsx5("div", {
|
|
1739
|
+
return metrics.length ? /* @__PURE__ */ jsx5("div", { className: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx5("span", { children: metric }, metric)) }) : null;
|
|
1642
1740
|
}
|
|
1643
1741
|
function PendingElapsed({ now }) {
|
|
1644
1742
|
const clock = now ?? Date.now;
|
|
@@ -1648,11 +1746,11 @@ function PendingElapsed({ now }) {
|
|
|
1648
1746
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1649
1747
|
return () => clearInterval(timer);
|
|
1650
1748
|
}, [clock]);
|
|
1651
|
-
return /* @__PURE__ */ jsx5("small", {
|
|
1749
|
+
return /* @__PURE__ */ jsx5("small", { className: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1652
1750
|
}
|
|
1653
1751
|
function LinePreview({ value, kind }) {
|
|
1654
1752
|
if (!value) return null;
|
|
1655
|
-
return /* @__PURE__ */ jsx5("ol", {
|
|
1753
|
+
return /* @__PURE__ */ jsx5("ol", { className: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1656
1754
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1657
1755
|
return /* @__PURE__ */ jsxs4("li", { "data-tone": tone, children: [
|
|
1658
1756
|
/* @__PURE__ */ jsx5("span", { children: index + 1 }),
|
|
@@ -1661,7 +1759,7 @@ function LinePreview({ value, kind }) {
|
|
|
1661
1759
|
}) });
|
|
1662
1760
|
}
|
|
1663
1761
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1664
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1762
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-terminal", children: [
|
|
1665
1763
|
/* @__PURE__ */ jsxs4("header", { children: [
|
|
1666
1764
|
/* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", children: [
|
|
1667
1765
|
/* @__PURE__ */ jsx5("i", {}),
|
|
@@ -1670,15 +1768,15 @@ function TerminalPreview({ presentation, pending, failed }) {
|
|
|
1670
1768
|
] }),
|
|
1671
1769
|
/* @__PURE__ */ jsx5("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1672
1770
|
] }),
|
|
1673
|
-
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", {
|
|
1771
|
+
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", { className: "scui-terminal-wait", children: [
|
|
1674
1772
|
/* @__PURE__ */ jsx5("i", {}),
|
|
1675
1773
|
" Waiting for output"
|
|
1676
|
-
] }) : /* @__PURE__ */ jsx5("div", {
|
|
1774
|
+
] }) : /* @__PURE__ */ jsx5("div", { className: "scui-terminal-empty", children: "No output" })
|
|
1677
1775
|
] });
|
|
1678
1776
|
}
|
|
1679
1777
|
function SearchPreview({ presentation }) {
|
|
1680
1778
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1681
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1779
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-search-preview", children: [
|
|
1682
1780
|
presentation.query ? /* @__PURE__ */ jsxs4("header", { children: [
|
|
1683
1781
|
/* @__PURE__ */ jsx5("span", { children: "Search" }),
|
|
1684
1782
|
/* @__PURE__ */ jsx5("code", { children: presentation.query })
|
|
@@ -1700,22 +1798,22 @@ function ToolPreview({ presentation, entry }) {
|
|
|
1700
1798
|
const pending = entry.status === "pending";
|
|
1701
1799
|
const failed = entry.status === "error";
|
|
1702
1800
|
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx5(TerminalPreview, { presentation, pending, failed });
|
|
1703
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx5("div", {
|
|
1704
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx5("div", {
|
|
1801
|
+
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx5("div", { className: "scui-tool-empty", children: "Edit completed without a textual diff" });
|
|
1802
|
+
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx5("div", { className: "scui-tool-empty", children: "File contents were not included in this event" });
|
|
1705
1803
|
if (presentation.detail === "matches") return /* @__PURE__ */ jsx5(SearchPreview, { presentation });
|
|
1706
|
-
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", {
|
|
1804
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", { className: "scui-web-preview", children: [
|
|
1707
1805
|
presentation.url ? /* @__PURE__ */ jsx5("code", { children: presentation.url }) : null,
|
|
1708
1806
|
presentation.preview ? /* @__PURE__ */ jsx5("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1709
1807
|
] });
|
|
1710
|
-
if (presentation.detail === "agent") return /* @__PURE__ */ jsx5("section", {
|
|
1808
|
+
if (presentation.detail === "agent") return /* @__PURE__ */ jsx5("section", { className: "scui-agent-preview", children: presentation.items?.length ? /* @__PURE__ */ jsx5("ol", { className: "scui-agent-roster", children: presentation.items.map((item, index) => /* @__PURE__ */ jsxs4("li", { children: [
|
|
1711
1809
|
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1712
1810
|
/* @__PURE__ */ jsx5("small", { children: item.status })
|
|
1713
1811
|
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx5("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1714
|
-
if (presentation.detail === "plan") return /* @__PURE__ */ jsx5("ol", {
|
|
1812
|
+
if (presentation.detail === "plan") return /* @__PURE__ */ jsx5("ol", { className: "scui-plan-preview", children: presentation.items?.map((item, index) => /* @__PURE__ */ jsxs4("li", { "data-status": item.status, children: [
|
|
1715
1813
|
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1716
1814
|
/* @__PURE__ */ jsx5("span", { children: item.label })
|
|
1717
1815
|
] }, `${item.label}:${index}`)) });
|
|
1718
|
-
return presentation.preview ? /* @__PURE__ */ jsx5("pre", {
|
|
1816
|
+
return presentation.preview ? /* @__PURE__ */ jsx5("pre", { className: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1719
1817
|
}
|
|
1720
1818
|
function ToolActions({ presentation, adapter }) {
|
|
1721
1819
|
const [copied, setCopied] = useState3(false);
|
|
@@ -1729,15 +1827,15 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1729
1827
|
clearTimeout(reset.current);
|
|
1730
1828
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1731
1829
|
};
|
|
1732
|
-
return action ? /* @__PURE__ */ jsx5("div", {
|
|
1830
|
+
return action ? /* @__PURE__ */ jsx5("div", { className: "scui-tool-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1733
1831
|
}
|
|
1734
1832
|
function ToolStack({ tools }) {
|
|
1735
1833
|
if (tools.length < 2) return null;
|
|
1736
|
-
return /* @__PURE__ */ jsx5("div", {
|
|
1834
|
+
return /* @__PURE__ */ jsx5("div", { className: "scui-tool-stack", "aria-label": "Coordinated tools", children: tools.map((tool) => /* @__PURE__ */ jsx5("span", { children: tool.replaceAll("__", " \xB7 ").replaceAll("_", " ") }, tool)) });
|
|
1737
1835
|
}
|
|
1738
1836
|
function TechnicalDetails({ entry }) {
|
|
1739
1837
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1740
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1838
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-tool-technical", children: [
|
|
1741
1839
|
/* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
|
|
1742
1840
|
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1743
1841
|
entry.arguments ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
@@ -1760,17 +1858,17 @@ function TechnicalDetails({ entry }) {
|
|
|
1760
1858
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1761
1859
|
if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1762
1860
|
if (entry.role === "reasoning") {
|
|
1763
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1861
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-reasoning", open: entry.streaming, children: [
|
|
1764
1862
|
/* @__PURE__ */ jsx5("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
1765
1863
|
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1766
1864
|
] });
|
|
1767
1865
|
}
|
|
1768
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", {
|
|
1769
|
-
return /* @__PURE__ */ jsxs4("article", {
|
|
1866
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", { className: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
1867
|
+
return /* @__PURE__ */ jsxs4("article", { className: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
1770
1868
|
/* @__PURE__ */ jsx5(MessageImages, { items: entry.images, adapter }),
|
|
1771
1869
|
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
1772
1870
|
/* @__PURE__ */ jsx5(ContextDisclosure, { context: entry.context }),
|
|
1773
|
-
entry.truncated ? /* @__PURE__ */ jsx5("small", {
|
|
1871
|
+
entry.truncated ? /* @__PURE__ */ jsx5("small", { className: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
1774
1872
|
/* @__PURE__ */ jsx5(MessageMeta, { entry, adapter })
|
|
1775
1873
|
] });
|
|
1776
1874
|
}
|
|
@@ -1786,20 +1884,20 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1786
1884
|
const summary = /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
1787
1885
|
/* @__PURE__ */ jsx5(ToolIcon, { category }),
|
|
1788
1886
|
/* @__PURE__ */ jsx5("strong", { children: toolAction2(entry, category, presentation) }),
|
|
1789
|
-
target ? /* @__PURE__ */ jsx5("code", {
|
|
1790
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1887
|
+
target ? /* @__PURE__ */ jsx5("code", { className: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
1888
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-spacer" }),
|
|
1791
1889
|
entry.status === "pending" ? /* @__PURE__ */ jsx5(PendingElapsed, { now: adapter?.now }) : null,
|
|
1792
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1793
|
-
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14,
|
|
1890
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-tool-status", role: "status", "data-status": entry.status ?? "completed", "aria-label": entry.status ?? "completed", children: entry.status === "pending" ? /* @__PURE__ */ jsx5("i", {}) : /* @__PURE__ */ jsx5(UiIcon, { name: entry.status === "error" ? "close" : "check", size: 12 }) }),
|
|
1891
|
+
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14, className: "scui-tool-chevron" }) : null
|
|
1794
1892
|
] });
|
|
1795
|
-
if (!hasDetail) return /* @__PURE__ */ jsx5("div", {
|
|
1796
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1797
|
-
/* @__PURE__ */ jsx5("summary", {
|
|
1798
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
1893
|
+
if (!hasDetail) return /* @__PURE__ */ jsx5("div", { className: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx5("div", { className: "scui-tool-head", children: summary }) });
|
|
1894
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
1895
|
+
/* @__PURE__ */ jsx5("summary", { className: "scui-tool-head", children: summary }),
|
|
1896
|
+
/* @__PURE__ */ jsxs4("div", { className: "scui-tool-detail", children: [
|
|
1799
1897
|
/* @__PURE__ */ jsx5(ToolMetrics, { presentation }),
|
|
1800
1898
|
/* @__PURE__ */ jsx5(ToolStack, { tools: presentation.tools ?? [] }),
|
|
1801
1899
|
/* @__PURE__ */ jsx5(ToolPreview, { presentation, entry }),
|
|
1802
|
-
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", {
|
|
1900
|
+
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", { className: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1803
1901
|
/* @__PURE__ */ jsx5("dt", { children: field.label }),
|
|
1804
1902
|
/* @__PURE__ */ jsx5("dd", { children: field.value })
|
|
1805
1903
|
] }, field.label)) }) : null,
|
|
@@ -1809,18 +1907,18 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1809
1907
|
] });
|
|
1810
1908
|
}
|
|
1811
1909
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1812
|
-
if (entries.length === 1) return /* @__PURE__ */ jsx5("section", {
|
|
1910
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx5("section", { className: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx5(ToolRow, { entry: entries[0], workspace: state.workspace, adapter }) });
|
|
1813
1911
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1814
1912
|
const [open, setOpen] = useState3(active);
|
|
1815
1913
|
const id = useId();
|
|
1816
1914
|
useEffect4(() => {
|
|
1817
1915
|
if (active) setOpen(true);
|
|
1818
1916
|
}, [active]);
|
|
1819
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1820
|
-
/* @__PURE__ */ jsxs4("button", {
|
|
1821
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1917
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-activity", children: [
|
|
1918
|
+
/* @__PURE__ */ jsxs4("button", { className: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1919
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14 }) }),
|
|
1822
1920
|
/* @__PURE__ */ jsx5("strong", { children: activitySummary(entries) }),
|
|
1823
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1921
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-spacer" }),
|
|
1824
1922
|
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1825
1923
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1826
1924
|
"/",
|
|
@@ -1833,7 +1931,7 @@ function ActivityGroup({ entries, state, adapter }) {
|
|
|
1833
1931
|
function TaskPlan({ plan }) {
|
|
1834
1932
|
if (!plan.items.length) return null;
|
|
1835
1933
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1836
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1934
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-plan", children: [
|
|
1837
1935
|
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1838
1936
|
/* @__PURE__ */ jsx5("span", { children: "Plan" }),
|
|
1839
1937
|
/* @__PURE__ */ jsxs4("small", { children: [
|
|
@@ -1851,7 +1949,7 @@ function TaskPlan({ plan }) {
|
|
|
1851
1949
|
}
|
|
1852
1950
|
function SessionDetails({ semantics }) {
|
|
1853
1951
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1854
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1952
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-details", children: [
|
|
1855
1953
|
/* @__PURE__ */ jsx5("summary", { children: "Session details" }),
|
|
1856
1954
|
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1857
1955
|
semantics.fidelity ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
@@ -1897,7 +1995,7 @@ function ConversationAnnouncements({ state }) {
|
|
|
1897
1995
|
}
|
|
1898
1996
|
previousBusy.current = state.busy;
|
|
1899
1997
|
}, [state.busy, state.error, state.harness]);
|
|
1900
|
-
return /* @__PURE__ */ jsx5("span", {
|
|
1998
|
+
return /* @__PURE__ */ jsx5("span", { className: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1901
1999
|
}
|
|
1902
2000
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1903
2001
|
const scroller = useRef4(null);
|
|
@@ -1946,9 +2044,9 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1946
2044
|
else pin();
|
|
1947
2045
|
} else if (atBottom) pin();
|
|
1948
2046
|
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1949
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
2047
|
+
return /* @__PURE__ */ jsxs4("div", { className: "scui-conversation-wrap", children: [
|
|
1950
2048
|
/* @__PURE__ */ jsx5(ConversationAnnouncements, { state }),
|
|
1951
|
-
/* @__PURE__ */ jsx5("div", {
|
|
2049
|
+
/* @__PURE__ */ jsx5("div", { className: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1952
2050
|
const element = event.currentTarget;
|
|
1953
2051
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1954
2052
|
setAtBottom(bottom);
|
|
@@ -1957,19 +2055,19 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1957
2055
|
Before ? /* @__PURE__ */ jsx5(Before, { state, adapter, value: null }) : null,
|
|
1958
2056
|
/* @__PURE__ */ jsx5(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
1959
2057
|
/* @__PURE__ */ jsx5(SessionDetails, { semantics: state.semantics }),
|
|
1960
|
-
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", {
|
|
2058
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", { className: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1961
2059
|
const element = scroller.current;
|
|
1962
2060
|
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1963
2061
|
setAtBottom(false);
|
|
1964
2062
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1965
2063
|
}, children: "Load earlier messages" }) : null,
|
|
1966
2064
|
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state }) : null,
|
|
1967
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx5(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx5("div", {
|
|
2065
|
+
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx5(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx5("div", { className: "scui-empty", children: state.error ?? (state.harness ? `${harnessDisplayName(state.harness)} is listening. Say something.` : "No transcript yet.") }) : null,
|
|
1968
2066
|
blocks.map((block, index) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1969
|
-
index === unreadBlock ? /* @__PURE__ */ jsx5("div", {
|
|
2067
|
+
index === unreadBlock ? /* @__PURE__ */ jsx5("div", { className: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx5("span", { children: "New" }) }) : null,
|
|
1970
2068
|
block.kind === "activity" ? /* @__PURE__ */ jsx5(Group, { value: block.entries, entries: block.entries, state, adapter }) : /* @__PURE__ */ jsx5(Entry, { value: block.entry, entry: block.entry, state, adapter })
|
|
1971
2069
|
] }, block.id)),
|
|
1972
|
-
pendingMessage ? /* @__PURE__ */ jsxs4("article", {
|
|
2070
|
+
pendingMessage ? /* @__PURE__ */ jsxs4("article", { className: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
1973
2071
|
/* @__PURE__ */ jsx5(MessageImages, { items: pendingMessage.images, adapter }),
|
|
1974
2072
|
/* @__PURE__ */ jsx5(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
1975
2073
|
/* @__PURE__ */ jsx5(ContextDisclosure, { context: pendingMessage.context }),
|
|
@@ -1981,7 +2079,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1981
2079
|
] }) : null
|
|
1982
2080
|
] })
|
|
1983
2081
|
] }) : null,
|
|
1984
|
-
state.busy ? /* @__PURE__ */ jsxs4("div", {
|
|
2082
|
+
state.busy ? /* @__PURE__ */ jsxs4("div", { className: "scui-working", role: "status", children: [
|
|
1985
2083
|
/* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
1986
2084
|
/* @__PURE__ */ jsx5("i", {}),
|
|
1987
2085
|
/* @__PURE__ */ jsx5("i", {}),
|
|
@@ -1993,7 +2091,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1993
2091
|
] }) : null,
|
|
1994
2092
|
After ? /* @__PURE__ */ jsx5(After, { state, adapter, value: null }) : null
|
|
1995
2093
|
] }) }),
|
|
1996
|
-
!atBottom ? /* @__PURE__ */ jsxs4("button", {
|
|
2094
|
+
!atBottom ? /* @__PURE__ */ jsxs4("button", { className: "scui-latest", type: "button", onClick: pin, children: [
|
|
1997
2095
|
/* @__PURE__ */ jsx5(UiIcon, { name: "down", size: 13 }),
|
|
1998
2096
|
" Latest"
|
|
1999
2097
|
] }) : null
|
|
@@ -2007,13 +2105,13 @@ var LOGOS = {
|
|
|
2007
2105
|
"claude-code": {
|
|
2008
2106
|
viewBox: "-1 3.5 26 18",
|
|
2009
2107
|
paths: [
|
|
2010
|
-
["path", {
|
|
2108
|
+
["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" }]
|
|
2011
2109
|
]
|
|
2012
2110
|
},
|
|
2013
2111
|
codex: {
|
|
2014
2112
|
viewBox: "-1 -1 26 26",
|
|
2015
2113
|
paths: [
|
|
2016
|
-
["path", {
|
|
2114
|
+
["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" }]
|
|
2017
2115
|
]
|
|
2018
2116
|
},
|
|
2019
2117
|
gemini: {
|
|
@@ -2033,7 +2131,7 @@ var LOGOS = {
|
|
|
2033
2131
|
pi: {
|
|
2034
2132
|
viewBox: "0 0 24 24",
|
|
2035
2133
|
paths: [
|
|
2036
|
-
["path", {
|
|
2134
|
+
["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
|
|
2037
2135
|
["path", { d: "M17.5 12H23v11h-5.5V12z" }]
|
|
2038
2136
|
]
|
|
2039
2137
|
},
|
|
@@ -2043,17 +2141,22 @@ var LOGOS = {
|
|
|
2043
2141
|
paths: [
|
|
2044
2142
|
["rect", { width: "64", height: "64", rx: "14", fill: "#111923" }],
|
|
2045
2143
|
["path", { d: "M18 21h28v6H18zm0 13h18v6H18z", fill: "#5f8fff" }],
|
|
2046
|
-
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa",
|
|
2144
|
+
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", strokeWidth: "4" }]
|
|
2047
2145
|
]
|
|
2048
2146
|
}
|
|
2049
2147
|
};
|
|
2148
|
+
var SVG_ATTRIBUTE_NAMES = Object.freeze({
|
|
2149
|
+
clipRule: "clip-rule",
|
|
2150
|
+
fillRule: "fill-rule",
|
|
2151
|
+
strokeWidth: "stroke-width"
|
|
2152
|
+
});
|
|
2050
2153
|
function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
2051
2154
|
const logo = LOGOS[id];
|
|
2052
2155
|
useEffect5(() => {
|
|
2053
2156
|
if (!logo) onMissingLogo?.(id);
|
|
2054
2157
|
}, [id, logo, onMissingLogo]);
|
|
2055
2158
|
if (!logo) return null;
|
|
2056
|
-
return /* @__PURE__ */ jsxs5("span", {
|
|
2159
|
+
return /* @__PURE__ */ jsxs5("span", { className: "scui-logo", "data-harness": id, "data-activity": activity, style: { "--scui-logo-size": `${size}px` }, "aria-hidden": "true", children: [
|
|
2057
2160
|
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
2058
2161
|
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
2059
2162
|
] });
|
|
@@ -2084,20 +2187,20 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2084
2187
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2085
2188
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2086
2189
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2087
|
-
return /* @__PURE__ */ jsxs6("button", {
|
|
2190
|
+
return /* @__PURE__ */ jsxs6("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: [
|
|
2088
2191
|
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2089
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2090
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2192
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
|
|
2193
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-session-title", children: [
|
|
2091
2194
|
/* @__PURE__ */ jsx7("strong", { children: title }),
|
|
2092
|
-
/* @__PURE__ */ jsx7("span", {
|
|
2195
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-session-meta", children: age ? /* @__PURE__ */ jsx7("time", { children: age }) : null })
|
|
2093
2196
|
] }),
|
|
2094
|
-
path.complete ? /* @__PURE__ */ jsxs6("small", {
|
|
2095
|
-
/* @__PURE__ */ jsx7("span", {
|
|
2096
|
-
path.separator ? /* @__PURE__ */ jsx7("span", {
|
|
2097
|
-
path.trailing ? /* @__PURE__ */ jsx7("span", {
|
|
2197
|
+
path.complete ? /* @__PURE__ */ jsxs6("small", { className: "scui-session-path", title: row.cwd, children: [
|
|
2198
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-session-path-leading", children: path.leading }),
|
|
2199
|
+
path.separator ? /* @__PURE__ */ jsx7("span", { className: "scui-session-path-separator", children: path.separator }) : null,
|
|
2200
|
+
path.trailing ? /* @__PURE__ */ jsx7("span", { className: "scui-session-path-trailing", children: path.trailing }) : null
|
|
2098
2201
|
] }) : null,
|
|
2099
|
-
working || preview || unreadCount ? /* @__PURE__ */ jsxs6("span", {
|
|
2100
|
-
working ? /* @__PURE__ */ jsxs6("span", {
|
|
2202
|
+
working || preview || unreadCount ? /* @__PURE__ */ jsxs6("span", { className: "scui-session-preview", children: [
|
|
2203
|
+
working ? /* @__PURE__ */ jsxs6("span", { className: "scui-session-working", "aria-hidden": "true", children: [
|
|
2101
2204
|
/* @__PURE__ */ jsx7("i", {}),
|
|
2102
2205
|
/* @__PURE__ */ jsx7("i", {}),
|
|
2103
2206
|
/* @__PURE__ */ jsx7("i", {})
|
|
@@ -2109,7 +2212,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2109
2212
|
] })
|
|
2110
2213
|
] });
|
|
2111
2214
|
}
|
|
2112
|
-
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2215
|
+
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, slots = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2113
2216
|
const remembered = sessionListMemory.get(memoryKey) ?? { query: "", top: 0 };
|
|
2114
2217
|
const [query, setQuery] = useState4(remembered.query);
|
|
2115
2218
|
const [loadingMore, setLoadingMore] = useState4(false);
|
|
@@ -2118,6 +2221,8 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2118
2221
|
const rowScroller = useRef5(null);
|
|
2119
2222
|
const rows = filterSessions(state.sessions, query);
|
|
2120
2223
|
const Row = components.SessionRow ?? SessionRow;
|
|
2224
|
+
const BeforeSessions = slots.beforeSessions;
|
|
2225
|
+
const AfterSessions = slots.afterSessions;
|
|
2121
2226
|
useLayoutEffect3(() => {
|
|
2122
2227
|
if (rowScroller.current) rowScroller.current.scrollTop = remembered.top;
|
|
2123
2228
|
}, [memoryKey]);
|
|
@@ -2141,9 +2246,9 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2141
2246
|
Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
|
|
2142
2247
|
}
|
|
2143
2248
|
};
|
|
2144
|
-
return /* @__PURE__ */ jsxs6("section", {
|
|
2145
|
-
/* @__PURE__ */ jsxs6("header", {
|
|
2146
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2249
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-list", ref: root, children: [
|
|
2250
|
+
/* @__PURE__ */ jsxs6("header", { className: "scui-head", children: [
|
|
2251
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-head-copy", children: [
|
|
2147
2252
|
/* @__PURE__ */ jsx7("strong", { children: labels.chats }),
|
|
2148
2253
|
/* @__PURE__ */ jsxs6("small", { children: [
|
|
2149
2254
|
state.sessions.length,
|
|
@@ -2155,7 +2260,7 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2155
2260
|
onClose ? /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx7(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2156
2261
|
] }),
|
|
2157
2262
|
state.startup !== "ready" ? /* @__PURE__ */ jsx7(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
2158
|
-
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", {
|
|
2263
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", { className: "scui-search", children: [
|
|
2159
2264
|
/* @__PURE__ */ jsx7(UiIcon, { name: "search", size: 15 }),
|
|
2160
2265
|
/* @__PURE__ */ jsx7("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
|
|
2161
2266
|
const value = event.currentTarget.value;
|
|
@@ -2165,10 +2270,12 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2165
2270
|
} }),
|
|
2166
2271
|
/* @__PURE__ */ jsx7("small", { children: rows.length })
|
|
2167
2272
|
] }) : null,
|
|
2168
|
-
/* @__PURE__ */ jsxs6("div", {
|
|
2169
|
-
|
|
2273
|
+
/* @__PURE__ */ jsxs6("div", { className: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
|
|
2274
|
+
BeforeSessions ? /* @__PURE__ */ jsx7(BeforeSessions, { state, adapter, value: { query, rows } }) : null,
|
|
2275
|
+
!rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx7("div", { className: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
|
|
2170
2276
|
rows.map((row) => /* @__PURE__ */ jsx7(Row, { value: row, row, state, adapter, onOpen, now }, row.key)),
|
|
2171
|
-
state.history.hasMoreSessions ? /* @__PURE__ */ jsx7("button", {
|
|
2277
|
+
state.history.hasMoreSessions ? /* @__PURE__ */ jsx7("button", { className: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null,
|
|
2278
|
+
AfterSessions ? /* @__PURE__ */ jsx7(AfterSessions, { state, adapter, value: { query, rows } }) : null
|
|
2172
2279
|
] })
|
|
2173
2280
|
] });
|
|
2174
2281
|
}
|
|
@@ -2179,7 +2286,7 @@ import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
|
2179
2286
|
function HarnessAdvisory({ state, onReview }) {
|
|
2180
2287
|
const advisory = state.interopSettings?.advisories[0];
|
|
2181
2288
|
if (!advisory && !state.interopSettingsError) return null;
|
|
2182
|
-
return /* @__PURE__ */ jsxs7("div", {
|
|
2289
|
+
return /* @__PURE__ */ jsxs7("div", { className: "scui-advisory", "data-severity": advisory?.severity ?? "error", role: advisory?.severity === "error" || !advisory ? "alert" : "status", children: [
|
|
2183
2290
|
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "!" }),
|
|
2184
2291
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2185
2292
|
/* @__PURE__ */ jsx8("strong", { children: advisory?.title ?? "Could not inspect harness settings" }),
|
|
@@ -2213,7 +2320,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2213
2320
|
document.addEventListener("keydown", dismiss);
|
|
2214
2321
|
return () => document.removeEventListener("keydown", dismiss);
|
|
2215
2322
|
}, [onClose]);
|
|
2216
|
-
if (!report) return /* @__PURE__ */ jsx8("section", { ref: panel,
|
|
2323
|
+
if (!report) return /* @__PURE__ */ jsx8("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: /* @__PURE__ */ jsxs7("header", { children: [
|
|
2217
2324
|
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }),
|
|
2218
2325
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2219
2326
|
/* @__PURE__ */ jsx8("strong", { id: titleId, children: "Harness settings" }),
|
|
@@ -2226,7 +2333,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2226
2333
|
if (!changed.length || !state.canConfigureSettings) return;
|
|
2227
2334
|
adapter.onIntent({ action: "configureHarness", harness: report.harness, changes: changed, expectedRevision: report.revision });
|
|
2228
2335
|
};
|
|
2229
|
-
return /* @__PURE__ */ jsxs7("section", { ref: panel,
|
|
2336
|
+
return /* @__PURE__ */ jsxs7("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [
|
|
2230
2337
|
/* @__PURE__ */ jsxs7("header", { children: [
|
|
2231
2338
|
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }),
|
|
2232
2339
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
@@ -2243,7 +2350,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2243
2350
|
const recommendation = report.advisories.map((advisory) => advisory.recommendation).find((item) => item.change.key === control.key && item.change.value === values[control.key]);
|
|
2244
2351
|
const consequence = choice?.risk ?? recommendation?.consequence;
|
|
2245
2352
|
return /* @__PURE__ */ jsxs7("fieldset", { disabled: !control.writable || Boolean(state.operation), children: [
|
|
2246
|
-
/* @__PURE__ */ jsxs7("label", {
|
|
2353
|
+
/* @__PURE__ */ jsxs7("label", { htmlFor: `scui-setting-${control.key}`, children: [
|
|
2247
2354
|
/* @__PURE__ */ jsx8("strong", { children: control.label }),
|
|
2248
2355
|
/* @__PURE__ */ jsx8("small", { children: control.description })
|
|
2249
2356
|
] }),
|
|
@@ -2252,11 +2359,11 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2252
2359
|
control.choices.map((item) => /* @__PURE__ */ jsx8("option", { value: item.value, children: item.label }, item.value))
|
|
2253
2360
|
] }),
|
|
2254
2361
|
choice ? /* @__PURE__ */ jsx8("p", { children: choice.description }) : null,
|
|
2255
|
-
consequence ? /* @__PURE__ */ jsxs7("p", {
|
|
2362
|
+
consequence ? /* @__PURE__ */ jsxs7("p", { className: "scui-setting-risk", children: [
|
|
2256
2363
|
/* @__PURE__ */ jsx8("strong", { children: "Security consequence" }),
|
|
2257
2364
|
consequence
|
|
2258
2365
|
] }) : null,
|
|
2259
|
-
/* @__PURE__ */ jsxs7("small", {
|
|
2366
|
+
/* @__PURE__ */ jsxs7("small", { className: "scui-setting-source", children: [
|
|
2260
2367
|
control.effectiveNote,
|
|
2261
2368
|
control.sourcePath ? ` Source: ${control.sourcePath}` : ""
|
|
2262
2369
|
] })
|
|
@@ -2269,16 +2376,41 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2269
2376
|
] })
|
|
2270
2377
|
] });
|
|
2271
2378
|
}
|
|
2379
|
+
function HarnessReadiness({ harnesses, adapter }) {
|
|
2380
|
+
const blocked = harnesses.filter((item) => !item.startable);
|
|
2381
|
+
if (!blocked.length) return null;
|
|
2382
|
+
return /* @__PURE__ */ jsxs7("details", { className: "scui-readiness", open: !harnesses.some((item) => item.startable), children: [
|
|
2383
|
+
/* @__PURE__ */ jsxs7("summary", { children: [
|
|
2384
|
+
blocked.length,
|
|
2385
|
+
" ",
|
|
2386
|
+
blocked.length === 1 ? "harness needs" : "harnesses need",
|
|
2387
|
+
" setup"
|
|
2388
|
+
] }),
|
|
2389
|
+
/* @__PURE__ */ jsx8("div", { children: blocked.map((item) => /* @__PURE__ */ jsxs7("section", { children: [
|
|
2390
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: item.id, size: 25 }),
|
|
2391
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2392
|
+
/* @__PURE__ */ jsx8("strong", { children: item.label }),
|
|
2393
|
+
/* @__PURE__ */ jsx8("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") }),
|
|
2394
|
+
item.protocol ? /* @__PURE__ */ jsxs7("em", { children: [
|
|
2395
|
+
item.protocol,
|
|
2396
|
+
" \xB7 ",
|
|
2397
|
+
item.runtime
|
|
2398
|
+
] }) : null
|
|
2399
|
+
] }),
|
|
2400
|
+
item.repair ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2401
|
+
] }, item.id)) })
|
|
2402
|
+
] });
|
|
2403
|
+
}
|
|
2272
2404
|
|
|
2273
2405
|
// src/messenger.jsx
|
|
2274
2406
|
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
2275
2407
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
2276
2408
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
2277
2409
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
2278
|
-
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2410
|
+
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "steer", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2279
2411
|
function Receipt({ state, adapter }) {
|
|
2280
2412
|
const receipt = state.reductionReceipt;
|
|
2281
|
-
if (receipt) return /* @__PURE__ */ jsx9("div", {
|
|
2413
|
+
if (receipt) return /* @__PURE__ */ jsx9("div", { className: "scui-receipt", children: /* @__PURE__ */ jsxs8("span", { children: [
|
|
2282
2414
|
/* @__PURE__ */ jsx9("strong", { children: "Reduced and verified" }),
|
|
2283
2415
|
/* @__PURE__ */ jsxs8("small", { children: [
|
|
2284
2416
|
receipt.sourceTokens.toLocaleString(),
|
|
@@ -2289,7 +2421,7 @@ function Receipt({ state, adapter }) {
|
|
|
2289
2421
|
"\xD7 \xB7 reversible"
|
|
2290
2422
|
] })
|
|
2291
2423
|
] }) });
|
|
2292
|
-
if (state.exportReceipt) return /* @__PURE__ */ jsxs8("div", {
|
|
2424
|
+
if (state.exportReceipt) return /* @__PURE__ */ jsxs8("div", { className: "scui-receipt", children: [
|
|
2293
2425
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2294
2426
|
/* @__PURE__ */ jsxs8("strong", { children: [
|
|
2295
2427
|
"Lossless export ready \xB7 ",
|
|
@@ -2304,7 +2436,7 @@ function Receipt({ state, adapter }) {
|
|
|
2304
2436
|
] }),
|
|
2305
2437
|
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(state.exportReceipt.path), children: "Copy path" })
|
|
2306
2438
|
] });
|
|
2307
|
-
if (state.terminalHandoff) return /* @__PURE__ */ jsxs8("div", {
|
|
2439
|
+
if (state.terminalHandoff) return /* @__PURE__ */ jsxs8("div", { className: "scui-receipt", children: [
|
|
2308
2440
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2309
2441
|
/* @__PURE__ */ jsx9("strong", { children: "Terminal handoff ready" }),
|
|
2310
2442
|
/* @__PURE__ */ jsx9("small", { children: state.terminalHandoff.cwd })
|
|
@@ -2361,7 +2493,7 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2361
2493
|
const dispatch = (item) => {
|
|
2362
2494
|
setOpen(false);
|
|
2363
2495
|
if (item.onSelect) item.onSelect();
|
|
2364
|
-
else adapter
|
|
2496
|
+
else dispatchConfirmedIntent(adapter, item.intent);
|
|
2365
2497
|
};
|
|
2366
2498
|
const navigate = (event) => {
|
|
2367
2499
|
if (event.key === "Escape") {
|
|
@@ -2379,11 +2511,11 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2379
2511
|
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;
|
|
2380
2512
|
items[index].focus({ preventScroll: true });
|
|
2381
2513
|
};
|
|
2382
|
-
return /* @__PURE__ */ jsxs8("div", {
|
|
2514
|
+
return /* @__PURE__ */ jsxs8("div", { className: "scui-menu", ref: root, onBlur: (event) => {
|
|
2383
2515
|
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
2384
2516
|
}, children: [
|
|
2385
|
-
/* @__PURE__ */ jsx9("button", { ref: trigger,
|
|
2386
|
-
open ? /* @__PURE__ */ jsx9("div", { ref: panel, id: menuId,
|
|
2517
|
+
/* @__PURE__ */ jsx9("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__ */ jsx9(UiIcon, { name: "menu", size: 18 }) }),
|
|
2518
|
+
open ? /* @__PURE__ */ jsx9("div", { ref: panel, id: menuId, className: "scui-menu-panel", role: "menu", "aria-label": "Conversation actions", onKeyDown: navigate, children: groups.map((group) => /* @__PURE__ */ jsxs8("section", { role: "group", "aria-label": group.label, children: [
|
|
2387
2519
|
/* @__PURE__ */ jsx9("strong", { children: group.label }),
|
|
2388
2520
|
group.items.map((item) => /* @__PURE__ */ jsx9("button", { role: "menuitem", type: "button", disabled: actionPending, onClick: () => dispatch(item), children: item.label }, item.key))
|
|
2389
2521
|
] }, group.label)) }) : null
|
|
@@ -2398,10 +2530,10 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2398
2530
|
useEffect8(() => {
|
|
2399
2531
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
2400
2532
|
}, []);
|
|
2401
|
-
return /* @__PURE__ */ jsxs8("header", {
|
|
2533
|
+
return /* @__PURE__ */ jsxs8("header", { className: "scui-head scui-chat-head", children: [
|
|
2402
2534
|
/* @__PURE__ */ jsx9("button", { ref: back, type: "button", "aria-label": "Back to chats", onClick: onBack, children: /* @__PURE__ */ jsx9(UiIcon, { name: "back", size: 18 }) }),
|
|
2403
2535
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: harness, size: 28 }),
|
|
2404
|
-
/* @__PURE__ */ jsxs8("span", {
|
|
2536
|
+
/* @__PURE__ */ jsxs8("span", { className: "scui-head-copy", children: [
|
|
2405
2537
|
/* @__PURE__ */ jsx9("strong", { children: title }),
|
|
2406
2538
|
/* @__PURE__ */ jsxs8("small", { children: [
|
|
2407
2539
|
harnessDisplayName(harness),
|
|
@@ -2415,7 +2547,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2415
2547
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2416
2548
|
] });
|
|
2417
2549
|
}
|
|
2418
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels }) {
|
|
2550
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2419
2551
|
const Header = slots.header;
|
|
2420
2552
|
const HeaderActions = slots.headerActions;
|
|
2421
2553
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2512,17 +2644,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2512
2644
|
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, context: pending.context, images: pending.images, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
2513
2645
|
const action = state.operation || pendingAction?.action || null;
|
|
2514
2646
|
const actionLabel = operationLabel(action);
|
|
2515
|
-
const actionState = action ? { ...state, operation: action, canInterrupt: false, canRespond: false } : state;
|
|
2647
|
+
const actionState = action ? { ...state, operation: action, canSteer: false, canInterrupt: false, canRespond: false } : state;
|
|
2516
2648
|
const unreadAfterMessages = state.attention.find((item) => item.key === state.attached?.key)?.afterMessages ?? null;
|
|
2517
2649
|
const Advisory = components.HarnessAdvisory ?? HarnessAdvisory;
|
|
2518
2650
|
const SettingsPanel = components.HarnessSettingsPanel ?? HarnessSettingsPanel;
|
|
2519
|
-
return /* @__PURE__ */ jsxs8("section", {
|
|
2651
|
+
return /* @__PURE__ */ jsxs8("section", { className: "scui-chat", children: [
|
|
2520
2652
|
Header ? /* @__PURE__ */ jsx9(Header, { state: actionState, adapter: trackedAdapter, value: null }) : /* @__PURE__ */ jsx9(ChatHeader, { state: actionState, adapter: trackedAdapter, pendingStatus: pending?.status ?? null, actionPending: Boolean(action), onBack, onNew, onClose, onSettings: () => setSettings({ recommendedChange: null }), headerActions: HeaderActions }),
|
|
2521
|
-
actionLabel ? /* @__PURE__ */ jsxs8("div", {
|
|
2653
|
+
actionLabel ? /* @__PURE__ */ jsxs8("div", { className: "scui-operation", role: "status", children: [
|
|
2522
2654
|
/* @__PURE__ */ jsx9("i", {}),
|
|
2523
2655
|
actionLabel
|
|
2524
2656
|
] }) : null,
|
|
2525
|
-
state.error ? /* @__PURE__ */ jsxs8("div", {
|
|
2657
|
+
state.error ? /* @__PURE__ */ jsxs8("div", { className: "scui-error", role: "alert", children: [
|
|
2526
2658
|
/* @__PURE__ */ jsx9("span", { children: state.error }),
|
|
2527
2659
|
state.recoverable ? /* @__PURE__ */ jsx9("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
|
|
2528
2660
|
] }) : null,
|
|
@@ -2530,11 +2662,11 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2530
2662
|
/* @__PURE__ */ jsx9(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2531
2663
|
/* @__PURE__ */ jsx9(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2532
2664
|
/* @__PURE__ */ jsx9(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
|
|
2533
|
-
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx9(Composer, { state: actionState, adapter: trackedAdapter, labels, memoryKey, pendingStatus: pending?.status ?? null, restoreDraft, onDraftRestored: (id) => setRestoreDraft((value) => value?.id === id ? null : value), onPending: beginPending }, memoryKey) : null,
|
|
2665
|
+
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx9(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,
|
|
2534
2666
|
settings ? /* @__PURE__ */ jsx9(SettingsPanel, { state: actionState, adapter: trackedAdapter, value: state.interopSettings, recommendedChange: settings.recommendedChange, onClose: () => setSettings(null) }) : null
|
|
2535
2667
|
] });
|
|
2536
2668
|
}
|
|
2537
|
-
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions }) {
|
|
2669
|
+
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation }) {
|
|
2538
2670
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
2539
2671
|
const startableKey = startable.map((item) => `${item.id}:${item.launchModes?.join(",")}:${item.preferredLaunchMode ?? ""}`).join("\0");
|
|
2540
2672
|
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [], modes: {} };
|
|
@@ -2550,6 +2682,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2550
2682
|
const startSequence = useRef7(0);
|
|
2551
2683
|
const textarea = useRef7(null);
|
|
2552
2684
|
const selectedHarness = startable.find((item) => item.id === harness) ?? null;
|
|
2685
|
+
const Readiness = components.HarnessReadiness ?? HarnessReadiness;
|
|
2553
2686
|
const launchModes = selectedHarness?.launchModes?.length ? selectedHarness.launchModes : ["headless"];
|
|
2554
2687
|
const rememberedMode = modes[harness];
|
|
2555
2688
|
const mode = launchModes.includes(rememberedMode) ? rememberedMode : launchModes.includes(selectedHarness?.preferredLaunchMode) ? selectedHarness.preferredLaunchMode : launchModes[0];
|
|
@@ -2576,6 +2709,19 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2576
2709
|
useEffect8(() => {
|
|
2577
2710
|
textarea.current?.focus({ preventScroll: true });
|
|
2578
2711
|
}, []);
|
|
2712
|
+
useEffect8(() => {
|
|
2713
|
+
if (!navigation) return;
|
|
2714
|
+
const nextHarness = startable.some((item) => item.id === navigation.harness) ? navigation.harness : harness;
|
|
2715
|
+
const nextDraft = typeof navigation.draft === "string" ? navigation.draft : draft;
|
|
2716
|
+
const nextContext = mergeContext([], navigation.context ?? []);
|
|
2717
|
+
const nextImages = mergeImages([], navigation.images ?? []);
|
|
2718
|
+
setHarness(nextHarness);
|
|
2719
|
+
setDraft(nextDraft);
|
|
2720
|
+
setContext(nextContext);
|
|
2721
|
+
setImages(nextImages);
|
|
2722
|
+
remember({ harness: nextHarness, draft: nextDraft, context: nextContext, images: nextImages });
|
|
2723
|
+
textarea.current?.focus({ preventScroll: true });
|
|
2724
|
+
}, [navigation?.id]);
|
|
2579
2725
|
const pickContext = () => {
|
|
2580
2726
|
if (mode === "terminal" || !adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
2581
2727
|
setPicking(true);
|
|
@@ -2596,6 +2742,15 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2596
2742
|
});
|
|
2597
2743
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
2598
2744
|
};
|
|
2745
|
+
const attachCandidate = (picked) => {
|
|
2746
|
+
if (mode === "terminal") return;
|
|
2747
|
+
const attachments = partitionAttachments(picked);
|
|
2748
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
2749
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
2750
|
+
setContext(nextContext);
|
|
2751
|
+
setImages(nextImages);
|
|
2752
|
+
remember({ context: nextContext, images: nextImages });
|
|
2753
|
+
};
|
|
2599
2754
|
const addImageFiles = (value, source) => {
|
|
2600
2755
|
const allFiles = Array.from(value ?? []);
|
|
2601
2756
|
if (!allFiles.length) return false;
|
|
@@ -2644,27 +2799,27 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2644
2799
|
Promise.resolve(result).catch(() => setStarting((current) => current?.id === id ? null : current));
|
|
2645
2800
|
}
|
|
2646
2801
|
};
|
|
2647
|
-
return /* @__PURE__ */ jsxs8("section", {
|
|
2648
|
-
/* @__PURE__ */ jsxs8("header", {
|
|
2802
|
+
return /* @__PURE__ */ jsxs8("section", { className: "scui-chat", children: [
|
|
2803
|
+
/* @__PURE__ */ jsxs8("header", { className: "scui-head", children: [
|
|
2649
2804
|
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Back", onClick: onBack, children: /* @__PURE__ */ jsx9(UiIcon, { name: "back", size: 18 }) }),
|
|
2650
|
-
/* @__PURE__ */ jsxs8("span", {
|
|
2805
|
+
/* @__PURE__ */ jsxs8("span", { className: "scui-head-copy", children: [
|
|
2651
2806
|
/* @__PURE__ */ jsx9("strong", { children: labels.newChat }),
|
|
2652
2807
|
/* @__PURE__ */ jsx9("small", { children: "No session is created until you send" })
|
|
2653
2808
|
] }),
|
|
2654
2809
|
HeaderActions ? /* @__PURE__ */ jsx9(HeaderActions, { state, adapter, value: "new" }) : null,
|
|
2655
2810
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2656
2811
|
] }),
|
|
2657
|
-
starting ? /* @__PURE__ */ jsxs8("div", {
|
|
2812
|
+
starting ? /* @__PURE__ */ jsxs8("div", { className: "scui-operation", role: "status", children: [
|
|
2658
2813
|
/* @__PURE__ */ jsx9("i", {}),
|
|
2659
2814
|
mode === "terminal" ? "Opening terminal\u2026" : operationLabel("start")
|
|
2660
2815
|
] }) : null,
|
|
2661
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2816
|
+
/* @__PURE__ */ jsxs8("div", { className: "scui-new", children: [
|
|
2662
2817
|
/* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2663
2818
|
/* @__PURE__ */ jsx9("strong", { children: "What should the agent build or fix?" }),
|
|
2664
2819
|
/* @__PURE__ */ jsx9("small", { children: "Choose a coding harness and send the first message." })
|
|
2665
2820
|
] }),
|
|
2666
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2667
|
-
/* @__PURE__ */ jsxs8("label", {
|
|
2821
|
+
/* @__PURE__ */ jsxs8("div", { className: "scui-compose", children: [
|
|
2822
|
+
/* @__PURE__ */ jsxs8("label", { className: "scui-harness-picker", children: [
|
|
2668
2823
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: harness, size: 24 }),
|
|
2669
2824
|
/* @__PURE__ */ jsx9("span", { children: "Coding harness" }),
|
|
2670
2825
|
/* @__PURE__ */ jsx9("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
@@ -2676,7 +2831,8 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2676
2831
|
item.startable ? "" : " \xB7 unavailable"
|
|
2677
2832
|
] }, item.id)) })
|
|
2678
2833
|
] }),
|
|
2679
|
-
|
|
2834
|
+
/* @__PURE__ */ jsx9(Readiness, { harnesses: state.harnesses, state, adapter }),
|
|
2835
|
+
launchModes.length > 1 ? /* @__PURE__ */ jsxs8("fieldset", { className: "scui-launch-modes", disabled: Boolean(starting), children: [
|
|
2680
2836
|
/* @__PURE__ */ jsx9("legend", { children: "Run as" }),
|
|
2681
2837
|
launchModes.map((item) => /* @__PURE__ */ jsxs8("label", { children: [
|
|
2682
2838
|
/* @__PURE__ */ jsx9("input", { type: "radio", name: `launch-mode-${memoryKey}`, value: item, checked: mode === item, onChange: () => {
|
|
@@ -2691,6 +2847,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2691
2847
|
] })
|
|
2692
2848
|
] }, item))
|
|
2693
2849
|
] }) : null,
|
|
2850
|
+
mode !== "terminal" ? /* @__PURE__ */ jsx9(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }) : null,
|
|
2694
2851
|
/* @__PURE__ */ jsx9(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
2695
2852
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2696
2853
|
remember({ images: next });
|
|
@@ -2701,8 +2858,8 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2701
2858
|
remember({ context: next });
|
|
2702
2859
|
return next;
|
|
2703
2860
|
}) }),
|
|
2704
|
-
terminalAttachments ? /* @__PURE__ */ jsx9("small", {
|
|
2705
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2861
|
+
terminalAttachments ? /* @__PURE__ */ jsx9("small", { className: "scui-context-error", role: "alert", children: "Terminal starts currently accept text only. Remove attachments or choose Chat." }) : pickerError ? /* @__PURE__ */ jsx9("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
2862
|
+
/* @__PURE__ */ jsxs8("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
2706
2863
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
2707
2864
|
event.preventDefault();
|
|
2708
2865
|
setDragging(true);
|
|
@@ -2712,7 +2869,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2712
2869
|
}, onDragLeave: (event) => {
|
|
2713
2870
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
2714
2871
|
}, onDrop: dropImages, children: [
|
|
2715
|
-
adapter.pickContext ? /* @__PURE__ */ jsx9("button", {
|
|
2872
|
+
adapter.pickContext ? /* @__PURE__ */ jsx9("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__ */ jsx9("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx9(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2716
2873
|
/* @__PURE__ */ jsx9("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) => {
|
|
2717
2874
|
const value = event.currentTarget.value;
|
|
2718
2875
|
setDraft(value);
|
|
@@ -2723,22 +2880,52 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2723
2880
|
send();
|
|
2724
2881
|
}
|
|
2725
2882
|
} }),
|
|
2726
|
-
/* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9("button", { type: "button",
|
|
2883
|
+
/* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9("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__ */ jsx9("i", { className: "scui-control-spinner" }) : /* @__PURE__ */ jsx9(UiIcon, { name: "send", size: 17 }) }) })
|
|
2727
2884
|
] })
|
|
2728
2885
|
] })
|
|
2729
2886
|
] });
|
|
2730
2887
|
}
|
|
2731
|
-
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, labels, components = {}, slots = {} }) {
|
|
2888
|
+
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, navigation = null, onViewChange, contextCandidates: candidatesInput = [], labels, components = {}, slots = {} }) {
|
|
2732
2889
|
const state = useMemo3(() => normalizeUiState(stateInput), [stateInput]);
|
|
2890
|
+
const contextCandidates = useMemo3(() => normalizeAttachmentCandidates(candidatesInput), [candidatesInput]);
|
|
2733
2891
|
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
2734
2892
|
const memoryKey = state.workspace || "@default";
|
|
2735
2893
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2736
2894
|
const [opening, setOpening] = useState6(null);
|
|
2895
|
+
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2737
2896
|
const [listFocus, setListFocus] = useState6(null);
|
|
2897
|
+
const lastNavigation = useRef7(null);
|
|
2738
2898
|
const setView = (next) => {
|
|
2739
2899
|
boundedSet(messengerViewMemory, memoryKey, next);
|
|
2740
2900
|
setViewState(next);
|
|
2901
|
+
onViewChange?.(next);
|
|
2741
2902
|
};
|
|
2903
|
+
useEffect8(() => {
|
|
2904
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2905
|
+
lastNavigation.current = navigation.id;
|
|
2906
|
+
if (navigation.view === "list") {
|
|
2907
|
+
setOpening(null);
|
|
2908
|
+
setView("list");
|
|
2909
|
+
return;
|
|
2910
|
+
}
|
|
2911
|
+
if (navigation.view === "new") {
|
|
2912
|
+
setListFocus("@new");
|
|
2913
|
+
setNewNavigation(navigation);
|
|
2914
|
+
setView("new");
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2918
|
+
setListFocus(navigation.sessionKey);
|
|
2919
|
+
if (state.attached?.key === navigation.sessionKey) {
|
|
2920
|
+
setOpening(null);
|
|
2921
|
+
setView("chat");
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
const row = state.sessions.find((item) => item.key === navigation.sessionKey);
|
|
2925
|
+
setOpening(row ?? { key: navigation.sessionKey, harness: "supercode", name: "Chat", title: "Chat" });
|
|
2926
|
+
adapter.onIntent({ action: "attach", key: navigation.sessionKey });
|
|
2927
|
+
}
|
|
2928
|
+
}, [adapter, navigation, state.attached?.key, state.sessions]);
|
|
2742
2929
|
useEffect8(() => {
|
|
2743
2930
|
if (!opening) return;
|
|
2744
2931
|
if (state.attached?.key === opening.key) {
|
|
@@ -2756,20 +2943,22 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2756
2943
|
const close = () => adapter.onClose?.();
|
|
2757
2944
|
const Footer = slots.footer;
|
|
2758
2945
|
const HeaderActions = slots.headerActions;
|
|
2759
|
-
return /* @__PURE__ */ jsxs8("main", {
|
|
2946
|
+
return /* @__PURE__ */ jsxs8("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2760
2947
|
view === "list" ? /* @__PURE__ */ jsx9(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2761
2948
|
setListFocus("@new");
|
|
2949
|
+
setNewNavigation(null);
|
|
2762
2950
|
setView("new");
|
|
2763
|
-
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, headerActions: HeaderActions }) : null,
|
|
2764
|
-
view === "new" ? /* @__PURE__ */ jsx9(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: (mode) => setView(mode === "terminal" ? "list" : "chat"), labels: copy, memoryKey, headerActions: HeaderActions }) : null,
|
|
2951
|
+
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
2952
|
+
view === "new" ? /* @__PURE__ */ jsx9(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,
|
|
2765
2953
|
view === "chat" ? /* @__PURE__ */ jsx9(Chat, { state, adapter, onBack: () => {
|
|
2766
2954
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2767
2955
|
setView("list");
|
|
2768
2956
|
}, onNew: () => {
|
|
2769
2957
|
setListFocus("@new");
|
|
2958
|
+
setNewNavigation(null);
|
|
2770
2959
|
setView("new");
|
|
2771
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy }) : null,
|
|
2772
|
-
opening ? /* @__PURE__ */ jsxs8("div", {
|
|
2960
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
2961
|
+
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2773
2962
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2774
2963
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2775
2964
|
/* @__PURE__ */ jsxs8("strong", { children: [
|