@volter-ai-dev/supercode-ui 0.1.35 → 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 +84 -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 +43 -0
- package/controller.mjs +127 -2
- package/conversation.mjs +75 -64
- package/core.d.ts +3 -0
- package/core.mjs +222 -2
- package/embed.mjs +338 -149
- package/icon.mjs +1 -1
- package/index.d.ts +68 -2
- package/logo.mjs +11 -6
- package/messenger.mjs +338 -149
- package/package.json +54 -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/messenger.mjs
CHANGED
|
@@ -32,6 +32,7 @@ var EMPTY_UI_STATE = Object.freeze({
|
|
|
32
32
|
mode: "none",
|
|
33
33
|
strategy: null,
|
|
34
34
|
canSend: false,
|
|
35
|
+
canSteer: false,
|
|
35
36
|
canResume: false,
|
|
36
37
|
continuationModes: Object.freeze([]),
|
|
37
38
|
canBranch: false,
|
|
@@ -719,6 +720,7 @@ function normalizeUiState(value) {
|
|
|
719
720
|
mode: MODES.has(raw.mode) ? raw.mode : "none",
|
|
720
721
|
strategy: STRATEGIES.has(raw.strategy) ? raw.strategy : null,
|
|
721
722
|
canSend: raw.canSend === true,
|
|
723
|
+
canSteer: raw.canSteer === true,
|
|
722
724
|
canResume,
|
|
723
725
|
continuationModes,
|
|
724
726
|
canBranch: raw.canBranch === true,
|
|
@@ -748,7 +750,29 @@ function normalizeUiState(value) {
|
|
|
748
750
|
const startable = item.startable === true;
|
|
749
751
|
const launchModes = Array.isArray(item.launchModes) ? [...new Set(item.launchModes.filter((mode) => mode === "headless" || mode === "terminal"))] : startable ? ["headless"] : [];
|
|
750
752
|
const preferredLaunchMode = launchModes.includes(item.preferredLaunchMode) ? item.preferredLaunchMode : launchModes[0] ?? null;
|
|
751
|
-
|
|
753
|
+
const capabilities = record(item.capabilities);
|
|
754
|
+
return [{
|
|
755
|
+
id: item.id,
|
|
756
|
+
label: string(item.label, harnessDisplayName(item.id)),
|
|
757
|
+
installed: item.installed === true,
|
|
758
|
+
startable,
|
|
759
|
+
reason: typeof item.reason === "string" ? boundedString(item.reason) : null,
|
|
760
|
+
auth: ["ready", "configured", "required", "unknown"].includes(item.auth) ? item.auth : "unknown",
|
|
761
|
+
runtime: ["ready", "degraded", "unavailable"].includes(item.runtime) ? item.runtime : startable ? "ready" : "unavailable",
|
|
762
|
+
protocol: boundedString(item.protocol, 100),
|
|
763
|
+
repair: typeof item.repair === "string" ? boundedString(item.repair, 4e3) : null,
|
|
764
|
+
capabilities: {
|
|
765
|
+
start: capabilities?.start === true,
|
|
766
|
+
resume: capabilities?.resume === true,
|
|
767
|
+
attach: capabilities?.attach === true,
|
|
768
|
+
send: capabilities?.send === true,
|
|
769
|
+
interrupt: capabilities?.interrupt === true,
|
|
770
|
+
steer: capabilities?.steer === true,
|
|
771
|
+
respond: capabilities?.respond === true
|
|
772
|
+
},
|
|
773
|
+
launchModes,
|
|
774
|
+
preferredLaunchMode
|
|
775
|
+
}];
|
|
752
776
|
}) : [],
|
|
753
777
|
history: { sessionLimit: number(history?.sessionLimit), hasMoreSessions: history?.hasMoreSessions === true, transcriptLimit: number(history?.transcriptLimit, 120), hasEarlier: history?.hasEarlier === true },
|
|
754
778
|
savedDraft: string(raw.savedDraft),
|
|
@@ -779,6 +803,16 @@ function sessionActivity(state, row) {
|
|
|
779
803
|
if (row.live || row.runtimeStatus === "idle") return "recent";
|
|
780
804
|
return "idle";
|
|
781
805
|
}
|
|
806
|
+
var ACTIVITY_PRIORITY = Object.freeze({
|
|
807
|
+
"needs-input": 70,
|
|
808
|
+
failed: 60,
|
|
809
|
+
working: 50,
|
|
810
|
+
unseen: 40,
|
|
811
|
+
finished: 30,
|
|
812
|
+
running: 20,
|
|
813
|
+
recent: 10,
|
|
814
|
+
idle: 0
|
|
815
|
+
});
|
|
782
816
|
function filterSessions(rows, query) {
|
|
783
817
|
const needle = query.trim().toLocaleLowerCase();
|
|
784
818
|
if (!needle) return [...rows];
|
|
@@ -837,7 +871,7 @@ function canContinueHere(state) {
|
|
|
837
871
|
}
|
|
838
872
|
function operationLabel(operation) {
|
|
839
873
|
if (!operation) return "";
|
|
840
|
-
const labels = { discover: "Refreshing chats\u2026", observe: "Loading recent messages\u2026", attach: "Opening chat\u2026", start: "Starting new chat\u2026", resume: "Continuing here\u2026", join: "Joining live session\u2026", detach: "Detaching to read-only\u2026", branch: "Starting continuation\u2026", reduce: "Reducing context and verifying reversibility\u2026", terminal: "Preparing terminal handoff\u2026", export: "Exporting losslessly\u2026", interrupt: "Stopping agent\u2026", respond: "Sending response\u2026", configureHarness: "Updating harness settings\u2026", loadEarlier: "Loading earlier messages\u2026", loadSessions: "Loading more chats\u2026", refresh: "Retrying\u2026" };
|
|
874
|
+
const labels = { discover: "Refreshing chats\u2026", observe: "Loading recent messages\u2026", attach: "Opening chat\u2026", start: "Starting new chat\u2026", resume: "Continuing here\u2026", join: "Joining live session\u2026", detach: "Detaching to read-only\u2026", branch: "Starting continuation\u2026", reduce: "Reducing context and verifying reversibility\u2026", terminal: "Preparing terminal handoff\u2026", export: "Exporting losslessly\u2026", steer: "Steering agent\u2026", interrupt: "Stopping agent\u2026", respond: "Sending response\u2026", configureHarness: "Updating harness settings\u2026", loadEarlier: "Loading earlier messages\u2026", loadSessions: "Loading more chats\u2026", refresh: "Retrying\u2026" };
|
|
841
875
|
return labels[operation] ?? `${operation.replaceAll("_", " ")}\u2026`;
|
|
842
876
|
}
|
|
843
877
|
function terminalCommand(handoff) {
|
|
@@ -905,7 +939,7 @@ var ICONS = {
|
|
|
905
939
|
function UiIcon({ name, size = 16, class: className = "" }) {
|
|
906
940
|
const Glyph = ICONS[name];
|
|
907
941
|
if (!Glyph) return null;
|
|
908
|
-
return /* @__PURE__ */ jsx("svg", {
|
|
942
|
+
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, {}) });
|
|
909
943
|
}
|
|
910
944
|
|
|
911
945
|
// src/context.jsx
|
|
@@ -979,6 +1013,39 @@ function partitionAttachments(value) {
|
|
|
979
1013
|
}
|
|
980
1014
|
return { context, images };
|
|
981
1015
|
}
|
|
1016
|
+
function normalizeAttachmentCandidates(value) {
|
|
1017
|
+
const candidates = [];
|
|
1018
|
+
for (const item of Array.isArray(value) ? value : []) {
|
|
1019
|
+
const context = normalizeContext(item)[0];
|
|
1020
|
+
if (context) {
|
|
1021
|
+
candidates.push(context);
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
const image = normalizeImages(item)[0];
|
|
1025
|
+
if (image) candidates.push(image);
|
|
1026
|
+
}
|
|
1027
|
+
return candidates.slice(0, MAX_CONTEXT_ITEMS + MAX_IMAGE_ITEMS);
|
|
1028
|
+
}
|
|
1029
|
+
function attachmentKey(item) {
|
|
1030
|
+
if (item.id) return `id:${item.id}`;
|
|
1031
|
+
return "detail" in item ? `context:${item.kind ?? ""}\0${item.label}\0${item.detail}` : `image:${item.url}`;
|
|
1032
|
+
}
|
|
1033
|
+
function ContextCandidate({ attachment, attached, onAttach }) {
|
|
1034
|
+
const image = "url" in attachment;
|
|
1035
|
+
return /* @__PURE__ */ jsxs2("button", { type: "button", disabled: attached, "aria-label": `${attached ? "Attached" : "Attach"} ${attachment.label}`, onClick: () => onAttach(attachment), children: [
|
|
1036
|
+
image ? /* @__PURE__ */ jsx2("img", { src: attachment.url, alt: "" }) : /* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 13 }),
|
|
1037
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1038
|
+
/* @__PURE__ */ jsx2("strong", { children: attachment.label }),
|
|
1039
|
+
/* @__PURE__ */ jsx2("small", { children: image ? "Image" : attachment.kind || "Context" })
|
|
1040
|
+
] }),
|
|
1041
|
+
attached ? /* @__PURE__ */ jsx2(UiIcon, { name: "check", size: 13 }) : /* @__PURE__ */ jsx2(UiIcon, { name: "plus", size: 13 })
|
|
1042
|
+
] });
|
|
1043
|
+
}
|
|
1044
|
+
function ContextCandidates({ items, context, images, state, adapter, onAttach, component: Candidate = ContextCandidate }) {
|
|
1045
|
+
if (!items.length) return null;
|
|
1046
|
+
const attached = new Set([...context, ...images].map(attachmentKey));
|
|
1047
|
+
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))) });
|
|
1048
|
+
}
|
|
982
1049
|
async function imageAttachmentsFromFiles(value) {
|
|
983
1050
|
const files = Array.from(value ?? []).filter((file) => file?.type?.startsWith("image/"));
|
|
984
1051
|
if (files.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images at a time.`);
|
|
@@ -996,7 +1063,7 @@ async function imageAttachmentsFromFiles(value) {
|
|
|
996
1063
|
}
|
|
997
1064
|
function ContextTray({ items, onRemove }) {
|
|
998
1065
|
if (!items.length) return null;
|
|
999
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1066
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
1000
1067
|
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
1001
1068
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
1002
1069
|
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
@@ -1004,7 +1071,7 @@ function ContextTray({ items, onRemove }) {
|
|
|
1004
1071
|
}
|
|
1005
1072
|
function ImageTray({ items, onRemove }) {
|
|
1006
1073
|
if (!items.length) return null;
|
|
1007
|
-
return /* @__PURE__ */ jsx2("div", {
|
|
1074
|
+
return /* @__PURE__ */ jsx2("div", { className: "scui-compose-images", "aria-label": "Attached images", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
1008
1075
|
/* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }),
|
|
1009
1076
|
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
1010
1077
|
onRemove ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove image ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) }) : null
|
|
@@ -1082,7 +1149,7 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1082
1149
|
"dialog",
|
|
1083
1150
|
{
|
|
1084
1151
|
ref: dialog,
|
|
1085
|
-
|
|
1152
|
+
className: "scui-image-viewer",
|
|
1086
1153
|
"aria-label": `Image preview: ${item.label}`,
|
|
1087
1154
|
onClose,
|
|
1088
1155
|
onClick: (event) => {
|
|
@@ -1110,19 +1177,19 @@ function ImageViewer({ items, index, adapter, onChange, onClose }) {
|
|
|
1110
1177
|
] })
|
|
1111
1178
|
] }),
|
|
1112
1179
|
/* @__PURE__ */ jsxs2("figure", { children: [
|
|
1113
|
-
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", {
|
|
1180
|
+
imageUrl ? /* @__PURE__ */ jsx2("img", { src: imageUrl, alt: item.label }) : resolution?.status === "error" ? /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "alert", children: [
|
|
1114
1181
|
/* @__PURE__ */ jsx2(UiIcon, { name: "image", size: 28 }),
|
|
1115
1182
|
/* @__PURE__ */ jsx2("strong", { children: "Could not load image" }),
|
|
1116
1183
|
/* @__PURE__ */ jsx2("small", { children: resolution.message }),
|
|
1117
1184
|
/* @__PURE__ */ jsx2("button", { type: "button", onClick: () => resolve(item, true), children: "Retry" })
|
|
1118
|
-
] }) : /* @__PURE__ */ jsxs2("div", {
|
|
1119
|
-
/* @__PURE__ */ jsx2("i", {
|
|
1185
|
+
] }) : /* @__PURE__ */ jsxs2("div", { className: "scui-image-resolution", role: "status", children: [
|
|
1186
|
+
/* @__PURE__ */ jsx2("i", { className: "scui-control-spinner" }),
|
|
1120
1187
|
/* @__PURE__ */ jsx2("strong", { children: "Loading image\u2026" }),
|
|
1121
1188
|
/* @__PURE__ */ jsx2("small", { children: "The original stays out of the transcript payload." })
|
|
1122
1189
|
] }),
|
|
1123
1190
|
items.length > 1 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1124
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1125
|
-
/* @__PURE__ */ jsx2("button", { type: "button",
|
|
1191
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-previous", "aria-label": "Previous image", onClick: () => move(-1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) }),
|
|
1192
|
+
/* @__PURE__ */ jsx2("button", { type: "button", className: "scui-image-next", "aria-label": "Next image", onClick: () => move(1), children: /* @__PURE__ */ jsx2(UiIcon, { name: "chevron", size: 19 }) })
|
|
1126
1193
|
] }) : null
|
|
1127
1194
|
] })
|
|
1128
1195
|
]
|
|
@@ -1139,7 +1206,7 @@ function MessageImages({ items, adapter }) {
|
|
|
1139
1206
|
requestAnimationFrame(() => opener.current?.focus({ preventScroll: true }));
|
|
1140
1207
|
};
|
|
1141
1208
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1142
|
-
/* @__PURE__ */ jsx2("div", {
|
|
1209
|
+
/* @__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) => {
|
|
1143
1210
|
opener.current = event.currentTarget;
|
|
1144
1211
|
setActive(viewable.indexOf(item));
|
|
1145
1212
|
}, 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) => {
|
|
@@ -1162,6 +1229,16 @@ function MessageImages({ items, adapter }) {
|
|
|
1162
1229
|
] });
|
|
1163
1230
|
}
|
|
1164
1231
|
|
|
1232
|
+
// src/intent.js
|
|
1233
|
+
var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
|
|
1234
|
+
async function dispatchConfirmedIntent(adapter, intent) {
|
|
1235
|
+
if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
|
|
1236
|
+
const confirmed = await adapter.confirmIntent(intent);
|
|
1237
|
+
if (!confirmed) return;
|
|
1238
|
+
}
|
|
1239
|
+
return adapter.onIntent(intent);
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1165
1242
|
// src/textarea.js
|
|
1166
1243
|
import { useLayoutEffect } from "preact/hooks";
|
|
1167
1244
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -1188,28 +1265,29 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
1188
1265
|
const terminal = resume && state.continuationModes?.includes("terminal");
|
|
1189
1266
|
const join = state.canAttach;
|
|
1190
1267
|
const branch = state.canBranch;
|
|
1191
|
-
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", {
|
|
1268
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { className: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
1192
1269
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1193
1270
|
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
1194
1271
|
] }) });
|
|
1195
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1272
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-continuation", children: [
|
|
1196
1273
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1197
1274
|
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
1198
1275
|
/* @__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." })
|
|
1199
1276
|
] }),
|
|
1200
|
-
/* @__PURE__ */ jsxs3("span", {
|
|
1201
|
-
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => adapter
|
|
1202
|
-
terminal ? /* @__PURE__ */ jsx3("button", { type: "button",
|
|
1277
|
+
/* @__PURE__ */ jsxs3("span", { className: "scui-continuation-actions", children: [
|
|
1278
|
+
/* @__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 }),
|
|
1279
|
+
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
|
|
1203
1280
|
] })
|
|
1204
1281
|
] });
|
|
1205
1282
|
}
|
|
1206
|
-
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
1283
|
+
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, contextCandidates = [], components = {}, onPending, onDraftRestored }) {
|
|
1207
1284
|
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
1208
1285
|
const [draft, setDraft] = useState2(remembered.draft);
|
|
1209
1286
|
const [context, setContext] = useState2(remembered.context ?? []);
|
|
1210
1287
|
const [images, setImages] = useState2(remembered.images ?? []);
|
|
1211
1288
|
const [queue, setQueue] = useState2((remembered.queue ?? []).map((item) => ({ ...item, context: item.context ?? [], images: item.images ?? [] })));
|
|
1212
1289
|
const [dispatching, setDispatching] = useState2(false);
|
|
1290
|
+
const [steering, setSteering] = useState2(false);
|
|
1213
1291
|
const [picking, setPicking] = useState2(false);
|
|
1214
1292
|
const [dragging, setDragging] = useState2(false);
|
|
1215
1293
|
const [pickerError, setPickerError] = useState2(null);
|
|
@@ -1224,8 +1302,10 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1224
1302
|
remember(draft, context, images, next);
|
|
1225
1303
|
return next;
|
|
1226
1304
|
});
|
|
1227
|
-
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
1228
|
-
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching;
|
|
1305
|
+
const queueBlocked = state.busy || pendingStatus !== null || dispatching || steering;
|
|
1306
|
+
const queuesNewMessage = state.busy || pendingStatus === "sending" || pendingStatus === "failed" || dispatching || steering;
|
|
1307
|
+
const steerAvailable = state.busy && state.canSteer && !steering && pendingStatus === null;
|
|
1308
|
+
const canSteerDraft = steerAvailable && Boolean(draft.trim()) && context.length === 0 && images.length === 0;
|
|
1229
1309
|
useEffect2(() => {
|
|
1230
1310
|
if (!queueBlocked && state.canSend && queue.length) {
|
|
1231
1311
|
const [next, ...rest] = queue;
|
|
@@ -1277,6 +1357,14 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1277
1357
|
});
|
|
1278
1358
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
1279
1359
|
};
|
|
1360
|
+
const attachCandidate = (picked) => {
|
|
1361
|
+
const attachments = partitionAttachments(picked);
|
|
1362
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
1363
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
1364
|
+
setContext(nextContext);
|
|
1365
|
+
setImages(nextImages);
|
|
1366
|
+
remember(draft, nextContext, nextImages, queue);
|
|
1367
|
+
};
|
|
1280
1368
|
const addImageFiles = (value, source) => {
|
|
1281
1369
|
const allFiles = Array.from(value ?? []);
|
|
1282
1370
|
if (!allFiles.length) return false;
|
|
@@ -1305,9 +1393,17 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1305
1393
|
setDragging(false);
|
|
1306
1394
|
if (addImageFiles(event.dataTransfer?.files, "drop")) event.preventDefault();
|
|
1307
1395
|
};
|
|
1308
|
-
const send = () => {
|
|
1396
|
+
const send = (forceQueue = false) => {
|
|
1309
1397
|
const text = draft.trim();
|
|
1310
1398
|
if (!text && !images.length) return;
|
|
1399
|
+
if (canSteerDraft && !forceQueue) {
|
|
1400
|
+
setSteering(true);
|
|
1401
|
+
Promise.resolve(adapter.onIntent({ action: "steer", text })).then(() => {
|
|
1402
|
+
setDraft("");
|
|
1403
|
+
remember("", context, images, queue);
|
|
1404
|
+
}, (error) => setPickerError(error instanceof Error ? error.message : "Could not steer the active turn.")).finally(() => setSteering(false));
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1311
1407
|
const message = { text, context, images };
|
|
1312
1408
|
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
1313
1409
|
else if (state.canSend) {
|
|
@@ -1320,8 +1416,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1320
1416
|
setImages([]);
|
|
1321
1417
|
remember("", [], [], queuesNewMessage ? [...queue, message] : queue);
|
|
1322
1418
|
};
|
|
1323
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
1324
|
-
queue.length ? /* @__PURE__ */ jsxs3("div", {
|
|
1419
|
+
return /* @__PURE__ */ jsxs3("div", { className: "scui-compose", children: [
|
|
1420
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { className: "scui-queue", children: [
|
|
1325
1421
|
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
1326
1422
|
queue.length,
|
|
1327
1423
|
" queued"
|
|
@@ -1337,6 +1433,7 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1337
1433
|
/* @__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 }) })
|
|
1338
1434
|
] }, `${index}:${item.text}`))
|
|
1339
1435
|
] }) : null,
|
|
1436
|
+
/* @__PURE__ */ jsx3(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }),
|
|
1340
1437
|
/* @__PURE__ */ jsx3(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
1341
1438
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1342
1439
|
remember(draft, context, next, queue);
|
|
@@ -1347,8 +1444,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1347
1444
|
remember(draft, next, images, queue);
|
|
1348
1445
|
return next;
|
|
1349
1446
|
}) }),
|
|
1350
|
-
pickerError ? /* @__PURE__ */ jsx3("small", {
|
|
1351
|
-
/* @__PURE__ */ jsxs3("div", {
|
|
1447
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { className: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
1448
|
+
/* @__PURE__ */ jsxs3("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
1352
1449
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
1353
1450
|
event.preventDefault();
|
|
1354
1451
|
setDragging(true);
|
|
@@ -1358,8 +1455,8 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1358
1455
|
}, onDragLeave: (event) => {
|
|
1359
1456
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
1360
1457
|
}, onDrop: dropImages, children: [
|
|
1361
|
-
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", {
|
|
1362
|
-
/* @__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) => {
|
|
1458
|
+
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,
|
|
1459
|
+
/* @__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) => {
|
|
1363
1460
|
const value = event.currentTarget.value;
|
|
1364
1461
|
setDraft(value);
|
|
1365
1462
|
remember(value, context, images, queue);
|
|
@@ -1370,8 +1467,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
1370
1467
|
}
|
|
1371
1468
|
} }),
|
|
1372
1469
|
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1373
|
-
state.busy ? /* @__PURE__ */ jsx3("button", {
|
|
1374
|
-
/* @__PURE__ */ jsx3("button", {
|
|
1470
|
+
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,
|
|
1471
|
+
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,
|
|
1472
|
+
/* @__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 }) })
|
|
1375
1473
|
] })
|
|
1376
1474
|
] })
|
|
1377
1475
|
] });
|
|
@@ -1471,7 +1569,7 @@ function Markdown({ value, copyText }) {
|
|
|
1471
1569
|
}, 1500);
|
|
1472
1570
|
resets.current.set(button, timer);
|
|
1473
1571
|
};
|
|
1474
|
-
return /* @__PURE__ */ jsx4("div", {
|
|
1572
|
+
return /* @__PURE__ */ jsx4("div", { className: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1475
1573
|
}
|
|
1476
1574
|
|
|
1477
1575
|
// src/conversation.jsx
|
|
@@ -1483,28 +1581,28 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1483
1581
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1484
1582
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1485
1583
|
}[state.startup];
|
|
1486
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
1487
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1488
|
-
/* @__PURE__ */ jsxs4("span", {
|
|
1584
|
+
return /* @__PURE__ */ jsxs4("div", { className: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1585
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("i", {}) }),
|
|
1586
|
+
/* @__PURE__ */ jsxs4("span", { className: "scui-loading-copy", children: [
|
|
1489
1587
|
/* @__PURE__ */ jsx5("strong", { children: copy[0] }),
|
|
1490
1588
|
/* @__PURE__ */ jsx5("small", { children: copy[1] })
|
|
1491
1589
|
] }),
|
|
1492
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1590
|
+
/* @__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)) })
|
|
1493
1591
|
] });
|
|
1494
1592
|
}
|
|
1495
1593
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1496
1594
|
const request = entry.request;
|
|
1497
1595
|
if (!request) return null;
|
|
1498
1596
|
if (request.status === "responded") {
|
|
1499
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
1597
|
+
return /* @__PURE__ */ jsxs4("div", { className: "scui-request-done", children: [
|
|
1500
1598
|
"\u2713 Request answered \xB7 ",
|
|
1501
1599
|
request.resolution?.name ?? request.requestKind
|
|
1502
1600
|
] });
|
|
1503
1601
|
}
|
|
1504
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1602
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1505
1603
|
/* @__PURE__ */ jsx5("strong", { children: "Agent needs input" }),
|
|
1506
1604
|
/* @__PURE__ */ jsx5(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1507
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
1605
|
+
/* @__PURE__ */ jsxs4("div", { className: "scui-request-actions", children: [
|
|
1508
1606
|
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)),
|
|
1509
1607
|
request.cancellable ? /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1510
1608
|
] })
|
|
@@ -1512,7 +1610,7 @@ function RequestCard({ entry, adapter, canRespond }) {
|
|
|
1512
1610
|
}
|
|
1513
1611
|
function ContextDisclosure({ context }) {
|
|
1514
1612
|
if (!context?.length) return null;
|
|
1515
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1613
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-context", children: [
|
|
1516
1614
|
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1517
1615
|
"Context \xB7 ",
|
|
1518
1616
|
context.length
|
|
@@ -1541,7 +1639,7 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1541
1639
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1542
1640
|
};
|
|
1543
1641
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1544
|
-
return /* @__PURE__ */ jsxs4("footer", {
|
|
1642
|
+
return /* @__PURE__ */ jsxs4("footer", { className: "scui-message-meta", children: [
|
|
1545
1643
|
validDate ? /* @__PURE__ */ jsx5("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1546
1644
|
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
|
|
1547
1645
|
] });
|
|
@@ -1580,7 +1678,7 @@ var TOOL_ICONS = {
|
|
|
1580
1678
|
};
|
|
1581
1679
|
function ToolIcon({ category }) {
|
|
1582
1680
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1583
|
-
return /* @__PURE__ */ jsx5("svg", {
|
|
1681
|
+
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, {}) });
|
|
1584
1682
|
}
|
|
1585
1683
|
function toolAction2(entry, category, presentation) {
|
|
1586
1684
|
if (presentation?.action) return presentation.action;
|
|
@@ -1635,7 +1733,7 @@ function ToolMetrics({ presentation }) {
|
|
|
1635
1733
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1636
1734
|
formatDuration(presentation.durationMs)
|
|
1637
1735
|
].filter(Boolean);
|
|
1638
|
-
return metrics.length ? /* @__PURE__ */ jsx5("div", {
|
|
1736
|
+
return metrics.length ? /* @__PURE__ */ jsx5("div", { className: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx5("span", { children: metric }, metric)) }) : null;
|
|
1639
1737
|
}
|
|
1640
1738
|
function PendingElapsed({ now }) {
|
|
1641
1739
|
const clock = now ?? Date.now;
|
|
@@ -1645,11 +1743,11 @@ function PendingElapsed({ now }) {
|
|
|
1645
1743
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1646
1744
|
return () => clearInterval(timer);
|
|
1647
1745
|
}, [clock]);
|
|
1648
|
-
return /* @__PURE__ */ jsx5("small", {
|
|
1746
|
+
return /* @__PURE__ */ jsx5("small", { className: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1649
1747
|
}
|
|
1650
1748
|
function LinePreview({ value, kind }) {
|
|
1651
1749
|
if (!value) return null;
|
|
1652
|
-
return /* @__PURE__ */ jsx5("ol", {
|
|
1750
|
+
return /* @__PURE__ */ jsx5("ol", { className: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1653
1751
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1654
1752
|
return /* @__PURE__ */ jsxs4("li", { "data-tone": tone, children: [
|
|
1655
1753
|
/* @__PURE__ */ jsx5("span", { children: index + 1 }),
|
|
@@ -1658,7 +1756,7 @@ function LinePreview({ value, kind }) {
|
|
|
1658
1756
|
}) });
|
|
1659
1757
|
}
|
|
1660
1758
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1661
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1759
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-terminal", children: [
|
|
1662
1760
|
/* @__PURE__ */ jsxs4("header", { children: [
|
|
1663
1761
|
/* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", children: [
|
|
1664
1762
|
/* @__PURE__ */ jsx5("i", {}),
|
|
@@ -1667,15 +1765,15 @@ function TerminalPreview({ presentation, pending, failed }) {
|
|
|
1667
1765
|
] }),
|
|
1668
1766
|
/* @__PURE__ */ jsx5("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1669
1767
|
] }),
|
|
1670
|
-
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", {
|
|
1768
|
+
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", { className: "scui-terminal-wait", children: [
|
|
1671
1769
|
/* @__PURE__ */ jsx5("i", {}),
|
|
1672
1770
|
" Waiting for output"
|
|
1673
|
-
] }) : /* @__PURE__ */ jsx5("div", {
|
|
1771
|
+
] }) : /* @__PURE__ */ jsx5("div", { className: "scui-terminal-empty", children: "No output" })
|
|
1674
1772
|
] });
|
|
1675
1773
|
}
|
|
1676
1774
|
function SearchPreview({ presentation }) {
|
|
1677
1775
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1678
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1776
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-search-preview", children: [
|
|
1679
1777
|
presentation.query ? /* @__PURE__ */ jsxs4("header", { children: [
|
|
1680
1778
|
/* @__PURE__ */ jsx5("span", { children: "Search" }),
|
|
1681
1779
|
/* @__PURE__ */ jsx5("code", { children: presentation.query })
|
|
@@ -1697,22 +1795,22 @@ function ToolPreview({ presentation, entry }) {
|
|
|
1697
1795
|
const pending = entry.status === "pending";
|
|
1698
1796
|
const failed = entry.status === "error";
|
|
1699
1797
|
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx5(TerminalPreview, { presentation, pending, failed });
|
|
1700
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx5("div", {
|
|
1701
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx5("div", {
|
|
1798
|
+
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" });
|
|
1799
|
+
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" });
|
|
1702
1800
|
if (presentation.detail === "matches") return /* @__PURE__ */ jsx5(SearchPreview, { presentation });
|
|
1703
|
-
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", {
|
|
1801
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", { className: "scui-web-preview", children: [
|
|
1704
1802
|
presentation.url ? /* @__PURE__ */ jsx5("code", { children: presentation.url }) : null,
|
|
1705
1803
|
presentation.preview ? /* @__PURE__ */ jsx5("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1706
1804
|
] });
|
|
1707
|
-
if (presentation.detail === "agent") return /* @__PURE__ */ jsx5("section", {
|
|
1805
|
+
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: [
|
|
1708
1806
|
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1709
1807
|
/* @__PURE__ */ jsx5("small", { children: item.status })
|
|
1710
1808
|
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx5("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1711
|
-
if (presentation.detail === "plan") return /* @__PURE__ */ jsx5("ol", {
|
|
1809
|
+
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: [
|
|
1712
1810
|
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1713
1811
|
/* @__PURE__ */ jsx5("span", { children: item.label })
|
|
1714
1812
|
] }, `${item.label}:${index}`)) });
|
|
1715
|
-
return presentation.preview ? /* @__PURE__ */ jsx5("pre", {
|
|
1813
|
+
return presentation.preview ? /* @__PURE__ */ jsx5("pre", { className: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1716
1814
|
}
|
|
1717
1815
|
function ToolActions({ presentation, adapter }) {
|
|
1718
1816
|
const [copied, setCopied] = useState3(false);
|
|
@@ -1726,15 +1824,15 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1726
1824
|
clearTimeout(reset.current);
|
|
1727
1825
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1728
1826
|
};
|
|
1729
|
-
return action ? /* @__PURE__ */ jsx5("div", {
|
|
1827
|
+
return action ? /* @__PURE__ */ jsx5("div", { className: "scui-tool-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1730
1828
|
}
|
|
1731
1829
|
function ToolStack({ tools }) {
|
|
1732
1830
|
if (tools.length < 2) return null;
|
|
1733
|
-
return /* @__PURE__ */ jsx5("div", {
|
|
1831
|
+
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)) });
|
|
1734
1832
|
}
|
|
1735
1833
|
function TechnicalDetails({ entry }) {
|
|
1736
1834
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1737
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1835
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-tool-technical", children: [
|
|
1738
1836
|
/* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
|
|
1739
1837
|
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1740
1838
|
entry.arguments ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
@@ -1757,17 +1855,17 @@ function TechnicalDetails({ entry }) {
|
|
|
1757
1855
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1758
1856
|
if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1759
1857
|
if (entry.role === "reasoning") {
|
|
1760
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1858
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-reasoning", open: entry.streaming, children: [
|
|
1761
1859
|
/* @__PURE__ */ jsx5("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
1762
1860
|
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1763
1861
|
] });
|
|
1764
1862
|
}
|
|
1765
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", {
|
|
1766
|
-
return /* @__PURE__ */ jsxs4("article", {
|
|
1863
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", { className: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
1864
|
+
return /* @__PURE__ */ jsxs4("article", { className: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
1767
1865
|
/* @__PURE__ */ jsx5(MessageImages, { items: entry.images, adapter }),
|
|
1768
1866
|
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
1769
1867
|
/* @__PURE__ */ jsx5(ContextDisclosure, { context: entry.context }),
|
|
1770
|
-
entry.truncated ? /* @__PURE__ */ jsx5("small", {
|
|
1868
|
+
entry.truncated ? /* @__PURE__ */ jsx5("small", { className: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
1771
1869
|
/* @__PURE__ */ jsx5(MessageMeta, { entry, adapter })
|
|
1772
1870
|
] });
|
|
1773
1871
|
}
|
|
@@ -1783,20 +1881,20 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1783
1881
|
const summary = /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
1784
1882
|
/* @__PURE__ */ jsx5(ToolIcon, { category }),
|
|
1785
1883
|
/* @__PURE__ */ jsx5("strong", { children: toolAction2(entry, category, presentation) }),
|
|
1786
|
-
target ? /* @__PURE__ */ jsx5("code", {
|
|
1787
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1884
|
+
target ? /* @__PURE__ */ jsx5("code", { className: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
1885
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-spacer" }),
|
|
1788
1886
|
entry.status === "pending" ? /* @__PURE__ */ jsx5(PendingElapsed, { now: adapter?.now }) : null,
|
|
1789
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1790
|
-
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14,
|
|
1887
|
+
/* @__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 }) }),
|
|
1888
|
+
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14, className: "scui-tool-chevron" }) : null
|
|
1791
1889
|
] });
|
|
1792
|
-
if (!hasDetail) return /* @__PURE__ */ jsx5("div", {
|
|
1793
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1794
|
-
/* @__PURE__ */ jsx5("summary", {
|
|
1795
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
1890
|
+
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 }) });
|
|
1891
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
1892
|
+
/* @__PURE__ */ jsx5("summary", { className: "scui-tool-head", children: summary }),
|
|
1893
|
+
/* @__PURE__ */ jsxs4("div", { className: "scui-tool-detail", children: [
|
|
1796
1894
|
/* @__PURE__ */ jsx5(ToolMetrics, { presentation }),
|
|
1797
1895
|
/* @__PURE__ */ jsx5(ToolStack, { tools: presentation.tools ?? [] }),
|
|
1798
1896
|
/* @__PURE__ */ jsx5(ToolPreview, { presentation, entry }),
|
|
1799
|
-
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", {
|
|
1897
|
+
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", { className: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1800
1898
|
/* @__PURE__ */ jsx5("dt", { children: field.label }),
|
|
1801
1899
|
/* @__PURE__ */ jsx5("dd", { children: field.value })
|
|
1802
1900
|
] }, field.label)) }) : null,
|
|
@@ -1806,18 +1904,18 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1806
1904
|
] });
|
|
1807
1905
|
}
|
|
1808
1906
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1809
|
-
if (entries.length === 1) return /* @__PURE__ */ jsx5("section", {
|
|
1907
|
+
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 }) });
|
|
1810
1908
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1811
1909
|
const [open, setOpen] = useState3(active);
|
|
1812
1910
|
const id = useId();
|
|
1813
1911
|
useEffect4(() => {
|
|
1814
1912
|
if (active) setOpen(true);
|
|
1815
1913
|
}, [active]);
|
|
1816
|
-
return /* @__PURE__ */ jsxs4("section", {
|
|
1817
|
-
/* @__PURE__ */ jsxs4("button", {
|
|
1818
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1914
|
+
return /* @__PURE__ */ jsxs4("section", { className: "scui-activity", children: [
|
|
1915
|
+
/* @__PURE__ */ jsxs4("button", { className: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1916
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14 }) }),
|
|
1819
1917
|
/* @__PURE__ */ jsx5("strong", { children: activitySummary(entries) }),
|
|
1820
|
-
/* @__PURE__ */ jsx5("span", {
|
|
1918
|
+
/* @__PURE__ */ jsx5("span", { className: "scui-spacer" }),
|
|
1821
1919
|
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1822
1920
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1823
1921
|
"/",
|
|
@@ -1830,7 +1928,7 @@ function ActivityGroup({ entries, state, adapter }) {
|
|
|
1830
1928
|
function TaskPlan({ plan }) {
|
|
1831
1929
|
if (!plan.items.length) return null;
|
|
1832
1930
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1833
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1931
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-plan", children: [
|
|
1834
1932
|
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1835
1933
|
/* @__PURE__ */ jsx5("span", { children: "Plan" }),
|
|
1836
1934
|
/* @__PURE__ */ jsxs4("small", { children: [
|
|
@@ -1848,7 +1946,7 @@ function TaskPlan({ plan }) {
|
|
|
1848
1946
|
}
|
|
1849
1947
|
function SessionDetails({ semantics }) {
|
|
1850
1948
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1851
|
-
return /* @__PURE__ */ jsxs4("details", {
|
|
1949
|
+
return /* @__PURE__ */ jsxs4("details", { className: "scui-details", children: [
|
|
1852
1950
|
/* @__PURE__ */ jsx5("summary", { children: "Session details" }),
|
|
1853
1951
|
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1854
1952
|
semantics.fidelity ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
@@ -1894,7 +1992,7 @@ function ConversationAnnouncements({ state }) {
|
|
|
1894
1992
|
}
|
|
1895
1993
|
previousBusy.current = state.busy;
|
|
1896
1994
|
}, [state.busy, state.error, state.harness]);
|
|
1897
|
-
return /* @__PURE__ */ jsx5("span", {
|
|
1995
|
+
return /* @__PURE__ */ jsx5("span", { className: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1898
1996
|
}
|
|
1899
1997
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1900
1998
|
const scroller = useRef4(null);
|
|
@@ -1943,9 +2041,9 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1943
2041
|
else pin();
|
|
1944
2042
|
} else if (atBottom) pin();
|
|
1945
2043
|
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1946
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
2044
|
+
return /* @__PURE__ */ jsxs4("div", { className: "scui-conversation-wrap", children: [
|
|
1947
2045
|
/* @__PURE__ */ jsx5(ConversationAnnouncements, { state }),
|
|
1948
|
-
/* @__PURE__ */ jsx5("div", {
|
|
2046
|
+
/* @__PURE__ */ jsx5("div", { className: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1949
2047
|
const element = event.currentTarget;
|
|
1950
2048
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1951
2049
|
setAtBottom(bottom);
|
|
@@ -1954,19 +2052,19 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1954
2052
|
Before ? /* @__PURE__ */ jsx5(Before, { state, adapter, value: null }) : null,
|
|
1955
2053
|
/* @__PURE__ */ jsx5(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
1956
2054
|
/* @__PURE__ */ jsx5(SessionDetails, { semantics: state.semantics }),
|
|
1957
|
-
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", {
|
|
2055
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", { className: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1958
2056
|
const element = scroller.current;
|
|
1959
2057
|
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1960
2058
|
setAtBottom(false);
|
|
1961
2059
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1962
2060
|
}, children: "Load earlier messages" }) : null,
|
|
1963
2061
|
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state }) : null,
|
|
1964
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx5(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx5("div", {
|
|
2062
|
+
!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,
|
|
1965
2063
|
blocks.map((block, index) => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1966
|
-
index === unreadBlock ? /* @__PURE__ */ jsx5("div", {
|
|
2064
|
+
index === unreadBlock ? /* @__PURE__ */ jsx5("div", { className: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx5("span", { children: "New" }) }) : null,
|
|
1967
2065
|
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 })
|
|
1968
2066
|
] }, block.id)),
|
|
1969
|
-
pendingMessage ? /* @__PURE__ */ jsxs4("article", {
|
|
2067
|
+
pendingMessage ? /* @__PURE__ */ jsxs4("article", { className: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
1970
2068
|
/* @__PURE__ */ jsx5(MessageImages, { items: pendingMessage.images, adapter }),
|
|
1971
2069
|
/* @__PURE__ */ jsx5(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
1972
2070
|
/* @__PURE__ */ jsx5(ContextDisclosure, { context: pendingMessage.context }),
|
|
@@ -1978,7 +2076,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1978
2076
|
] }) : null
|
|
1979
2077
|
] })
|
|
1980
2078
|
] }) : null,
|
|
1981
|
-
state.busy ? /* @__PURE__ */ jsxs4("div", {
|
|
2079
|
+
state.busy ? /* @__PURE__ */ jsxs4("div", { className: "scui-working", role: "status", children: [
|
|
1982
2080
|
/* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
1983
2081
|
/* @__PURE__ */ jsx5("i", {}),
|
|
1984
2082
|
/* @__PURE__ */ jsx5("i", {}),
|
|
@@ -1990,7 +2088,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1990
2088
|
] }) : null,
|
|
1991
2089
|
After ? /* @__PURE__ */ jsx5(After, { state, adapter, value: null }) : null
|
|
1992
2090
|
] }) }),
|
|
1993
|
-
!atBottom ? /* @__PURE__ */ jsxs4("button", {
|
|
2091
|
+
!atBottom ? /* @__PURE__ */ jsxs4("button", { className: "scui-latest", type: "button", onClick: pin, children: [
|
|
1994
2092
|
/* @__PURE__ */ jsx5(UiIcon, { name: "down", size: 13 }),
|
|
1995
2093
|
" Latest"
|
|
1996
2094
|
] }) : null
|
|
@@ -2004,13 +2102,13 @@ var LOGOS = {
|
|
|
2004
2102
|
"claude-code": {
|
|
2005
2103
|
viewBox: "-1 3.5 26 18",
|
|
2006
2104
|
paths: [
|
|
2007
|
-
["path", {
|
|
2105
|
+
["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" }]
|
|
2008
2106
|
]
|
|
2009
2107
|
},
|
|
2010
2108
|
codex: {
|
|
2011
2109
|
viewBox: "-1 -1 26 26",
|
|
2012
2110
|
paths: [
|
|
2013
|
-
["path", {
|
|
2111
|
+
["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" }]
|
|
2014
2112
|
]
|
|
2015
2113
|
},
|
|
2016
2114
|
gemini: {
|
|
@@ -2030,7 +2128,7 @@ var LOGOS = {
|
|
|
2030
2128
|
pi: {
|
|
2031
2129
|
viewBox: "0 0 24 24",
|
|
2032
2130
|
paths: [
|
|
2033
|
-
["path", {
|
|
2131
|
+
["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
|
|
2034
2132
|
["path", { d: "M17.5 12H23v11h-5.5V12z" }]
|
|
2035
2133
|
]
|
|
2036
2134
|
},
|
|
@@ -2040,17 +2138,22 @@ var LOGOS = {
|
|
|
2040
2138
|
paths: [
|
|
2041
2139
|
["rect", { width: "64", height: "64", rx: "14", fill: "#111923" }],
|
|
2042
2140
|
["path", { d: "M18 21h28v6H18zm0 13h18v6H18z", fill: "#5f8fff" }],
|
|
2043
|
-
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa",
|
|
2141
|
+
["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", strokeWidth: "4" }]
|
|
2044
2142
|
]
|
|
2045
2143
|
}
|
|
2046
2144
|
};
|
|
2145
|
+
var SVG_ATTRIBUTE_NAMES = Object.freeze({
|
|
2146
|
+
clipRule: "clip-rule",
|
|
2147
|
+
fillRule: "fill-rule",
|
|
2148
|
+
strokeWidth: "stroke-width"
|
|
2149
|
+
});
|
|
2047
2150
|
function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
2048
2151
|
const logo = LOGOS[id];
|
|
2049
2152
|
useEffect5(() => {
|
|
2050
2153
|
if (!logo) onMissingLogo?.(id);
|
|
2051
2154
|
}, [id, logo, onMissingLogo]);
|
|
2052
2155
|
if (!logo) return null;
|
|
2053
|
-
return /* @__PURE__ */ jsxs5("span", {
|
|
2156
|
+
return /* @__PURE__ */ jsxs5("span", { className: "scui-logo", "data-harness": id, "data-activity": activity, style: { "--scui-logo-size": `${size}px` }, "aria-hidden": "true", children: [
|
|
2054
2157
|
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
2055
2158
|
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
2056
2159
|
] });
|
|
@@ -2081,20 +2184,20 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2081
2184
|
const unreadCount = attention?.unreadCount ?? 0;
|
|
2082
2185
|
const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
|
|
2083
2186
|
const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
|
|
2084
|
-
return /* @__PURE__ */ jsxs6("button", {
|
|
2187
|
+
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: [
|
|
2085
2188
|
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
2086
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2087
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2189
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
|
|
2190
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-session-title", children: [
|
|
2088
2191
|
/* @__PURE__ */ jsx7("strong", { children: title }),
|
|
2089
|
-
/* @__PURE__ */ jsx7("span", {
|
|
2192
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-session-meta", children: age ? /* @__PURE__ */ jsx7("time", { children: age }) : null })
|
|
2090
2193
|
] }),
|
|
2091
|
-
path.complete ? /* @__PURE__ */ jsxs6("small", {
|
|
2092
|
-
/* @__PURE__ */ jsx7("span", {
|
|
2093
|
-
path.separator ? /* @__PURE__ */ jsx7("span", {
|
|
2094
|
-
path.trailing ? /* @__PURE__ */ jsx7("span", {
|
|
2194
|
+
path.complete ? /* @__PURE__ */ jsxs6("small", { className: "scui-session-path", title: row.cwd, children: [
|
|
2195
|
+
/* @__PURE__ */ jsx7("span", { className: "scui-session-path-leading", children: path.leading }),
|
|
2196
|
+
path.separator ? /* @__PURE__ */ jsx7("span", { className: "scui-session-path-separator", children: path.separator }) : null,
|
|
2197
|
+
path.trailing ? /* @__PURE__ */ jsx7("span", { className: "scui-session-path-trailing", children: path.trailing }) : null
|
|
2095
2198
|
] }) : null,
|
|
2096
|
-
working || preview || unreadCount ? /* @__PURE__ */ jsxs6("span", {
|
|
2097
|
-
working ? /* @__PURE__ */ jsxs6("span", {
|
|
2199
|
+
working || preview || unreadCount ? /* @__PURE__ */ jsxs6("span", { className: "scui-session-preview", children: [
|
|
2200
|
+
working ? /* @__PURE__ */ jsxs6("span", { className: "scui-session-working", "aria-hidden": "true", children: [
|
|
2098
2201
|
/* @__PURE__ */ jsx7("i", {}),
|
|
2099
2202
|
/* @__PURE__ */ jsx7("i", {}),
|
|
2100
2203
|
/* @__PURE__ */ jsx7("i", {})
|
|
@@ -2106,7 +2209,7 @@ function SessionRow({ row, state, onOpen, now = Date.now() }) {
|
|
|
2106
2209
|
] })
|
|
2107
2210
|
] });
|
|
2108
2211
|
}
|
|
2109
|
-
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2212
|
+
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, slots = {}, labels = DEFAULT_LABELS, focusKey = null, memoryKey = state.workspace || "@default", headerActions: HeaderActions }) {
|
|
2110
2213
|
const remembered = sessionListMemory.get(memoryKey) ?? { query: "", top: 0 };
|
|
2111
2214
|
const [query, setQuery] = useState4(remembered.query);
|
|
2112
2215
|
const [loadingMore, setLoadingMore] = useState4(false);
|
|
@@ -2115,6 +2218,8 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2115
2218
|
const rowScroller = useRef5(null);
|
|
2116
2219
|
const rows = filterSessions(state.sessions, query);
|
|
2117
2220
|
const Row = components.SessionRow ?? SessionRow;
|
|
2221
|
+
const BeforeSessions = slots.beforeSessions;
|
|
2222
|
+
const AfterSessions = slots.afterSessions;
|
|
2118
2223
|
useLayoutEffect3(() => {
|
|
2119
2224
|
if (rowScroller.current) rowScroller.current.scrollTop = remembered.top;
|
|
2120
2225
|
}, [memoryKey]);
|
|
@@ -2138,9 +2243,9 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2138
2243
|
Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
|
|
2139
2244
|
}
|
|
2140
2245
|
};
|
|
2141
|
-
return /* @__PURE__ */ jsxs6("section", {
|
|
2142
|
-
/* @__PURE__ */ jsxs6("header", {
|
|
2143
|
-
/* @__PURE__ */ jsxs6("span", {
|
|
2246
|
+
return /* @__PURE__ */ jsxs6("section", { className: "scui-list", ref: root, children: [
|
|
2247
|
+
/* @__PURE__ */ jsxs6("header", { className: "scui-head", children: [
|
|
2248
|
+
/* @__PURE__ */ jsxs6("span", { className: "scui-head-copy", children: [
|
|
2144
2249
|
/* @__PURE__ */ jsx7("strong", { children: labels.chats }),
|
|
2145
2250
|
/* @__PURE__ */ jsxs6("small", { children: [
|
|
2146
2251
|
state.sessions.length,
|
|
@@ -2152,7 +2257,7 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2152
2257
|
onClose ? /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx7(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2153
2258
|
] }),
|
|
2154
2259
|
state.startup !== "ready" ? /* @__PURE__ */ jsx7(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
2155
|
-
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", {
|
|
2260
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", { className: "scui-search", children: [
|
|
2156
2261
|
/* @__PURE__ */ jsx7(UiIcon, { name: "search", size: 15 }),
|
|
2157
2262
|
/* @__PURE__ */ jsx7("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
|
|
2158
2263
|
const value = event.currentTarget.value;
|
|
@@ -2162,10 +2267,12 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
2162
2267
|
} }),
|
|
2163
2268
|
/* @__PURE__ */ jsx7("small", { children: rows.length })
|
|
2164
2269
|
] }) : null,
|
|
2165
|
-
/* @__PURE__ */ jsxs6("div", {
|
|
2166
|
-
|
|
2270
|
+
/* @__PURE__ */ jsxs6("div", { className: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
|
|
2271
|
+
BeforeSessions ? /* @__PURE__ */ jsx7(BeforeSessions, { state, adapter, value: { query, rows } }) : null,
|
|
2272
|
+
!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,
|
|
2167
2273
|
rows.map((row) => /* @__PURE__ */ jsx7(Row, { value: row, row, state, adapter, onOpen, now }, row.key)),
|
|
2168
|
-
state.history.hasMoreSessions ? /* @__PURE__ */ jsx7("button", {
|
|
2274
|
+
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,
|
|
2275
|
+
AfterSessions ? /* @__PURE__ */ jsx7(AfterSessions, { state, adapter, value: { query, rows } }) : null
|
|
2169
2276
|
] })
|
|
2170
2277
|
] });
|
|
2171
2278
|
}
|
|
@@ -2176,7 +2283,7 @@ import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
|
2176
2283
|
function HarnessAdvisory({ state, onReview }) {
|
|
2177
2284
|
const advisory = state.interopSettings?.advisories[0];
|
|
2178
2285
|
if (!advisory && !state.interopSettingsError) return null;
|
|
2179
|
-
return /* @__PURE__ */ jsxs7("div", {
|
|
2286
|
+
return /* @__PURE__ */ jsxs7("div", { className: "scui-advisory", "data-severity": advisory?.severity ?? "error", role: advisory?.severity === "error" || !advisory ? "alert" : "status", children: [
|
|
2180
2287
|
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "!" }),
|
|
2181
2288
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2182
2289
|
/* @__PURE__ */ jsx8("strong", { children: advisory?.title ?? "Could not inspect harness settings" }),
|
|
@@ -2210,7 +2317,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2210
2317
|
document.addEventListener("keydown", dismiss);
|
|
2211
2318
|
return () => document.removeEventListener("keydown", dismiss);
|
|
2212
2319
|
}, [onClose]);
|
|
2213
|
-
if (!report) return /* @__PURE__ */ jsx8("section", { ref: panel,
|
|
2320
|
+
if (!report) return /* @__PURE__ */ jsx8("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: /* @__PURE__ */ jsxs7("header", { children: [
|
|
2214
2321
|
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }),
|
|
2215
2322
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2216
2323
|
/* @__PURE__ */ jsx8("strong", { id: titleId, children: "Harness settings" }),
|
|
@@ -2223,7 +2330,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2223
2330
|
if (!changed.length || !state.canConfigureSettings) return;
|
|
2224
2331
|
adapter.onIntent({ action: "configureHarness", harness: report.harness, changes: changed, expectedRevision: report.revision });
|
|
2225
2332
|
};
|
|
2226
|
-
return /* @__PURE__ */ jsxs7("section", { ref: panel,
|
|
2333
|
+
return /* @__PURE__ */ jsxs7("section", { ref: panel, className: "scui-settings", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [
|
|
2227
2334
|
/* @__PURE__ */ jsxs7("header", { children: [
|
|
2228
2335
|
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close settings", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }),
|
|
2229
2336
|
/* @__PURE__ */ jsxs7("span", { children: [
|
|
@@ -2240,7 +2347,7 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2240
2347
|
const recommendation = report.advisories.map((advisory) => advisory.recommendation).find((item) => item.change.key === control.key && item.change.value === values[control.key]);
|
|
2241
2348
|
const consequence = choice?.risk ?? recommendation?.consequence;
|
|
2242
2349
|
return /* @__PURE__ */ jsxs7("fieldset", { disabled: !control.writable || Boolean(state.operation), children: [
|
|
2243
|
-
/* @__PURE__ */ jsxs7("label", {
|
|
2350
|
+
/* @__PURE__ */ jsxs7("label", { htmlFor: `scui-setting-${control.key}`, children: [
|
|
2244
2351
|
/* @__PURE__ */ jsx8("strong", { children: control.label }),
|
|
2245
2352
|
/* @__PURE__ */ jsx8("small", { children: control.description })
|
|
2246
2353
|
] }),
|
|
@@ -2249,11 +2356,11 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2249
2356
|
control.choices.map((item) => /* @__PURE__ */ jsx8("option", { value: item.value, children: item.label }, item.value))
|
|
2250
2357
|
] }),
|
|
2251
2358
|
choice ? /* @__PURE__ */ jsx8("p", { children: choice.description }) : null,
|
|
2252
|
-
consequence ? /* @__PURE__ */ jsxs7("p", {
|
|
2359
|
+
consequence ? /* @__PURE__ */ jsxs7("p", { className: "scui-setting-risk", children: [
|
|
2253
2360
|
/* @__PURE__ */ jsx8("strong", { children: "Security consequence" }),
|
|
2254
2361
|
consequence
|
|
2255
2362
|
] }) : null,
|
|
2256
|
-
/* @__PURE__ */ jsxs7("small", {
|
|
2363
|
+
/* @__PURE__ */ jsxs7("small", { className: "scui-setting-source", children: [
|
|
2257
2364
|
control.effectiveNote,
|
|
2258
2365
|
control.sourcePath ? ` Source: ${control.sourcePath}` : ""
|
|
2259
2366
|
] })
|
|
@@ -2266,16 +2373,41 @@ function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = nul
|
|
|
2266
2373
|
] })
|
|
2267
2374
|
] });
|
|
2268
2375
|
}
|
|
2376
|
+
function HarnessReadiness({ harnesses, adapter }) {
|
|
2377
|
+
const blocked = harnesses.filter((item) => !item.startable);
|
|
2378
|
+
if (!blocked.length) return null;
|
|
2379
|
+
return /* @__PURE__ */ jsxs7("details", { className: "scui-readiness", open: !harnesses.some((item) => item.startable), children: [
|
|
2380
|
+
/* @__PURE__ */ jsxs7("summary", { children: [
|
|
2381
|
+
blocked.length,
|
|
2382
|
+
" ",
|
|
2383
|
+
blocked.length === 1 ? "harness needs" : "harnesses need",
|
|
2384
|
+
" setup"
|
|
2385
|
+
] }),
|
|
2386
|
+
/* @__PURE__ */ jsx8("div", { children: blocked.map((item) => /* @__PURE__ */ jsxs7("section", { children: [
|
|
2387
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: item.id, size: 25 }),
|
|
2388
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2389
|
+
/* @__PURE__ */ jsx8("strong", { children: item.label }),
|
|
2390
|
+
/* @__PURE__ */ jsx8("small", { children: item.reason || (item.auth === "required" ? "Authentication required" : "Unavailable") }),
|
|
2391
|
+
item.protocol ? /* @__PURE__ */ jsxs7("em", { children: [
|
|
2392
|
+
item.protocol,
|
|
2393
|
+
" \xB7 ",
|
|
2394
|
+
item.runtime
|
|
2395
|
+
] }) : null
|
|
2396
|
+
] }),
|
|
2397
|
+
item.repair ? /* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(item.repair), children: "Copy fix" }) : null
|
|
2398
|
+
] }, item.id)) })
|
|
2399
|
+
] });
|
|
2400
|
+
}
|
|
2269
2401
|
|
|
2270
2402
|
// src/messenger.jsx
|
|
2271
2403
|
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
2272
2404
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
2273
2405
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
2274
2406
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
2275
|
-
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2407
|
+
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "steer", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
|
|
2276
2408
|
function Receipt({ state, adapter }) {
|
|
2277
2409
|
const receipt = state.reductionReceipt;
|
|
2278
|
-
if (receipt) return /* @__PURE__ */ jsx9("div", {
|
|
2410
|
+
if (receipt) return /* @__PURE__ */ jsx9("div", { className: "scui-receipt", children: /* @__PURE__ */ jsxs8("span", { children: [
|
|
2279
2411
|
/* @__PURE__ */ jsx9("strong", { children: "Reduced and verified" }),
|
|
2280
2412
|
/* @__PURE__ */ jsxs8("small", { children: [
|
|
2281
2413
|
receipt.sourceTokens.toLocaleString(),
|
|
@@ -2286,7 +2418,7 @@ function Receipt({ state, adapter }) {
|
|
|
2286
2418
|
"\xD7 \xB7 reversible"
|
|
2287
2419
|
] })
|
|
2288
2420
|
] }) });
|
|
2289
|
-
if (state.exportReceipt) return /* @__PURE__ */ jsxs8("div", {
|
|
2421
|
+
if (state.exportReceipt) return /* @__PURE__ */ jsxs8("div", { className: "scui-receipt", children: [
|
|
2290
2422
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2291
2423
|
/* @__PURE__ */ jsxs8("strong", { children: [
|
|
2292
2424
|
"Lossless export ready \xB7 ",
|
|
@@ -2301,7 +2433,7 @@ function Receipt({ state, adapter }) {
|
|
|
2301
2433
|
] }),
|
|
2302
2434
|
/* @__PURE__ */ jsx9("button", { type: "button", onClick: () => adapter.copyText?.(state.exportReceipt.path), children: "Copy path" })
|
|
2303
2435
|
] });
|
|
2304
|
-
if (state.terminalHandoff) return /* @__PURE__ */ jsxs8("div", {
|
|
2436
|
+
if (state.terminalHandoff) return /* @__PURE__ */ jsxs8("div", { className: "scui-receipt", children: [
|
|
2305
2437
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2306
2438
|
/* @__PURE__ */ jsx9("strong", { children: "Terminal handoff ready" }),
|
|
2307
2439
|
/* @__PURE__ */ jsx9("small", { children: state.terminalHandoff.cwd })
|
|
@@ -2358,7 +2490,7 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2358
2490
|
const dispatch = (item) => {
|
|
2359
2491
|
setOpen(false);
|
|
2360
2492
|
if (item.onSelect) item.onSelect();
|
|
2361
|
-
else adapter
|
|
2493
|
+
else dispatchConfirmedIntent(adapter, item.intent);
|
|
2362
2494
|
};
|
|
2363
2495
|
const navigate = (event) => {
|
|
2364
2496
|
if (event.key === "Escape") {
|
|
@@ -2376,11 +2508,11 @@ function ConversationActions({ state, adapter, actionPending, onSettings }) {
|
|
|
2376
2508
|
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;
|
|
2377
2509
|
items[index].focus({ preventScroll: true });
|
|
2378
2510
|
};
|
|
2379
|
-
return /* @__PURE__ */ jsxs8("div", {
|
|
2511
|
+
return /* @__PURE__ */ jsxs8("div", { className: "scui-menu", ref: root, onBlur: (event) => {
|
|
2380
2512
|
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
2381
2513
|
}, children: [
|
|
2382
|
-
/* @__PURE__ */ jsx9("button", { ref: trigger,
|
|
2383
|
-
open ? /* @__PURE__ */ jsx9("div", { ref: panel, id: menuId,
|
|
2514
|
+
/* @__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 }) }),
|
|
2515
|
+
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: [
|
|
2384
2516
|
/* @__PURE__ */ jsx9("strong", { children: group.label }),
|
|
2385
2517
|
group.items.map((item) => /* @__PURE__ */ jsx9("button", { role: "menuitem", type: "button", disabled: actionPending, onClick: () => dispatch(item), children: item.label }, item.key))
|
|
2386
2518
|
] }, group.label)) }) : null
|
|
@@ -2395,10 +2527,10 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2395
2527
|
useEffect8(() => {
|
|
2396
2528
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
2397
2529
|
}, []);
|
|
2398
|
-
return /* @__PURE__ */ jsxs8("header", {
|
|
2530
|
+
return /* @__PURE__ */ jsxs8("header", { className: "scui-head scui-chat-head", children: [
|
|
2399
2531
|
/* @__PURE__ */ jsx9("button", { ref: back, type: "button", "aria-label": "Back to chats", onClick: onBack, children: /* @__PURE__ */ jsx9(UiIcon, { name: "back", size: 18 }) }),
|
|
2400
2532
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: harness, size: 28 }),
|
|
2401
|
-
/* @__PURE__ */ jsxs8("span", {
|
|
2533
|
+
/* @__PURE__ */ jsxs8("span", { className: "scui-head-copy", children: [
|
|
2402
2534
|
/* @__PURE__ */ jsx9("strong", { children: title }),
|
|
2403
2535
|
/* @__PURE__ */ jsxs8("small", { children: [
|
|
2404
2536
|
harnessDisplayName(harness),
|
|
@@ -2412,7 +2544,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2412
2544
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2413
2545
|
] });
|
|
2414
2546
|
}
|
|
2415
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels }) {
|
|
2547
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2416
2548
|
const Header = slots.header;
|
|
2417
2549
|
const HeaderActions = slots.headerActions;
|
|
2418
2550
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2509,17 +2641,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2509
2641
|
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, context: pending.context, images: pending.images, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
2510
2642
|
const action = state.operation || pendingAction?.action || null;
|
|
2511
2643
|
const actionLabel = operationLabel(action);
|
|
2512
|
-
const actionState = action ? { ...state, operation: action, canInterrupt: false, canRespond: false } : state;
|
|
2644
|
+
const actionState = action ? { ...state, operation: action, canSteer: false, canInterrupt: false, canRespond: false } : state;
|
|
2513
2645
|
const unreadAfterMessages = state.attention.find((item) => item.key === state.attached?.key)?.afterMessages ?? null;
|
|
2514
2646
|
const Advisory = components.HarnessAdvisory ?? HarnessAdvisory;
|
|
2515
2647
|
const SettingsPanel = components.HarnessSettingsPanel ?? HarnessSettingsPanel;
|
|
2516
|
-
return /* @__PURE__ */ jsxs8("section", {
|
|
2648
|
+
return /* @__PURE__ */ jsxs8("section", { className: "scui-chat", children: [
|
|
2517
2649
|
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 }),
|
|
2518
|
-
actionLabel ? /* @__PURE__ */ jsxs8("div", {
|
|
2650
|
+
actionLabel ? /* @__PURE__ */ jsxs8("div", { className: "scui-operation", role: "status", children: [
|
|
2519
2651
|
/* @__PURE__ */ jsx9("i", {}),
|
|
2520
2652
|
actionLabel
|
|
2521
2653
|
] }) : null,
|
|
2522
|
-
state.error ? /* @__PURE__ */ jsxs8("div", {
|
|
2654
|
+
state.error ? /* @__PURE__ */ jsxs8("div", { className: "scui-error", role: "alert", children: [
|
|
2523
2655
|
/* @__PURE__ */ jsx9("span", { children: state.error }),
|
|
2524
2656
|
state.recoverable ? /* @__PURE__ */ jsx9("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
|
|
2525
2657
|
] }) : null,
|
|
@@ -2527,11 +2659,11 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2527
2659
|
/* @__PURE__ */ jsx9(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2528
2660
|
/* @__PURE__ */ jsx9(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2529
2661
|
/* @__PURE__ */ jsx9(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
|
|
2530
|
-
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,
|
|
2662
|
+
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,
|
|
2531
2663
|
settings ? /* @__PURE__ */ jsx9(SettingsPanel, { state: actionState, adapter: trackedAdapter, value: state.interopSettings, recommendedChange: settings.recommendedChange, onClose: () => setSettings(null) }) : null
|
|
2532
2664
|
] });
|
|
2533
2665
|
}
|
|
2534
|
-
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions }) {
|
|
2666
|
+
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation }) {
|
|
2535
2667
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
2536
2668
|
const startableKey = startable.map((item) => `${item.id}:${item.launchModes?.join(",")}:${item.preferredLaunchMode ?? ""}`).join("\0");
|
|
2537
2669
|
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [], modes: {} };
|
|
@@ -2547,6 +2679,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2547
2679
|
const startSequence = useRef7(0);
|
|
2548
2680
|
const textarea = useRef7(null);
|
|
2549
2681
|
const selectedHarness = startable.find((item) => item.id === harness) ?? null;
|
|
2682
|
+
const Readiness = components.HarnessReadiness ?? HarnessReadiness;
|
|
2550
2683
|
const launchModes = selectedHarness?.launchModes?.length ? selectedHarness.launchModes : ["headless"];
|
|
2551
2684
|
const rememberedMode = modes[harness];
|
|
2552
2685
|
const mode = launchModes.includes(rememberedMode) ? rememberedMode : launchModes.includes(selectedHarness?.preferredLaunchMode) ? selectedHarness.preferredLaunchMode : launchModes[0];
|
|
@@ -2573,6 +2706,19 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2573
2706
|
useEffect8(() => {
|
|
2574
2707
|
textarea.current?.focus({ preventScroll: true });
|
|
2575
2708
|
}, []);
|
|
2709
|
+
useEffect8(() => {
|
|
2710
|
+
if (!navigation) return;
|
|
2711
|
+
const nextHarness = startable.some((item) => item.id === navigation.harness) ? navigation.harness : harness;
|
|
2712
|
+
const nextDraft = typeof navigation.draft === "string" ? navigation.draft : draft;
|
|
2713
|
+
const nextContext = mergeContext([], navigation.context ?? []);
|
|
2714
|
+
const nextImages = mergeImages([], navigation.images ?? []);
|
|
2715
|
+
setHarness(nextHarness);
|
|
2716
|
+
setDraft(nextDraft);
|
|
2717
|
+
setContext(nextContext);
|
|
2718
|
+
setImages(nextImages);
|
|
2719
|
+
remember({ harness: nextHarness, draft: nextDraft, context: nextContext, images: nextImages });
|
|
2720
|
+
textarea.current?.focus({ preventScroll: true });
|
|
2721
|
+
}, [navigation?.id]);
|
|
2576
2722
|
const pickContext = () => {
|
|
2577
2723
|
if (mode === "terminal" || !adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
2578
2724
|
setPicking(true);
|
|
@@ -2593,6 +2739,15 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2593
2739
|
});
|
|
2594
2740
|
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
2595
2741
|
};
|
|
2742
|
+
const attachCandidate = (picked) => {
|
|
2743
|
+
if (mode === "terminal") return;
|
|
2744
|
+
const attachments = partitionAttachments(picked);
|
|
2745
|
+
const nextContext = mergeContext(context, attachments.context);
|
|
2746
|
+
const nextImages = mergeImages(images, attachments.images);
|
|
2747
|
+
setContext(nextContext);
|
|
2748
|
+
setImages(nextImages);
|
|
2749
|
+
remember({ context: nextContext, images: nextImages });
|
|
2750
|
+
};
|
|
2596
2751
|
const addImageFiles = (value, source) => {
|
|
2597
2752
|
const allFiles = Array.from(value ?? []);
|
|
2598
2753
|
if (!allFiles.length) return false;
|
|
@@ -2641,27 +2796,27 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2641
2796
|
Promise.resolve(result).catch(() => setStarting((current) => current?.id === id ? null : current));
|
|
2642
2797
|
}
|
|
2643
2798
|
};
|
|
2644
|
-
return /* @__PURE__ */ jsxs8("section", {
|
|
2645
|
-
/* @__PURE__ */ jsxs8("header", {
|
|
2799
|
+
return /* @__PURE__ */ jsxs8("section", { className: "scui-chat", children: [
|
|
2800
|
+
/* @__PURE__ */ jsxs8("header", { className: "scui-head", children: [
|
|
2646
2801
|
/* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Back", onClick: onBack, children: /* @__PURE__ */ jsx9(UiIcon, { name: "back", size: 18 }) }),
|
|
2647
|
-
/* @__PURE__ */ jsxs8("span", {
|
|
2802
|
+
/* @__PURE__ */ jsxs8("span", { className: "scui-head-copy", children: [
|
|
2648
2803
|
/* @__PURE__ */ jsx9("strong", { children: labels.newChat }),
|
|
2649
2804
|
/* @__PURE__ */ jsx9("small", { children: "No session is created until you send" })
|
|
2650
2805
|
] }),
|
|
2651
2806
|
HeaderActions ? /* @__PURE__ */ jsx9(HeaderActions, { state, adapter, value: "new" }) : null,
|
|
2652
2807
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2653
2808
|
] }),
|
|
2654
|
-
starting ? /* @__PURE__ */ jsxs8("div", {
|
|
2809
|
+
starting ? /* @__PURE__ */ jsxs8("div", { className: "scui-operation", role: "status", children: [
|
|
2655
2810
|
/* @__PURE__ */ jsx9("i", {}),
|
|
2656
2811
|
mode === "terminal" ? "Opening terminal\u2026" : operationLabel("start")
|
|
2657
2812
|
] }) : null,
|
|
2658
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2813
|
+
/* @__PURE__ */ jsxs8("div", { className: "scui-new", children: [
|
|
2659
2814
|
/* @__PURE__ */ jsx9("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2660
2815
|
/* @__PURE__ */ jsx9("strong", { children: "What should the agent build or fix?" }),
|
|
2661
2816
|
/* @__PURE__ */ jsx9("small", { children: "Choose a coding harness and send the first message." })
|
|
2662
2817
|
] }),
|
|
2663
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2664
|
-
/* @__PURE__ */ jsxs8("label", {
|
|
2818
|
+
/* @__PURE__ */ jsxs8("div", { className: "scui-compose", children: [
|
|
2819
|
+
/* @__PURE__ */ jsxs8("label", { className: "scui-harness-picker", children: [
|
|
2665
2820
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: harness, size: 24 }),
|
|
2666
2821
|
/* @__PURE__ */ jsx9("span", { children: "Coding harness" }),
|
|
2667
2822
|
/* @__PURE__ */ jsx9("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
@@ -2673,7 +2828,8 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2673
2828
|
item.startable ? "" : " \xB7 unavailable"
|
|
2674
2829
|
] }, item.id)) })
|
|
2675
2830
|
] }),
|
|
2676
|
-
|
|
2831
|
+
/* @__PURE__ */ jsx9(Readiness, { harnesses: state.harnesses, state, adapter }),
|
|
2832
|
+
launchModes.length > 1 ? /* @__PURE__ */ jsxs8("fieldset", { className: "scui-launch-modes", disabled: Boolean(starting), children: [
|
|
2677
2833
|
/* @__PURE__ */ jsx9("legend", { children: "Run as" }),
|
|
2678
2834
|
launchModes.map((item) => /* @__PURE__ */ jsxs8("label", { children: [
|
|
2679
2835
|
/* @__PURE__ */ jsx9("input", { type: "radio", name: `launch-mode-${memoryKey}`, value: item, checked: mode === item, onChange: () => {
|
|
@@ -2688,6 +2844,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2688
2844
|
] })
|
|
2689
2845
|
] }, item))
|
|
2690
2846
|
] }) : null,
|
|
2847
|
+
mode !== "terminal" ? /* @__PURE__ */ jsx9(ContextCandidates, { items: contextCandidates, context, images, state, adapter, onAttach: attachCandidate, component: components.ContextCandidate }) : null,
|
|
2691
2848
|
/* @__PURE__ */ jsx9(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
2692
2849
|
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2693
2850
|
remember({ images: next });
|
|
@@ -2698,8 +2855,8 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2698
2855
|
remember({ context: next });
|
|
2699
2856
|
return next;
|
|
2700
2857
|
}) }),
|
|
2701
|
-
terminalAttachments ? /* @__PURE__ */ jsx9("small", {
|
|
2702
|
-
/* @__PURE__ */ jsxs8("div", {
|
|
2858
|
+
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,
|
|
2859
|
+
/* @__PURE__ */ jsxs8("div", { className: `scui-envelope${dragging ? " scui-drop-target" : ""}`, onDragEnter: (event) => {
|
|
2703
2860
|
if (Array.from(event.dataTransfer?.types ?? []).includes("Files")) {
|
|
2704
2861
|
event.preventDefault();
|
|
2705
2862
|
setDragging(true);
|
|
@@ -2709,7 +2866,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2709
2866
|
}, onDragLeave: (event) => {
|
|
2710
2867
|
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
2711
2868
|
}, onDrop: dropImages, children: [
|
|
2712
|
-
adapter.pickContext ? /* @__PURE__ */ jsx9("button", {
|
|
2869
|
+
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,
|
|
2713
2870
|
/* @__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) => {
|
|
2714
2871
|
const value = event.currentTarget.value;
|
|
2715
2872
|
setDraft(value);
|
|
@@ -2720,22 +2877,52 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2720
2877
|
send();
|
|
2721
2878
|
}
|
|
2722
2879
|
} }),
|
|
2723
|
-
/* @__PURE__ */ jsx9("span", { children: /* @__PURE__ */ jsx9("button", { type: "button",
|
|
2880
|
+
/* @__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 }) }) })
|
|
2724
2881
|
] })
|
|
2725
2882
|
] })
|
|
2726
2883
|
] });
|
|
2727
2884
|
}
|
|
2728
|
-
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, labels, components = {}, slots = {} }) {
|
|
2885
|
+
function SupercodeMessenger({ state: stateInput, adapter, class: className = "", initialView, navigation = null, onViewChange, contextCandidates: candidatesInput = [], labels, components = {}, slots = {} }) {
|
|
2729
2886
|
const state = useMemo3(() => normalizeUiState(stateInput), [stateInput]);
|
|
2887
|
+
const contextCandidates = useMemo3(() => normalizeAttachmentCandidates(candidatesInput), [candidatesInput]);
|
|
2730
2888
|
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
2731
2889
|
const memoryKey = state.workspace || "@default";
|
|
2732
2890
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2733
2891
|
const [opening, setOpening] = useState6(null);
|
|
2892
|
+
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2734
2893
|
const [listFocus, setListFocus] = useState6(null);
|
|
2894
|
+
const lastNavigation = useRef7(null);
|
|
2735
2895
|
const setView = (next) => {
|
|
2736
2896
|
boundedSet(messengerViewMemory, memoryKey, next);
|
|
2737
2897
|
setViewState(next);
|
|
2898
|
+
onViewChange?.(next);
|
|
2738
2899
|
};
|
|
2900
|
+
useEffect8(() => {
|
|
2901
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2902
|
+
lastNavigation.current = navigation.id;
|
|
2903
|
+
if (navigation.view === "list") {
|
|
2904
|
+
setOpening(null);
|
|
2905
|
+
setView("list");
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2908
|
+
if (navigation.view === "new") {
|
|
2909
|
+
setListFocus("@new");
|
|
2910
|
+
setNewNavigation(navigation);
|
|
2911
|
+
setView("new");
|
|
2912
|
+
return;
|
|
2913
|
+
}
|
|
2914
|
+
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2915
|
+
setListFocus(navigation.sessionKey);
|
|
2916
|
+
if (state.attached?.key === navigation.sessionKey) {
|
|
2917
|
+
setOpening(null);
|
|
2918
|
+
setView("chat");
|
|
2919
|
+
return;
|
|
2920
|
+
}
|
|
2921
|
+
const row = state.sessions.find((item) => item.key === navigation.sessionKey);
|
|
2922
|
+
setOpening(row ?? { key: navigation.sessionKey, harness: "supercode", name: "Chat", title: "Chat" });
|
|
2923
|
+
adapter.onIntent({ action: "attach", key: navigation.sessionKey });
|
|
2924
|
+
}
|
|
2925
|
+
}, [adapter, navigation, state.attached?.key, state.sessions]);
|
|
2739
2926
|
useEffect8(() => {
|
|
2740
2927
|
if (!opening) return;
|
|
2741
2928
|
if (state.attached?.key === opening.key) {
|
|
@@ -2753,20 +2940,22 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2753
2940
|
const close = () => adapter.onClose?.();
|
|
2754
2941
|
const Footer = slots.footer;
|
|
2755
2942
|
const HeaderActions = slots.headerActions;
|
|
2756
|
-
return /* @__PURE__ */ jsxs8("main", {
|
|
2943
|
+
return /* @__PURE__ */ jsxs8("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2757
2944
|
view === "list" ? /* @__PURE__ */ jsx9(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2758
2945
|
setListFocus("@new");
|
|
2946
|
+
setNewNavigation(null);
|
|
2759
2947
|
setView("new");
|
|
2760
|
-
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, headerActions: HeaderActions }) : null,
|
|
2761
|
-
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,
|
|
2948
|
+
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
2949
|
+
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,
|
|
2762
2950
|
view === "chat" ? /* @__PURE__ */ jsx9(Chat, { state, adapter, onBack: () => {
|
|
2763
2951
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2764
2952
|
setView("list");
|
|
2765
2953
|
}, onNew: () => {
|
|
2766
2954
|
setListFocus("@new");
|
|
2955
|
+
setNewNavigation(null);
|
|
2767
2956
|
setView("new");
|
|
2768
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy }) : null,
|
|
2769
|
-
opening ? /* @__PURE__ */ jsxs8("div", {
|
|
2957
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
2958
|
+
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2770
2959
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2771
2960
|
/* @__PURE__ */ jsxs8("span", { children: [
|
|
2772
2961
|
/* @__PURE__ */ jsxs8("strong", { children: [
|