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