@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/embed.mjs
CHANGED
|
@@ -504,6 +504,16 @@ function readTranscript(value) {
|
|
|
504
504
|
}] : [];
|
|
505
505
|
});
|
|
506
506
|
}
|
|
507
|
+
if (Array.isArray(item.images)) {
|
|
508
|
+
entry.images = item.images.flatMap((raw) => {
|
|
509
|
+
const image = record(raw);
|
|
510
|
+
return image && typeof image.label === "string" ? [{
|
|
511
|
+
...typeof image.id === "string" ? { id: image.id } : {},
|
|
512
|
+
label: image.label,
|
|
513
|
+
...typeof image.url === "string" ? { url: image.url } : {}
|
|
514
|
+
}] : [];
|
|
515
|
+
}).slice(0, 4);
|
|
516
|
+
}
|
|
507
517
|
const request = record(item.request);
|
|
508
518
|
if (request && typeof request.requestKind === "string" && typeof request.payloadText === "string") {
|
|
509
519
|
entry.request = {
|
|
@@ -684,7 +694,7 @@ function sessionActivity(state, row) {
|
|
|
684
694
|
function filterSessions(rows, query) {
|
|
685
695
|
const needle = query.trim().toLocaleLowerCase();
|
|
686
696
|
if (!needle) return [...rows];
|
|
687
|
-
return rows.filter((row) => [row.name, row.title, row.cwd, row.harness, harnessDisplayName(row.harness)].some((value) => value.toLocaleLowerCase().includes(needle)));
|
|
697
|
+
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)));
|
|
688
698
|
}
|
|
689
699
|
function groupConversation(entries) {
|
|
690
700
|
const blocks = [];
|
|
@@ -764,6 +774,7 @@ function boundedSet(map, key, value) {
|
|
|
764
774
|
// src/icon.jsx
|
|
765
775
|
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
766
776
|
var ICONS = {
|
|
777
|
+
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" }),
|
|
767
778
|
back: () => /* @__PURE__ */ jsx("path", { d: "m11.5 4.5-4.5 4.5 4.5 4.5" }),
|
|
768
779
|
check: () => /* @__PURE__ */ jsx("path", { d: "m4 9 3.25 3.25L14 5.5" }),
|
|
769
780
|
chevron: () => /* @__PURE__ */ jsx("path", { d: "m7 4.5 4.5 4.5L7 13.5" }),
|
|
@@ -779,6 +790,11 @@ var ICONS = {
|
|
|
779
790
|
/* @__PURE__ */ jsx("path", { d: "M9 3.5v10" }),
|
|
780
791
|
/* @__PURE__ */ jsx("path", { d: "m4.75 9.5 4.25 4 4.25-4" })
|
|
781
792
|
] }),
|
|
793
|
+
image: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
794
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "3.5", width: "12", height: "11", rx: "1.75" }),
|
|
795
|
+
/* @__PURE__ */ jsx("circle", { cx: "6.5", cy: "7", r: "1.25" }),
|
|
796
|
+
/* @__PURE__ */ jsx("path", { d: "m4.5 13 3.25-3 2.1 1.85 1.65-1.5L14 13" })
|
|
797
|
+
] }),
|
|
782
798
|
menu: () => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
783
799
|
/* @__PURE__ */ jsx("circle", { cx: "4", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
784
800
|
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
|
|
@@ -804,6 +820,114 @@ function UiIcon({ name, size = 16, class: className = "" }) {
|
|
|
804
820
|
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, {}) });
|
|
805
821
|
}
|
|
806
822
|
|
|
823
|
+
// src/context.jsx
|
|
824
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
825
|
+
var MAX_CONTEXT_ITEMS = 32;
|
|
826
|
+
var MAX_IMAGE_ITEMS = 4;
|
|
827
|
+
var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
828
|
+
var IMAGE_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
|
|
829
|
+
function normalizeContext(value) {
|
|
830
|
+
return (Array.isArray(value) ? value : value ? [value] : []).flatMap((item) => {
|
|
831
|
+
if (!item || typeof item.label !== "string" || typeof item.detail !== "string") return [];
|
|
832
|
+
const label = item.label.trim().slice(0, 200);
|
|
833
|
+
const detail = item.detail.slice(0, 2e4);
|
|
834
|
+
if (!label || !detail) return [];
|
|
835
|
+
return [{
|
|
836
|
+
...typeof item.id === "string" && item.id ? { id: item.id.slice(0, 2e3) } : {},
|
|
837
|
+
...typeof item.kind === "string" && item.kind ? { kind: item.kind.slice(0, 100) } : {},
|
|
838
|
+
label,
|
|
839
|
+
detail
|
|
840
|
+
}];
|
|
841
|
+
}).slice(0, MAX_CONTEXT_ITEMS);
|
|
842
|
+
}
|
|
843
|
+
function mergeContext(current, picked) {
|
|
844
|
+
const next = [...current];
|
|
845
|
+
const seen = new Set(current.map((item) => item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`));
|
|
846
|
+
for (const item of normalizeContext(picked)) {
|
|
847
|
+
const key = item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`;
|
|
848
|
+
if (seen.has(key)) continue;
|
|
849
|
+
seen.add(key);
|
|
850
|
+
next.push(item);
|
|
851
|
+
if (next.length === MAX_CONTEXT_ITEMS) break;
|
|
852
|
+
}
|
|
853
|
+
return next;
|
|
854
|
+
}
|
|
855
|
+
function normalizeImages(value) {
|
|
856
|
+
const seen = /* @__PURE__ */ new Set();
|
|
857
|
+
return (Array.isArray(value) ? value : value ? [value] : []).flatMap((item) => {
|
|
858
|
+
if (!item || typeof item.label !== "string" || typeof item.url !== "string") return [];
|
|
859
|
+
const label = item.label.trim().slice(0, 200);
|
|
860
|
+
const url = item.url;
|
|
861
|
+
if (!label || seen.has(url) || !(url.startsWith("data:image/") || url.startsWith("https://") || url.startsWith("http://"))) return [];
|
|
862
|
+
seen.add(url);
|
|
863
|
+
return [{
|
|
864
|
+
...typeof item.id === "string" && item.id ? { id: item.id.slice(0, 2e3) } : {},
|
|
865
|
+
label,
|
|
866
|
+
url
|
|
867
|
+
}];
|
|
868
|
+
}).slice(0, MAX_IMAGE_ITEMS);
|
|
869
|
+
}
|
|
870
|
+
function mergeImages(current, picked) {
|
|
871
|
+
const next = [...current];
|
|
872
|
+
const seen = new Set(current.map((item) => item.url));
|
|
873
|
+
for (const item of normalizeImages(picked)) {
|
|
874
|
+
if (seen.has(item.url)) continue;
|
|
875
|
+
seen.add(item.url);
|
|
876
|
+
next.push(item);
|
|
877
|
+
if (next.length === MAX_IMAGE_ITEMS) break;
|
|
878
|
+
}
|
|
879
|
+
return next;
|
|
880
|
+
}
|
|
881
|
+
function partitionAttachments(value) {
|
|
882
|
+
const values = Array.isArray(value) ? value : value ? [value] : [];
|
|
883
|
+
const context = [];
|
|
884
|
+
const images = [];
|
|
885
|
+
for (const item of values) {
|
|
886
|
+
if (item && typeof item.label === "string" && item.label.trim() && typeof item.detail === "string" && item.detail) context.push(item);
|
|
887
|
+
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);
|
|
888
|
+
else throw new Error("The attachment picker returned an invalid item.");
|
|
889
|
+
}
|
|
890
|
+
return { context, images };
|
|
891
|
+
}
|
|
892
|
+
async function imageAttachmentsFromFiles(value) {
|
|
893
|
+
const files = Array.from(value ?? []).filter((file) => file?.type?.startsWith("image/"));
|
|
894
|
+
if (files.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images at a time.`);
|
|
895
|
+
return Promise.all(files.map(async (file) => {
|
|
896
|
+
if (!IMAGE_TYPES.has(file.type)) throw new Error(`${file.name || "That image"} is not PNG, JPEG, GIF, or WebP.`);
|
|
897
|
+
if (file.size > MAX_IMAGE_BYTES) throw new Error(`${file.name || "That image"} is larger than 5 MB.`);
|
|
898
|
+
const url = await new Promise((resolve, reject) => {
|
|
899
|
+
const reader = new FileReader();
|
|
900
|
+
reader.onload = () => resolve(reader.result);
|
|
901
|
+
reader.onerror = () => reject(reader.error ?? new Error(`Could not read ${file.name || "image"}.`));
|
|
902
|
+
reader.readAsDataURL(file);
|
|
903
|
+
});
|
|
904
|
+
return { id: `${file.name}:${file.size}:${file.lastModified}`, label: file.name || "Pasted image", url };
|
|
905
|
+
}));
|
|
906
|
+
}
|
|
907
|
+
function ContextTray({ items, onRemove }) {
|
|
908
|
+
if (!items.length) return null;
|
|
909
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
910
|
+
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
911
|
+
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
912
|
+
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
913
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
914
|
+
}
|
|
915
|
+
function ImageTray({ items, onRemove }) {
|
|
916
|
+
if (!items.length) return null;
|
|
917
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-compose-images", "aria-label": "Attached images", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
918
|
+
/* @__PURE__ */ jsx2("img", { src: item.url, alt: "" }),
|
|
919
|
+
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
920
|
+
onRemove ? /* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove image ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) }) : null
|
|
921
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
922
|
+
}
|
|
923
|
+
function MessageImages({ items }) {
|
|
924
|
+
if (!items?.length) return null;
|
|
925
|
+
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: [
|
|
926
|
+
/* @__PURE__ */ jsx2(UiIcon, { name: "image", size: 14 }),
|
|
927
|
+
item.label
|
|
928
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
929
|
+
}
|
|
930
|
+
|
|
807
931
|
// src/textarea.js
|
|
808
932
|
import { useLayoutEffect } from "preact/hooks";
|
|
809
933
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -819,7 +943,7 @@ function useAutosizeTextarea(ref, value) {
|
|
|
819
943
|
}
|
|
820
944
|
|
|
821
945
|
// src/composer.jsx
|
|
822
|
-
import { jsx as
|
|
946
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
823
947
|
var composerMemory = /* @__PURE__ */ new Map();
|
|
824
948
|
function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
825
949
|
if (state.mode !== "mirror" || state.canSend) return null;
|
|
@@ -829,29 +953,36 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
829
953
|
const resume = canContinueHere(state);
|
|
830
954
|
const join = state.canAttach;
|
|
831
955
|
const branch = state.canBranch;
|
|
832
|
-
if (!resume && !join && !branch) return /* @__PURE__ */
|
|
833
|
-
/* @__PURE__ */
|
|
834
|
-
/* @__PURE__ */
|
|
956
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { class: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
957
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
958
|
+
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
835
959
|
] }) });
|
|
836
|
-
return /* @__PURE__ */
|
|
837
|
-
/* @__PURE__ */
|
|
838
|
-
/* @__PURE__ */
|
|
839
|
-
/* @__PURE__ */
|
|
960
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-continuation", children: [
|
|
961
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
962
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
963
|
+
/* @__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." })
|
|
840
964
|
] }),
|
|
841
|
-
/* @__PURE__ */
|
|
965
|
+
/* @__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 })
|
|
842
966
|
] });
|
|
843
967
|
}
|
|
844
968
|
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
845
|
-
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, queue: [] };
|
|
969
|
+
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], images: [], queue: [] };
|
|
846
970
|
const [draft, setDraft] = useState(remembered.draft);
|
|
847
|
-
const [
|
|
971
|
+
const [context, setContext] = useState(remembered.context ?? []);
|
|
972
|
+
const [images, setImages] = useState(remembered.images ?? []);
|
|
973
|
+
const [queue, setQueue] = useState((remembered.queue ?? []).map((item) => ({ ...item, context: item.context ?? [], images: item.images ?? [] })));
|
|
848
974
|
const [dispatching, setDispatching] = useState(false);
|
|
975
|
+
const [picking, setPicking] = useState(false);
|
|
976
|
+
const [pickerError, setPickerError] = useState(null);
|
|
849
977
|
const textarea = useRef(null);
|
|
850
978
|
useAutosizeTextarea(textarea, draft);
|
|
851
|
-
const remember = (nextDraft, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, queue: nextQueue });
|
|
979
|
+
const remember = (nextDraft, nextContext, nextImages, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, context: nextContext, images: nextImages, queue: nextQueue });
|
|
980
|
+
useEffect(() => {
|
|
981
|
+
remember(draft, context, images, queue);
|
|
982
|
+
}, [draft, context, images, memoryKey, queue]);
|
|
852
983
|
const updateQueue = (update) => setQueue((items) => {
|
|
853
984
|
const next = update(items);
|
|
854
|
-
remember(draft, next);
|
|
985
|
+
remember(draft, context, images, next);
|
|
855
986
|
return next;
|
|
856
987
|
});
|
|
857
988
|
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
@@ -861,9 +992,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
861
992
|
const [next, ...rest] = queue;
|
|
862
993
|
setDispatching(true);
|
|
863
994
|
setQueue(rest);
|
|
864
|
-
remember(draft, rest);
|
|
865
|
-
onPending?.(next);
|
|
866
|
-
adapter.onIntent({ action: "send", text: next });
|
|
995
|
+
remember(draft, context, images, rest);
|
|
996
|
+
onPending?.(next.text, next.context, next.images);
|
|
997
|
+
adapter.onIntent({ action: "send", text: next.text, ...next.context.length ? { context: next.context } : {}, ...next.images.length ? { images: next.images } : {} });
|
|
867
998
|
}
|
|
868
999
|
}, [adapter, draft, memoryKey, onPending, queue, queueBlocked, state.canSend]);
|
|
869
1000
|
useEffect(() => {
|
|
@@ -875,7 +1006,11 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
875
1006
|
useEffect(() => {
|
|
876
1007
|
if (!restoreDraft) return;
|
|
877
1008
|
setDraft(restoreDraft.text);
|
|
878
|
-
|
|
1009
|
+
const restoredContext = normalizeContext(restoreDraft.context);
|
|
1010
|
+
const restoredImages = normalizeImages(restoreDraft.images);
|
|
1011
|
+
setContext(restoredContext);
|
|
1012
|
+
setImages(restoredImages);
|
|
1013
|
+
remember(restoreDraft.text, restoredContext, restoredImages, queue);
|
|
879
1014
|
textarea.current?.focus({ preventScroll: true });
|
|
880
1015
|
onDraftRestored?.(restoreDraft.id);
|
|
881
1016
|
}, [onDraftRestored, restoreDraft?.id]);
|
|
@@ -883,43 +1018,100 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
883
1018
|
const timer = setTimeout(() => adapter.onIntent({ action: "draft", text: draft }), 250);
|
|
884
1019
|
return () => clearTimeout(timer);
|
|
885
1020
|
}, [adapter, draft]);
|
|
1021
|
+
const pickContext = () => {
|
|
1022
|
+
if (!adapter.pickContext || state.mode !== "control" || picking || context.length >= MAX_CONTEXT_ITEMS && images.length >= MAX_IMAGE_ITEMS) return;
|
|
1023
|
+
setPicking(true);
|
|
1024
|
+
setPickerError(null);
|
|
1025
|
+
Promise.resolve().then(() => adapter.pickContext()).then((picked) => {
|
|
1026
|
+
const attachments = partitionAttachments(picked);
|
|
1027
|
+
if (context.length + attachments.context.length > MAX_CONTEXT_ITEMS) throw new Error(`Attach at most ${MAX_CONTEXT_ITEMS} text items.`);
|
|
1028
|
+
if (images.length + attachments.images.length > MAX_IMAGE_ITEMS) throw new Error(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
1029
|
+
setContext((current) => {
|
|
1030
|
+
const next = mergeContext(current, attachments.context);
|
|
1031
|
+
remember(draft, next, images, queue);
|
|
1032
|
+
return next;
|
|
1033
|
+
});
|
|
1034
|
+
setImages((current) => {
|
|
1035
|
+
const next = mergeImages(current, attachments.images);
|
|
1036
|
+
remember(draft, context, next, queue);
|
|
1037
|
+
return next;
|
|
1038
|
+
});
|
|
1039
|
+
}).catch((error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
1040
|
+
};
|
|
1041
|
+
const pasteImages = (event) => {
|
|
1042
|
+
const files = Array.from(event.clipboardData?.files ?? []).filter((file) => file.type.startsWith("image/"));
|
|
1043
|
+
if (!files.length) return;
|
|
1044
|
+
event.preventDefault();
|
|
1045
|
+
if (images.length + files.length > MAX_IMAGE_ITEMS) {
|
|
1046
|
+
setPickerError(`Attach at most ${MAX_IMAGE_ITEMS} images.`);
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
setPicking(true);
|
|
1050
|
+
setPickerError(null);
|
|
1051
|
+
imageAttachmentsFromFiles(files).then((picked) => setImages((current) => {
|
|
1052
|
+
const next = mergeImages(current, picked);
|
|
1053
|
+
remember(draft, context, next, queue);
|
|
1054
|
+
return next;
|
|
1055
|
+
}), (error) => setPickerError(error instanceof Error ? error.message : "Could not paste image.")).finally(() => setPicking(false));
|
|
1056
|
+
};
|
|
886
1057
|
const send = () => {
|
|
887
1058
|
const text = draft.trim();
|
|
888
1059
|
if (!text) return;
|
|
889
|
-
|
|
1060
|
+
const message = { text, context, images };
|
|
1061
|
+
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
890
1062
|
else if (state.canSend) {
|
|
891
1063
|
if (onPending) setDispatching(true);
|
|
892
|
-
onPending?.(text);
|
|
893
|
-
adapter.onIntent({ action: "send", text });
|
|
1064
|
+
onPending?.(text, context, images);
|
|
1065
|
+
adapter.onIntent({ action: "send", text, ...context.length ? { context } : {}, ...images.length ? { images } : {} });
|
|
894
1066
|
} else return;
|
|
895
1067
|
setDraft("");
|
|
896
|
-
|
|
1068
|
+
setContext([]);
|
|
1069
|
+
setImages([]);
|
|
1070
|
+
remember("", [], [], queuesNewMessage ? [...queue, message] : queue);
|
|
897
1071
|
};
|
|
898
|
-
return /* @__PURE__ */
|
|
899
|
-
queue.length ? /* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
1072
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-compose", children: [
|
|
1073
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { class: "scui-queue", children: [
|
|
1074
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
901
1075
|
queue.length,
|
|
902
1076
|
" queued"
|
|
903
1077
|
] }),
|
|
904
|
-
queue.map((item, index) => /* @__PURE__ */
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1078
|
+
queue.map((item, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
1079
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1080
|
+
item.text,
|
|
1081
|
+
item.context.length + item.images.length ? /* @__PURE__ */ jsxs3("small", { children: [
|
|
1082
|
+
item.context.length + item.images.length,
|
|
1083
|
+
" attached"
|
|
1084
|
+
] }) : null
|
|
1085
|
+
] }),
|
|
1086
|
+
/* @__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 }) })
|
|
1087
|
+
] }, `${index}:${item.text}`))
|
|
908
1088
|
] }) : null,
|
|
909
|
-
/* @__PURE__ */
|
|
910
|
-
|
|
1089
|
+
/* @__PURE__ */ jsx3(ImageTray, { items: images, onRemove: (index) => setImages((items) => {
|
|
1090
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1091
|
+
remember(draft, context, next, queue);
|
|
1092
|
+
return next;
|
|
1093
|
+
}) }),
|
|
1094
|
+
/* @__PURE__ */ jsx3(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
1095
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
1096
|
+
remember(draft, next, images, queue);
|
|
1097
|
+
return next;
|
|
1098
|
+
}) }),
|
|
1099
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { class: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
1100
|
+
/* @__PURE__ */ jsxs3("div", { class: "scui-envelope", children: [
|
|
1101
|
+
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,
|
|
1102
|
+
/* @__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) => {
|
|
911
1103
|
const value = event.currentTarget.value;
|
|
912
1104
|
setDraft(value);
|
|
913
|
-
remember(value, queue);
|
|
1105
|
+
remember(value, context, images, queue);
|
|
914
1106
|
}, onKeyDown: (event) => {
|
|
915
1107
|
if (isSendKey(event)) {
|
|
916
1108
|
event.preventDefault();
|
|
917
1109
|
send();
|
|
918
1110
|
}
|
|
919
1111
|
} }),
|
|
920
|
-
/* @__PURE__ */
|
|
921
|
-
state.busy ? /* @__PURE__ */
|
|
922
|
-
/* @__PURE__ */
|
|
1112
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1113
|
+
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,
|
|
1114
|
+
/* @__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 }) })
|
|
923
1115
|
] })
|
|
924
1116
|
] })
|
|
925
1117
|
] });
|
|
@@ -932,7 +1124,7 @@ import { useEffect as useEffect3, useId, useLayoutEffect as useLayoutEffect2, us
|
|
|
932
1124
|
// src/markdown.jsx
|
|
933
1125
|
import MarkdownIt from "markdown-it";
|
|
934
1126
|
import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "preact/hooks";
|
|
935
|
-
import { jsx as
|
|
1127
|
+
import { jsx as jsx4 } from "preact/jsx-runtime";
|
|
936
1128
|
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
937
1129
|
var LANGUAGE_LABELS = {
|
|
938
1130
|
bash: "Shell",
|
|
@@ -1019,11 +1211,11 @@ function Markdown({ value, copyText }) {
|
|
|
1019
1211
|
}, 1500);
|
|
1020
1212
|
resets.current.set(button, timer);
|
|
1021
1213
|
};
|
|
1022
|
-
return /* @__PURE__ */
|
|
1214
|
+
return /* @__PURE__ */ jsx4("div", { class: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1023
1215
|
}
|
|
1024
1216
|
|
|
1025
1217
|
// src/conversation.jsx
|
|
1026
|
-
import { Fragment as Fragment3, jsx as
|
|
1218
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
1027
1219
|
function LoadingStatus({ state, compact = false }) {
|
|
1028
1220
|
const copy = {
|
|
1029
1221
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -1031,43 +1223,43 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1031
1223
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1032
1224
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1033
1225
|
}[state.startup];
|
|
1034
|
-
return /* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
/* @__PURE__ */
|
|
1037
|
-
/* @__PURE__ */
|
|
1038
|
-
/* @__PURE__ */
|
|
1226
|
+
return /* @__PURE__ */ jsxs4("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1227
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("i", {}) }),
|
|
1228
|
+
/* @__PURE__ */ jsxs4("span", { class: "scui-loading-copy", children: [
|
|
1229
|
+
/* @__PURE__ */ jsx5("strong", { children: copy[0] }),
|
|
1230
|
+
/* @__PURE__ */ jsx5("small", { children: copy[1] })
|
|
1039
1231
|
] }),
|
|
1040
|
-
/* @__PURE__ */
|
|
1232
|
+
/* @__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)) })
|
|
1041
1233
|
] });
|
|
1042
1234
|
}
|
|
1043
1235
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1044
1236
|
const request = entry.request;
|
|
1045
1237
|
if (!request) return null;
|
|
1046
1238
|
if (request.status === "responded") {
|
|
1047
|
-
return /* @__PURE__ */
|
|
1239
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-request-done", children: [
|
|
1048
1240
|
"\u2713 Request answered \xB7 ",
|
|
1049
1241
|
request.resolution?.name ?? request.requestKind
|
|
1050
1242
|
] });
|
|
1051
1243
|
}
|
|
1052
|
-
return /* @__PURE__ */
|
|
1053
|
-
/* @__PURE__ */
|
|
1054
|
-
/* @__PURE__ */
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
request.options.map((option) => /* @__PURE__ */
|
|
1057
|
-
request.cancellable ? /* @__PURE__ */
|
|
1244
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1245
|
+
/* @__PURE__ */ jsx5("strong", { children: "Agent needs input" }),
|
|
1246
|
+
/* @__PURE__ */ jsx5(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1247
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-request-actions", children: [
|
|
1248
|
+
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)),
|
|
1249
|
+
request.cancellable ? /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1058
1250
|
] })
|
|
1059
1251
|
] });
|
|
1060
1252
|
}
|
|
1061
1253
|
function ContextDisclosure({ context }) {
|
|
1062
1254
|
if (!context?.length) return null;
|
|
1063
|
-
return /* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1255
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-context", children: [
|
|
1256
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1065
1257
|
"Context \xB7 ",
|
|
1066
1258
|
context.length
|
|
1067
1259
|
] }),
|
|
1068
|
-
/* @__PURE__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1260
|
+
/* @__PURE__ */ jsx5("div", { children: context.map((item, index) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1261
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1262
|
+
/* @__PURE__ */ jsx5("span", { children: item.detail })
|
|
1071
1263
|
] }, item.id ?? index)) })
|
|
1072
1264
|
] });
|
|
1073
1265
|
}
|
|
@@ -1089,46 +1281,46 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1089
1281
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1090
1282
|
};
|
|
1091
1283
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1092
|
-
return /* @__PURE__ */
|
|
1093
|
-
validDate ? /* @__PURE__ */
|
|
1094
|
-
adapter?.copyText && entry.text ? /* @__PURE__ */
|
|
1284
|
+
return /* @__PURE__ */ jsxs4("footer", { class: "scui-message-meta", children: [
|
|
1285
|
+
validDate ? /* @__PURE__ */ jsx5("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1286
|
+
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
|
|
1095
1287
|
] });
|
|
1096
1288
|
}
|
|
1097
1289
|
var TOOL_ICONS = {
|
|
1098
|
-
read: () => /* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
1100
|
-
/* @__PURE__ */
|
|
1290
|
+
read: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1291
|
+
/* @__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" }),
|
|
1292
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
1101
1293
|
] }),
|
|
1102
|
-
search: () => /* @__PURE__ */
|
|
1103
|
-
/* @__PURE__ */
|
|
1104
|
-
/* @__PURE__ */
|
|
1294
|
+
search: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1295
|
+
/* @__PURE__ */ jsx5("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
1296
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.5 11.5 3 3" })
|
|
1105
1297
|
] }),
|
|
1106
|
-
edit: () => /* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1298
|
+
edit: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1299
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
1300
|
+
/* @__PURE__ */ jsx5("path", { d: "m10 5 3 3" })
|
|
1109
1301
|
] }),
|
|
1110
|
-
command: () => /* @__PURE__ */
|
|
1111
|
-
test: () => /* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1302
|
+
command: () => /* @__PURE__ */ jsx5(Fragment3, { children: /* @__PURE__ */ jsx5("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
1303
|
+
test: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1304
|
+
/* @__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" }),
|
|
1305
|
+
/* @__PURE__ */ jsx5("path", { d: "M5 2.5h8" })
|
|
1114
1306
|
] }),
|
|
1115
|
-
web: () => /* @__PURE__ */
|
|
1116
|
-
/* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1307
|
+
web: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1308
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
1309
|
+
/* @__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" })
|
|
1118
1310
|
] }),
|
|
1119
|
-
agent: () => /* @__PURE__ */
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1311
|
+
agent: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1312
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
1313
|
+
/* @__PURE__ */ jsx5("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
1122
1314
|
] }),
|
|
1123
|
-
plan: () => /* @__PURE__ */
|
|
1124
|
-
other: () => /* @__PURE__ */
|
|
1125
|
-
/* @__PURE__ */
|
|
1126
|
-
/* @__PURE__ */
|
|
1315
|
+
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" }) }),
|
|
1316
|
+
other: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1317
|
+
/* @__PURE__ */ jsx5("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
1318
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
1127
1319
|
] })
|
|
1128
1320
|
};
|
|
1129
1321
|
function ToolIcon({ category }) {
|
|
1130
1322
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1131
|
-
return /* @__PURE__ */
|
|
1323
|
+
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, {}) });
|
|
1132
1324
|
}
|
|
1133
1325
|
function toolAction2(entry, category, presentation) {
|
|
1134
1326
|
if (presentation?.action) return presentation.action;
|
|
@@ -1183,7 +1375,7 @@ function ToolMetrics({ presentation }) {
|
|
|
1183
1375
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1184
1376
|
formatDuration(presentation.durationMs)
|
|
1185
1377
|
].filter(Boolean);
|
|
1186
|
-
return metrics.length ? /* @__PURE__ */
|
|
1378
|
+
return metrics.length ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx5("span", { children: metric }, metric)) }) : null;
|
|
1187
1379
|
}
|
|
1188
1380
|
function PendingElapsed({ now }) {
|
|
1189
1381
|
const clock = now ?? Date.now;
|
|
@@ -1193,74 +1385,74 @@ function PendingElapsed({ now }) {
|
|
|
1193
1385
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1194
1386
|
return () => clearInterval(timer);
|
|
1195
1387
|
}, [clock]);
|
|
1196
|
-
return /* @__PURE__ */
|
|
1388
|
+
return /* @__PURE__ */ jsx5("small", { class: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1197
1389
|
}
|
|
1198
1390
|
function LinePreview({ value, kind }) {
|
|
1199
1391
|
if (!value) return null;
|
|
1200
|
-
return /* @__PURE__ */
|
|
1392
|
+
return /* @__PURE__ */ jsx5("ol", { class: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1201
1393
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1202
|
-
return /* @__PURE__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1394
|
+
return /* @__PURE__ */ jsxs4("li", { "data-tone": tone, children: [
|
|
1395
|
+
/* @__PURE__ */ jsx5("span", { children: index + 1 }),
|
|
1396
|
+
/* @__PURE__ */ jsx5("code", { children: line || " " })
|
|
1205
1397
|
] }, index);
|
|
1206
1398
|
}) });
|
|
1207
1399
|
}
|
|
1208
1400
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1209
|
-
return /* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1401
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-terminal", children: [
|
|
1402
|
+
/* @__PURE__ */ jsxs4("header", { children: [
|
|
1403
|
+
/* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", children: [
|
|
1404
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1405
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1406
|
+
/* @__PURE__ */ jsx5("i", {})
|
|
1215
1407
|
] }),
|
|
1216
|
-
/* @__PURE__ */
|
|
1408
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1217
1409
|
] }),
|
|
1218
|
-
presentation.preview ? /* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1410
|
+
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", { class: "scui-terminal-wait", children: [
|
|
1411
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1220
1412
|
" Waiting for output"
|
|
1221
|
-
] }) : /* @__PURE__ */
|
|
1413
|
+
] }) : /* @__PURE__ */ jsx5("div", { class: "scui-terminal-empty", children: "No output" })
|
|
1222
1414
|
] });
|
|
1223
1415
|
}
|
|
1224
1416
|
function SearchPreview({ presentation }) {
|
|
1225
1417
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1226
|
-
return /* @__PURE__ */
|
|
1227
|
-
presentation.query ? /* @__PURE__ */
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1418
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-search-preview", children: [
|
|
1419
|
+
presentation.query ? /* @__PURE__ */ jsxs4("header", { children: [
|
|
1420
|
+
/* @__PURE__ */ jsx5("span", { children: "Search" }),
|
|
1421
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.query })
|
|
1230
1422
|
] }) : null,
|
|
1231
|
-
lines.length ? /* @__PURE__ */
|
|
1423
|
+
lines.length ? /* @__PURE__ */ jsx5("ol", { children: lines.map((line, index) => {
|
|
1232
1424
|
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
1233
|
-
return /* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1235
|
-
/* @__PURE__ */
|
|
1425
|
+
return /* @__PURE__ */ jsx5("li", { children: match ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1426
|
+
/* @__PURE__ */ jsx5("code", { children: match[1] }),
|
|
1427
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1236
1428
|
match[2],
|
|
1237
1429
|
match[3] ? `:${match[3]}` : ""
|
|
1238
1430
|
] }),
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
] }) : /* @__PURE__ */
|
|
1241
|
-
}) }) : /* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsx5("span", { children: match[4] })
|
|
1432
|
+
] }) : /* @__PURE__ */ jsx5("span", { children: line }) }, index);
|
|
1433
|
+
}) }) : /* @__PURE__ */ jsx5("p", { children: "No textual results" })
|
|
1242
1434
|
] });
|
|
1243
1435
|
}
|
|
1244
1436
|
function ToolPreview({ presentation, entry }) {
|
|
1245
1437
|
const pending = entry.status === "pending";
|
|
1246
1438
|
const failed = entry.status === "error";
|
|
1247
|
-
if (presentation.detail === "terminal") return /* @__PURE__ */
|
|
1248
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */
|
|
1249
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */
|
|
1250
|
-
if (presentation.detail === "matches") return /* @__PURE__ */
|
|
1251
|
-
if (presentation.detail === "web") return /* @__PURE__ */
|
|
1252
|
-
presentation.url ? /* @__PURE__ */
|
|
1253
|
-
presentation.preview ? /* @__PURE__ */
|
|
1439
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx5(TerminalPreview, { presentation, pending, failed });
|
|
1440
|
+
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" });
|
|
1441
|
+
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" });
|
|
1442
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx5(SearchPreview, { presentation });
|
|
1443
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", { class: "scui-web-preview", children: [
|
|
1444
|
+
presentation.url ? /* @__PURE__ */ jsx5("code", { children: presentation.url }) : null,
|
|
1445
|
+
presentation.preview ? /* @__PURE__ */ jsx5("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1254
1446
|
] });
|
|
1255
|
-
if (presentation.detail === "agent") return /* @__PURE__ */
|
|
1256
|
-
/* @__PURE__ */
|
|
1257
|
-
/* @__PURE__ */
|
|
1258
|
-
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */
|
|
1259
|
-
if (presentation.detail === "plan") return /* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
1447
|
+
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: [
|
|
1448
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1449
|
+
/* @__PURE__ */ jsx5("small", { children: item.status })
|
|
1450
|
+
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx5("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1451
|
+
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: [
|
|
1452
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1453
|
+
/* @__PURE__ */ jsx5("span", { children: item.label })
|
|
1262
1454
|
] }, `${item.label}:${index}`)) });
|
|
1263
|
-
return presentation.preview ? /* @__PURE__ */
|
|
1455
|
+
return presentation.preview ? /* @__PURE__ */ jsx5("pre", { class: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1264
1456
|
}
|
|
1265
1457
|
function ToolActions({ presentation, adapter }) {
|
|
1266
1458
|
const [copied, setCopied] = useState2(false);
|
|
@@ -1274,27 +1466,27 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1274
1466
|
clearTimeout(reset.current);
|
|
1275
1467
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1276
1468
|
};
|
|
1277
|
-
return action ? /* @__PURE__ */
|
|
1469
|
+
return action ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1278
1470
|
}
|
|
1279
1471
|
function ToolStack({ tools }) {
|
|
1280
1472
|
if (tools.length < 2) return null;
|
|
1281
|
-
return /* @__PURE__ */
|
|
1473
|
+
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)) });
|
|
1282
1474
|
}
|
|
1283
1475
|
function TechnicalDetails({ entry }) {
|
|
1284
1476
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1285
|
-
return /* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
entry.arguments ? /* @__PURE__ */
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1477
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool-technical", children: [
|
|
1478
|
+
/* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
|
|
1479
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1480
|
+
entry.arguments ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1481
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native arguments" }),
|
|
1482
|
+
/* @__PURE__ */ jsx5("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1483
|
+
/* @__PURE__ */ jsx5("dt", { children: row.label }),
|
|
1484
|
+
/* @__PURE__ */ jsx5("dd", { children: /* @__PURE__ */ jsx5("pre", { children: row.value }) })
|
|
1293
1485
|
] }, row.key)) })
|
|
1294
1486
|
] }) : null,
|
|
1295
|
-
entry.resultText ? /* @__PURE__ */
|
|
1296
|
-
/* @__PURE__ */
|
|
1297
|
-
/* @__PURE__ */
|
|
1487
|
+
entry.resultText ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1488
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native result" }),
|
|
1489
|
+
/* @__PURE__ */ jsxs4("pre", { "data-error": entry.status === "error", children: [
|
|
1298
1490
|
entry.resultText,
|
|
1299
1491
|
entry.truncated ? "\n[truncated]" : ""
|
|
1300
1492
|
] })
|
|
@@ -1303,19 +1495,20 @@ function TechnicalDetails({ entry }) {
|
|
|
1303
1495
|
] });
|
|
1304
1496
|
}
|
|
1305
1497
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1306
|
-
if (entry.role === "request") return /* @__PURE__ */
|
|
1498
|
+
if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1307
1499
|
if (entry.role === "reasoning") {
|
|
1308
|
-
return /* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1500
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-reasoning", open: entry.streaming, children: [
|
|
1501
|
+
/* @__PURE__ */ jsx5("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
1502
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1311
1503
|
] });
|
|
1312
1504
|
}
|
|
1313
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */
|
|
1314
|
-
return /* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1317
|
-
|
|
1318
|
-
/* @__PURE__ */
|
|
1505
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", { class: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
1506
|
+
return /* @__PURE__ */ jsxs4("article", { class: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
1507
|
+
/* @__PURE__ */ jsx5(MessageImages, { items: entry.images }),
|
|
1508
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
1509
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: entry.context }),
|
|
1510
|
+
entry.truncated ? /* @__PURE__ */ jsx5("small", { class: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
1511
|
+
/* @__PURE__ */ jsx5(MessageMeta, { entry, adapter })
|
|
1319
1512
|
] });
|
|
1320
1513
|
}
|
|
1321
1514
|
function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
@@ -1327,102 +1520,102 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1327
1520
|
const target = compactToolTarget(presentation.target, workspace);
|
|
1328
1521
|
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
1329
1522
|
const category = presentation.category ?? toolCategory(entry);
|
|
1330
|
-
const summary = /* @__PURE__ */
|
|
1331
|
-
/* @__PURE__ */
|
|
1332
|
-
/* @__PURE__ */
|
|
1333
|
-
target ? /* @__PURE__ */
|
|
1334
|
-
/* @__PURE__ */
|
|
1335
|
-
entry.status === "pending" ? /* @__PURE__ */
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
hasDetail ? /* @__PURE__ */
|
|
1523
|
+
const summary = /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1524
|
+
/* @__PURE__ */ jsx5(ToolIcon, { category }),
|
|
1525
|
+
/* @__PURE__ */ jsx5("strong", { children: toolAction2(entry, category, presentation) }),
|
|
1526
|
+
target ? /* @__PURE__ */ jsx5("code", { class: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
1527
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1528
|
+
entry.status === "pending" ? /* @__PURE__ */ jsx5(PendingElapsed, { now: adapter?.now }) : null,
|
|
1529
|
+
/* @__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 }) }),
|
|
1530
|
+
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14, class: "scui-tool-chevron" }) : null
|
|
1338
1531
|
] });
|
|
1339
|
-
if (!hasDetail) return /* @__PURE__ */
|
|
1340
|
-
return /* @__PURE__ */
|
|
1341
|
-
/* @__PURE__ */
|
|
1342
|
-
/* @__PURE__ */
|
|
1343
|
-
/* @__PURE__ */
|
|
1344
|
-
/* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1346
|
-
presentation.fields.length ? /* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1532
|
+
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 }) });
|
|
1533
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
1534
|
+
/* @__PURE__ */ jsx5("summary", { class: "scui-tool-head", children: summary }),
|
|
1535
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-tool-detail", children: [
|
|
1536
|
+
/* @__PURE__ */ jsx5(ToolMetrics, { presentation }),
|
|
1537
|
+
/* @__PURE__ */ jsx5(ToolStack, { tools: presentation.tools ?? [] }),
|
|
1538
|
+
/* @__PURE__ */ jsx5(ToolPreview, { presentation, entry }),
|
|
1539
|
+
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", { class: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1540
|
+
/* @__PURE__ */ jsx5("dt", { children: field.label }),
|
|
1541
|
+
/* @__PURE__ */ jsx5("dd", { children: field.value })
|
|
1349
1542
|
] }, field.label)) }) : null,
|
|
1350
|
-
/* @__PURE__ */
|
|
1351
|
-
/* @__PURE__ */
|
|
1543
|
+
/* @__PURE__ */ jsx5(ToolActions, { presentation, adapter }),
|
|
1544
|
+
/* @__PURE__ */ jsx5(TechnicalDetails, { entry })
|
|
1352
1545
|
] })
|
|
1353
1546
|
] });
|
|
1354
1547
|
}
|
|
1355
1548
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1356
|
-
if (entries.length === 1) return /* @__PURE__ */
|
|
1549
|
+
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 }) });
|
|
1357
1550
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1358
1551
|
const [open, setOpen] = useState2(active);
|
|
1359
1552
|
const id = useId();
|
|
1360
1553
|
useEffect3(() => {
|
|
1361
1554
|
if (active) setOpen(true);
|
|
1362
1555
|
}, [active]);
|
|
1363
|
-
return /* @__PURE__ */
|
|
1364
|
-
/* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
/* @__PURE__ */
|
|
1367
|
-
/* @__PURE__ */
|
|
1368
|
-
/* @__PURE__ */
|
|
1556
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-activity", children: [
|
|
1557
|
+
/* @__PURE__ */ jsxs4("button", { class: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1558
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14 }) }),
|
|
1559
|
+
/* @__PURE__ */ jsx5("strong", { children: activitySummary(entries) }),
|
|
1560
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1561
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1369
1562
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1370
1563
|
"/",
|
|
1371
1564
|
entries.length
|
|
1372
1565
|
] })
|
|
1373
1566
|
] }),
|
|
1374
|
-
open ? /* @__PURE__ */
|
|
1567
|
+
open ? /* @__PURE__ */ jsx5("div", { id, children: entries.map((entry) => /* @__PURE__ */ jsx5(ToolRow, { entry, workspace: state.workspace, adapter }, entry.id)) }) : null
|
|
1375
1568
|
] });
|
|
1376
1569
|
}
|
|
1377
1570
|
function TaskPlan({ plan }) {
|
|
1378
1571
|
if (!plan.items.length) return null;
|
|
1379
1572
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1380
|
-
return /* @__PURE__ */
|
|
1381
|
-
/* @__PURE__ */
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
/* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-plan", children: [
|
|
1574
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1575
|
+
/* @__PURE__ */ jsx5("span", { children: "Plan" }),
|
|
1576
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1384
1577
|
complete,
|
|
1385
1578
|
"/",
|
|
1386
1579
|
plan.items.length
|
|
1387
1580
|
] })
|
|
1388
1581
|
] }),
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1582
|
+
/* @__PURE__ */ jsx5("ol", { tabIndex: 0, "aria-label": "Task plan steps", children: plan.items.map((item) => /* @__PURE__ */ jsxs4("li", { "data-status": item.status, children: [
|
|
1583
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1391
1584
|
" ",
|
|
1392
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx5("span", { children: item.title })
|
|
1393
1586
|
] }, item.id)) })
|
|
1394
1587
|
] });
|
|
1395
1588
|
}
|
|
1396
1589
|
function SessionDetails({ semantics }) {
|
|
1397
1590
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1398
|
-
return /* @__PURE__ */
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
semantics.fidelity ? /* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
/* @__PURE__ */
|
|
1591
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-details", children: [
|
|
1592
|
+
/* @__PURE__ */ jsx5("summary", { children: "Session details" }),
|
|
1593
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1594
|
+
semantics.fidelity ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1595
|
+
/* @__PURE__ */ jsx5("strong", { children: "Fidelity" }),
|
|
1596
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.fidelity.replaceAll("_", " ") })
|
|
1404
1597
|
] }) : null,
|
|
1405
|
-
/* @__PURE__ */
|
|
1406
|
-
/* @__PURE__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1598
|
+
/* @__PURE__ */ jsxs4("p", { children: [
|
|
1599
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native records" }),
|
|
1600
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.rawRecords })
|
|
1408
1601
|
] }),
|
|
1409
|
-
semantics.residueCount ? /* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1602
|
+
semantics.residueCount ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1603
|
+
/* @__PURE__ */ jsx5("strong", { children: "Residue" }),
|
|
1604
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1412
1605
|
semantics.residueCount,
|
|
1413
1606
|
" retained"
|
|
1414
1607
|
] })
|
|
1415
1608
|
] }) : null,
|
|
1416
|
-
semantics.parseErrors ? /* @__PURE__ */
|
|
1417
|
-
/* @__PURE__ */
|
|
1418
|
-
/* @__PURE__ */
|
|
1609
|
+
semantics.parseErrors ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1610
|
+
/* @__PURE__ */ jsx5("strong", { children: "Parse diagnostics" }),
|
|
1611
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.parseErrors })
|
|
1419
1612
|
] }) : null,
|
|
1420
|
-
semantics.subagents.map((agent) => /* @__PURE__ */
|
|
1421
|
-
/* @__PURE__ */
|
|
1613
|
+
semantics.subagents.map((agent) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1614
|
+
/* @__PURE__ */ jsxs4("strong", { children: [
|
|
1422
1615
|
agent.source,
|
|
1423
1616
|
" subagent"
|
|
1424
1617
|
] }),
|
|
1425
|
-
/* @__PURE__ */
|
|
1618
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1426
1619
|
agent.messages,
|
|
1427
1620
|
" messages \xB7 ",
|
|
1428
1621
|
agent.fidelity.replaceAll("_", " ")
|
|
@@ -1441,7 +1634,7 @@ function ConversationAnnouncements({ state }) {
|
|
|
1441
1634
|
}
|
|
1442
1635
|
previousBusy.current = state.busy;
|
|
1443
1636
|
}, [state.busy, state.error, state.harness]);
|
|
1444
|
-
return /* @__PURE__ */
|
|
1637
|
+
return /* @__PURE__ */ jsx5("span", { class: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1445
1638
|
}
|
|
1446
1639
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1447
1640
|
const scroller = useRef3(null);
|
|
@@ -1473,65 +1666,72 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1473
1666
|
const element = scroller.current;
|
|
1474
1667
|
if (!element) return;
|
|
1475
1668
|
const anchor = earlierAnchor.current;
|
|
1476
|
-
if (anchor
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1669
|
+
if (anchor) {
|
|
1670
|
+
if (state.operation === "loadEarlier") anchor.seenOperation = true;
|
|
1671
|
+
const prepended = state.transcript.length > anchor.entries && state.transcript[0]?.id !== anchor.firstId;
|
|
1672
|
+
if (prepended) {
|
|
1673
|
+
element.scrollTop = anchor.top + (element.scrollHeight - anchor.height);
|
|
1674
|
+
earlierAnchor.current = null;
|
|
1675
|
+
remember({ top: element.scrollTop, atBottom: false });
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
if (state.error || anchor.seenOperation && state.operation !== "loadEarlier") earlierAnchor.current = null;
|
|
1481
1679
|
}
|
|
1482
1680
|
if (!restored.current) {
|
|
1483
1681
|
restored.current = true;
|
|
1484
1682
|
if (remembered.top !== null && !remembered.atBottom) element.scrollTop = remembered.top;
|
|
1485
1683
|
else pin();
|
|
1486
1684
|
} else if (atBottom) pin();
|
|
1487
|
-
}, [memoryKey, state.transcript, state.busy, state.operation, pendingMessage?.text, pendingMessage?.status]);
|
|
1488
|
-
return /* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__PURE__ */
|
|
1685
|
+
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1686
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-conversation-wrap", children: [
|
|
1687
|
+
/* @__PURE__ */ jsx5(ConversationAnnouncements, { state }),
|
|
1688
|
+
/* @__PURE__ */ jsx5("div", { class: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1491
1689
|
const element = event.currentTarget;
|
|
1492
1690
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1493
1691
|
setAtBottom(bottom);
|
|
1494
1692
|
remember({ top: element.scrollTop, atBottom: bottom });
|
|
1495
|
-
}, children: /* @__PURE__ */
|
|
1496
|
-
Before ? /* @__PURE__ */
|
|
1497
|
-
/* @__PURE__ */
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
state.history.hasEarlier ? /* @__PURE__ */
|
|
1693
|
+
}, children: /* @__PURE__ */ jsxs4("div", { children: [
|
|
1694
|
+
Before ? /* @__PURE__ */ jsx5(Before, { state, adapter, value: null }) : null,
|
|
1695
|
+
/* @__PURE__ */ jsx5(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
1696
|
+
/* @__PURE__ */ jsx5(SessionDetails, { semantics: state.semantics }),
|
|
1697
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", { class: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1500
1698
|
const element = scroller.current;
|
|
1501
|
-
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length };
|
|
1699
|
+
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1502
1700
|
setAtBottom(false);
|
|
1503
1701
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1504
1702
|
}, children: "Load earlier messages" }) : null,
|
|
1505
|
-
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */
|
|
1506
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */
|
|
1507
|
-
blocks.map((block, index) => /* @__PURE__ */
|
|
1508
|
-
index === unreadBlock ? /* @__PURE__ */
|
|
1509
|
-
block.kind === "activity" ? /* @__PURE__ */
|
|
1703
|
+
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state }) : null,
|
|
1704
|
+
!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,
|
|
1705
|
+
blocks.map((block, index) => /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1706
|
+
index === unreadBlock ? /* @__PURE__ */ jsx5("div", { class: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx5("span", { children: "New" }) }) : null,
|
|
1707
|
+
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 })
|
|
1510
1708
|
] }, block.id)),
|
|
1511
|
-
pendingMessage ? /* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1709
|
+
pendingMessage ? /* @__PURE__ */ jsxs4("article", { class: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
1710
|
+
/* @__PURE__ */ jsx5(MessageImages, { items: pendingMessage.images }),
|
|
1711
|
+
/* @__PURE__ */ jsx5(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
1712
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: pendingMessage.context }),
|
|
1713
|
+
/* @__PURE__ */ jsxs4("footer", { children: [
|
|
1714
|
+
/* @__PURE__ */ jsx5("small", { children: pendingMessage.status === "failed" ? "Not sent" : "Sending\u2026" }),
|
|
1715
|
+
pendingMessage.status === "failed" ? /* @__PURE__ */ jsxs4("span", { children: [
|
|
1716
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onRetry, children: "Retry" }),
|
|
1717
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onEdit, children: "Edit" })
|
|
1518
1718
|
] }) : null
|
|
1519
1719
|
] })
|
|
1520
1720
|
] }) : null,
|
|
1521
|
-
state.busy ? /* @__PURE__ */
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1526
|
-
/* @__PURE__ */
|
|
1721
|
+
state.busy ? /* @__PURE__ */ jsxs4("div", { class: "scui-working", role: "status", children: [
|
|
1722
|
+
/* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
1723
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1724
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1725
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1726
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1527
1727
|
harnessDisplayName(state.harness),
|
|
1528
1728
|
" is working"
|
|
1529
1729
|
] })
|
|
1530
1730
|
] }) : null,
|
|
1531
|
-
After ? /* @__PURE__ */
|
|
1731
|
+
After ? /* @__PURE__ */ jsx5(After, { state, adapter, value: null }) : null
|
|
1532
1732
|
] }) }),
|
|
1533
|
-
!atBottom ? /* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1733
|
+
!atBottom ? /* @__PURE__ */ jsxs4("button", { class: "scui-latest", type: "button", onClick: pin, children: [
|
|
1734
|
+
/* @__PURE__ */ jsx5(UiIcon, { name: "down", size: 13 }),
|
|
1535
1735
|
" Latest"
|
|
1536
1736
|
] }) : null
|
|
1537
1737
|
] });
|
|
@@ -1539,7 +1739,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1539
1739
|
|
|
1540
1740
|
// src/logo.jsx
|
|
1541
1741
|
import { useEffect as useEffect4 } from "preact/hooks";
|
|
1542
|
-
import { jsx as
|
|
1742
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
1543
1743
|
var LOGOS = {
|
|
1544
1744
|
"claude-code": {
|
|
1545
1745
|
viewBox: "-1 3.5 26 18",
|
|
@@ -1590,30 +1790,30 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
|
1590
1790
|
if (!logo) onMissingLogo?.(id);
|
|
1591
1791
|
}, [id, logo, onMissingLogo]);
|
|
1592
1792
|
if (!logo) return null;
|
|
1593
|
-
return /* @__PURE__ */
|
|
1594
|
-
/* @__PURE__ */
|
|
1595
|
-
activity && activity !== "idle" ? /* @__PURE__ */
|
|
1793
|
+
return /* @__PURE__ */ jsxs5("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
|
|
1794
|
+
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
1795
|
+
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
1596
1796
|
] });
|
|
1597
1797
|
}
|
|
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,40 +2297,40 @@ 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
|
|
|
2074
2328
|
// src/embed.jsx
|
|
2075
|
-
import { jsx as
|
|
2329
|
+
import { jsx as jsx9 } from "preact/jsx-runtime";
|
|
2076
2330
|
function mountSupercodeMessenger(element, options) {
|
|
2077
2331
|
if (!(element instanceof Element)) throw new TypeError("mountSupercodeMessenger requires an Element");
|
|
2078
2332
|
let state = options.state;
|
|
2079
|
-
const draw = () => render(/* @__PURE__ */
|
|
2333
|
+
const draw = () => render(/* @__PURE__ */ jsx9(SupercodeMessenger, { ...options, state }), element);
|
|
2080
2334
|
options.adapter.onIntent({ action: "mounted" });
|
|
2081
2335
|
draw();
|
|
2082
2336
|
return {
|