@volter-ai-dev/supercode-ui 0.1.18 → 0.1.21
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 +9 -0
- package/components.mjs +602 -348
- package/composer.mjs +209 -34
- package/controller.mjs +21 -2
- package/conversation.mjs +226 -201
- package/core.mjs +13 -1
- package/embed.mjs +604 -350
- package/icon.mjs +6 -0
- package/index.d.ts +17 -4
- package/messenger.mjs +602 -348
- package/package.json +1 -1
- package/sessions.mjs +47 -37
- package/styles.css +5 -1
package/components.mjs
CHANGED
|
@@ -501,6 +501,16 @@ function readTranscript(value) {
|
|
|
501
501
|
}] : [];
|
|
502
502
|
});
|
|
503
503
|
}
|
|
504
|
+
if (Array.isArray(item.images)) {
|
|
505
|
+
entry.images = item.images.flatMap((raw) => {
|
|
506
|
+
const image = record(raw);
|
|
507
|
+
return image && typeof image.label === "string" ? [{
|
|
508
|
+
...typeof image.id === "string" ? { id: image.id } : {},
|
|
509
|
+
label: image.label,
|
|
510
|
+
...typeof image.url === "string" ? { url: image.url } : {}
|
|
511
|
+
}] : [];
|
|
512
|
+
}).slice(0, 4);
|
|
513
|
+
}
|
|
504
514
|
const request = record(item.request);
|
|
505
515
|
if (request && typeof request.requestKind === "string" && typeof request.payloadText === "string") {
|
|
506
516
|
entry.request = {
|
|
@@ -681,7 +691,7 @@ function sessionActivity(state, row) {
|
|
|
681
691
|
function filterSessions(rows, query) {
|
|
682
692
|
const needle = query.trim().toLocaleLowerCase();
|
|
683
693
|
if (!needle) return [...rows];
|
|
684
|
-
return rows.filter((row) => [row.name, row.title, row.cwd, row.harness, harnessDisplayName(row.harness)].some((value) => value.toLocaleLowerCase().includes(needle)));
|
|
694
|
+
return rows.filter((row) => [row.name, row.title, row.preview, row.cwd, row.harness, harnessDisplayName(row.harness)].some((value) => typeof value === "string" && value.toLocaleLowerCase().includes(needle)));
|
|
685
695
|
}
|
|
686
696
|
function groupConversation(entries) {
|
|
687
697
|
const blocks = [];
|
|
@@ -758,6 +768,7 @@ function boundedSet(map, key, value) {
|
|
|
758
768
|
// src/icon.jsx
|
|
759
769
|
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
760
770
|
var ICONS = {
|
|
771
|
+
attach: () => /* @__PURE__ */ jsx("path", { d: "M6.25 9.75 10.6 5.4a2.1 2.1 0 0 1 2.97 2.97l-5.4 5.4a3.3 3.3 0 0 1-4.67-4.66l5.52-5.52" }),
|
|
761
772
|
back: () => /* @__PURE__ */ jsx("path", { d: "m11.5 4.5-4.5 4.5 4.5 4.5" }),
|
|
762
773
|
check: () => /* @__PURE__ */ jsx("path", { d: "m4 9 3.25 3.25L14 5.5" }),
|
|
763
774
|
chevron: () => /* @__PURE__ */ jsx("path", { d: "m7 4.5 4.5 4.5L7 13.5" }),
|
|
@@ -773,6 +784,11 @@ var ICONS = {
|
|
|
773
784
|
/* @__PURE__ */ jsx("path", { d: "M9 3.5v10" }),
|
|
774
785
|
/* @__PURE__ */ jsx("path", { d: "m4.75 9.5 4.25 4 4.25-4" })
|
|
775
786
|
] }),
|
|
787
|
+
image: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
788
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "3.5", width: "12", height: "11", rx: "1.75" }),
|
|
789
|
+
/* @__PURE__ */ jsx("circle", { cx: "6.5", cy: "7", r: "1.25" }),
|
|
790
|
+
/* @__PURE__ */ jsx("path", { d: "m4.5 13 3.25-3 2.1 1.85 1.65-1.5L14 13" })
|
|
791
|
+
] }),
|
|
776
792
|
menu: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
777
793
|
/* @__PURE__ */ jsx("circle", { cx: "4", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
778
794
|
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
@@ -798,6 +814,114 @@ function UiIcon({ name, size = 16, class: className = "" }) {
|
|
|
798
814
|
return /* @__PURE__ */ jsx("svg", { class: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Glyph, {}) });
|
|
799
815
|
}
|
|
800
816
|
|
|
817
|
+
// src/context.jsx
|
|
818
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
819
|
+
var MAX_CONTEXT_ITEMS = 32;
|
|
820
|
+
var MAX_IMAGE_ITEMS = 4;
|
|
821
|
+
var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
822
|
+
var IMAGE_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
|
|
823
|
+
function normalizeContext(value) {
|
|
824
|
+
return (Array.isArray(value) ? value : value ? [value] : []).flatMap((item) => {
|
|
825
|
+
if (!item || typeof item.label !== "string" || typeof item.detail !== "string") return [];
|
|
826
|
+
const label = item.label.trim().slice(0, 200);
|
|
827
|
+
const detail = item.detail.slice(0, 2e4);
|
|
828
|
+
if (!label || !detail) return [];
|
|
829
|
+
return [{
|
|
830
|
+
...typeof item.id === "string" && item.id ? { id: item.id.slice(0, 2e3) } : {},
|
|
831
|
+
...typeof item.kind === "string" && item.kind ? { kind: item.kind.slice(0, 100) } : {},
|
|
832
|
+
label,
|
|
833
|
+
detail
|
|
834
|
+
}];
|
|
835
|
+
}).slice(0, MAX_CONTEXT_ITEMS);
|
|
836
|
+
}
|
|
837
|
+
function mergeContext(current, picked) {
|
|
838
|
+
const next = [...current];
|
|
839
|
+
const seen = new Set(current.map((item) => item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`));
|
|
840
|
+
for (const item of normalizeContext(picked)) {
|
|
841
|
+
const key = item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`;
|
|
842
|
+
if (seen.has(key)) continue;
|
|
843
|
+
seen.add(key);
|
|
844
|
+
next.push(item);
|
|
845
|
+
if (next.length === MAX_CONTEXT_ITEMS) break;
|
|
846
|
+
}
|
|
847
|
+
return next;
|
|
848
|
+
}
|
|
849
|
+
function normalizeImages(value) {
|
|
850
|
+
const seen = /* @__PURE__ */ new Set();
|
|
851
|
+
return (Array.isArray(value) ? value : value ? [value] : []).flatMap((item) => {
|
|
852
|
+
if (!item || typeof item.label !== "string" || typeof item.url !== "string") return [];
|
|
853
|
+
const label = item.label.trim().slice(0, 200);
|
|
854
|
+
const url = item.url;
|
|
855
|
+
if (!label || seen.has(url) || !(url.startsWith("data:image/") || url.startsWith("https://") || url.startsWith("http://"))) return [];
|
|
856
|
+
seen.add(url);
|
|
857
|
+
return [{
|
|
858
|
+
...typeof item.id === "string" && item.id ? { id: item.id.slice(0, 2e3) } : {},
|
|
859
|
+
label,
|
|
860
|
+
url
|
|
861
|
+
}];
|
|
862
|
+
}).slice(0, MAX_IMAGE_ITEMS);
|
|
863
|
+
}
|
|
864
|
+
function mergeImages(current, picked) {
|
|
865
|
+
const next = [...current];
|
|
866
|
+
const seen = new Set(current.map((item) => item.url));
|
|
867
|
+
for (const item of normalizeImages(picked)) {
|
|
868
|
+
if (seen.has(item.url)) continue;
|
|
869
|
+
seen.add(item.url);
|
|
870
|
+
next.push(item);
|
|
871
|
+
if (next.length === MAX_IMAGE_ITEMS) break;
|
|
872
|
+
}
|
|
873
|
+
return next;
|
|
874
|
+
}
|
|
875
|
+
function partitionAttachments(value) {
|
|
876
|
+
const values = Array.isArray(value) ? value : value ? [value] : [];
|
|
877
|
+
const context = [];
|
|
878
|
+
const images = [];
|
|
879
|
+
for (const item of values) {
|
|
880
|
+
if (item && typeof item.label === "string" && item.label.trim() && typeof item.detail === "string" && item.detail) context.push(item);
|
|
881
|
+
else if (item && typeof item.label === "string" && item.label.trim() && typeof item.url === "string" && (item.url.startsWith("data:image/") || item.url.startsWith("https://") || item.url.startsWith("http://"))) images.push(item);
|
|
882
|
+
else throw new Error("The attachment picker returned an invalid item.");
|
|
883
|
+
}
|
|
884
|
+
return { context, images };
|
|
885
|
+
}
|
|
886
|
+
async function imageAttachmentsFromFiles(value) {
|
|
887
|
+
const files = Array.from(value ?? []).filter((file) => file?.type?.startsWith("image/"));
|
|
888
|
+
if (files.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images at a time.`);
|
|
889
|
+
return Promise.all(files.map(async (file) => {
|
|
890
|
+
if (!IMAGE_TYPES.has(file.type)) throw new Error(`${file.name || "That image"} is not PNG, JPEG, GIF, or WebP.`);
|
|
891
|
+
if (file.size > MAX_IMAGE_BYTES) throw new Error(`${file.name || "That image"} is larger than 5 MB.`);
|
|
892
|
+
const url = await new Promise((resolve, reject) => {
|
|
893
|
+
const reader = new FileReader();
|
|
894
|
+
reader.onload = () => resolve(reader.result);
|
|
895
|
+
reader.onerror = () => reject(reader.error ?? new Error(`Could not read ${file.name || "image"}.`));
|
|
896
|
+
reader.readAsDataURL(file);
|
|
897
|
+
});
|
|
898
|
+
return { id: `${file.name}:${file.size}:${file.lastModified}`, label: file.name || "Pasted image", url };
|
|
899
|
+
}));
|
|
900
|
+
}
|
|
901
|
+
function ContextTray({ items, onRemove }) {
|
|
902
|
+
if (!items.length) return null;
|
|
903
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
904
|
+
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
905
|
+
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
906
|
+
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
907
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
908
|
+
}
|
|
909
|
+
function ImageTray({ items, onRemove }) {
|
|
910
|
+
if (!items.length) return null;
|
|
911
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-compose-images", "aria-label": "Attached images", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
912
|
+
/* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }),
|
|
913
|
+
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
914
|
+
onRemove ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove image ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) }) : null
|
|
915
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
916
|
+
}
|
|
917
|
+
function MessageImages({ items }) {
|
|
918
|
+
if (!items?.length) return null;
|
|
919
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-message-images", children: items.map((item, index) => item.url ? /* @__PURE__ */ jsx2("img", { src: item.url, alt: item.label }, item.id ?? `${item.label}:${index}`) : /* @__PURE__ */ jsxs2("span", { children: [
|
|
920
|
+
/* @__PURE__ */ jsx2(UiIcon, { name: "image", size: 14 }),
|
|
921
|
+
item.label
|
|
922
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
923
|
+
}
|
|
924
|
+
|
|
801
925
|
// src/textarea.js
|
|
802
926
|
import { useLayoutEffect } from "preact/hooks";
|
|
803
927
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -813,7 +937,7 @@ function useAutosizeTextarea(ref, value) {
|
|
|
813
937
|
}
|
|
814
938
|
|
|
815
939
|
// src/composer.jsx
|
|
816
|
-
import { jsx as
|
|
940
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
817
941
|
var composerMemory = /* @__PURE__ */ new Map();
|
|
818
942
|
function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
819
943
|
if (state.mode !== "mirror" || state.canSend) return null;
|
|
@@ -823,29 +947,36 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
823
947
|
const resume = canContinueHere(state);
|
|
824
948
|
const join = state.canAttach;
|
|
825
949
|
const branch = state.canBranch;
|
|
826
|
-
if (!resume && !join && !branch) return /* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
950
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { class: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
951
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
952
|
+
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
829
953
|
] }) });
|
|
830
|
-
return /* @__PURE__ */
|
|
831
|
-
/* @__PURE__ */
|
|
832
|
-
/* @__PURE__ */
|
|
833
|
-
/* @__PURE__ */
|
|
954
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-continuation", children: [
|
|
955
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
956
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
957
|
+
/* @__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." })
|
|
834
958
|
] }),
|
|
835
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => adapter.onIntent(join ? { action: "join" } : resume ? { action: "resume" } : { action: "branch" }), children: join ? labels.joinLive : resume ? labels.continueHere : labels.forkHere })
|
|
836
960
|
] });
|
|
837
961
|
}
|
|
838
962
|
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
839
|
-
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, queue: [] };
|
|
963
|
+
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
840
964
|
const [draft, setDraft] = useState(remembered.draft);
|
|
841
|
-
const [
|
|
965
|
+
const [context, setContext] = useState(remembered.context ?? []);
|
|
966
|
+
const [images, setImages] = useState(remembered.images ?? []);
|
|
967
|
+
const [queue, setQueue] = useState((remembered.queue ?? []).map((item) => ({ ...item, context: item.context ?? [], images: item.images ?? [] })));
|
|
842
968
|
const [dispatching, setDispatching] = useState(false);
|
|
969
|
+
const [picking, setPicking] = useState(false);
|
|
970
|
+
const [pickerError, setPickerError] = useState(null);
|
|
843
971
|
const textarea = useRef(null);
|
|
844
972
|
useAutosizeTextarea(textarea, draft);
|
|
845
|
-
const remember = (nextDraft, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, queue: nextQueue });
|
|
973
|
+
const remember = (nextDraft, nextContext, nextImages, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, context: nextContext, images: nextImages, queue: nextQueue });
|
|
974
|
+
useEffect(() => {
|
|
975
|
+
remember(draft, context, images, queue);
|
|
976
|
+
}, [draft, context, images, memoryKey, queue]);
|
|
846
977
|
const updateQueue = (update) => setQueue((items) => {
|
|
847
978
|
const next = update(items);
|
|
848
|
-
remember(draft, next);
|
|
979
|
+
remember(draft, context, images, next);
|
|
849
980
|
return next;
|
|
850
981
|
});
|
|
851
982
|
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
@@ -855,9 +986,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
855
986
|
const [next, ...rest] = queue;
|
|
856
987
|
setDispatching(true);
|
|
857
988
|
setQueue(rest);
|
|
858
|
-
remember(draft, rest);
|
|
859
|
-
onPending?.(next);
|
|
860
|
-
adapter.onIntent({ action: "send", text: next });
|
|
989
|
+
remember(draft, context, images, rest);
|
|
990
|
+
onPending?.(next.text, next.context, next.images);
|
|
991
|
+
adapter.onIntent({ action: "send", text: next.text, ...next.context.length ? { context: next.context } : {}, ...next.images.length ? { images: next.images } : {} });
|
|
861
992
|
}
|
|
862
993
|
}, [adapter, draft, memoryKey, onPending, queue, queueBlocked, state.canSend]);
|
|
863
994
|
useEffect(() => {
|
|
@@ -869,7 +1000,11 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
869
1000
|
useEffect(() => {
|
|
870
1001
|
if (!restoreDraft) return;
|
|
871
1002
|
setDraft(restoreDraft.text);
|
|
872
|
-
|
|
1003
|
+
const restoredContext = normalizeContext(restoreDraft.context);
|
|
1004
|
+
const restoredImages = normalizeImages(restoreDraft.images);
|
|
1005
|
+
setContext(restoredContext);
|
|
1006
|
+
setImages(restoredImages);
|
|
1007
|
+
remember(restoreDraft.text, restoredContext, restoredImages, queue);
|
|
873
1008
|
textarea.current?.focus({ preventScroll: true });
|
|
874
1009
|
onDraftRestored?.(restoreDraft.id);
|
|
875
1010
|
}, [onDraftRestored, restoreDraft?.id]);
|
|
@@ -877,43 +1012,100 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
877
1012
|
const timer = setTimeout(() => adapter.onIntent({ action: "draft", text: draft }), 250);
|
|
878
1013
|
return () => clearTimeout(timer);
|
|
879
1014
|
}, [adapter, draft]);
|
|
1015
|
+
const pickContext = () => {
|
|
1016
|
+
if (!adapter.pickContext || state.mode !== "control" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
1017
|
+
setPicking(true);
|
|
1018
|
+
setPickerError(null);
|
|
1019
|
+
Promise.resolve().then(() => adapter.pickContext()).then((picked) => {
|
|
1020
|
+
const attachments = partitionAttachments(picked);
|
|
1021
|
+
if (context.length + attachments.context.length > MAX_CONTEXT_ITEMS) throw new Error(`Attach at most ${MAX_CONTEXT_ITEMS} text items.`);
|
|
1022
|
+
if (images.length + attachments.images.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
1023
|
+
setContext((current) => {
|
|
1024
|
+
const next = mergeContext(current, attachments.context);
|
|
1025
|
+
remember(draft, next, images, queue);
|
|
1026
|
+
return next;
|
|
1027
|
+
});
|
|
1028
|
+
setImages((current) => {
|
|
1029
|
+
const next = mergeImages(current, attachments.images);
|
|
1030
|
+
remember(draft, context, next, queue);
|
|
1031
|
+
return next;
|
|
1032
|
+
});
|
|
1033
|
+
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
1034
|
+
};
|
|
1035
|
+
const pasteImages = (event) => {
|
|
1036
|
+
const files = Array.from(event.clipboardData?.files ?? []).filter((file) => file.type.startsWith("image/"));
|
|
1037
|
+
if (!files.length) return;
|
|
1038
|
+
event.preventDefault();
|
|
1039
|
+
if (images.length + files.length > MAX_IMAGE_ITEMS) {
|
|
1040
|
+
setPickerError(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
setPicking(true);
|
|
1044
|
+
setPickerError(null);
|
|
1045
|
+
imageAttachmentsFromFiles(files).then((picked) => setImages((current) => {
|
|
1046
|
+
const next = mergeImages(current, picked);
|
|
1047
|
+
remember(draft, context, next, queue);
|
|
1048
|
+
return next;
|
|
1049
|
+
}), (error) => setPickerError(error instanceof Error ? error.message : "Could not paste image.")).finally(() => setPicking(false));
|
|
1050
|
+
};
|
|
880
1051
|
const send = () => {
|
|
881
1052
|
const text = draft.trim();
|
|
882
1053
|
if (!text) return;
|
|
883
|
-
|
|
1054
|
+
const message = { text, context, images };
|
|
1055
|
+
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
884
1056
|
else if (state.canSend) {
|
|
885
1057
|
if (onPending) setDispatching(true);
|
|
886
|
-
onPending?.(text);
|
|
887
|
-
adapter.onIntent({ action: "send", text });
|
|
1058
|
+
onPending?.(text, context, images);
|
|
1059
|
+
adapter.onIntent({ action: "send", text, ...context.length ? { context } : {}, ...images.length ? { images } : {} });
|
|
888
1060
|
} else return;
|
|
889
1061
|
setDraft("");
|
|
890
|
-
|
|
1062
|
+
setContext([]);
|
|
1063
|
+
setImages([]);
|
|
1064
|
+
remember("", [], [], queuesNewMessage ? [...queue, message] : queue);
|
|
891
1065
|
};
|
|
892
|
-
return /* @__PURE__ */
|
|
893
|
-
queue.length ? /* @__PURE__ */
|
|
894
|
-
/* @__PURE__ */
|
|
1066
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-compose", children: [
|
|
1067
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { class: "scui-queue", children: [
|
|
1068
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
895
1069
|
queue.length,
|
|
896
1070
|
" queued"
|
|
897
1071
|
] }),
|
|
898
|
-
queue.map((item, index) => /* @__PURE__ */
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1072
|
+
queue.map((item, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
1073
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1074
|
+
item.text,
|
|
1075
|
+
item.context.length + item.images.length ? /* @__PURE__ */ jsxs3("small", { children: [
|
|
1076
|
+
item.context.length + item.images.length,
|
|
1077
|
+
" attached"
|
|
1078
|
+
] }) : null
|
|
1079
|
+
] }),
|
|
1080
|
+
/* @__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 }) })
|
|
1081
|
+
] }, `${index}:${item.text}`))
|
|
902
1082
|
] }) : null,
|
|
903
|
-
/* @__PURE__ */
|
|
904
|
-
|
|
1083
|
+
/* @__PURE__ */ jsx3(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
1084
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1085
|
+
remember(draft, context, next, queue);
|
|
1086
|
+
return next;
|
|
1087
|
+
}) }),
|
|
1088
|
+
/* @__PURE__ */ jsx3(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
1089
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1090
|
+
remember(draft, next, images, queue);
|
|
1091
|
+
return next;
|
|
1092
|
+
}) }),
|
|
1093
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { class: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
1094
|
+
/* @__PURE__ */ jsxs3("div", { class: "scui-envelope", children: [
|
|
1095
|
+
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", { class: "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", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx3(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
1096
|
+
/* @__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) => {
|
|
905
1097
|
const value = event.currentTarget.value;
|
|
906
1098
|
setDraft(value);
|
|
907
|
-
remember(value, queue);
|
|
1099
|
+
remember(value, context, images, queue);
|
|
908
1100
|
}, onKeyDown: (event) => {
|
|
909
1101
|
if (isSendKey(event)) {
|
|
910
1102
|
event.preventDefault();
|
|
911
1103
|
send();
|
|
912
1104
|
}
|
|
913
1105
|
} }),
|
|
914
|
-
/* @__PURE__ */
|
|
915
|
-
state.busy ? /* @__PURE__ */
|
|
916
|
-
/* @__PURE__ */
|
|
1106
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1107
|
+
state.busy ? /* @__PURE__ */ jsx3("button", { class: "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,
|
|
1108
|
+
/* @__PURE__ */ jsx3("button", { class: "scui-send", type: "button", "aria-label": queuesNewMessage ? "Queue message" : "Send message", disabled: !draft.trim() || !queuesNewMessage && !state.canSend, onClick: send, children: /* @__PURE__ */ jsx3(UiIcon, { name: queuesNewMessage ? "plus" : "send", size: 17 }) })
|
|
917
1109
|
] })
|
|
918
1110
|
] })
|
|
919
1111
|
] });
|
|
@@ -926,7 +1118,7 @@ import { useEffect as useEffect3, useId, useLayoutEffect as useLayoutEffect2, us
|
|
|
926
1118
|
// src/markdown.jsx
|
|
927
1119
|
import MarkdownIt from "markdown-it";
|
|
928
1120
|
import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "preact/hooks";
|
|
929
|
-
import { jsx as
|
|
1121
|
+
import { jsx as jsx4 } from "preact/jsx-runtime";
|
|
930
1122
|
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
931
1123
|
var LANGUAGE_LABELS = {
|
|
932
1124
|
bash: "Shell",
|
|
@@ -1013,11 +1205,11 @@ function Markdown({ value, copyText }) {
|
|
|
1013
1205
|
}, 1500);
|
|
1014
1206
|
resets.current.set(button, timer);
|
|
1015
1207
|
};
|
|
1016
|
-
return /* @__PURE__ */
|
|
1208
|
+
return /* @__PURE__ */ jsx4("div", { class: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1017
1209
|
}
|
|
1018
1210
|
|
|
1019
1211
|
// src/conversation.jsx
|
|
1020
|
-
import { Fragment as Fragment3, jsx as
|
|
1212
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
1021
1213
|
function LoadingStatus({ state, compact = false }) {
|
|
1022
1214
|
const copy = {
|
|
1023
1215
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -1025,43 +1217,43 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1025
1217
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1026
1218
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1027
1219
|
}[state.startup];
|
|
1028
|
-
return /* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
1220
|
+
return /* @__PURE__ */ jsxs4("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1221
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("i", {}) }),
|
|
1222
|
+
/* @__PURE__ */ jsxs4("span", { class: "scui-loading-copy", children: [
|
|
1223
|
+
/* @__PURE__ */ jsx5("strong", { children: copy[0] }),
|
|
1224
|
+
/* @__PURE__ */ jsx5("small", { children: copy[1] })
|
|
1033
1225
|
] }),
|
|
1034
|
-
/* @__PURE__ */
|
|
1226
|
+
/* @__PURE__ */ jsx5("span", { class: "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)) })
|
|
1035
1227
|
] });
|
|
1036
1228
|
}
|
|
1037
1229
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1038
1230
|
const request = entry.request;
|
|
1039
1231
|
if (!request) return null;
|
|
1040
1232
|
if (request.status === "responded") {
|
|
1041
|
-
return /* @__PURE__ */
|
|
1233
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-request-done", children: [
|
|
1042
1234
|
"\u2713 Request answered \xB7 ",
|
|
1043
1235
|
request.resolution?.name ?? request.requestKind
|
|
1044
1236
|
] });
|
|
1045
1237
|
}
|
|
1046
|
-
return /* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
request.options.map((option) => /* @__PURE__ */
|
|
1051
|
-
request.cancellable ? /* @__PURE__ */
|
|
1238
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1239
|
+
/* @__PURE__ */ jsx5("strong", { children: "Agent needs input" }),
|
|
1240
|
+
/* @__PURE__ */ jsx5(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1241
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-request-actions", children: [
|
|
1242
|
+
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)),
|
|
1243
|
+
request.cancellable ? /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1052
1244
|
] })
|
|
1053
1245
|
] });
|
|
1054
1246
|
}
|
|
1055
1247
|
function ContextDisclosure({ context }) {
|
|
1056
1248
|
if (!context?.length) return null;
|
|
1057
|
-
return /* @__PURE__ */
|
|
1058
|
-
/* @__PURE__ */
|
|
1249
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-context", children: [
|
|
1250
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1059
1251
|
"Context \xB7 ",
|
|
1060
1252
|
context.length
|
|
1061
1253
|
] }),
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1254
|
+
/* @__PURE__ */ jsx5("div", { children: context.map((item, index) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1255
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1256
|
+
/* @__PURE__ */ jsx5("span", { children: item.detail })
|
|
1065
1257
|
] }, item.id ?? index)) })
|
|
1066
1258
|
] });
|
|
1067
1259
|
}
|
|
@@ -1083,46 +1275,46 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1083
1275
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1084
1276
|
};
|
|
1085
1277
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1086
|
-
return /* @__PURE__ */
|
|
1087
|
-
validDate ? /* @__PURE__ */
|
|
1088
|
-
adapter?.copyText && entry.text ? /* @__PURE__ */
|
|
1278
|
+
return /* @__PURE__ */ jsxs4("footer", { class: "scui-message-meta", children: [
|
|
1279
|
+
validDate ? /* @__PURE__ */ jsx5("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1280
|
+
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
|
|
1089
1281
|
] });
|
|
1090
1282
|
}
|
|
1091
1283
|
var TOOL_ICONS = {
|
|
1092
|
-
read: () => /* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1284
|
+
read: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1285
|
+
/* @__PURE__ */ jsx5("path", { d: "M5 2.75h7.25L15 5.5v7.75A1.75 1.75 0 0 1 13.25 15h-8.5A1.75 1.75 0 0 1 3 13.25v-8.5A2 2 0 0 1 5 2.75Z" }),
|
|
1286
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
1095
1287
|
] }),
|
|
1096
|
-
search: () => /* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1288
|
+
search: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1289
|
+
/* @__PURE__ */ jsx5("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
1290
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.5 11.5 3 3" })
|
|
1099
1291
|
] }),
|
|
1100
|
-
edit: () => /* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1102
|
-
/* @__PURE__ */
|
|
1292
|
+
edit: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1293
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
1294
|
+
/* @__PURE__ */ jsx5("path", { d: "m10 5 3 3" })
|
|
1103
1295
|
] }),
|
|
1104
|
-
command: () => /* @__PURE__ */
|
|
1105
|
-
test: () => /* @__PURE__ */
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1296
|
+
command: () => /* @__PURE__ */ jsx5(Fragment3, { children: /* @__PURE__ */ jsx5("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
1297
|
+
test: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1298
|
+
/* @__PURE__ */ jsx5("path", { d: "M6 2.5v3L3 12a2 2 0 0 0 1.8 3h8.4a2 2 0 0 0 1.8-3l-3-6.5v-3M5 9h8" }),
|
|
1299
|
+
/* @__PURE__ */ jsx5("path", { d: "M5 2.5h8" })
|
|
1108
1300
|
] }),
|
|
1109
|
-
web: () => /* @__PURE__ */
|
|
1110
|
-
/* @__PURE__ */
|
|
1111
|
-
/* @__PURE__ */
|
|
1301
|
+
web: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1302
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
1303
|
+
/* @__PURE__ */ jsx5("path", { d: "M2.75 9h12.5M9 2.5c2 1.8 3 4 3 6.5s-1 4.7-3 6.5c-2-1.8-3-4-3-6.5s1-4.7 3-6.5Z" })
|
|
1112
1304
|
] }),
|
|
1113
|
-
agent: () => /* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1305
|
+
agent: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1306
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
1307
|
+
/* @__PURE__ */ jsx5("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
1116
1308
|
] }),
|
|
1117
|
-
plan: () => /* @__PURE__ */
|
|
1118
|
-
other: () => /* @__PURE__ */
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
/* @__PURE__ */
|
|
1309
|
+
plan: () => /* @__PURE__ */ jsx5(Fragment3, { children: /* @__PURE__ */ jsx5("path", { d: "m3 5 1 1 2-2M3 9l1 1 2-2M3 13l1 1 2-2M8 5h7M8 9h7M8 13h7" }) }),
|
|
1310
|
+
other: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1311
|
+
/* @__PURE__ */ jsx5("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
1312
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
1121
1313
|
] })
|
|
1122
1314
|
};
|
|
1123
1315
|
function ToolIcon({ category }) {
|
|
1124
1316
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1125
|
-
return /* @__PURE__ */
|
|
1317
|
+
return /* @__PURE__ */ jsx5("svg", { class: "scui-tool-icon", viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.35", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(Glyph, {}) });
|
|
1126
1318
|
}
|
|
1127
1319
|
function toolAction2(entry, category, presentation) {
|
|
1128
1320
|
if (presentation?.action) return presentation.action;
|
|
@@ -1177,7 +1369,7 @@ function ToolMetrics({ presentation }) {
|
|
|
1177
1369
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1178
1370
|
formatDuration(presentation.durationMs)
|
|
1179
1371
|
].filter(Boolean);
|
|
1180
|
-
return metrics.length ? /* @__PURE__ */
|
|
1372
|
+
return metrics.length ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx5("span", { children: metric }, metric)) }) : null;
|
|
1181
1373
|
}
|
|
1182
1374
|
function PendingElapsed({ now }) {
|
|
1183
1375
|
const clock = now ?? Date.now;
|
|
@@ -1187,74 +1379,74 @@ function PendingElapsed({ now }) {
|
|
|
1187
1379
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1188
1380
|
return () => clearInterval(timer);
|
|
1189
1381
|
}, [clock]);
|
|
1190
|
-
return /* @__PURE__ */
|
|
1382
|
+
return /* @__PURE__ */ jsx5("small", { class: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1191
1383
|
}
|
|
1192
1384
|
function LinePreview({ value, kind }) {
|
|
1193
1385
|
if (!value) return null;
|
|
1194
|
-
return /* @__PURE__ */
|
|
1386
|
+
return /* @__PURE__ */ jsx5("ol", { class: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1195
1387
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1196
|
-
return /* @__PURE__ */
|
|
1197
|
-
/* @__PURE__ */
|
|
1198
|
-
/* @__PURE__ */
|
|
1388
|
+
return /* @__PURE__ */ jsxs4("li", { "data-tone": tone, children: [
|
|
1389
|
+
/* @__PURE__ */ jsx5("span", { children: index + 1 }),
|
|
1390
|
+
/* @__PURE__ */ jsx5("code", { children: line || " " })
|
|
1199
1391
|
] }, index);
|
|
1200
1392
|
}) });
|
|
1201
1393
|
}
|
|
1202
1394
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1203
|
-
return /* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-terminal", children: [
|
|
1396
|
+
/* @__PURE__ */ jsxs4("header", { children: [
|
|
1397
|
+
/* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", children: [
|
|
1398
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1399
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1400
|
+
/* @__PURE__ */ jsx5("i", {})
|
|
1209
1401
|
] }),
|
|
1210
|
-
/* @__PURE__ */
|
|
1402
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1211
1403
|
] }),
|
|
1212
|
-
presentation.preview ? /* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1404
|
+
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", { class: "scui-terminal-wait", children: [
|
|
1405
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1214
1406
|
" Waiting for output"
|
|
1215
|
-
] }) : /* @__PURE__ */
|
|
1407
|
+
] }) : /* @__PURE__ */ jsx5("div", { class: "scui-terminal-empty", children: "No output" })
|
|
1216
1408
|
] });
|
|
1217
1409
|
}
|
|
1218
1410
|
function SearchPreview({ presentation }) {
|
|
1219
1411
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1220
|
-
return /* @__PURE__ */
|
|
1221
|
-
presentation.query ? /* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
/* @__PURE__ */
|
|
1412
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-search-preview", children: [
|
|
1413
|
+
presentation.query ? /* @__PURE__ */ jsxs4("header", { children: [
|
|
1414
|
+
/* @__PURE__ */ jsx5("span", { children: "Search" }),
|
|
1415
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.query })
|
|
1224
1416
|
] }) : null,
|
|
1225
|
-
lines.length ? /* @__PURE__ */
|
|
1417
|
+
lines.length ? /* @__PURE__ */ jsx5("ol", { children: lines.map((line, index) => {
|
|
1226
1418
|
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
1227
|
-
return /* @__PURE__ */
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1419
|
+
return /* @__PURE__ */ jsx5("li", { children: match ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1420
|
+
/* @__PURE__ */ jsx5("code", { children: match[1] }),
|
|
1421
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1230
1422
|
match[2],
|
|
1231
1423
|
match[3] ? `:${match[3]}` : ""
|
|
1232
1424
|
] }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
] }) : /* @__PURE__ */
|
|
1235
|
-
}) }) : /* @__PURE__ */
|
|
1425
|
+
/* @__PURE__ */ jsx5("span", { children: match[4] })
|
|
1426
|
+
] }) : /* @__PURE__ */ jsx5("span", { children: line }) }, index);
|
|
1427
|
+
}) }) : /* @__PURE__ */ jsx5("p", { children: "No textual results" })
|
|
1236
1428
|
] });
|
|
1237
1429
|
}
|
|
1238
1430
|
function ToolPreview({ presentation, entry }) {
|
|
1239
1431
|
const pending = entry.status === "pending";
|
|
1240
1432
|
const failed = entry.status === "error";
|
|
1241
|
-
if (presentation.detail === "terminal") return /* @__PURE__ */
|
|
1242
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */
|
|
1243
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */
|
|
1244
|
-
if (presentation.detail === "matches") return /* @__PURE__ */
|
|
1245
|
-
if (presentation.detail === "web") return /* @__PURE__ */
|
|
1246
|
-
presentation.url ? /* @__PURE__ */
|
|
1247
|
-
presentation.preview ? /* @__PURE__ */
|
|
1433
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx5(TerminalPreview, { presentation, pending, failed });
|
|
1434
|
+
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "diff" }) : /* @__PURE__ */ jsx5("div", { class: "scui-tool-empty", children: "Edit completed without a textual diff" });
|
|
1435
|
+
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */ jsx5(LinePreview, { value: presentation.preview, kind: "file" }) : /* @__PURE__ */ jsx5("div", { class: "scui-tool-empty", children: "File contents were not included in this event" });
|
|
1436
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx5(SearchPreview, { presentation });
|
|
1437
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", { class: "scui-web-preview", children: [
|
|
1438
|
+
presentation.url ? /* @__PURE__ */ jsx5("code", { children: presentation.url }) : null,
|
|
1439
|
+
presentation.preview ? /* @__PURE__ */ jsx5("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1248
1440
|
] });
|
|
1249
|
-
if (presentation.detail === "agent") return /* @__PURE__ */
|
|
1250
|
-
/* @__PURE__ */
|
|
1251
|
-
/* @__PURE__ */
|
|
1252
|
-
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */
|
|
1253
|
-
if (presentation.detail === "plan") return /* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1441
|
+
if (presentation.detail === "agent") return /* @__PURE__ */ jsx5("section", { class: "scui-agent-preview", children: presentation.items?.length ? /* @__PURE__ */ jsx5("ol", { class: "scui-agent-roster", children: presentation.items.map((item, index) => /* @__PURE__ */ jsxs4("li", { children: [
|
|
1442
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1443
|
+
/* @__PURE__ */ jsx5("small", { children: item.status })
|
|
1444
|
+
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx5("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1445
|
+
if (presentation.detail === "plan") return /* @__PURE__ */ jsx5("ol", { class: "scui-plan-preview", children: presentation.items?.map((item, index) => /* @__PURE__ */ jsxs4("li", { "data-status": item.status, children: [
|
|
1446
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1447
|
+
/* @__PURE__ */ jsx5("span", { children: item.label })
|
|
1256
1448
|
] }, `${item.label}:${index}`)) });
|
|
1257
|
-
return presentation.preview ? /* @__PURE__ */
|
|
1449
|
+
return presentation.preview ? /* @__PURE__ */ jsx5("pre", { class: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1258
1450
|
}
|
|
1259
1451
|
function ToolActions({ presentation, adapter }) {
|
|
1260
1452
|
const [copied, setCopied] = useState2(false);
|
|
@@ -1268,27 +1460,27 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1268
1460
|
clearTimeout(reset.current);
|
|
1269
1461
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1270
1462
|
};
|
|
1271
|
-
return action ? /* @__PURE__ */
|
|
1463
|
+
return action ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1272
1464
|
}
|
|
1273
1465
|
function ToolStack({ tools }) {
|
|
1274
1466
|
if (tools.length < 2) return null;
|
|
1275
|
-
return /* @__PURE__ */
|
|
1467
|
+
return /* @__PURE__ */ jsx5("div", { class: "scui-tool-stack", "aria-label": "Coordinated tools", children: tools.map((tool) => /* @__PURE__ */ jsx5("span", { children: tool.replaceAll("__", " \xB7 ").replaceAll("_", " ") }, tool)) });
|
|
1276
1468
|
}
|
|
1277
1469
|
function TechnicalDetails({ entry }) {
|
|
1278
1470
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1279
|
-
return /* @__PURE__ */
|
|
1280
|
-
/* @__PURE__ */
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
entry.arguments ? /* @__PURE__ */
|
|
1283
|
-
/* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1471
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool-technical", children: [
|
|
1472
|
+
/* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
|
|
1473
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1474
|
+
entry.arguments ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1475
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native arguments" }),
|
|
1476
|
+
/* @__PURE__ */ jsx5("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1477
|
+
/* @__PURE__ */ jsx5("dt", { children: row.label }),
|
|
1478
|
+
/* @__PURE__ */ jsx5("dd", { children: /* @__PURE__ */ jsx5("pre", { children: row.value }) })
|
|
1287
1479
|
] }, row.key)) })
|
|
1288
1480
|
] }) : null,
|
|
1289
|
-
entry.resultText ? /* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1481
|
+
entry.resultText ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1482
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native result" }),
|
|
1483
|
+
/* @__PURE__ */ jsxs4("pre", { "data-error": entry.status === "error", children: [
|
|
1292
1484
|
entry.resultText,
|
|
1293
1485
|
entry.truncated ? "\n[truncated]" : ""
|
|
1294
1486
|
] })
|
|
@@ -1297,19 +1489,20 @@ function TechnicalDetails({ entry }) {
|
|
|
1297
1489
|
] });
|
|
1298
1490
|
}
|
|
1299
1491
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1300
|
-
if (entry.role === "request") return /* @__PURE__ */
|
|
1492
|
+
if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1301
1493
|
if (entry.role === "reasoning") {
|
|
1302
|
-
return /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1494
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-reasoning", open: entry.streaming, children: [
|
|
1495
|
+
/* @__PURE__ */ jsx5("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
1496
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1305
1497
|
] });
|
|
1306
1498
|
}
|
|
1307
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */
|
|
1308
|
-
return /* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1311
|
-
|
|
1312
|
-
/* @__PURE__ */
|
|
1499
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", { class: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
1500
|
+
return /* @__PURE__ */ jsxs4("article", { class: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
1501
|
+
/* @__PURE__ */ jsx5(MessageImages, { items: entry.images }),
|
|
1502
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
1503
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: entry.context }),
|
|
1504
|
+
entry.truncated ? /* @__PURE__ */ jsx5("small", { class: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
1505
|
+
/* @__PURE__ */ jsx5(MessageMeta, { entry, adapter })
|
|
1313
1506
|
] });
|
|
1314
1507
|
}
|
|
1315
1508
|
function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
@@ -1321,102 +1514,102 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1321
1514
|
const target = compactToolTarget(presentation.target, workspace);
|
|
1322
1515
|
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
1323
1516
|
const category = presentation.category ?? toolCategory(entry);
|
|
1324
|
-
const summary = /* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
target ? /* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
entry.status === "pending" ? /* @__PURE__ */
|
|
1330
|
-
/* @__PURE__ */
|
|
1331
|
-
hasDetail ? /* @__PURE__ */
|
|
1517
|
+
const summary = /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1518
|
+
/* @__PURE__ */ jsx5(ToolIcon, { category }),
|
|
1519
|
+
/* @__PURE__ */ jsx5("strong", { children: toolAction2(entry, category, presentation) }),
|
|
1520
|
+
target ? /* @__PURE__ */ jsx5("code", { class: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
1521
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1522
|
+
entry.status === "pending" ? /* @__PURE__ */ jsx5(PendingElapsed, { now: adapter?.now }) : null,
|
|
1523
|
+
/* @__PURE__ */ jsx5("span", { class: "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 }) }),
|
|
1524
|
+
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14, class: "scui-tool-chevron" }) : null
|
|
1332
1525
|
] });
|
|
1333
|
-
if (!hasDetail) return /* @__PURE__ */
|
|
1334
|
-
return /* @__PURE__ */
|
|
1335
|
-
/* @__PURE__ */
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1338
|
-
/* @__PURE__ */
|
|
1339
|
-
/* @__PURE__ */
|
|
1340
|
-
presentation.fields.length ? /* @__PURE__ */
|
|
1341
|
-
/* @__PURE__ */
|
|
1342
|
-
/* @__PURE__ */
|
|
1526
|
+
if (!hasDetail) return /* @__PURE__ */ jsx5("div", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, children: /* @__PURE__ */ jsx5("div", { class: "scui-tool-head", children: summary }) });
|
|
1527
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
1528
|
+
/* @__PURE__ */ jsx5("summary", { class: "scui-tool-head", children: summary }),
|
|
1529
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-tool-detail", children: [
|
|
1530
|
+
/* @__PURE__ */ jsx5(ToolMetrics, { presentation }),
|
|
1531
|
+
/* @__PURE__ */ jsx5(ToolStack, { tools: presentation.tools ?? [] }),
|
|
1532
|
+
/* @__PURE__ */ jsx5(ToolPreview, { presentation, entry }),
|
|
1533
|
+
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", { class: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1534
|
+
/* @__PURE__ */ jsx5("dt", { children: field.label }),
|
|
1535
|
+
/* @__PURE__ */ jsx5("dd", { children: field.value })
|
|
1343
1536
|
] }, field.label)) }) : null,
|
|
1344
|
-
/* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1537
|
+
/* @__PURE__ */ jsx5(ToolActions, { presentation, adapter }),
|
|
1538
|
+
/* @__PURE__ */ jsx5(TechnicalDetails, { entry })
|
|
1346
1539
|
] })
|
|
1347
1540
|
] });
|
|
1348
1541
|
}
|
|
1349
1542
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1350
|
-
if (entries.length === 1) return /* @__PURE__ */
|
|
1543
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx5("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx5(ToolRow, { entry: entries[0], workspace: state.workspace, adapter }) });
|
|
1351
1544
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1352
1545
|
const [open, setOpen] = useState2(active);
|
|
1353
1546
|
const id = useId();
|
|
1354
1547
|
useEffect3(() => {
|
|
1355
1548
|
if (active) setOpen(true);
|
|
1356
1549
|
}, [active]);
|
|
1357
|
-
return /* @__PURE__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
/* @__PURE__ */
|
|
1361
|
-
/* @__PURE__ */
|
|
1362
|
-
/* @__PURE__ */
|
|
1550
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-activity", children: [
|
|
1551
|
+
/* @__PURE__ */ jsxs4("button", { class: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1552
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14 }) }),
|
|
1553
|
+
/* @__PURE__ */ jsx5("strong", { children: activitySummary(entries) }),
|
|
1554
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1555
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1363
1556
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1364
1557
|
"/",
|
|
1365
1558
|
entries.length
|
|
1366
1559
|
] })
|
|
1367
1560
|
] }),
|
|
1368
|
-
open ? /* @__PURE__ */
|
|
1561
|
+
open ? /* @__PURE__ */ jsx5("div", { id, children: entries.map((entry) => /* @__PURE__ */ jsx5(ToolRow, { entry, workspace: state.workspace, adapter }, entry.id)) }) : null
|
|
1369
1562
|
] });
|
|
1370
1563
|
}
|
|
1371
1564
|
function TaskPlan({ plan }) {
|
|
1372
1565
|
if (!plan.items.length) return null;
|
|
1373
1566
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1374
|
-
return /* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1567
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-plan", children: [
|
|
1568
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1569
|
+
/* @__PURE__ */ jsx5("span", { children: "Plan" }),
|
|
1570
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1378
1571
|
complete,
|
|
1379
1572
|
"/",
|
|
1380
1573
|
plan.items.length
|
|
1381
1574
|
] })
|
|
1382
1575
|
] }),
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1576
|
+
/* @__PURE__ */ jsx5("ol", { tabIndex: 0, "aria-label": "Task plan steps", children: plan.items.map((item) => /* @__PURE__ */ jsxs4("li", { "data-status": item.status, children: [
|
|
1577
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1385
1578
|
" ",
|
|
1386
|
-
/* @__PURE__ */
|
|
1579
|
+
/* @__PURE__ */ jsx5("span", { children: item.title })
|
|
1387
1580
|
] }, item.id)) })
|
|
1388
1581
|
] });
|
|
1389
1582
|
}
|
|
1390
1583
|
function SessionDetails({ semantics }) {
|
|
1391
1584
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1392
|
-
return /* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
semantics.fidelity ? /* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1585
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-details", children: [
|
|
1586
|
+
/* @__PURE__ */ jsx5("summary", { children: "Session details" }),
|
|
1587
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1588
|
+
semantics.fidelity ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1589
|
+
/* @__PURE__ */ jsx5("strong", { children: "Fidelity" }),
|
|
1590
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.fidelity.replaceAll("_", " ") })
|
|
1398
1591
|
] }) : null,
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsxs4("p", { children: [
|
|
1593
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native records" }),
|
|
1594
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.rawRecords })
|
|
1402
1595
|
] }),
|
|
1403
|
-
semantics.residueCount ? /* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1596
|
+
semantics.residueCount ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1597
|
+
/* @__PURE__ */ jsx5("strong", { children: "Residue" }),
|
|
1598
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1406
1599
|
semantics.residueCount,
|
|
1407
1600
|
" retained"
|
|
1408
1601
|
] })
|
|
1409
1602
|
] }) : null,
|
|
1410
|
-
semantics.parseErrors ? /* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1412
|
-
/* @__PURE__ */
|
|
1603
|
+
semantics.parseErrors ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1604
|
+
/* @__PURE__ */ jsx5("strong", { children: "Parse diagnostics" }),
|
|
1605
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.parseErrors })
|
|
1413
1606
|
] }) : null,
|
|
1414
|
-
semantics.subagents.map((agent) => /* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1607
|
+
semantics.subagents.map((agent) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1608
|
+
/* @__PURE__ */ jsxs4("strong", { children: [
|
|
1416
1609
|
agent.source,
|
|
1417
1610
|
" subagent"
|
|
1418
1611
|
] }),
|
|
1419
|
-
/* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1420
1613
|
agent.messages,
|
|
1421
1614
|
" messages \xB7 ",
|
|
1422
1615
|
agent.fidelity.replaceAll("_", " ")
|
|
@@ -1435,7 +1628,7 @@ function ConversationAnnouncements({ state }) {
|
|
|
1435
1628
|
}
|
|
1436
1629
|
previousBusy.current = state.busy;
|
|
1437
1630
|
}, [state.busy, state.error, state.harness]);
|
|
1438
|
-
return /* @__PURE__ */
|
|
1631
|
+
return /* @__PURE__ */ jsx5("span", { class: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1439
1632
|
}
|
|
1440
1633
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1441
1634
|
const scroller = useRef3(null);
|
|
@@ -1467,65 +1660,72 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1467
1660
|
const element = scroller.current;
|
|
1468
1661
|
if (!element) return;
|
|
1469
1662
|
const anchor = earlierAnchor.current;
|
|
1470
|
-
if (anchor
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1663
|
+
if (anchor) {
|
|
1664
|
+
if (state.operation === "loadEarlier") anchor.seenOperation = true;
|
|
1665
|
+
const prepended = state.transcript.length > anchor.entries && state.transcript[0]?.id !== anchor.firstId;
|
|
1666
|
+
if (prepended) {
|
|
1667
|
+
element.scrollTop = anchor.top + (element.scrollHeight - anchor.height);
|
|
1668
|
+
earlierAnchor.current = null;
|
|
1669
|
+
remember({ top: element.scrollTop, atBottom: false });
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
if (state.error || anchor.seenOperation && state.operation !== "loadEarlier") earlierAnchor.current = null;
|
|
1475
1673
|
}
|
|
1476
1674
|
if (!restored.current) {
|
|
1477
1675
|
restored.current = true;
|
|
1478
1676
|
if (remembered.top !== null && !remembered.atBottom) element.scrollTop = remembered.top;
|
|
1479
1677
|
else pin();
|
|
1480
1678
|
} else if (atBottom) pin();
|
|
1481
|
-
}, [memoryKey, state.transcript, state.busy, state.operation, pendingMessage?.text, pendingMessage?.status]);
|
|
1482
|
-
return /* @__PURE__ */
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
1679
|
+
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1680
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-conversation-wrap", children: [
|
|
1681
|
+
/* @__PURE__ */ jsx5(ConversationAnnouncements, { state }),
|
|
1682
|
+
/* @__PURE__ */ jsx5("div", { class: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1485
1683
|
const element = event.currentTarget;
|
|
1486
1684
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1487
1685
|
setAtBottom(bottom);
|
|
1488
1686
|
remember({ top: element.scrollTop, atBottom: bottom });
|
|
1489
|
-
}, children: /* @__PURE__ */
|
|
1490
|
-
Before ? /* @__PURE__ */
|
|
1491
|
-
/* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
state.history.hasEarlier ? /* @__PURE__ */
|
|
1687
|
+
}, children: /* @__PURE__ */ jsxs4("div", { children: [
|
|
1688
|
+
Before ? /* @__PURE__ */ jsx5(Before, { state, adapter, value: null }) : null,
|
|
1689
|
+
/* @__PURE__ */ jsx5(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
1690
|
+
/* @__PURE__ */ jsx5(SessionDetails, { semantics: state.semantics }),
|
|
1691
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", { class: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1494
1692
|
const element = scroller.current;
|
|
1495
|
-
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length };
|
|
1693
|
+
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1496
1694
|
setAtBottom(false);
|
|
1497
1695
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1498
1696
|
}, children: "Load earlier messages" }) : null,
|
|
1499
|
-
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */
|
|
1500
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */
|
|
1501
|
-
blocks.map((block, index) => /* @__PURE__ */
|
|
1502
|
-
index === unreadBlock ? /* @__PURE__ */
|
|
1503
|
-
block.kind === "activity" ? /* @__PURE__ */
|
|
1697
|
+
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state }) : null,
|
|
1698
|
+
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */ jsx5(Empty, { state, adapter, value: null }) : /* @__PURE__ */ jsx5("div", { class: "scui-empty", children: state.error ?? (state.harness ? `${harnessDisplayName(state.harness)} is listening. Say something.` : "No transcript yet.") }) : null,
|
|
1699
|
+
blocks.map((block, index) => /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1700
|
+
index === unreadBlock ? /* @__PURE__ */ jsx5("div", { class: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx5("span", { children: "New" }) }) : null,
|
|
1701
|
+
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 })
|
|
1504
1702
|
] }, block.id)),
|
|
1505
|
-
pendingMessage ? /* @__PURE__ */
|
|
1506
|
-
/* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1703
|
+
pendingMessage ? /* @__PURE__ */ jsxs4("article", { class: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
1704
|
+
/* @__PURE__ */ jsx5(MessageImages, { items: pendingMessage.images }),
|
|
1705
|
+
/* @__PURE__ */ jsx5(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
1706
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: pendingMessage.context }),
|
|
1707
|
+
/* @__PURE__ */ jsxs4("footer", { children: [
|
|
1708
|
+
/* @__PURE__ */ jsx5("small", { children: pendingMessage.status === "failed" ? "Not sent" : "Sending\u2026" }),
|
|
1709
|
+
pendingMessage.status === "failed" ? /* @__PURE__ */ jsxs4("span", { children: [
|
|
1710
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onRetry, children: "Retry" }),
|
|
1711
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onEdit, children: "Edit" })
|
|
1512
1712
|
] }) : null
|
|
1513
1713
|
] })
|
|
1514
1714
|
] }) : null,
|
|
1515
|
-
state.busy ? /* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
/* @__PURE__ */
|
|
1715
|
+
state.busy ? /* @__PURE__ */ jsxs4("div", { class: "scui-working", role: "status", children: [
|
|
1716
|
+
/* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
1717
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1718
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1719
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1720
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1521
1721
|
harnessDisplayName(state.harness),
|
|
1522
1722
|
" is working"
|
|
1523
1723
|
] })
|
|
1524
1724
|
] }) : null,
|
|
1525
|
-
After ? /* @__PURE__ */
|
|
1725
|
+
After ? /* @__PURE__ */ jsx5(After, { state, adapter, value: null }) : null
|
|
1526
1726
|
] }) }),
|
|
1527
|
-
!atBottom ? /* @__PURE__ */
|
|
1528
|
-
/* @__PURE__ */
|
|
1727
|
+
!atBottom ? /* @__PURE__ */ jsxs4("button", { class: "scui-latest", type: "button", onClick: pin, children: [
|
|
1728
|
+
/* @__PURE__ */ jsx5(UiIcon, { name: "down", size: 13 }),
|
|
1529
1729
|
" Latest"
|
|
1530
1730
|
] }) : null
|
|
1531
1731
|
] });
|
|
@@ -1533,7 +1733,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1533
1733
|
|
|
1534
1734
|
// src/logo.jsx
|
|
1535
1735
|
import { useEffect as useEffect4 } from "preact/hooks";
|
|
1536
|
-
import { jsx as
|
|
1736
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
1537
1737
|
var LOGOS = {
|
|
1538
1738
|
"claude-code": {
|
|
1539
1739
|
viewBox: "-1 3.5 26 18",
|
|
@@ -1587,9 +1787,9 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
|
1587
1787
|
if (!logo) onMissingLogo?.(id);
|
|
1588
1788
|
}, [id, logo, onMissingLogo]);
|
|
1589
1789
|
if (!logo) return null;
|
|
1590
|
-
return /* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1592
|
-
activity && activity !== "idle" ? /* @__PURE__ */
|
|
1790
|
+
return /* @__PURE__ */ jsxs5("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
|
|
1791
|
+
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
1792
|
+
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
1593
1793
|
] });
|
|
1594
1794
|
}
|
|
1595
1795
|
|
|
@@ -1598,22 +1798,22 @@ import { useEffect as useEffect6, useId as useId2, useMemo as useMemo2, useRef a
|
|
|
1598
1798
|
|
|
1599
1799
|
// src/sessions.jsx
|
|
1600
1800
|
import { useEffect as useEffect5, useLayoutEffect as useLayoutEffect3, useRef as useRef4, useState as useState3 } from "preact/hooks";
|
|
1601
|
-
import { jsx as
|
|
1801
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
1602
1802
|
var sessionListMemory = /* @__PURE__ */ new Map();
|
|
1603
1803
|
function SessionRow({ row, state, onOpen }) {
|
|
1604
1804
|
const activity = sessionActivity(state, row);
|
|
1605
1805
|
const attentionPreview = state.attention.find((item) => item.key === row.key)?.preview;
|
|
1606
1806
|
const title = sessionDisplayName(row);
|
|
1607
1807
|
const detail = attentionPreview || row.preview || (row.name && row.name !== title ? row.name : row.cwd);
|
|
1608
|
-
return /* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1808
|
+
return /* @__PURE__ */ jsxs6("button", { class: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${detail ? ` \xB7 ${detail}` : ""}${row.age ? ` \xB7 ${row.age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
|
|
1809
|
+
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
1810
|
+
/* @__PURE__ */ jsxs6("span", { class: "scui-session-copy", children: [
|
|
1811
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
1812
|
+
/* @__PURE__ */ jsx7("strong", { children: title }),
|
|
1813
|
+
/* @__PURE__ */ jsx7("small", { children: row.age })
|
|
1614
1814
|
] }),
|
|
1615
|
-
detail ? /* @__PURE__ */
|
|
1616
|
-
state.attachError?.key === row.key ? /* @__PURE__ */
|
|
1815
|
+
detail ? /* @__PURE__ */ jsx7("span", { children: /* @__PURE__ */ jsx7("small", { title: row.cwd, children: detail }) }) : null,
|
|
1816
|
+
state.attachError?.key === row.key ? /* @__PURE__ */ jsx7("em", { children: state.attachError.message }) : null
|
|
1617
1817
|
] })
|
|
1618
1818
|
] });
|
|
1619
1819
|
}
|
|
@@ -1644,48 +1844,48 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
1644
1844
|
Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
|
|
1645
1845
|
}
|
|
1646
1846
|
};
|
|
1647
|
-
return /* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1847
|
+
return /* @__PURE__ */ jsxs6("section", { class: "scui-list", ref: root, children: [
|
|
1848
|
+
/* @__PURE__ */ jsxs6("header", { class: "scui-head", children: [
|
|
1849
|
+
/* @__PURE__ */ jsxs6("span", { class: "scui-head-copy", children: [
|
|
1850
|
+
/* @__PURE__ */ jsx7("strong", { children: labels.chats }),
|
|
1851
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1652
1852
|
state.sessions.length,
|
|
1653
1853
|
" recent conversations"
|
|
1654
1854
|
] })
|
|
1655
1855
|
] }),
|
|
1656
|
-
/* @__PURE__ */
|
|
1657
|
-
onClose ? /* @__PURE__ */
|
|
1856
|
+
/* @__PURE__ */ jsx7("button", { type: "button", "data-list-focus": "new", "aria-label": labels.newChat, disabled: !state.harnesses.some((item) => item.startable), onClick: onNew, children: /* @__PURE__ */ jsx7(UiIcon, { name: "plus", size: 18 }) }),
|
|
1857
|
+
onClose ? /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx7(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1658
1858
|
] }),
|
|
1659
|
-
state.startup !== "ready" ? /* @__PURE__ */
|
|
1660
|
-
state.sessions.length > 4 ? /* @__PURE__ */
|
|
1661
|
-
/* @__PURE__ */
|
|
1662
|
-
/* @__PURE__ */
|
|
1859
|
+
state.startup !== "ready" ? /* @__PURE__ */ jsx7(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
1860
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", { class: "scui-search", children: [
|
|
1861
|
+
/* @__PURE__ */ jsx7(UiIcon, { name: "search", size: 15 }),
|
|
1862
|
+
/* @__PURE__ */ jsx7("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
|
|
1663
1863
|
const value = event.currentTarget.value;
|
|
1664
1864
|
setQuery(value);
|
|
1665
1865
|
boundedSet(sessionListMemory, memoryKey, { query: value, top: 0 });
|
|
1666
1866
|
if (rowScroller.current) rowScroller.current.scrollTop = 0;
|
|
1667
1867
|
} }),
|
|
1668
|
-
/* @__PURE__ */
|
|
1868
|
+
/* @__PURE__ */ jsx7("small", { children: rows.length })
|
|
1669
1869
|
] }) : null,
|
|
1670
|
-
/* @__PURE__ */
|
|
1671
|
-
!rows.length && state.startup === "ready" ? /* @__PURE__ */
|
|
1672
|
-
rows.map((row) => /* @__PURE__ */
|
|
1673
|
-
state.history.hasMoreSessions ? /* @__PURE__ */
|
|
1870
|
+
/* @__PURE__ */ jsxs6("div", { class: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
|
|
1871
|
+
!rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx7("div", { class: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
|
|
1872
|
+
rows.map((row) => /* @__PURE__ */ jsx7(Row, { value: row, row, state, adapter, onOpen }, row.key)),
|
|
1873
|
+
state.history.hasMoreSessions ? /* @__PURE__ */ jsx7("button", { class: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null
|
|
1674
1874
|
] })
|
|
1675
1875
|
] });
|
|
1676
1876
|
}
|
|
1677
1877
|
|
|
1678
1878
|
// src/messenger.jsx
|
|
1679
|
-
import { jsx as
|
|
1879
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
1680
1880
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
1681
1881
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
1682
1882
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
1683
1883
|
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "interrupt", "respond", "refresh", "loadEarlier", "loadSessions"]);
|
|
1684
1884
|
function Receipt({ state, adapter }) {
|
|
1685
1885
|
const receipt = state.reductionReceipt;
|
|
1686
|
-
if (receipt) return /* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
/* @__PURE__ */
|
|
1886
|
+
if (receipt) return /* @__PURE__ */ jsx8("div", { class: "scui-receipt", children: /* @__PURE__ */ jsxs7("span", { children: [
|
|
1887
|
+
/* @__PURE__ */ jsx8("strong", { children: "Reduced and verified" }),
|
|
1888
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1689
1889
|
receipt.sourceTokens.toLocaleString(),
|
|
1690
1890
|
" \u2192 ",
|
|
1691
1891
|
receipt.reducedTokens.toLocaleString(),
|
|
@@ -1694,27 +1894,27 @@ function Receipt({ state, adapter }) {
|
|
|
1694
1894
|
"\xD7 \xB7 reversible"
|
|
1695
1895
|
] })
|
|
1696
1896
|
] }) });
|
|
1697
|
-
if (state.exportReceipt) return /* @__PURE__ */
|
|
1698
|
-
/* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1897
|
+
if (state.exportReceipt) return /* @__PURE__ */ jsxs7("div", { class: "scui-receipt", children: [
|
|
1898
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1899
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
1700
1900
|
"Lossless export ready \xB7 ",
|
|
1701
1901
|
harnessDisplayName(state.exportReceipt.targetHarness)
|
|
1702
1902
|
] }),
|
|
1703
|
-
/* @__PURE__ */
|
|
1903
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1704
1904
|
state.exportReceipt.path,
|
|
1705
1905
|
" \xB7 ",
|
|
1706
1906
|
state.exportReceipt.files,
|
|
1707
1907
|
" files"
|
|
1708
1908
|
] })
|
|
1709
1909
|
] }),
|
|
1710
|
-
/* @__PURE__ */
|
|
1910
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(state.exportReceipt.path), children: "Copy path" })
|
|
1711
1911
|
] });
|
|
1712
|
-
if (state.terminalHandoff) return /* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
1715
|
-
/* @__PURE__ */
|
|
1912
|
+
if (state.terminalHandoff) return /* @__PURE__ */ jsxs7("div", { class: "scui-receipt", children: [
|
|
1913
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1914
|
+
/* @__PURE__ */ jsx8("strong", { children: "Terminal handoff ready" }),
|
|
1915
|
+
/* @__PURE__ */ jsx8("small", { children: state.terminalHandoff.cwd })
|
|
1716
1916
|
] }),
|
|
1717
|
-
/* @__PURE__ */
|
|
1917
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(terminalCommand(state.terminalHandoff)), children: "Copy command" })
|
|
1718
1918
|
] });
|
|
1719
1919
|
return null;
|
|
1720
1920
|
}
|
|
@@ -1782,13 +1982,13 @@ function ConversationActions({ state, adapter, actionPending }) {
|
|
|
1782
1982
|
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;
|
|
1783
1983
|
items[index].focus({ preventScroll: true });
|
|
1784
1984
|
};
|
|
1785
|
-
return /* @__PURE__ */
|
|
1985
|
+
return /* @__PURE__ */ jsxs7("div", { class: "scui-menu", ref: root, onBlur: (event) => {
|
|
1786
1986
|
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
1787
1987
|
}, children: [
|
|
1788
|
-
/* @__PURE__ */
|
|
1789
|
-
open ? /* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
1791
|
-
group.items.map((item) => /* @__PURE__ */
|
|
1988
|
+
/* @__PURE__ */ jsx8("button", { ref: trigger, class: "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__ */ jsx8(UiIcon, { name: "menu", size: 18 }) }),
|
|
1989
|
+
open ? /* @__PURE__ */ jsx8("div", { ref: panel, id: menuId, class: "scui-menu-panel", role: "menu", "aria-label": "Conversation actions", onKeyDown: navigate, children: groups.map((group) => /* @__PURE__ */ jsxs7("section", { role: "group", "aria-label": group.label, children: [
|
|
1990
|
+
/* @__PURE__ */ jsx8("strong", { children: group.label }),
|
|
1991
|
+
group.items.map((item) => /* @__PURE__ */ jsx8("button", { role: "menuitem", type: "button", disabled: actionPending, onClick: () => dispatch(item.intent), children: item.label }, item.key))
|
|
1792
1992
|
] }, group.label)) }) : null
|
|
1793
1993
|
] });
|
|
1794
1994
|
}
|
|
@@ -1801,20 +2001,20 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
1801
2001
|
useEffect6(() => {
|
|
1802
2002
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
1803
2003
|
}, []);
|
|
1804
|
-
return /* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
1806
|
-
/* @__PURE__ */
|
|
1807
|
-
/* @__PURE__ */
|
|
1808
|
-
/* @__PURE__ */
|
|
1809
|
-
/* @__PURE__ */
|
|
2004
|
+
return /* @__PURE__ */ jsxs7("header", { class: "scui-head scui-chat-head", children: [
|
|
2005
|
+
/* @__PURE__ */ jsx8("button", { ref: back, type: "button", "aria-label": "Back to chats", onClick: onBack, children: /* @__PURE__ */ jsx8(UiIcon, { name: "back", size: 18 }) }),
|
|
2006
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: harness, size: 28 }),
|
|
2007
|
+
/* @__PURE__ */ jsxs7("span", { class: "scui-head-copy", children: [
|
|
2008
|
+
/* @__PURE__ */ jsx8("strong", { children: title }),
|
|
2009
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1810
2010
|
harnessDisplayName(harness),
|
|
1811
2011
|
" \xB7 ",
|
|
1812
2012
|
status
|
|
1813
2013
|
] })
|
|
1814
2014
|
] }),
|
|
1815
|
-
menu ? /* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
onClose ? /* @__PURE__ */
|
|
2015
|
+
menu ? /* @__PURE__ */ jsx8(ConversationActions, { state, adapter, actionPending }) : null,
|
|
2016
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ jsx8(UiIcon, { name: "plus", size: 18 }) }),
|
|
2017
|
+
onClose ? /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1818
2018
|
] });
|
|
1819
2019
|
}
|
|
1820
2020
|
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels }) {
|
|
@@ -1846,8 +2046,10 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1846
2046
|
if (pending.status === "sending" && state.busy && !pending.seenBusy) setPending({ ...pending, seenBusy: true });
|
|
1847
2047
|
else if (pending.status === "sending" && state.error && !state.busy && !state.operation && (pending.seenBusy || state.error !== pending.initialError)) setPending({ ...pending, status: "failed" });
|
|
1848
2048
|
}, [pending, state.busy, state.error, state.operation, state.transcript]);
|
|
1849
|
-
const beginPending = (text) => setPending({
|
|
2049
|
+
const beginPending = (text, context = [], images = []) => setPending({
|
|
1850
2050
|
text,
|
|
2051
|
+
context,
|
|
2052
|
+
images,
|
|
1851
2053
|
status: "sending",
|
|
1852
2054
|
initialError: state.error,
|
|
1853
2055
|
seenBusy: state.busy,
|
|
@@ -1855,13 +2057,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1855
2057
|
});
|
|
1856
2058
|
const retryPending = () => {
|
|
1857
2059
|
if (!pending) return;
|
|
1858
|
-
adapter.onIntent({ action: "send", text: pending.text });
|
|
2060
|
+
adapter.onIntent({ action: "send", text: pending.text, ...pending.context?.length ? { context: pending.context } : {}, ...pending.images?.length ? { images: pending.images } : {} });
|
|
1859
2061
|
setPending({ ...pending, status: "sending", initialError: state.error, seenBusy: state.busy });
|
|
1860
2062
|
};
|
|
1861
2063
|
const editPending = () => {
|
|
1862
2064
|
if (!pending) return;
|
|
1863
2065
|
restoreSequence.current += 1;
|
|
1864
|
-
setRestoreDraft({ id: restoreSequence.current, text: pending.text });
|
|
2066
|
+
setRestoreDraft({ id: restoreSequence.current, text: pending.text, context: pending.context, images: pending.images });
|
|
1865
2067
|
setPending({ ...pending, status: "editing" });
|
|
1866
2068
|
};
|
|
1867
2069
|
useEffect6(() => {
|
|
@@ -1907,34 +2109,38 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1907
2109
|
setPendingAction(null);
|
|
1908
2110
|
}
|
|
1909
2111
|
}, [pendingAction, state.error, state.operation]);
|
|
1910
|
-
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
2112
|
+
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, context: pending.context, images: pending.images, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
1911
2113
|
const action = state.operation || pendingAction?.action || null;
|
|
1912
2114
|
const actionLabel = operationLabel(action);
|
|
1913
2115
|
const actionState = action ? { ...state, operation: action, canInterrupt: false, canRespond: false } : state;
|
|
1914
2116
|
const unreadAfterMessages = state.attention.find((item) => item.key === state.attached?.key)?.afterMessages ?? null;
|
|
1915
|
-
return /* @__PURE__ */
|
|
1916
|
-
Header ? /* @__PURE__ */
|
|
1917
|
-
actionLabel ? /* @__PURE__ */
|
|
1918
|
-
/* @__PURE__ */
|
|
2117
|
+
return /* @__PURE__ */ jsxs7("section", { class: "scui-chat", children: [
|
|
2118
|
+
Header ? /* @__PURE__ */ jsx8(Header, { state: actionState, adapter: trackedAdapter, value: null }) : /* @__PURE__ */ jsx8(ChatHeader, { state: actionState, adapter: trackedAdapter, pendingStatus: pending?.status ?? null, actionPending: Boolean(action), onBack, onNew, onClose }),
|
|
2119
|
+
actionLabel ? /* @__PURE__ */ jsxs7("div", { class: "scui-operation", role: "status", children: [
|
|
2120
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
1919
2121
|
actionLabel
|
|
1920
2122
|
] }) : null,
|
|
1921
|
-
state.error ? /* @__PURE__ */
|
|
1922
|
-
/* @__PURE__ */
|
|
1923
|
-
state.recoverable ? /* @__PURE__ */
|
|
2123
|
+
state.error ? /* @__PURE__ */ jsxs7("div", { class: "scui-error", role: "alert", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx8("span", { children: state.error }),
|
|
2125
|
+
state.recoverable ? /* @__PURE__ */ jsx8("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
|
|
1924
2126
|
] }) : null,
|
|
1925
|
-
/* @__PURE__ */
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
1928
|
-
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */
|
|
2127
|
+
/* @__PURE__ */ jsx8(Receipt, { state, adapter }),
|
|
2128
|
+
/* @__PURE__ */ jsx8(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2129
|
+
/* @__PURE__ */ jsx8(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2130
|
+
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx8(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
|
|
1929
2131
|
] });
|
|
1930
2132
|
}
|
|
1931
2133
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey }) {
|
|
1932
2134
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1933
2135
|
const startableKey = startable.map((item) => item.id).join("\0");
|
|
1934
|
-
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "" };
|
|
2136
|
+
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [] };
|
|
1935
2137
|
const [harness, setHarness] = useState4(remembered.harness);
|
|
1936
2138
|
const [draft, setDraft] = useState4(remembered.draft);
|
|
2139
|
+
const [context, setContext] = useState4(remembered.context);
|
|
2140
|
+
const [images, setImages] = useState4(remembered.images ?? []);
|
|
1937
2141
|
const [starting, setStarting] = useState4(null);
|
|
2142
|
+
const [picking, setPicking] = useState4(false);
|
|
2143
|
+
const [pickerError, setPickerError] = useState4(null);
|
|
1938
2144
|
const startSequence = useRef5(0);
|
|
1939
2145
|
const textarea = useRef5(null);
|
|
1940
2146
|
useAutosizeTextarea(textarea, draft);
|
|
@@ -1942,7 +2148,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
1942
2148
|
if (startable.some((item) => item.id === harness)) return;
|
|
1943
2149
|
const next = startable[0]?.id ?? "";
|
|
1944
2150
|
setHarness(next);
|
|
1945
|
-
boundedSet(newChatMemory, memoryKey, { harness: next, draft });
|
|
2151
|
+
boundedSet(newChatMemory, memoryKey, { harness: next, draft, context, images });
|
|
1946
2152
|
}, [harness, startableKey]);
|
|
1947
2153
|
useEffect6(() => {
|
|
1948
2154
|
if (!starting) return;
|
|
@@ -1958,60 +2164,108 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
1958
2164
|
useEffect6(() => {
|
|
1959
2165
|
textarea.current?.focus({ preventScroll: true });
|
|
1960
2166
|
}, []);
|
|
2167
|
+
const pickContext = () => {
|
|
2168
|
+
if (!adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
2169
|
+
setPicking(true);
|
|
2170
|
+
setPickerError(null);
|
|
2171
|
+
Promise.resolve().then(() => adapter.pickContext()).then((picked) => {
|
|
2172
|
+
const attachments = partitionAttachments(picked);
|
|
2173
|
+
if (context.length + attachments.context.length > MAX_CONTEXT_ITEMS) throw new Error(`Attach at most ${MAX_CONTEXT_ITEMS} text items.`);
|
|
2174
|
+
if (images.length + attachments.images.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
2175
|
+
setContext((current) => {
|
|
2176
|
+
const next = mergeContext(current, attachments.context);
|
|
2177
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context: next, images });
|
|
2178
|
+
return next;
|
|
2179
|
+
});
|
|
2180
|
+
setImages((current) => {
|
|
2181
|
+
const next = mergeImages(current, attachments.images);
|
|
2182
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context, images: next });
|
|
2183
|
+
return next;
|
|
2184
|
+
});
|
|
2185
|
+
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
2186
|
+
};
|
|
2187
|
+
const pasteImages = (event) => {
|
|
2188
|
+
const files = Array.from(event.clipboardData?.files ?? []).filter((file) => file.type.startsWith("image/"));
|
|
2189
|
+
if (!files.length) return;
|
|
2190
|
+
event.preventDefault();
|
|
2191
|
+
if (images.length + files.length > MAX_IMAGE_ITEMS) {
|
|
2192
|
+
setPickerError(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
setPicking(true);
|
|
2196
|
+
setPickerError(null);
|
|
2197
|
+
imageAttachmentsFromFiles(files).then((picked) => setImages((current) => {
|
|
2198
|
+
const next = mergeImages(current, picked);
|
|
2199
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context, images: next });
|
|
2200
|
+
return next;
|
|
2201
|
+
}), (error) => setPickerError(error instanceof Error ? error.message : "Could not paste image.")).finally(() => setPicking(false));
|
|
2202
|
+
};
|
|
1961
2203
|
const send = () => {
|
|
1962
2204
|
const text = draft.trim();
|
|
1963
2205
|
if (!text || !harness || starting) return;
|
|
1964
2206
|
const id = startSequence.current + 1;
|
|
1965
2207
|
startSequence.current = id;
|
|
1966
2208
|
setStarting({ id, attachedKey: state.attached?.key ?? null, busy: state.busy, initialError: state.error });
|
|
1967
|
-
const result = adapter.onIntent({ action: "new", harness, text });
|
|
2209
|
+
const result = adapter.onIntent({ action: "new", harness, text, ...context.length ? { context } : {}, ...images.length ? { images } : {} });
|
|
1968
2210
|
if (result && typeof result.then === "function") {
|
|
1969
2211
|
Promise.resolve(result).catch(() => setStarting((current) => current?.id === id ? null : current));
|
|
1970
2212
|
}
|
|
1971
2213
|
};
|
|
1972
|
-
return /* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
1975
|
-
/* @__PURE__ */
|
|
1976
|
-
/* @__PURE__ */
|
|
1977
|
-
/* @__PURE__ */
|
|
2214
|
+
return /* @__PURE__ */ jsxs7("section", { class: "scui-chat", children: [
|
|
2215
|
+
/* @__PURE__ */ jsxs7("header", { class: "scui-head", children: [
|
|
2216
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Back", onClick: onBack, children: /* @__PURE__ */ jsx8(UiIcon, { name: "back", size: 18 }) }),
|
|
2217
|
+
/* @__PURE__ */ jsxs7("span", { class: "scui-head-copy", children: [
|
|
2218
|
+
/* @__PURE__ */ jsx8("strong", { children: labels.newChat }),
|
|
2219
|
+
/* @__PURE__ */ jsx8("small", { children: "No session is created until you send" })
|
|
1978
2220
|
] }),
|
|
1979
|
-
onClose ? /* @__PURE__ */
|
|
2221
|
+
onClose ? /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1980
2222
|
] }),
|
|
1981
|
-
starting ? /* @__PURE__ */
|
|
1982
|
-
/* @__PURE__ */
|
|
2223
|
+
starting ? /* @__PURE__ */ jsxs7("div", { class: "scui-operation", role: "status", children: [
|
|
2224
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
1983
2225
|
operationLabel("start")
|
|
1984
2226
|
] }) : null,
|
|
1985
|
-
/* @__PURE__ */
|
|
1986
|
-
/* @__PURE__ */
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
2227
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-new", children: [
|
|
2228
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2229
|
+
/* @__PURE__ */ jsx8("strong", { children: "What should the agent build or fix?" }),
|
|
2230
|
+
/* @__PURE__ */ jsx8("small", { children: "Choose a coding harness and send the first message." })
|
|
1989
2231
|
] }),
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
1993
|
-
/* @__PURE__ */
|
|
1994
|
-
/* @__PURE__ */
|
|
2232
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-compose", children: [
|
|
2233
|
+
/* @__PURE__ */ jsxs7("label", { class: "scui-harness-picker", children: [
|
|
2234
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: harness, size: 24 }),
|
|
2235
|
+
/* @__PURE__ */ jsx8("span", { children: "Coding harness" }),
|
|
2236
|
+
/* @__PURE__ */ jsx8("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
1995
2237
|
const value = event.currentTarget.value;
|
|
1996
2238
|
setHarness(value);
|
|
1997
|
-
boundedSet(newChatMemory, memoryKey, { harness: value, draft });
|
|
1998
|
-
}, children: state.harnesses.map((item) => /* @__PURE__ */
|
|
2239
|
+
boundedSet(newChatMemory, memoryKey, { harness: value, draft, context, images });
|
|
2240
|
+
}, children: state.harnesses.map((item) => /* @__PURE__ */ jsxs7("option", { value: item.id, disabled: !item.startable, children: [
|
|
1999
2241
|
item.label,
|
|
2000
2242
|
item.startable ? "" : " \xB7 unavailable"
|
|
2001
2243
|
] }, item.id)) })
|
|
2002
2244
|
] }),
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
|
|
2245
|
+
/* @__PURE__ */ jsx8(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
2246
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2247
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context, images: next });
|
|
2248
|
+
return next;
|
|
2249
|
+
}) }),
|
|
2250
|
+
/* @__PURE__ */ jsx8(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
2251
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2252
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context: next, images });
|
|
2253
|
+
return next;
|
|
2254
|
+
}) }),
|
|
2255
|
+
pickerError ? /* @__PURE__ */ jsx8("small", { class: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
2256
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-envelope", children: [
|
|
2257
|
+
adapter.pickContext ? /* @__PURE__ */ jsx8("button", { class: "scui-attach", type: "button", "aria-label": "Attach files or images", disabled: picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx8("i", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx8(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2258
|
+
/* @__PURE__ */ jsx8("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) => {
|
|
2005
2259
|
const value = event.currentTarget.value;
|
|
2006
2260
|
setDraft(value);
|
|
2007
|
-
boundedSet(newChatMemory, memoryKey, { harness, draft: value });
|
|
2261
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft: value, context, images });
|
|
2008
2262
|
}, onKeyDown: (event) => {
|
|
2009
2263
|
if (isSendKey(event)) {
|
|
2010
2264
|
event.preventDefault();
|
|
2011
2265
|
send();
|
|
2012
2266
|
}
|
|
2013
2267
|
} }),
|
|
2014
|
-
/* @__PURE__ */
|
|
2268
|
+
/* @__PURE__ */ jsx8("span", { children: /* @__PURE__ */ jsx8("button", { type: "button", class: "scui-send", "aria-label": "Start chat", disabled: !draft.trim() || !harness || Boolean(starting), onClick: send, children: starting ? /* @__PURE__ */ jsx8("i", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx8(UiIcon, { name: "send", size: 17 }) }) })
|
|
2015
2269
|
] })
|
|
2016
2270
|
] })
|
|
2017
2271
|
] });
|
|
@@ -2043,31 +2297,31 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2043
2297
|
};
|
|
2044
2298
|
const close = () => adapter.onClose?.();
|
|
2045
2299
|
const Footer = slots.footer;
|
|
2046
|
-
return /* @__PURE__ */
|
|
2047
|
-
view === "list" ? /* @__PURE__ */
|
|
2300
|
+
return /* @__PURE__ */ jsxs7("main", { class: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2301
|
+
view === "list" ? /* @__PURE__ */ jsx8(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2048
2302
|
setListFocus("@new");
|
|
2049
2303
|
setView("new");
|
|
2050
2304
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey }) : null,
|
|
2051
|
-
view === "new" ? /* @__PURE__ */
|
|
2052
|
-
view === "chat" ? /* @__PURE__ */
|
|
2305
|
+
view === "new" ? /* @__PURE__ */ jsx8(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: () => setView("chat"), labels: copy, memoryKey }) : null,
|
|
2306
|
+
view === "chat" ? /* @__PURE__ */ jsx8(Chat, { state, adapter, onBack: () => {
|
|
2053
2307
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2054
2308
|
setView("list");
|
|
2055
2309
|
}, onNew: () => {
|
|
2056
2310
|
setListFocus("@new");
|
|
2057
2311
|
setView("new");
|
|
2058
2312
|
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy }) : null,
|
|
2059
|
-
opening ? /* @__PURE__ */
|
|
2060
|
-
/* @__PURE__ */
|
|
2061
|
-
/* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
2313
|
+
opening ? /* @__PURE__ */ jsxs7("div", { class: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2314
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2315
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2316
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
2063
2317
|
"Opening ",
|
|
2064
2318
|
sessionDisplayName(opening)
|
|
2065
2319
|
] }),
|
|
2066
|
-
/* @__PURE__ */
|
|
2320
|
+
/* @__PURE__ */ jsx8("small", { children: "Loading the latest transcript window\u2026" })
|
|
2067
2321
|
] }),
|
|
2068
|
-
/* @__PURE__ */
|
|
2322
|
+
/* @__PURE__ */ jsx8("i", {})
|
|
2069
2323
|
] }) : null,
|
|
2070
|
-
Footer ? /* @__PURE__ */
|
|
2324
|
+
Footer ? /* @__PURE__ */ jsx8(Footer, { state, adapter, value: copy }) : null
|
|
2071
2325
|
] });
|
|
2072
2326
|
}
|
|
2073
2327
|
export {
|