@volter-ai-dev/supercode-ui 0.1.18 → 0.1.20
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 +6 -0
- package/components.mjs +447 -347
- package/composer.mjs +104 -33
- package/controller.mjs +2 -2
- package/conversation.mjs +14 -7
- package/core.mjs +1 -1
- package/embed.mjs +449 -349
- package/icon.mjs +1 -0
- package/index.d.ts +7 -4
- package/messenger.mjs +447 -347
- package/package.json +1 -1
- package/sessions.mjs +3 -2
- package/styles.css +3 -1
package/components.mjs
CHANGED
|
@@ -681,7 +681,7 @@ function sessionActivity(state, row) {
|
|
|
681
681
|
function filterSessions(rows, query) {
|
|
682
682
|
const needle = query.trim().toLocaleLowerCase();
|
|
683
683
|
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)));
|
|
684
|
+
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
685
|
}
|
|
686
686
|
function groupConversation(entries) {
|
|
687
687
|
const blocks = [];
|
|
@@ -758,6 +758,7 @@ function boundedSet(map, key, value) {
|
|
|
758
758
|
// src/icon.jsx
|
|
759
759
|
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
760
760
|
var ICONS = {
|
|
761
|
+
attach: () => /* @__PURE__ */ jsx("path", { d: "M6.25 9.75 10.6 5.4a2.1 2.1 0 0 1 2.97 2.97l-5.4 5.4a3.3 3.3 0 0 1-4.67-4.66l5.52-5.52" }),
|
|
761
762
|
back: () => /* @__PURE__ */ jsx("path", { d: "m11.5 4.5-4.5 4.5 4.5 4.5" }),
|
|
762
763
|
check: () => /* @__PURE__ */ jsx("path", { d: "m4 9 3.25 3.25L14 5.5" }),
|
|
763
764
|
chevron: () => /* @__PURE__ */ jsx("path", { d: "m7 4.5 4.5 4.5L7 13.5" }),
|
|
@@ -798,6 +799,44 @@ function UiIcon({ name, size = 16, class: className = "" }) {
|
|
|
798
799
|
return /* @__PURE__ */ jsx("svg", { class: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Glyph, {}) });
|
|
799
800
|
}
|
|
800
801
|
|
|
802
|
+
// src/context.jsx
|
|
803
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
804
|
+
var MAX_CONTEXT_ITEMS = 32;
|
|
805
|
+
function normalizeContext(value) {
|
|
806
|
+
return (Array.isArray(value) ? value : value ? [value] : []).flatMap((item) => {
|
|
807
|
+
if (!item || typeof item.label !== "string" || typeof item.detail !== "string") return [];
|
|
808
|
+
const label = item.label.trim().slice(0, 200);
|
|
809
|
+
const detail = item.detail.slice(0, 2e4);
|
|
810
|
+
if (!label || !detail) return [];
|
|
811
|
+
return [{
|
|
812
|
+
...typeof item.id === "string" && item.id ? { id: item.id.slice(0, 2e3) } : {},
|
|
813
|
+
...typeof item.kind === "string" && item.kind ? { kind: item.kind.slice(0, 100) } : {},
|
|
814
|
+
label,
|
|
815
|
+
detail
|
|
816
|
+
}];
|
|
817
|
+
}).slice(0, MAX_CONTEXT_ITEMS);
|
|
818
|
+
}
|
|
819
|
+
function mergeContext(current, picked) {
|
|
820
|
+
const next = [...current];
|
|
821
|
+
const seen = new Set(current.map((item) => item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`));
|
|
822
|
+
for (const item of normalizeContext(picked)) {
|
|
823
|
+
const key = item.id ? `id:${item.id}` : `value:${item.kind ?? ""}\0${item.label}\0${item.detail}`;
|
|
824
|
+
if (seen.has(key)) continue;
|
|
825
|
+
seen.add(key);
|
|
826
|
+
next.push(item);
|
|
827
|
+
if (next.length === MAX_CONTEXT_ITEMS) break;
|
|
828
|
+
}
|
|
829
|
+
return next;
|
|
830
|
+
}
|
|
831
|
+
function ContextTray({ items, onRemove }) {
|
|
832
|
+
if (!items.length) return null;
|
|
833
|
+
return /* @__PURE__ */ jsx2("div", { class: "scui-compose-context", "aria-label": "Attached context", children: items.map((item, index) => /* @__PURE__ */ jsxs2("span", { children: [
|
|
834
|
+
/* @__PURE__ */ jsx2(UiIcon, { name: "attach", size: 12 }),
|
|
835
|
+
/* @__PURE__ */ jsx2("strong", { children: item.label }),
|
|
836
|
+
/* @__PURE__ */ jsx2("button", { type: "button", "aria-label": `Remove context ${item.label}`, onClick: () => onRemove(index), children: /* @__PURE__ */ jsx2(UiIcon, { name: "close", size: 12 }) })
|
|
837
|
+
] }, item.id ?? `${item.label}:${index}`)) });
|
|
838
|
+
}
|
|
839
|
+
|
|
801
840
|
// src/textarea.js
|
|
802
841
|
import { useLayoutEffect } from "preact/hooks";
|
|
803
842
|
function useAutosizeTextarea(ref, value) {
|
|
@@ -813,7 +852,7 @@ function useAutosizeTextarea(ref, value) {
|
|
|
813
852
|
}
|
|
814
853
|
|
|
815
854
|
// src/composer.jsx
|
|
816
|
-
import { jsx as
|
|
855
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
|
|
817
856
|
var composerMemory = /* @__PURE__ */ new Map();
|
|
818
857
|
function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
819
858
|
if (state.mode !== "mirror" || state.canSend) return null;
|
|
@@ -823,29 +862,32 @@ function ContinuationBar({ state, adapter, labels = DEFAULT_LABELS }) {
|
|
|
823
862
|
const resume = canContinueHere(state);
|
|
824
863
|
const join = state.canAttach;
|
|
825
864
|
const branch = state.canBranch;
|
|
826
|
-
if (!resume && !join && !branch) return /* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
865
|
+
if (!resume && !join && !branch) return /* @__PURE__ */ jsx3("div", { class: "scui-continuation", children: /* @__PURE__ */ jsxs3("span", { children: [
|
|
866
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
867
|
+
/* @__PURE__ */ jsx3("small", { children: "This session cannot be continued by an available harness." })
|
|
829
868
|
] }) });
|
|
830
|
-
return /* @__PURE__ */
|
|
831
|
-
/* @__PURE__ */
|
|
832
|
-
/* @__PURE__ */
|
|
833
|
-
/* @__PURE__ */
|
|
869
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-continuation", children: [
|
|
870
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
871
|
+
/* @__PURE__ */ jsx3("strong", { children: activeElsewhere ? "Active elsewhere" : "Read-only" }),
|
|
872
|
+
/* @__PURE__ */ jsx3("small", { children: join ? "Join the proven live runtime without taking it over." : resume ? `Resume this ${harnessDisplayName(state.harness)} session here.` : "Start an independent continuation." })
|
|
834
873
|
] }),
|
|
835
|
-
/* @__PURE__ */
|
|
874
|
+
/* @__PURE__ */ jsx3("button", { type: "button", disabled: Boolean(state.operation), onClick: () => adapter.onIntent(join ? { action: "join" } : resume ? { action: "resume" } : { action: "branch" }), children: join ? labels.joinLive : resume ? labels.continueHere : labels.forkHere })
|
|
836
875
|
] });
|
|
837
876
|
}
|
|
838
877
|
function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pendingStatus = null, restoreDraft = null, onPending, onDraftRestored }) {
|
|
839
|
-
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, queue: [] };
|
|
878
|
+
const remembered = composerMemory.get(memoryKey) ?? { draft: state.savedDraft, context: [], queue: [] };
|
|
840
879
|
const [draft, setDraft] = useState(remembered.draft);
|
|
880
|
+
const [context, setContext] = useState(remembered.context);
|
|
841
881
|
const [queue, setQueue] = useState(remembered.queue);
|
|
842
882
|
const [dispatching, setDispatching] = useState(false);
|
|
883
|
+
const [picking, setPicking] = useState(false);
|
|
884
|
+
const [pickerError, setPickerError] = useState(null);
|
|
843
885
|
const textarea = useRef(null);
|
|
844
886
|
useAutosizeTextarea(textarea, draft);
|
|
845
|
-
const remember = (nextDraft, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, queue: nextQueue });
|
|
887
|
+
const remember = (nextDraft, nextContext, nextQueue) => boundedSet(composerMemory, memoryKey, { draft: nextDraft, context: nextContext, queue: nextQueue });
|
|
846
888
|
const updateQueue = (update) => setQueue((items) => {
|
|
847
889
|
const next = update(items);
|
|
848
|
-
remember(draft, next);
|
|
890
|
+
remember(draft, context, next);
|
|
849
891
|
return next;
|
|
850
892
|
});
|
|
851
893
|
const queueBlocked = state.busy || pendingStatus !== null || dispatching;
|
|
@@ -855,9 +897,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
855
897
|
const [next, ...rest] = queue;
|
|
856
898
|
setDispatching(true);
|
|
857
899
|
setQueue(rest);
|
|
858
|
-
remember(draft, rest);
|
|
859
|
-
onPending?.(next);
|
|
860
|
-
adapter.onIntent({ action: "send", text: next });
|
|
900
|
+
remember(draft, context, rest);
|
|
901
|
+
onPending?.(next.text, next.context);
|
|
902
|
+
adapter.onIntent({ action: "send", text: next.text, ...next.context.length ? { context: next.context } : {} });
|
|
861
903
|
}
|
|
862
904
|
}, [adapter, draft, memoryKey, onPending, queue, queueBlocked, state.canSend]);
|
|
863
905
|
useEffect(() => {
|
|
@@ -869,7 +911,9 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
869
911
|
useEffect(() => {
|
|
870
912
|
if (!restoreDraft) return;
|
|
871
913
|
setDraft(restoreDraft.text);
|
|
872
|
-
|
|
914
|
+
const restoredContext = normalizeContext(restoreDraft.context);
|
|
915
|
+
setContext(restoredContext);
|
|
916
|
+
remember(restoreDraft.text, restoredContext, queue);
|
|
873
917
|
textarea.current?.focus({ preventScroll: true });
|
|
874
918
|
onDraftRestored?.(restoreDraft.id);
|
|
875
919
|
}, [onDraftRestored, restoreDraft?.id]);
|
|
@@ -877,43 +921,70 @@ function Composer({ state, adapter, labels = DEFAULT_LABELS, memoryKey = state.a
|
|
|
877
921
|
const timer = setTimeout(() => adapter.onIntent({ action: "draft", text: draft }), 250);
|
|
878
922
|
return () => clearTimeout(timer);
|
|
879
923
|
}, [adapter, draft]);
|
|
924
|
+
const pickContext = () => {
|
|
925
|
+
if (!adapter.pickContext || state.mode !== "control" || picking || context.length >= MAX_CONTEXT_ITEMS) return;
|
|
926
|
+
setPicking(true);
|
|
927
|
+
setPickerError(null);
|
|
928
|
+
Promise.resolve().then(() => adapter.pickContext()).then((picked) => {
|
|
929
|
+
setContext((current) => {
|
|
930
|
+
const next = mergeContext(current, picked);
|
|
931
|
+
remember(draft, next, queue);
|
|
932
|
+
return next;
|
|
933
|
+
});
|
|
934
|
+
}, (error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
935
|
+
};
|
|
880
936
|
const send = () => {
|
|
881
937
|
const text = draft.trim();
|
|
882
938
|
if (!text) return;
|
|
883
|
-
|
|
939
|
+
const message = { text, context };
|
|
940
|
+
if (queuesNewMessage) updateQueue((items) => [...items, message]);
|
|
884
941
|
else if (state.canSend) {
|
|
885
942
|
if (onPending) setDispatching(true);
|
|
886
|
-
onPending?.(text);
|
|
887
|
-
adapter.onIntent({ action: "send", text });
|
|
943
|
+
onPending?.(text, context);
|
|
944
|
+
adapter.onIntent({ action: "send", text, ...context.length ? { context } : {} });
|
|
888
945
|
} else return;
|
|
889
946
|
setDraft("");
|
|
890
|
-
|
|
947
|
+
setContext([]);
|
|
948
|
+
remember("", [], queuesNewMessage ? [...queue, message] : queue);
|
|
891
949
|
};
|
|
892
|
-
return /* @__PURE__ */
|
|
893
|
-
queue.length ? /* @__PURE__ */
|
|
894
|
-
/* @__PURE__ */
|
|
950
|
+
return /* @__PURE__ */ jsxs3("div", { class: "scui-compose", children: [
|
|
951
|
+
queue.length ? /* @__PURE__ */ jsxs3("div", { class: "scui-queue", children: [
|
|
952
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
895
953
|
queue.length,
|
|
896
954
|
" queued"
|
|
897
955
|
] }),
|
|
898
|
-
queue.map((item, index) => /* @__PURE__ */
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
956
|
+
queue.map((item, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
957
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
958
|
+
item.text,
|
|
959
|
+
item.context.length ? /* @__PURE__ */ jsxs3("small", { children: [
|
|
960
|
+
item.context.length,
|
|
961
|
+
" attached"
|
|
962
|
+
] }) : null
|
|
963
|
+
] }),
|
|
964
|
+
/* @__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 }) })
|
|
965
|
+
] }, `${index}:${item.text}`))
|
|
902
966
|
] }) : null,
|
|
903
|
-
/* @__PURE__ */
|
|
904
|
-
|
|
967
|
+
/* @__PURE__ */ jsx3(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
968
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
969
|
+
remember(draft, next, queue);
|
|
970
|
+
return next;
|
|
971
|
+
}) }),
|
|
972
|
+
pickerError ? /* @__PURE__ */ jsx3("small", { class: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
973
|
+
/* @__PURE__ */ jsxs3("div", { class: "scui-envelope", children: [
|
|
974
|
+
adapter.pickContext && state.mode === "control" ? /* @__PURE__ */ jsx3("button", { class: "scui-attach", type: "button", "aria-label": "Attach context", disabled: picking || context.length >= MAX_CONTEXT_ITEMS, onClick: pickContext, children: picking ? /* @__PURE__ */ jsx3("i", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx3(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
975
|
+
/* @__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, onInput: (event) => {
|
|
905
976
|
const value = event.currentTarget.value;
|
|
906
977
|
setDraft(value);
|
|
907
|
-
remember(value, queue);
|
|
978
|
+
remember(value, context, queue);
|
|
908
979
|
}, onKeyDown: (event) => {
|
|
909
980
|
if (isSendKey(event)) {
|
|
910
981
|
event.preventDefault();
|
|
911
982
|
send();
|
|
912
983
|
}
|
|
913
984
|
} }),
|
|
914
|
-
/* @__PURE__ */
|
|
915
|
-
state.busy ? /* @__PURE__ */
|
|
916
|
-
/* @__PURE__ */
|
|
985
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
986
|
+
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,
|
|
987
|
+
/* @__PURE__ */ jsx3("button", { class: "scui-send", type: "button", "aria-label": queuesNewMessage ? "Queue message" : "Send message", disabled: !draft.trim() || !queuesNewMessage && !state.canSend, onClick: send, children: /* @__PURE__ */ jsx3(UiIcon, { name: queuesNewMessage ? "plus" : "send", size: 17 }) })
|
|
917
988
|
] })
|
|
918
989
|
] })
|
|
919
990
|
] });
|
|
@@ -926,7 +997,7 @@ import { useEffect as useEffect3, useId, useLayoutEffect as useLayoutEffect2, us
|
|
|
926
997
|
// src/markdown.jsx
|
|
927
998
|
import MarkdownIt from "markdown-it";
|
|
928
999
|
import { useEffect as useEffect2, useMemo, useRef as useRef2 } from "preact/hooks";
|
|
929
|
-
import { jsx as
|
|
1000
|
+
import { jsx as jsx4 } from "preact/jsx-runtime";
|
|
930
1001
|
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
931
1002
|
var LANGUAGE_LABELS = {
|
|
932
1003
|
bash: "Shell",
|
|
@@ -1013,11 +1084,11 @@ function Markdown({ value, copyText }) {
|
|
|
1013
1084
|
}, 1500);
|
|
1014
1085
|
resets.current.set(button, timer);
|
|
1015
1086
|
};
|
|
1016
|
-
return /* @__PURE__ */
|
|
1087
|
+
return /* @__PURE__ */ jsx4("div", { class: "scui-markdown", "data-copyable": Boolean(copyText), onClick: copyCode, dangerouslySetInnerHTML: { __html: html } });
|
|
1017
1088
|
}
|
|
1018
1089
|
|
|
1019
1090
|
// src/conversation.jsx
|
|
1020
|
-
import { Fragment as Fragment3, jsx as
|
|
1091
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
|
|
1021
1092
|
function LoadingStatus({ state, compact = false }) {
|
|
1022
1093
|
const copy = {
|
|
1023
1094
|
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
@@ -1025,43 +1096,43 @@ function LoadingStatus({ state, compact = false }) {
|
|
|
1025
1096
|
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
1026
1097
|
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
1027
1098
|
}[state.startup];
|
|
1028
|
-
return /* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
1099
|
+
return /* @__PURE__ */ jsxs4("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
1100
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx5("i", {}) }),
|
|
1101
|
+
/* @__PURE__ */ jsxs4("span", { class: "scui-loading-copy", children: [
|
|
1102
|
+
/* @__PURE__ */ jsx5("strong", { children: copy[0] }),
|
|
1103
|
+
/* @__PURE__ */ jsx5("small", { children: copy[1] })
|
|
1033
1104
|
] }),
|
|
1034
|
-
/* @__PURE__ */
|
|
1105
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx5("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
|
|
1035
1106
|
] });
|
|
1036
1107
|
}
|
|
1037
1108
|
function RequestCard({ entry, adapter, canRespond }) {
|
|
1038
1109
|
const request = entry.request;
|
|
1039
1110
|
if (!request) return null;
|
|
1040
1111
|
if (request.status === "responded") {
|
|
1041
|
-
return /* @__PURE__ */
|
|
1112
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-request-done", children: [
|
|
1042
1113
|
"\u2713 Request answered \xB7 ",
|
|
1043
1114
|
request.resolution?.name ?? request.requestKind
|
|
1044
1115
|
] });
|
|
1045
1116
|
}
|
|
1046
|
-
return /* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
request.options.map((option) => /* @__PURE__ */
|
|
1051
|
-
request.cancellable ? /* @__PURE__ */
|
|
1117
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-request", role: "alert", "aria-label": `${request.requestKind} needs input`, children: [
|
|
1118
|
+
/* @__PURE__ */ jsx5("strong", { children: "Agent needs input" }),
|
|
1119
|
+
/* @__PURE__ */ jsx5(Markdown, { value: request.payloadText || entry.text, copyText: adapter?.copyText }),
|
|
1120
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-request-actions", children: [
|
|
1121
|
+
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)),
|
|
1122
|
+
request.cancellable ? /* @__PURE__ */ jsx5("button", { type: "button", disabled: !canRespond, onClick: () => adapter.onIntent({ action: "respond", requestId: request.requestId, optionId: null }), children: "Cancel" }) : null
|
|
1052
1123
|
] })
|
|
1053
1124
|
] });
|
|
1054
1125
|
}
|
|
1055
1126
|
function ContextDisclosure({ context }) {
|
|
1056
1127
|
if (!context?.length) return null;
|
|
1057
|
-
return /* @__PURE__ */
|
|
1058
|
-
/* @__PURE__ */
|
|
1128
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-context", children: [
|
|
1129
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1059
1130
|
"Context \xB7 ",
|
|
1060
1131
|
context.length
|
|
1061
1132
|
] }),
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1133
|
+
/* @__PURE__ */ jsx5("div", { children: context.map((item, index) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1134
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1135
|
+
/* @__PURE__ */ jsx5("span", { children: item.detail })
|
|
1065
1136
|
] }, item.id ?? index)) })
|
|
1066
1137
|
] });
|
|
1067
1138
|
}
|
|
@@ -1083,46 +1154,46 @@ function MessageMeta({ entry, adapter }) {
|
|
|
1083
1154
|
reset.current = setTimeout(() => setCopyState2("idle"), 1500);
|
|
1084
1155
|
};
|
|
1085
1156
|
const copyLabel = copyState === "copied" ? "Message copied" : copyState === "failed" ? "Copy failed \xB7 retry" : "Copy message";
|
|
1086
|
-
return /* @__PURE__ */
|
|
1087
|
-
validDate ? /* @__PURE__ */
|
|
1088
|
-
adapter?.copyText && entry.text ? /* @__PURE__ */
|
|
1157
|
+
return /* @__PURE__ */ jsxs4("footer", { class: "scui-message-meta", children: [
|
|
1158
|
+
validDate ? /* @__PURE__ */ jsx5("time", { dateTime: validDate.toISOString(), title: validDate.toLocaleString(), children: validDate.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) }) : null,
|
|
1159
|
+
adapter?.copyText && entry.text ? /* @__PURE__ */ jsx5("button", { type: "button", "aria-label": copyLabel, title: copyLabel, onClick: copy, "data-status": copyState, children: /* @__PURE__ */ jsx5(UiIcon, { name: "copy", size: 13 }) }) : null
|
|
1089
1160
|
] });
|
|
1090
1161
|
}
|
|
1091
1162
|
var TOOL_ICONS = {
|
|
1092
|
-
read: () => /* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1163
|
+
read: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1164
|
+
/* @__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" }),
|
|
1165
|
+
/* @__PURE__ */ jsx5("path", { d: "M12 2.9v3h2.85M6 9h6M6 12h4" })
|
|
1095
1166
|
] }),
|
|
1096
|
-
search: () => /* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1167
|
+
search: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1168
|
+
/* @__PURE__ */ jsx5("circle", { cx: "8", cy: "8", r: "4.5" }),
|
|
1169
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.5 11.5 3 3" })
|
|
1099
1170
|
] }),
|
|
1100
|
-
edit: () => /* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1102
|
-
/* @__PURE__ */
|
|
1171
|
+
edit: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1172
|
+
/* @__PURE__ */ jsx5("path", { d: "m11.75 3.25 3 3-8.5 8.5-3.75.75.75-3.75 8.5-8.5Z" }),
|
|
1173
|
+
/* @__PURE__ */ jsx5("path", { d: "m10 5 3 3" })
|
|
1103
1174
|
] }),
|
|
1104
|
-
command: () => /* @__PURE__ */
|
|
1105
|
-
test: () => /* @__PURE__ */
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1175
|
+
command: () => /* @__PURE__ */ jsx5(Fragment3, { children: /* @__PURE__ */ jsx5("path", { d: "m3 5 3 3-3 3M8 12h6" }) }),
|
|
1176
|
+
test: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1177
|
+
/* @__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" }),
|
|
1178
|
+
/* @__PURE__ */ jsx5("path", { d: "M5 2.5h8" })
|
|
1108
1179
|
] }),
|
|
1109
|
-
web: () => /* @__PURE__ */
|
|
1110
|
-
/* @__PURE__ */
|
|
1111
|
-
/* @__PURE__ */
|
|
1180
|
+
web: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1181
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "6.5" }),
|
|
1182
|
+
/* @__PURE__ */ jsx5("path", { d: "M2.75 9h12.5M9 2.5c2 1.8 3 4 3 6.5s-1 4.7-3 6.5c-2-1.8-3-4-3-6.5s1-4.7 3-6.5Z" })
|
|
1112
1183
|
] }),
|
|
1113
|
-
agent: () => /* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1184
|
+
agent: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1185
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "6", r: "2.5" }),
|
|
1186
|
+
/* @__PURE__ */ jsx5("path", { d: "M4 15c.4-3 2-4.5 5-4.5s4.6 1.5 5 4.5" })
|
|
1116
1187
|
] }),
|
|
1117
|
-
plan: () => /* @__PURE__ */
|
|
1118
|
-
other: () => /* @__PURE__ */
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
/* @__PURE__ */
|
|
1188
|
+
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" }) }),
|
|
1189
|
+
other: () => /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1190
|
+
/* @__PURE__ */ jsx5("path", { d: "M9 2.5v3M9 12.5v3M2.5 9h3M12.5 9h3" }),
|
|
1191
|
+
/* @__PURE__ */ jsx5("circle", { cx: "9", cy: "9", r: "3.5" })
|
|
1121
1192
|
] })
|
|
1122
1193
|
};
|
|
1123
1194
|
function ToolIcon({ category }) {
|
|
1124
1195
|
const Glyph = TOOL_ICONS[category] ?? TOOL_ICONS.other;
|
|
1125
|
-
return /* @__PURE__ */
|
|
1196
|
+
return /* @__PURE__ */ jsx5("svg", { class: "scui-tool-icon", viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.35", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx5(Glyph, {}) });
|
|
1126
1197
|
}
|
|
1127
1198
|
function toolAction2(entry, category, presentation) {
|
|
1128
1199
|
if (presentation?.action) return presentation.action;
|
|
@@ -1177,7 +1248,7 @@ function ToolMetrics({ presentation }) {
|
|
|
1177
1248
|
presentation.exitCode === null ? "" : `exit ${presentation.exitCode}`,
|
|
1178
1249
|
formatDuration(presentation.durationMs)
|
|
1179
1250
|
].filter(Boolean);
|
|
1180
|
-
return metrics.length ? /* @__PURE__ */
|
|
1251
|
+
return metrics.length ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-metrics", children: metrics.map((metric) => /* @__PURE__ */ jsx5("span", { children: metric }, metric)) }) : null;
|
|
1181
1252
|
}
|
|
1182
1253
|
function PendingElapsed({ now }) {
|
|
1183
1254
|
const clock = now ?? Date.now;
|
|
@@ -1187,74 +1258,74 @@ function PendingElapsed({ now }) {
|
|
|
1187
1258
|
const timer = setInterval(() => setElapsed(Math.max(0, clock() - started.current)), 1e3);
|
|
1188
1259
|
return () => clearInterval(timer);
|
|
1189
1260
|
}, [clock]);
|
|
1190
|
-
return /* @__PURE__ */
|
|
1261
|
+
return /* @__PURE__ */ jsx5("small", { class: "scui-tool-elapsed", children: elapsed < 1e3 ? "now" : formatDuration(elapsed) });
|
|
1191
1262
|
}
|
|
1192
1263
|
function LinePreview({ value, kind }) {
|
|
1193
1264
|
if (!value) return null;
|
|
1194
|
-
return /* @__PURE__ */
|
|
1265
|
+
return /* @__PURE__ */ jsx5("ol", { class: "scui-code-preview", "data-kind": kind, children: stripAnsi(value).split("\n").map((line, index) => {
|
|
1195
1266
|
const tone = kind === "diff" ? line.startsWith("+") && !line.startsWith("+++") ? "add" : line.startsWith("-") && !line.startsWith("---") ? "remove" : line.startsWith("@@") ? "hunk" : "plain" : "plain";
|
|
1196
|
-
return /* @__PURE__ */
|
|
1197
|
-
/* @__PURE__ */
|
|
1198
|
-
/* @__PURE__ */
|
|
1267
|
+
return /* @__PURE__ */ jsxs4("li", { "data-tone": tone, children: [
|
|
1268
|
+
/* @__PURE__ */ jsx5("span", { children: index + 1 }),
|
|
1269
|
+
/* @__PURE__ */ jsx5("code", { children: line || " " })
|
|
1199
1270
|
] }, index);
|
|
1200
1271
|
}) });
|
|
1201
1272
|
}
|
|
1202
1273
|
function TerminalPreview({ presentation, pending, failed }) {
|
|
1203
|
-
return /* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1274
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-terminal", children: [
|
|
1275
|
+
/* @__PURE__ */ jsxs4("header", { children: [
|
|
1276
|
+
/* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", children: [
|
|
1277
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1278
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1279
|
+
/* @__PURE__ */ jsx5("i", {})
|
|
1209
1280
|
] }),
|
|
1210
|
-
/* @__PURE__ */
|
|
1281
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.command ? `$ ${presentation.command}` : "Terminal" })
|
|
1211
1282
|
] }),
|
|
1212
|
-
presentation.preview ? /* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1283
|
+
presentation.preview ? /* @__PURE__ */ jsx5("pre", { "data-error": failed, children: stripAnsi(presentation.preview) }) : pending ? /* @__PURE__ */ jsxs4("div", { class: "scui-terminal-wait", children: [
|
|
1284
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1214
1285
|
" Waiting for output"
|
|
1215
|
-
] }) : /* @__PURE__ */
|
|
1286
|
+
] }) : /* @__PURE__ */ jsx5("div", { class: "scui-terminal-empty", children: "No output" })
|
|
1216
1287
|
] });
|
|
1217
1288
|
}
|
|
1218
1289
|
function SearchPreview({ presentation }) {
|
|
1219
1290
|
const lines = stripAnsi(presentation.preview).split("\n").filter(Boolean);
|
|
1220
|
-
return /* @__PURE__ */
|
|
1221
|
-
presentation.query ? /* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
/* @__PURE__ */
|
|
1291
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-search-preview", children: [
|
|
1292
|
+
presentation.query ? /* @__PURE__ */ jsxs4("header", { children: [
|
|
1293
|
+
/* @__PURE__ */ jsx5("span", { children: "Search" }),
|
|
1294
|
+
/* @__PURE__ */ jsx5("code", { children: presentation.query })
|
|
1224
1295
|
] }) : null,
|
|
1225
|
-
lines.length ? /* @__PURE__ */
|
|
1296
|
+
lines.length ? /* @__PURE__ */ jsx5("ol", { children: lines.map((line, index) => {
|
|
1226
1297
|
const match = /^(.*?):(\d+)(?::(\d+))?:(.*)$/.exec(line);
|
|
1227
|
-
return /* @__PURE__ */
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1298
|
+
return /* @__PURE__ */ jsx5("li", { children: match ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1299
|
+
/* @__PURE__ */ jsx5("code", { children: match[1] }),
|
|
1300
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1230
1301
|
match[2],
|
|
1231
1302
|
match[3] ? `:${match[3]}` : ""
|
|
1232
1303
|
] }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
] }) : /* @__PURE__ */
|
|
1235
|
-
}) }) : /* @__PURE__ */
|
|
1304
|
+
/* @__PURE__ */ jsx5("span", { children: match[4] })
|
|
1305
|
+
] }) : /* @__PURE__ */ jsx5("span", { children: line }) }, index);
|
|
1306
|
+
}) }) : /* @__PURE__ */ jsx5("p", { children: "No textual results" })
|
|
1236
1307
|
] });
|
|
1237
1308
|
}
|
|
1238
1309
|
function ToolPreview({ presentation, entry }) {
|
|
1239
1310
|
const pending = entry.status === "pending";
|
|
1240
1311
|
const failed = entry.status === "error";
|
|
1241
|
-
if (presentation.detail === "terminal") return /* @__PURE__ */
|
|
1242
|
-
if (presentation.detail === "diff") return presentation.preview ? /* @__PURE__ */
|
|
1243
|
-
if (presentation.detail === "file") return presentation.preview ? /* @__PURE__ */
|
|
1244
|
-
if (presentation.detail === "matches") return /* @__PURE__ */
|
|
1245
|
-
if (presentation.detail === "web") return /* @__PURE__ */
|
|
1246
|
-
presentation.url ? /* @__PURE__ */
|
|
1247
|
-
presentation.preview ? /* @__PURE__ */
|
|
1312
|
+
if (presentation.detail === "terminal") return /* @__PURE__ */ jsx5(TerminalPreview, { presentation, pending, failed });
|
|
1313
|
+
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" });
|
|
1314
|
+
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" });
|
|
1315
|
+
if (presentation.detail === "matches") return /* @__PURE__ */ jsx5(SearchPreview, { presentation });
|
|
1316
|
+
if (presentation.detail === "web") return /* @__PURE__ */ jsxs4("section", { class: "scui-web-preview", children: [
|
|
1317
|
+
presentation.url ? /* @__PURE__ */ jsx5("code", { children: presentation.url }) : null,
|
|
1318
|
+
presentation.preview ? /* @__PURE__ */ jsx5("p", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Waiting for the page" : "No page summary returned" })
|
|
1248
1319
|
] });
|
|
1249
|
-
if (presentation.detail === "agent") return /* @__PURE__ */
|
|
1250
|
-
/* @__PURE__ */
|
|
1251
|
-
/* @__PURE__ */
|
|
1252
|
-
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */
|
|
1253
|
-
if (presentation.detail === "plan") return /* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1320
|
+
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: [
|
|
1321
|
+
/* @__PURE__ */ jsx5("strong", { children: item.label }),
|
|
1322
|
+
/* @__PURE__ */ jsx5("small", { children: item.status })
|
|
1323
|
+
] }, `${item.label}:${index}`)) }) : presentation.preview ? /* @__PURE__ */ jsx5("pre", { children: stripAnsi(presentation.preview) }) : /* @__PURE__ */ jsx5("small", { children: pending ? "Agent is working" : "No textual handoff returned" }) });
|
|
1324
|
+
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: [
|
|
1325
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1326
|
+
/* @__PURE__ */ jsx5("span", { children: item.label })
|
|
1256
1327
|
] }, `${item.label}:${index}`)) });
|
|
1257
|
-
return presentation.preview ? /* @__PURE__ */
|
|
1328
|
+
return presentation.preview ? /* @__PURE__ */ jsx5("pre", { class: "scui-tool-output", "data-error": failed, children: stripAnsi(presentation.preview) }) : null;
|
|
1258
1329
|
}
|
|
1259
1330
|
function ToolActions({ presentation, adapter }) {
|
|
1260
1331
|
const [copied, setCopied] = useState2(false);
|
|
@@ -1268,27 +1339,27 @@ function ToolActions({ presentation, adapter }) {
|
|
|
1268
1339
|
clearTimeout(reset.current);
|
|
1269
1340
|
reset.current = setTimeout(() => setCopied(false), 1500);
|
|
1270
1341
|
};
|
|
1271
|
-
return action ? /* @__PURE__ */
|
|
1342
|
+
return action ? /* @__PURE__ */ jsx5("div", { class: "scui-tool-actions", children: /* @__PURE__ */ jsx5("button", { type: "button", onClick: copy, children: copied ? "Copied" : action[0] }) }) : null;
|
|
1272
1343
|
}
|
|
1273
1344
|
function ToolStack({ tools }) {
|
|
1274
1345
|
if (tools.length < 2) return null;
|
|
1275
|
-
return /* @__PURE__ */
|
|
1346
|
+
return /* @__PURE__ */ jsx5("div", { class: "scui-tool-stack", "aria-label": "Coordinated tools", children: tools.map((tool) => /* @__PURE__ */ jsx5("span", { children: tool.replaceAll("__", " \xB7 ").replaceAll("_", " ") }, tool)) });
|
|
1276
1347
|
}
|
|
1277
1348
|
function TechnicalDetails({ entry }) {
|
|
1278
1349
|
if (!entry.arguments && !entry.resultText) return null;
|
|
1279
|
-
return /* @__PURE__ */
|
|
1280
|
-
/* @__PURE__ */
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
entry.arguments ? /* @__PURE__ */
|
|
1283
|
-
/* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1350
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool-technical", children: [
|
|
1351
|
+
/* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
|
|
1352
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1353
|
+
entry.arguments ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1354
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native arguments" }),
|
|
1355
|
+
/* @__PURE__ */ jsx5("dl", { children: argumentRows(entry.arguments).map((row) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1356
|
+
/* @__PURE__ */ jsx5("dt", { children: row.label }),
|
|
1357
|
+
/* @__PURE__ */ jsx5("dd", { children: /* @__PURE__ */ jsx5("pre", { children: row.value }) })
|
|
1287
1358
|
] }, row.key)) })
|
|
1288
1359
|
] }) : null,
|
|
1289
|
-
entry.resultText ? /* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
/* @__PURE__ */
|
|
1360
|
+
entry.resultText ? /* @__PURE__ */ jsxs4("section", { children: [
|
|
1361
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native result" }),
|
|
1362
|
+
/* @__PURE__ */ jsxs4("pre", { "data-error": entry.status === "error", children: [
|
|
1292
1363
|
entry.resultText,
|
|
1293
1364
|
entry.truncated ? "\n[truncated]" : ""
|
|
1294
1365
|
] })
|
|
@@ -1297,19 +1368,19 @@ function TechnicalDetails({ entry }) {
|
|
|
1297
1368
|
] });
|
|
1298
1369
|
}
|
|
1299
1370
|
function TranscriptEntry({ entry, state, adapter }) {
|
|
1300
|
-
if (entry.role === "request") return /* @__PURE__ */
|
|
1371
|
+
if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
|
|
1301
1372
|
if (entry.role === "reasoning") {
|
|
1302
|
-
return /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1373
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-reasoning", open: entry.streaming, children: [
|
|
1374
|
+
/* @__PURE__ */ jsx5("summary", { children: entry.streaming ? "Reasoning\u2026" : "Reasoning" }),
|
|
1375
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText })
|
|
1305
1376
|
] });
|
|
1306
1377
|
}
|
|
1307
|
-
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */
|
|
1308
|
-
return /* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1311
|
-
entry.truncated ? /* @__PURE__ */
|
|
1312
|
-
/* @__PURE__ */
|
|
1378
|
+
if (entry.role === "notice" || entry.role === "system") return /* @__PURE__ */ jsx5("div", { class: "scui-notice", "data-code": entry.code, children: entry.text });
|
|
1379
|
+
return /* @__PURE__ */ jsxs4("article", { class: "scui-message", "data-role": entry.role, "aria-label": `${entry.role === "user" ? "Your" : "Assistant"} message`, children: [
|
|
1380
|
+
/* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }),
|
|
1381
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: entry.context }),
|
|
1382
|
+
entry.truncated ? /* @__PURE__ */ jsx5("small", { class: "scui-truncated", children: "Entry truncated by host \xB7 load native session for the complete value" }) : null,
|
|
1383
|
+
/* @__PURE__ */ jsx5(MessageMeta, { entry, adapter })
|
|
1313
1384
|
] });
|
|
1314
1385
|
}
|
|
1315
1386
|
function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
@@ -1321,102 +1392,102 @@ function ToolRow({ entry, workspace, open = false, adapter }) {
|
|
|
1321
1392
|
const target = compactToolTarget(presentation.target, workspace);
|
|
1322
1393
|
const hasDetail = Boolean(entry.arguments || entry.resultText || presentation.preview || presentation.fields.length);
|
|
1323
1394
|
const category = presentation.category ?? toolCategory(entry);
|
|
1324
|
-
const summary = /* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
target ? /* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1329
|
-
entry.status === "pending" ? /* @__PURE__ */
|
|
1330
|
-
/* @__PURE__ */
|
|
1331
|
-
hasDetail ? /* @__PURE__ */
|
|
1395
|
+
const summary = /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1396
|
+
/* @__PURE__ */ jsx5(ToolIcon, { category }),
|
|
1397
|
+
/* @__PURE__ */ jsx5("strong", { children: toolAction2(entry, category, presentation) }),
|
|
1398
|
+
target ? /* @__PURE__ */ jsx5("code", { class: "scui-tool-target", title: presentation.target, children: target }) : null,
|
|
1399
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1400
|
+
entry.status === "pending" ? /* @__PURE__ */ jsx5(PendingElapsed, { now: adapter?.now }) : null,
|
|
1401
|
+
/* @__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 }) }),
|
|
1402
|
+
hasDetail ? /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14, class: "scui-tool-chevron" }) : null
|
|
1332
1403
|
] });
|
|
1333
|
-
if (!hasDetail) return /* @__PURE__ */
|
|
1334
|
-
return /* @__PURE__ */
|
|
1335
|
-
/* @__PURE__ */
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1338
|
-
/* @__PURE__ */
|
|
1339
|
-
/* @__PURE__ */
|
|
1340
|
-
presentation.fields.length ? /* @__PURE__ */
|
|
1341
|
-
/* @__PURE__ */
|
|
1342
|
-
/* @__PURE__ */
|
|
1404
|
+
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 }) });
|
|
1405
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-tool", "data-status": entry.status ?? "completed", "data-category": category, open: expanded, onToggle: (event) => setExpanded(event.currentTarget.open), children: [
|
|
1406
|
+
/* @__PURE__ */ jsx5("summary", { class: "scui-tool-head", children: summary }),
|
|
1407
|
+
/* @__PURE__ */ jsxs4("div", { class: "scui-tool-detail", children: [
|
|
1408
|
+
/* @__PURE__ */ jsx5(ToolMetrics, { presentation }),
|
|
1409
|
+
/* @__PURE__ */ jsx5(ToolStack, { tools: presentation.tools ?? [] }),
|
|
1410
|
+
/* @__PURE__ */ jsx5(ToolPreview, { presentation, entry }),
|
|
1411
|
+
presentation.fields.length ? /* @__PURE__ */ jsx5("dl", { class: "scui-tool-fields", children: presentation.fields.map((field) => /* @__PURE__ */ jsxs4("div", { children: [
|
|
1412
|
+
/* @__PURE__ */ jsx5("dt", { children: field.label }),
|
|
1413
|
+
/* @__PURE__ */ jsx5("dd", { children: field.value })
|
|
1343
1414
|
] }, field.label)) }) : null,
|
|
1344
|
-
/* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1415
|
+
/* @__PURE__ */ jsx5(ToolActions, { presentation, adapter }),
|
|
1416
|
+
/* @__PURE__ */ jsx5(TechnicalDetails, { entry })
|
|
1346
1417
|
] })
|
|
1347
1418
|
] });
|
|
1348
1419
|
}
|
|
1349
1420
|
function ActivityGroup({ entries, state, adapter }) {
|
|
1350
|
-
if (entries.length === 1) return /* @__PURE__ */
|
|
1421
|
+
if (entries.length === 1) return /* @__PURE__ */ jsx5("section", { class: "scui-activity", "data-single": "true", children: /* @__PURE__ */ jsx5(ToolRow, { entry: entries[0], workspace: state.workspace, adapter }) });
|
|
1351
1422
|
const active = entries.some((entry) => entry.status === "pending");
|
|
1352
1423
|
const [open, setOpen] = useState2(active);
|
|
1353
1424
|
const id = useId();
|
|
1354
1425
|
useEffect3(() => {
|
|
1355
1426
|
if (active) setOpen(true);
|
|
1356
1427
|
}, [active]);
|
|
1357
|
-
return /* @__PURE__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
/* @__PURE__ */
|
|
1361
|
-
/* @__PURE__ */
|
|
1362
|
-
/* @__PURE__ */
|
|
1428
|
+
return /* @__PURE__ */ jsxs4("section", { class: "scui-activity", children: [
|
|
1429
|
+
/* @__PURE__ */ jsxs4("button", { class: "scui-activity-head", type: "button", "aria-expanded": open, "aria-controls": id, onClick: () => setOpen((value) => !value), children: [
|
|
1430
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-fold", "data-open": open, children: /* @__PURE__ */ jsx5(UiIcon, { name: "chevron", size: 14 }) }),
|
|
1431
|
+
/* @__PURE__ */ jsx5("strong", { children: activitySummary(entries) }),
|
|
1432
|
+
/* @__PURE__ */ jsx5("span", { class: "scui-spacer" }),
|
|
1433
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1363
1434
|
entries.filter((entry) => entry.status !== "pending").length,
|
|
1364
1435
|
"/",
|
|
1365
1436
|
entries.length
|
|
1366
1437
|
] })
|
|
1367
1438
|
] }),
|
|
1368
|
-
open ? /* @__PURE__ */
|
|
1439
|
+
open ? /* @__PURE__ */ jsx5("div", { id, children: entries.map((entry) => /* @__PURE__ */ jsx5(ToolRow, { entry, workspace: state.workspace, adapter }, entry.id)) }) : null
|
|
1369
1440
|
] });
|
|
1370
1441
|
}
|
|
1371
1442
|
function TaskPlan({ plan }) {
|
|
1372
1443
|
if (!plan.items.length) return null;
|
|
1373
1444
|
const complete = plan.items.filter((item) => item.status === "completed" || item.status === "cancelled").length;
|
|
1374
|
-
return /* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
/* @__PURE__ */
|
|
1377
|
-
/* @__PURE__ */
|
|
1445
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-plan", children: [
|
|
1446
|
+
/* @__PURE__ */ jsxs4("summary", { children: [
|
|
1447
|
+
/* @__PURE__ */ jsx5("span", { children: "Plan" }),
|
|
1448
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1378
1449
|
complete,
|
|
1379
1450
|
"/",
|
|
1380
1451
|
plan.items.length
|
|
1381
1452
|
] })
|
|
1382
1453
|
] }),
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1454
|
+
/* @__PURE__ */ jsx5("ol", { tabIndex: 0, "aria-label": "Task plan steps", children: plan.items.map((item) => /* @__PURE__ */ jsxs4("li", { "data-status": item.status, children: [
|
|
1455
|
+
/* @__PURE__ */ jsx5("i", { "aria-hidden": "true" }),
|
|
1385
1456
|
" ",
|
|
1386
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsx5("span", { children: item.title })
|
|
1387
1458
|
] }, item.id)) })
|
|
1388
1459
|
] });
|
|
1389
1460
|
}
|
|
1390
1461
|
function SessionDetails({ semantics }) {
|
|
1391
1462
|
if (!semantics.fidelity && !semantics.residueCount && !semantics.parseErrors && !semantics.subagents.length) return null;
|
|
1392
|
-
return /* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
semantics.fidelity ? /* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1463
|
+
return /* @__PURE__ */ jsxs4("details", { class: "scui-details", children: [
|
|
1464
|
+
/* @__PURE__ */ jsx5("summary", { children: "Session details" }),
|
|
1465
|
+
/* @__PURE__ */ jsxs4("div", { children: [
|
|
1466
|
+
semantics.fidelity ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1467
|
+
/* @__PURE__ */ jsx5("strong", { children: "Fidelity" }),
|
|
1468
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.fidelity.replaceAll("_", " ") })
|
|
1398
1469
|
] }) : null,
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1470
|
+
/* @__PURE__ */ jsxs4("p", { children: [
|
|
1471
|
+
/* @__PURE__ */ jsx5("strong", { children: "Native records" }),
|
|
1472
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.rawRecords })
|
|
1402
1473
|
] }),
|
|
1403
|
-
semantics.residueCount ? /* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1474
|
+
semantics.residueCount ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1475
|
+
/* @__PURE__ */ jsx5("strong", { children: "Residue" }),
|
|
1476
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1406
1477
|
semantics.residueCount,
|
|
1407
1478
|
" retained"
|
|
1408
1479
|
] })
|
|
1409
1480
|
] }) : null,
|
|
1410
|
-
semantics.parseErrors ? /* @__PURE__ */
|
|
1411
|
-
/* @__PURE__ */
|
|
1412
|
-
/* @__PURE__ */
|
|
1481
|
+
semantics.parseErrors ? /* @__PURE__ */ jsxs4("p", { children: [
|
|
1482
|
+
/* @__PURE__ */ jsx5("strong", { children: "Parse diagnostics" }),
|
|
1483
|
+
/* @__PURE__ */ jsx5("span", { children: semantics.parseErrors })
|
|
1413
1484
|
] }) : null,
|
|
1414
|
-
semantics.subagents.map((agent) => /* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1485
|
+
semantics.subagents.map((agent) => /* @__PURE__ */ jsxs4("p", { children: [
|
|
1486
|
+
/* @__PURE__ */ jsxs4("strong", { children: [
|
|
1416
1487
|
agent.source,
|
|
1417
1488
|
" subagent"
|
|
1418
1489
|
] }),
|
|
1419
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
1420
1491
|
agent.messages,
|
|
1421
1492
|
" messages \xB7 ",
|
|
1422
1493
|
agent.fidelity.replaceAll("_", " ")
|
|
@@ -1435,7 +1506,7 @@ function ConversationAnnouncements({ state }) {
|
|
|
1435
1506
|
}
|
|
1436
1507
|
previousBusy.current = state.busy;
|
|
1437
1508
|
}, [state.busy, state.error, state.harness]);
|
|
1438
|
-
return /* @__PURE__ */
|
|
1509
|
+
return /* @__PURE__ */ jsx5("span", { class: "scui-sr-only", role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement });
|
|
1439
1510
|
}
|
|
1440
1511
|
function Conversation({ state, adapter, components = {}, slots = {}, memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`, pending = null, unreadAfterMessages = null }) {
|
|
1441
1512
|
const scroller = useRef3(null);
|
|
@@ -1467,65 +1538,71 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1467
1538
|
const element = scroller.current;
|
|
1468
1539
|
if (!element) return;
|
|
1469
1540
|
const anchor = earlierAnchor.current;
|
|
1470
|
-
if (anchor
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1541
|
+
if (anchor) {
|
|
1542
|
+
if (state.operation === "loadEarlier") anchor.seenOperation = true;
|
|
1543
|
+
const prepended = state.transcript.length > anchor.entries && state.transcript[0]?.id !== anchor.firstId;
|
|
1544
|
+
if (prepended) {
|
|
1545
|
+
element.scrollTop = anchor.top + (element.scrollHeight - anchor.height);
|
|
1546
|
+
earlierAnchor.current = null;
|
|
1547
|
+
remember({ top: element.scrollTop, atBottom: false });
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
if (state.error || anchor.seenOperation && state.operation !== "loadEarlier") earlierAnchor.current = null;
|
|
1475
1551
|
}
|
|
1476
1552
|
if (!restored.current) {
|
|
1477
1553
|
restored.current = true;
|
|
1478
1554
|
if (remembered.top !== null && !remembered.atBottom) element.scrollTop = remembered.top;
|
|
1479
1555
|
else pin();
|
|
1480
1556
|
} else if (atBottom) pin();
|
|
1481
|
-
}, [memoryKey, state.transcript, state.busy, state.operation, pendingMessage?.text, pendingMessage?.status]);
|
|
1482
|
-
return /* @__PURE__ */
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
1557
|
+
}, [memoryKey, state.transcript, state.busy, state.operation, state.error, pendingMessage?.text, pendingMessage?.status]);
|
|
1558
|
+
return /* @__PURE__ */ jsxs4("div", { class: "scui-conversation-wrap", children: [
|
|
1559
|
+
/* @__PURE__ */ jsx5(ConversationAnnouncements, { state }),
|
|
1560
|
+
/* @__PURE__ */ jsx5("div", { class: "scui-conversation", ref: scroller, tabIndex: 0, "aria-label": "Conversation", onScroll: (event) => {
|
|
1485
1561
|
const element = event.currentTarget;
|
|
1486
1562
|
const bottom = element.scrollHeight - element.scrollTop - element.clientHeight <= 64;
|
|
1487
1563
|
setAtBottom(bottom);
|
|
1488
1564
|
remember({ top: element.scrollTop, atBottom: bottom });
|
|
1489
|
-
}, children: /* @__PURE__ */
|
|
1490
|
-
Before ? /* @__PURE__ */
|
|
1491
|
-
/* @__PURE__ */
|
|
1492
|
-
/* @__PURE__ */
|
|
1493
|
-
state.history.hasEarlier ? /* @__PURE__ */
|
|
1565
|
+
}, children: /* @__PURE__ */ jsxs4("div", { children: [
|
|
1566
|
+
Before ? /* @__PURE__ */ jsx5(Before, { state, adapter, value: null }) : null,
|
|
1567
|
+
/* @__PURE__ */ jsx5(Plan, { plan: state.taskPlan, value: state.taskPlan, state, adapter }),
|
|
1568
|
+
/* @__PURE__ */ jsx5(SessionDetails, { semantics: state.semantics }),
|
|
1569
|
+
state.history.hasEarlier ? /* @__PURE__ */ jsx5("button", { class: "scui-load", type: "button", disabled: Boolean(state.operation), onClick: () => {
|
|
1494
1570
|
const element = scroller.current;
|
|
1495
|
-
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length };
|
|
1571
|
+
if (element) earlierAnchor.current = { height: element.scrollHeight, top: element.scrollTop, entries: state.transcript.length, firstId: state.transcript[0]?.id, seenOperation: false };
|
|
1496
1572
|
setAtBottom(false);
|
|
1497
1573
|
adapter.onIntent({ action: "loadEarlier" });
|
|
1498
1574
|
}, children: "Load earlier messages" }) : null,
|
|
1499
|
-
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */
|
|
1500
|
-
!blocks.length && state.startup === "ready" ? Empty ? /* @__PURE__ */
|
|
1501
|
-
blocks.map((block, index) => /* @__PURE__ */
|
|
1502
|
-
index === unreadBlock ? /* @__PURE__ */
|
|
1503
|
-
block.kind === "activity" ? /* @__PURE__ */
|
|
1575
|
+
!blocks.length && state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state }) : null,
|
|
1576
|
+
!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,
|
|
1577
|
+
blocks.map((block, index) => /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1578
|
+
index === unreadBlock ? /* @__PURE__ */ jsx5("div", { class: "scui-unread-divider", role: "separator", "aria-label": "New messages", children: /* @__PURE__ */ jsx5("span", { children: "New" }) }) : null,
|
|
1579
|
+
block.kind === "activity" ? /* @__PURE__ */ jsx5(Group, { value: block.entries, entries: block.entries, state, adapter }) : /* @__PURE__ */ jsx5(Entry, { value: block.entry, entry: block.entry, state, adapter })
|
|
1504
1580
|
] }, block.id)),
|
|
1505
|
-
pendingMessage ? /* @__PURE__ */
|
|
1506
|
-
/* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1508
|
-
|
|
1509
|
-
pendingMessage.status === "failed" ?
|
|
1510
|
-
|
|
1511
|
-
/* @__PURE__ */
|
|
1581
|
+
pendingMessage ? /* @__PURE__ */ jsxs4("article", { class: "scui-message scui-pending", "data-role": "user", "data-status": pendingMessage.status, "aria-label": "Your pending message", children: [
|
|
1582
|
+
/* @__PURE__ */ jsx5(Markdown, { value: pendingMessage.text, copyText: adapter?.copyText }),
|
|
1583
|
+
/* @__PURE__ */ jsx5(ContextDisclosure, { context: pendingMessage.context }),
|
|
1584
|
+
/* @__PURE__ */ jsxs4("footer", { children: [
|
|
1585
|
+
/* @__PURE__ */ jsx5("small", { children: pendingMessage.status === "failed" ? "Not sent" : "Sending\u2026" }),
|
|
1586
|
+
pendingMessage.status === "failed" ? /* @__PURE__ */ jsxs4("span", { children: [
|
|
1587
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onRetry, children: "Retry" }),
|
|
1588
|
+
/* @__PURE__ */ jsx5("button", { type: "button", onClick: pendingMessage.onEdit, children: "Edit" })
|
|
1512
1589
|
] }) : null
|
|
1513
1590
|
] })
|
|
1514
1591
|
] }) : null,
|
|
1515
|
-
state.busy ? /* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
/* @__PURE__ */
|
|
1520
|
-
/* @__PURE__ */
|
|
1592
|
+
state.busy ? /* @__PURE__ */ jsxs4("div", { class: "scui-working", role: "status", children: [
|
|
1593
|
+
/* @__PURE__ */ jsx5("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
1594
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1595
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1596
|
+
/* @__PURE__ */ jsx5("i", {}),
|
|
1597
|
+
/* @__PURE__ */ jsxs4("small", { children: [
|
|
1521
1598
|
harnessDisplayName(state.harness),
|
|
1522
1599
|
" is working"
|
|
1523
1600
|
] })
|
|
1524
1601
|
] }) : null,
|
|
1525
|
-
After ? /* @__PURE__ */
|
|
1602
|
+
After ? /* @__PURE__ */ jsx5(After, { state, adapter, value: null }) : null
|
|
1526
1603
|
] }) }),
|
|
1527
|
-
!atBottom ? /* @__PURE__ */
|
|
1528
|
-
/* @__PURE__ */
|
|
1604
|
+
!atBottom ? /* @__PURE__ */ jsxs4("button", { class: "scui-latest", type: "button", onClick: pin, children: [
|
|
1605
|
+
/* @__PURE__ */ jsx5(UiIcon, { name: "down", size: 13 }),
|
|
1529
1606
|
" Latest"
|
|
1530
1607
|
] }) : null
|
|
1531
1608
|
] });
|
|
@@ -1533,7 +1610,7 @@ function Conversation({ state, adapter, components = {}, slots = {}, memoryKey =
|
|
|
1533
1610
|
|
|
1534
1611
|
// src/logo.jsx
|
|
1535
1612
|
import { useEffect as useEffect4 } from "preact/hooks";
|
|
1536
|
-
import { jsx as
|
|
1613
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
|
|
1537
1614
|
var LOGOS = {
|
|
1538
1615
|
"claude-code": {
|
|
1539
1616
|
viewBox: "-1 3.5 26 18",
|
|
@@ -1587,9 +1664,9 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
|
1587
1664
|
if (!logo) onMissingLogo?.(id);
|
|
1588
1665
|
}, [id, logo, onMissingLogo]);
|
|
1589
1666
|
if (!logo) return null;
|
|
1590
|
-
return /* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1592
|
-
activity && activity !== "idle" ? /* @__PURE__ */
|
|
1667
|
+
return /* @__PURE__ */ jsxs5("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
|
|
1668
|
+
/* @__PURE__ */ jsx6("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx6(Tag, { ...props }, index)) }),
|
|
1669
|
+
activity && activity !== "idle" ? /* @__PURE__ */ jsx6("i", {}) : null
|
|
1593
1670
|
] });
|
|
1594
1671
|
}
|
|
1595
1672
|
|
|
@@ -1598,22 +1675,22 @@ import { useEffect as useEffect6, useId as useId2, useMemo as useMemo2, useRef a
|
|
|
1598
1675
|
|
|
1599
1676
|
// src/sessions.jsx
|
|
1600
1677
|
import { useEffect as useEffect5, useLayoutEffect as useLayoutEffect3, useRef as useRef4, useState as useState3 } from "preact/hooks";
|
|
1601
|
-
import { jsx as
|
|
1678
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "preact/jsx-runtime";
|
|
1602
1679
|
var sessionListMemory = /* @__PURE__ */ new Map();
|
|
1603
1680
|
function SessionRow({ row, state, onOpen }) {
|
|
1604
1681
|
const activity = sessionActivity(state, row);
|
|
1605
1682
|
const attentionPreview = state.attention.find((item) => item.key === row.key)?.preview;
|
|
1606
1683
|
const title = sessionDisplayName(row);
|
|
1607
1684
|
const detail = attentionPreview || row.preview || (row.name && row.name !== title ? row.name : row.cwd);
|
|
1608
|
-
return /* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1685
|
+
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: [
|
|
1686
|
+
/* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
1687
|
+
/* @__PURE__ */ jsxs6("span", { class: "scui-session-copy", children: [
|
|
1688
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
1689
|
+
/* @__PURE__ */ jsx7("strong", { children: title }),
|
|
1690
|
+
/* @__PURE__ */ jsx7("small", { children: row.age })
|
|
1614
1691
|
] }),
|
|
1615
|
-
detail ? /* @__PURE__ */
|
|
1616
|
-
state.attachError?.key === row.key ? /* @__PURE__ */
|
|
1692
|
+
detail ? /* @__PURE__ */ jsx7("span", { children: /* @__PURE__ */ jsx7("small", { title: row.cwd, children: detail }) }) : null,
|
|
1693
|
+
state.attachError?.key === row.key ? /* @__PURE__ */ jsx7("em", { children: state.attachError.message }) : null
|
|
1617
1694
|
] })
|
|
1618
1695
|
] });
|
|
1619
1696
|
}
|
|
@@ -1644,48 +1721,48 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
|
|
|
1644
1721
|
Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
|
|
1645
1722
|
}
|
|
1646
1723
|
};
|
|
1647
|
-
return /* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1724
|
+
return /* @__PURE__ */ jsxs6("section", { class: "scui-list", ref: root, children: [
|
|
1725
|
+
/* @__PURE__ */ jsxs6("header", { class: "scui-head", children: [
|
|
1726
|
+
/* @__PURE__ */ jsxs6("span", { class: "scui-head-copy", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx7("strong", { children: labels.chats }),
|
|
1728
|
+
/* @__PURE__ */ jsxs6("small", { children: [
|
|
1652
1729
|
state.sessions.length,
|
|
1653
1730
|
" recent conversations"
|
|
1654
1731
|
] })
|
|
1655
1732
|
] }),
|
|
1656
|
-
/* @__PURE__ */
|
|
1657
|
-
onClose ? /* @__PURE__ */
|
|
1733
|
+
/* @__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 }) }),
|
|
1734
|
+
onClose ? /* @__PURE__ */ jsx7("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx7(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1658
1735
|
] }),
|
|
1659
|
-
state.startup !== "ready" ? /* @__PURE__ */
|
|
1660
|
-
state.sessions.length > 4 ? /* @__PURE__ */
|
|
1661
|
-
/* @__PURE__ */
|
|
1662
|
-
/* @__PURE__ */
|
|
1736
|
+
state.startup !== "ready" ? /* @__PURE__ */ jsx7(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
1737
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs6("label", { class: "scui-search", children: [
|
|
1738
|
+
/* @__PURE__ */ jsx7(UiIcon, { name: "search", size: 15 }),
|
|
1739
|
+
/* @__PURE__ */ jsx7("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
|
|
1663
1740
|
const value = event.currentTarget.value;
|
|
1664
1741
|
setQuery(value);
|
|
1665
1742
|
boundedSet(sessionListMemory, memoryKey, { query: value, top: 0 });
|
|
1666
1743
|
if (rowScroller.current) rowScroller.current.scrollTop = 0;
|
|
1667
1744
|
} }),
|
|
1668
|
-
/* @__PURE__ */
|
|
1745
|
+
/* @__PURE__ */ jsx7("small", { children: rows.length })
|
|
1669
1746
|
] }) : null,
|
|
1670
|
-
/* @__PURE__ */
|
|
1671
|
-
!rows.length && state.startup === "ready" ? /* @__PURE__ */
|
|
1672
|
-
rows.map((row) => /* @__PURE__ */
|
|
1673
|
-
state.history.hasMoreSessions ? /* @__PURE__ */
|
|
1747
|
+
/* @__PURE__ */ jsxs6("div", { class: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
|
|
1748
|
+
!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,
|
|
1749
|
+
rows.map((row) => /* @__PURE__ */ jsx7(Row, { value: row, row, state, adapter, onOpen }, row.key)),
|
|
1750
|
+
state.history.hasMoreSessions ? /* @__PURE__ */ jsx7("button", { class: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null
|
|
1674
1751
|
] })
|
|
1675
1752
|
] });
|
|
1676
1753
|
}
|
|
1677
1754
|
|
|
1678
1755
|
// src/messenger.jsx
|
|
1679
|
-
import { jsx as
|
|
1756
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
1680
1757
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
1681
1758
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
1682
1759
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
1683
1760
|
var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "interrupt", "respond", "refresh", "loadEarlier", "loadSessions"]);
|
|
1684
1761
|
function Receipt({ state, adapter }) {
|
|
1685
1762
|
const receipt = state.reductionReceipt;
|
|
1686
|
-
if (receipt) return /* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
/* @__PURE__ */
|
|
1763
|
+
if (receipt) return /* @__PURE__ */ jsx8("div", { class: "scui-receipt", children: /* @__PURE__ */ jsxs7("span", { children: [
|
|
1764
|
+
/* @__PURE__ */ jsx8("strong", { children: "Reduced and verified" }),
|
|
1765
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1689
1766
|
receipt.sourceTokens.toLocaleString(),
|
|
1690
1767
|
" \u2192 ",
|
|
1691
1768
|
receipt.reducedTokens.toLocaleString(),
|
|
@@ -1694,27 +1771,27 @@ function Receipt({ state, adapter }) {
|
|
|
1694
1771
|
"\xD7 \xB7 reversible"
|
|
1695
1772
|
] })
|
|
1696
1773
|
] }) });
|
|
1697
|
-
if (state.exportReceipt) return /* @__PURE__ */
|
|
1698
|
-
/* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1774
|
+
if (state.exportReceipt) return /* @__PURE__ */ jsxs7("div", { class: "scui-receipt", children: [
|
|
1775
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1776
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
1700
1777
|
"Lossless export ready \xB7 ",
|
|
1701
1778
|
harnessDisplayName(state.exportReceipt.targetHarness)
|
|
1702
1779
|
] }),
|
|
1703
|
-
/* @__PURE__ */
|
|
1780
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1704
1781
|
state.exportReceipt.path,
|
|
1705
1782
|
" \xB7 ",
|
|
1706
1783
|
state.exportReceipt.files,
|
|
1707
1784
|
" files"
|
|
1708
1785
|
] })
|
|
1709
1786
|
] }),
|
|
1710
|
-
/* @__PURE__ */
|
|
1787
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(state.exportReceipt.path), children: "Copy path" })
|
|
1711
1788
|
] });
|
|
1712
|
-
if (state.terminalHandoff) return /* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
1715
|
-
/* @__PURE__ */
|
|
1789
|
+
if (state.terminalHandoff) return /* @__PURE__ */ jsxs7("div", { class: "scui-receipt", children: [
|
|
1790
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
1791
|
+
/* @__PURE__ */ jsx8("strong", { children: "Terminal handoff ready" }),
|
|
1792
|
+
/* @__PURE__ */ jsx8("small", { children: state.terminalHandoff.cwd })
|
|
1716
1793
|
] }),
|
|
1717
|
-
/* @__PURE__ */
|
|
1794
|
+
/* @__PURE__ */ jsx8("button", { type: "button", onClick: () => adapter.copyText?.(terminalCommand(state.terminalHandoff)), children: "Copy command" })
|
|
1718
1795
|
] });
|
|
1719
1796
|
return null;
|
|
1720
1797
|
}
|
|
@@ -1782,13 +1859,13 @@ function ConversationActions({ state, adapter, actionPending }) {
|
|
|
1782
1859
|
const index = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowDown" ? (current + 1) % items.length : (current <= 0 ? items.length : current) - 1;
|
|
1783
1860
|
items[index].focus({ preventScroll: true });
|
|
1784
1861
|
};
|
|
1785
|
-
return /* @__PURE__ */
|
|
1862
|
+
return /* @__PURE__ */ jsxs7("div", { class: "scui-menu", ref: root, onBlur: (event) => {
|
|
1786
1863
|
if (event.relatedTarget && !event.currentTarget.contains(event.relatedTarget)) setOpen(false);
|
|
1787
1864
|
}, children: [
|
|
1788
|
-
/* @__PURE__ */
|
|
1789
|
-
open ? /* @__PURE__ */
|
|
1790
|
-
/* @__PURE__ */
|
|
1791
|
-
group.items.map((item) => /* @__PURE__ */
|
|
1865
|
+
/* @__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 }) }),
|
|
1866
|
+
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: [
|
|
1867
|
+
/* @__PURE__ */ jsx8("strong", { children: group.label }),
|
|
1868
|
+
group.items.map((item) => /* @__PURE__ */ jsx8("button", { role: "menuitem", type: "button", disabled: actionPending, onClick: () => dispatch(item.intent), children: item.label }, item.key))
|
|
1792
1869
|
] }, group.label)) }) : null
|
|
1793
1870
|
] });
|
|
1794
1871
|
}
|
|
@@ -1801,20 +1878,20 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
1801
1878
|
useEffect6(() => {
|
|
1802
1879
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
1803
1880
|
}, []);
|
|
1804
|
-
return /* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
1806
|
-
/* @__PURE__ */
|
|
1807
|
-
/* @__PURE__ */
|
|
1808
|
-
/* @__PURE__ */
|
|
1809
|
-
/* @__PURE__ */
|
|
1881
|
+
return /* @__PURE__ */ jsxs7("header", { class: "scui-head scui-chat-head", children: [
|
|
1882
|
+
/* @__PURE__ */ jsx8("button", { ref: back, type: "button", "aria-label": "Back to chats", onClick: onBack, children: /* @__PURE__ */ jsx8(UiIcon, { name: "back", size: 18 }) }),
|
|
1883
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: harness, size: 28 }),
|
|
1884
|
+
/* @__PURE__ */ jsxs7("span", { class: "scui-head-copy", children: [
|
|
1885
|
+
/* @__PURE__ */ jsx8("strong", { children: title }),
|
|
1886
|
+
/* @__PURE__ */ jsxs7("small", { children: [
|
|
1810
1887
|
harnessDisplayName(harness),
|
|
1811
1888
|
" \xB7 ",
|
|
1812
1889
|
status
|
|
1813
1890
|
] })
|
|
1814
1891
|
] }),
|
|
1815
|
-
menu ? /* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
onClose ? /* @__PURE__ */
|
|
1892
|
+
menu ? /* @__PURE__ */ jsx8(ConversationActions, { state, adapter, actionPending }) : null,
|
|
1893
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ jsx8(UiIcon, { name: "plus", size: 18 }) }),
|
|
1894
|
+
onClose ? /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1818
1895
|
] });
|
|
1819
1896
|
}
|
|
1820
1897
|
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels }) {
|
|
@@ -1846,8 +1923,9 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1846
1923
|
if (pending.status === "sending" && state.busy && !pending.seenBusy) setPending({ ...pending, seenBusy: true });
|
|
1847
1924
|
else if (pending.status === "sending" && state.error && !state.busy && !state.operation && (pending.seenBusy || state.error !== pending.initialError)) setPending({ ...pending, status: "failed" });
|
|
1848
1925
|
}, [pending, state.busy, state.error, state.operation, state.transcript]);
|
|
1849
|
-
const beginPending = (text) => setPending({
|
|
1926
|
+
const beginPending = (text, context = []) => setPending({
|
|
1850
1927
|
text,
|
|
1928
|
+
context,
|
|
1851
1929
|
status: "sending",
|
|
1852
1930
|
initialError: state.error,
|
|
1853
1931
|
seenBusy: state.busy,
|
|
@@ -1855,13 +1933,13 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1855
1933
|
});
|
|
1856
1934
|
const retryPending = () => {
|
|
1857
1935
|
if (!pending) return;
|
|
1858
|
-
adapter.onIntent({ action: "send", text: pending.text });
|
|
1936
|
+
adapter.onIntent({ action: "send", text: pending.text, ...pending.context?.length ? { context: pending.context } : {} });
|
|
1859
1937
|
setPending({ ...pending, status: "sending", initialError: state.error, seenBusy: state.busy });
|
|
1860
1938
|
};
|
|
1861
1939
|
const editPending = () => {
|
|
1862
1940
|
if (!pending) return;
|
|
1863
1941
|
restoreSequence.current += 1;
|
|
1864
|
-
setRestoreDraft({ id: restoreSequence.current, text: pending.text });
|
|
1942
|
+
setRestoreDraft({ id: restoreSequence.current, text: pending.text, context: pending.context });
|
|
1865
1943
|
setPending({ ...pending, status: "editing" });
|
|
1866
1944
|
};
|
|
1867
1945
|
useEffect6(() => {
|
|
@@ -1907,34 +1985,37 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
1907
1985
|
setPendingAction(null);
|
|
1908
1986
|
}
|
|
1909
1987
|
}, [pendingAction, state.error, state.operation]);
|
|
1910
|
-
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
1988
|
+
const pendingMessage = pending && pending.status !== "editing" ? { text: pending.text, context: pending.context, status: pending.status, onRetry: retryPending, onEdit: editPending } : null;
|
|
1911
1989
|
const action = state.operation || pendingAction?.action || null;
|
|
1912
1990
|
const actionLabel = operationLabel(action);
|
|
1913
1991
|
const actionState = action ? { ...state, operation: action, canInterrupt: false, canRespond: false } : state;
|
|
1914
1992
|
const unreadAfterMessages = state.attention.find((item) => item.key === state.attached?.key)?.afterMessages ?? null;
|
|
1915
|
-
return /* @__PURE__ */
|
|
1916
|
-
Header ? /* @__PURE__ */
|
|
1917
|
-
actionLabel ? /* @__PURE__ */
|
|
1918
|
-
/* @__PURE__ */
|
|
1993
|
+
return /* @__PURE__ */ jsxs7("section", { class: "scui-chat", children: [
|
|
1994
|
+
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 }),
|
|
1995
|
+
actionLabel ? /* @__PURE__ */ jsxs7("div", { class: "scui-operation", role: "status", children: [
|
|
1996
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
1919
1997
|
actionLabel
|
|
1920
1998
|
] }) : null,
|
|
1921
|
-
state.error ? /* @__PURE__ */
|
|
1922
|
-
/* @__PURE__ */
|
|
1923
|
-
state.recoverable ? /* @__PURE__ */
|
|
1999
|
+
state.error ? /* @__PURE__ */ jsxs7("div", { class: "scui-error", role: "alert", children: [
|
|
2000
|
+
/* @__PURE__ */ jsx8("span", { children: state.error }),
|
|
2001
|
+
state.recoverable ? /* @__PURE__ */ jsx8("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
|
|
1924
2002
|
] }) : null,
|
|
1925
|
-
/* @__PURE__ */
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
1928
|
-
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */
|
|
2003
|
+
/* @__PURE__ */ jsx8(Receipt, { state, adapter }),
|
|
2004
|
+
/* @__PURE__ */ jsx8(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
|
|
2005
|
+
/* @__PURE__ */ jsx8(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
|
|
2006
|
+
state.mode !== "mirror" || state.canSend ? /* @__PURE__ */ jsx8(Composer, { state: actionState, adapter: trackedAdapter, labels, memoryKey, pendingStatus: pending?.status ?? null, restoreDraft, onDraftRestored: (id) => setRestoreDraft((value) => value?.id === id ? null : value), onPending: beginPending }, memoryKey) : null
|
|
1929
2007
|
] });
|
|
1930
2008
|
}
|
|
1931
2009
|
function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey }) {
|
|
1932
2010
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
1933
2011
|
const startableKey = startable.map((item) => item.id).join("\0");
|
|
1934
|
-
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "" };
|
|
2012
|
+
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [] };
|
|
1935
2013
|
const [harness, setHarness] = useState4(remembered.harness);
|
|
1936
2014
|
const [draft, setDraft] = useState4(remembered.draft);
|
|
2015
|
+
const [context, setContext] = useState4(remembered.context);
|
|
1937
2016
|
const [starting, setStarting] = useState4(null);
|
|
2017
|
+
const [picking, setPicking] = useState4(false);
|
|
2018
|
+
const [pickerError, setPickerError] = useState4(null);
|
|
1938
2019
|
const startSequence = useRef5(0);
|
|
1939
2020
|
const textarea = useRef5(null);
|
|
1940
2021
|
useAutosizeTextarea(textarea, draft);
|
|
@@ -1942,7 +2023,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
1942
2023
|
if (startable.some((item) => item.id === harness)) return;
|
|
1943
2024
|
const next = startable[0]?.id ?? "";
|
|
1944
2025
|
setHarness(next);
|
|
1945
|
-
boundedSet(newChatMemory, memoryKey, { harness: next, draft });
|
|
2026
|
+
boundedSet(newChatMemory, memoryKey, { harness: next, draft, context });
|
|
1946
2027
|
}, [harness, startableKey]);
|
|
1947
2028
|
useEffect6(() => {
|
|
1948
2029
|
if (!starting) return;
|
|
@@ -1958,60 +2039,79 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
1958
2039
|
useEffect6(() => {
|
|
1959
2040
|
textarea.current?.focus({ preventScroll: true });
|
|
1960
2041
|
}, []);
|
|
2042
|
+
const pickContext = () => {
|
|
2043
|
+
if (!adapter.pickContext || picking || context.length >= MAX_CONTEXT_ITEMS) return;
|
|
2044
|
+
setPicking(true);
|
|
2045
|
+
setPickerError(null);
|
|
2046
|
+
Promise.resolve().then(() => adapter.pickContext()).then((picked) => {
|
|
2047
|
+
setContext((current) => {
|
|
2048
|
+
const next = mergeContext(current, picked);
|
|
2049
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context: next });
|
|
2050
|
+
return next;
|
|
2051
|
+
});
|
|
2052
|
+
}, (error) => setPickerError(error instanceof Error ? error.message : "Could not attach context.")).finally(() => setPicking(false));
|
|
2053
|
+
};
|
|
1961
2054
|
const send = () => {
|
|
1962
2055
|
const text = draft.trim();
|
|
1963
2056
|
if (!text || !harness || starting) return;
|
|
1964
2057
|
const id = startSequence.current + 1;
|
|
1965
2058
|
startSequence.current = id;
|
|
1966
2059
|
setStarting({ id, attachedKey: state.attached?.key ?? null, busy: state.busy, initialError: state.error });
|
|
1967
|
-
const result = adapter.onIntent({ action: "new", harness, text });
|
|
2060
|
+
const result = adapter.onIntent({ action: "new", harness, text, ...context.length ? { context } : {} });
|
|
1968
2061
|
if (result && typeof result.then === "function") {
|
|
1969
2062
|
Promise.resolve(result).catch(() => setStarting((current) => current?.id === id ? null : current));
|
|
1970
2063
|
}
|
|
1971
2064
|
};
|
|
1972
|
-
return /* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
1975
|
-
/* @__PURE__ */
|
|
1976
|
-
/* @__PURE__ */
|
|
1977
|
-
/* @__PURE__ */
|
|
2065
|
+
return /* @__PURE__ */ jsxs7("section", { class: "scui-chat", children: [
|
|
2066
|
+
/* @__PURE__ */ jsxs7("header", { class: "scui-head", children: [
|
|
2067
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Back", onClick: onBack, children: /* @__PURE__ */ jsx8(UiIcon, { name: "back", size: 18 }) }),
|
|
2068
|
+
/* @__PURE__ */ jsxs7("span", { class: "scui-head-copy", children: [
|
|
2069
|
+
/* @__PURE__ */ jsx8("strong", { children: labels.newChat }),
|
|
2070
|
+
/* @__PURE__ */ jsx8("small", { children: "No session is created until you send" })
|
|
1978
2071
|
] }),
|
|
1979
|
-
onClose ? /* @__PURE__ */
|
|
2072
|
+
onClose ? /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) }) : null
|
|
1980
2073
|
] }),
|
|
1981
|
-
starting ? /* @__PURE__ */
|
|
1982
|
-
/* @__PURE__ */
|
|
2074
|
+
starting ? /* @__PURE__ */ jsxs7("div", { class: "scui-operation", role: "status", children: [
|
|
2075
|
+
/* @__PURE__ */ jsx8("i", {}),
|
|
1983
2076
|
operationLabel("start")
|
|
1984
2077
|
] }) : null,
|
|
1985
|
-
/* @__PURE__ */
|
|
1986
|
-
/* @__PURE__ */
|
|
1987
|
-
/* @__PURE__ */
|
|
1988
|
-
/* @__PURE__ */
|
|
2078
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-new", children: [
|
|
2079
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\u2726" }),
|
|
2080
|
+
/* @__PURE__ */ jsx8("strong", { children: "What should the agent build or fix?" }),
|
|
2081
|
+
/* @__PURE__ */ jsx8("small", { children: "Choose a coding harness and send the first message." })
|
|
1989
2082
|
] }),
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
1993
|
-
/* @__PURE__ */
|
|
1994
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-compose", children: [
|
|
2084
|
+
/* @__PURE__ */ jsxs7("label", { class: "scui-harness-picker", children: [
|
|
2085
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: harness, size: 24 }),
|
|
2086
|
+
/* @__PURE__ */ jsx8("span", { children: "Coding harness" }),
|
|
2087
|
+
/* @__PURE__ */ jsx8("select", { value: harness, disabled: Boolean(starting), onChange: (event) => {
|
|
1995
2088
|
const value = event.currentTarget.value;
|
|
1996
2089
|
setHarness(value);
|
|
1997
|
-
boundedSet(newChatMemory, memoryKey, { harness: value, draft });
|
|
1998
|
-
}, children: state.harnesses.map((item) => /* @__PURE__ */
|
|
2090
|
+
boundedSet(newChatMemory, memoryKey, { harness: value, draft, context });
|
|
2091
|
+
}, children: state.harnesses.map((item) => /* @__PURE__ */ jsxs7("option", { value: item.id, disabled: !item.startable, children: [
|
|
1999
2092
|
item.label,
|
|
2000
2093
|
item.startable ? "" : " \xB7 unavailable"
|
|
2001
2094
|
] }, item.id)) })
|
|
2002
2095
|
] }),
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
|
|
2096
|
+
/* @__PURE__ */ jsx8(ContextTray, { items: context, onRemove: (index) => setContext((items) => {
|
|
2097
|
+
const next = items.filter((_, itemIndex) => itemIndex !== index);
|
|
2098
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft, context: next });
|
|
2099
|
+
return next;
|
|
2100
|
+
}) }),
|
|
2101
|
+
pickerError ? /* @__PURE__ */ jsx8("small", { class: "scui-context-error", role: "alert", children: pickerError }) : null,
|
|
2102
|
+
/* @__PURE__ */ jsxs7("div", { class: "scui-envelope", children: [
|
|
2103
|
+
adapter.pickContext ? /* @__PURE__ */ jsx8("button", { class: "scui-attach", type: "button", "aria-label": "Attach context", disabled: picking || context.length >= MAX_CONTEXT_ITEMS || Boolean(starting), onClick: pickContext, children: picking ? /* @__PURE__ */ jsx8("i", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx8(UiIcon, { name: "attach", size: 17 }) }) : null,
|
|
2104
|
+
/* @__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), onInput: (event) => {
|
|
2005
2105
|
const value = event.currentTarget.value;
|
|
2006
2106
|
setDraft(value);
|
|
2007
|
-
boundedSet(newChatMemory, memoryKey, { harness, draft: value });
|
|
2107
|
+
boundedSet(newChatMemory, memoryKey, { harness, draft: value, context });
|
|
2008
2108
|
}, onKeyDown: (event) => {
|
|
2009
2109
|
if (isSendKey(event)) {
|
|
2010
2110
|
event.preventDefault();
|
|
2011
2111
|
send();
|
|
2012
2112
|
}
|
|
2013
2113
|
} }),
|
|
2014
|
-
/* @__PURE__ */
|
|
2114
|
+
/* @__PURE__ */ jsx8("span", { children: /* @__PURE__ */ jsx8("button", { type: "button", class: "scui-send", "aria-label": "Start chat", disabled: !draft.trim() || !harness || Boolean(starting), onClick: send, children: starting ? /* @__PURE__ */ jsx8("i", { class: "scui-control-spinner" }) : /* @__PURE__ */ jsx8(UiIcon, { name: "send", size: 17 }) }) })
|
|
2015
2115
|
] })
|
|
2016
2116
|
] })
|
|
2017
2117
|
] });
|
|
@@ -2043,31 +2143,31 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2043
2143
|
};
|
|
2044
2144
|
const close = () => adapter.onClose?.();
|
|
2045
2145
|
const Footer = slots.footer;
|
|
2046
|
-
return /* @__PURE__ */
|
|
2047
|
-
view === "list" ? /* @__PURE__ */
|
|
2146
|
+
return /* @__PURE__ */ jsxs7("main", { class: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2147
|
+
view === "list" ? /* @__PURE__ */ jsx8(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2048
2148
|
setListFocus("@new");
|
|
2049
2149
|
setView("new");
|
|
2050
2150
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey }) : null,
|
|
2051
|
-
view === "new" ? /* @__PURE__ */
|
|
2052
|
-
view === "chat" ? /* @__PURE__ */
|
|
2151
|
+
view === "new" ? /* @__PURE__ */ jsx8(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: () => setView("chat"), labels: copy, memoryKey }) : null,
|
|
2152
|
+
view === "chat" ? /* @__PURE__ */ jsx8(Chat, { state, adapter, onBack: () => {
|
|
2053
2153
|
setListFocus(state.attached?.key ?? listFocus);
|
|
2054
2154
|
setView("list");
|
|
2055
2155
|
}, onNew: () => {
|
|
2056
2156
|
setListFocus("@new");
|
|
2057
2157
|
setView("new");
|
|
2058
2158
|
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy }) : null,
|
|
2059
|
-
opening ? /* @__PURE__ */
|
|
2060
|
-
/* @__PURE__ */
|
|
2061
|
-
/* @__PURE__ */
|
|
2062
|
-
/* @__PURE__ */
|
|
2159
|
+
opening ? /* @__PURE__ */ jsxs7("div", { class: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2160
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2161
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2162
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
2063
2163
|
"Opening ",
|
|
2064
2164
|
sessionDisplayName(opening)
|
|
2065
2165
|
] }),
|
|
2066
|
-
/* @__PURE__ */
|
|
2166
|
+
/* @__PURE__ */ jsx8("small", { children: "Loading the latest transcript window\u2026" })
|
|
2067
2167
|
] }),
|
|
2068
|
-
/* @__PURE__ */
|
|
2168
|
+
/* @__PURE__ */ jsx8("i", {})
|
|
2069
2169
|
] }) : null,
|
|
2070
|
-
Footer ? /* @__PURE__ */
|
|
2170
|
+
Footer ? /* @__PURE__ */ jsx8(Footer, { state, adapter, value: copy }) : null
|
|
2071
2171
|
] });
|
|
2072
2172
|
}
|
|
2073
2173
|
export {
|