@volter-ai-dev/supercode-ui 0.1.38 → 0.1.39
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 +1 -1
- package/components.mjs +22 -2
- package/embed.mjs +22 -2
- package/index.d.ts +1 -1
- package/messenger.mjs +22 -2
- package/package.json +1 -1
- package/react/components.mjs +22 -2
- package/react/messenger.mjs +22 -2
package/README.md
CHANGED
|
@@ -135,7 +135,7 @@ Hosts do not need to fork the messenger to connect their own object model:
|
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
`navigation` is an event, not duplicated router state: change its `id` to open a conversation or
|
|
138
|
-
prefill
|
|
138
|
+
prefill either an existing or new one, while `onViewChange` observes user navigation. Context candidates use the exact
|
|
139
139
|
bounded `TranscriptAttachment` envelope sent to the harness; a custom candidate component changes
|
|
140
140
|
presentation without inventing a second context protocol. `beforeSessions` and `afterSessions`
|
|
141
141
|
place host-owned rows inside the same searchable scroller. `confirmIntent` runs before resume,
|
package/components.mjs
CHANGED
|
@@ -2627,7 +2627,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2627
2627
|
onClose ? /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx10(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2628
2628
|
] });
|
|
2629
2629
|
}
|
|
2630
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2630
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2631
2631
|
const Header = slots.header;
|
|
2632
2632
|
const HeaderActions = slots.headerActions;
|
|
2633
2633
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2637,6 +2637,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2637
2637
|
const [settings, setSettings] = useState6(null);
|
|
2638
2638
|
const restoreSequence = useRef7(0);
|
|
2639
2639
|
const actionSequence = useRef7(0);
|
|
2640
|
+
const lastNavigation = useRef7(null);
|
|
2640
2641
|
const acknowledged = useRef7(/* @__PURE__ */ new Set());
|
|
2641
2642
|
const setPending = (update) => setPendingState((current) => {
|
|
2642
2643
|
const next = typeof update === "function" ? update(current) : update;
|
|
@@ -2649,6 +2650,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2649
2650
|
setPendingAction(null);
|
|
2650
2651
|
setRestoreDraft(null);
|
|
2651
2652
|
}, [memoryKey]);
|
|
2653
|
+
useEffect8(() => {
|
|
2654
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2655
|
+
lastNavigation.current = navigation.id;
|
|
2656
|
+
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
2657
|
+
setRestoreDraft({
|
|
2658
|
+
id: `host:${String(navigation.id)}`,
|
|
2659
|
+
text: navigation.draft ?? "",
|
|
2660
|
+
context: navigation.context,
|
|
2661
|
+
images: navigation.images
|
|
2662
|
+
});
|
|
2663
|
+
}, [navigation]);
|
|
2652
2664
|
useEffect8(() => {
|
|
2653
2665
|
if (!pending) return;
|
|
2654
2666
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
@@ -2973,6 +2985,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2973
2985
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2974
2986
|
const [opening, setOpening] = useState6(null);
|
|
2975
2987
|
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2988
|
+
const [chatNavigation, setChatNavigation] = useState6(null);
|
|
2976
2989
|
const [listFocus, setListFocus] = useState6(null);
|
|
2977
2990
|
const lastNavigation = useRef7(null);
|
|
2978
2991
|
const setView = (next) => {
|
|
@@ -2985,17 +2998,21 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2985
2998
|
lastNavigation.current = navigation.id;
|
|
2986
2999
|
if (navigation.view === "list") {
|
|
2987
3000
|
setOpening(null);
|
|
3001
|
+
setChatNavigation(null);
|
|
2988
3002
|
setView("list");
|
|
2989
3003
|
return;
|
|
2990
3004
|
}
|
|
2991
3005
|
if (navigation.view === "new") {
|
|
2992
3006
|
setListFocus("@new");
|
|
3007
|
+
setChatNavigation(null);
|
|
2993
3008
|
setNewNavigation(navigation);
|
|
2994
3009
|
setView("new");
|
|
2995
3010
|
return;
|
|
2996
3011
|
}
|
|
2997
3012
|
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2998
3013
|
setListFocus(navigation.sessionKey);
|
|
3014
|
+
setNewNavigation(null);
|
|
3015
|
+
setChatNavigation(navigation);
|
|
2999
3016
|
if (state.attached?.key === navigation.sessionKey) {
|
|
3000
3017
|
setOpening(null);
|
|
3001
3018
|
setView("chat");
|
|
@@ -3017,6 +3034,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3017
3034
|
}, [opening, state.attachError?.key, state.attached?.key, state.error, state.operation]);
|
|
3018
3035
|
const open = (row) => {
|
|
3019
3036
|
setListFocus(row.key);
|
|
3037
|
+
setChatNavigation(null);
|
|
3020
3038
|
setOpening(row);
|
|
3021
3039
|
adapter.onIntent({ action: "attach", key: row.key });
|
|
3022
3040
|
};
|
|
@@ -3026,6 +3044,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3026
3044
|
return /* @__PURE__ */ jsxs9("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
3027
3045
|
view === "list" ? /* @__PURE__ */ jsx10(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
3028
3046
|
setListFocus("@new");
|
|
3047
|
+
setChatNavigation(null);
|
|
3029
3048
|
setNewNavigation(null);
|
|
3030
3049
|
setView("new");
|
|
3031
3050
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
@@ -3035,9 +3054,10 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3035
3054
|
setView("list");
|
|
3036
3055
|
}, onNew: () => {
|
|
3037
3056
|
setListFocus("@new");
|
|
3057
|
+
setChatNavigation(null);
|
|
3038
3058
|
setNewNavigation(null);
|
|
3039
3059
|
setView("new");
|
|
3040
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
3060
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
3041
3061
|
opening ? /* @__PURE__ */ jsxs9("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
3042
3062
|
/* @__PURE__ */ jsx10(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
3043
3063
|
/* @__PURE__ */ jsxs9("span", { children: [
|
package/embed.mjs
CHANGED
|
@@ -2547,7 +2547,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2547
2547
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2548
2548
|
] });
|
|
2549
2549
|
}
|
|
2550
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2550
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2551
2551
|
const Header = slots.header;
|
|
2552
2552
|
const HeaderActions = slots.headerActions;
|
|
2553
2553
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2557,6 +2557,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2557
2557
|
const [settings, setSettings] = useState6(null);
|
|
2558
2558
|
const restoreSequence = useRef7(0);
|
|
2559
2559
|
const actionSequence = useRef7(0);
|
|
2560
|
+
const lastNavigation = useRef7(null);
|
|
2560
2561
|
const acknowledged = useRef7(/* @__PURE__ */ new Set());
|
|
2561
2562
|
const setPending = (update) => setPendingState((current) => {
|
|
2562
2563
|
const next = typeof update === "function" ? update(current) : update;
|
|
@@ -2569,6 +2570,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2569
2570
|
setPendingAction(null);
|
|
2570
2571
|
setRestoreDraft(null);
|
|
2571
2572
|
}, [memoryKey]);
|
|
2573
|
+
useEffect8(() => {
|
|
2574
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2575
|
+
lastNavigation.current = navigation.id;
|
|
2576
|
+
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
2577
|
+
setRestoreDraft({
|
|
2578
|
+
id: `host:${String(navigation.id)}`,
|
|
2579
|
+
text: navigation.draft ?? "",
|
|
2580
|
+
context: navigation.context,
|
|
2581
|
+
images: navigation.images
|
|
2582
|
+
});
|
|
2583
|
+
}, [navigation]);
|
|
2572
2584
|
useEffect8(() => {
|
|
2573
2585
|
if (!pending) return;
|
|
2574
2586
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
@@ -2893,6 +2905,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2893
2905
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2894
2906
|
const [opening, setOpening] = useState6(null);
|
|
2895
2907
|
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2908
|
+
const [chatNavigation, setChatNavigation] = useState6(null);
|
|
2896
2909
|
const [listFocus, setListFocus] = useState6(null);
|
|
2897
2910
|
const lastNavigation = useRef7(null);
|
|
2898
2911
|
const setView = (next) => {
|
|
@@ -2905,17 +2918,21 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2905
2918
|
lastNavigation.current = navigation.id;
|
|
2906
2919
|
if (navigation.view === "list") {
|
|
2907
2920
|
setOpening(null);
|
|
2921
|
+
setChatNavigation(null);
|
|
2908
2922
|
setView("list");
|
|
2909
2923
|
return;
|
|
2910
2924
|
}
|
|
2911
2925
|
if (navigation.view === "new") {
|
|
2912
2926
|
setListFocus("@new");
|
|
2927
|
+
setChatNavigation(null);
|
|
2913
2928
|
setNewNavigation(navigation);
|
|
2914
2929
|
setView("new");
|
|
2915
2930
|
return;
|
|
2916
2931
|
}
|
|
2917
2932
|
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2918
2933
|
setListFocus(navigation.sessionKey);
|
|
2934
|
+
setNewNavigation(null);
|
|
2935
|
+
setChatNavigation(navigation);
|
|
2919
2936
|
if (state.attached?.key === navigation.sessionKey) {
|
|
2920
2937
|
setOpening(null);
|
|
2921
2938
|
setView("chat");
|
|
@@ -2937,6 +2954,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2937
2954
|
}, [opening, state.attachError?.key, state.attached?.key, state.error, state.operation]);
|
|
2938
2955
|
const open = (row) => {
|
|
2939
2956
|
setListFocus(row.key);
|
|
2957
|
+
setChatNavigation(null);
|
|
2940
2958
|
setOpening(row);
|
|
2941
2959
|
adapter.onIntent({ action: "attach", key: row.key });
|
|
2942
2960
|
};
|
|
@@ -2946,6 +2964,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2946
2964
|
return /* @__PURE__ */ jsxs8("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2947
2965
|
view === "list" ? /* @__PURE__ */ jsx9(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2948
2966
|
setListFocus("@new");
|
|
2967
|
+
setChatNavigation(null);
|
|
2949
2968
|
setNewNavigation(null);
|
|
2950
2969
|
setView("new");
|
|
2951
2970
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
@@ -2955,9 +2974,10 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2955
2974
|
setView("list");
|
|
2956
2975
|
}, onNew: () => {
|
|
2957
2976
|
setListFocus("@new");
|
|
2977
|
+
setChatNavigation(null);
|
|
2958
2978
|
setNewNavigation(null);
|
|
2959
2979
|
setView("new");
|
|
2960
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
2980
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
2961
2981
|
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2962
2982
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2963
2983
|
/* @__PURE__ */ jsxs8("span", { children: [
|
package/index.d.ts
CHANGED
|
@@ -468,7 +468,7 @@ export interface MessengerSlots {
|
|
|
468
468
|
|
|
469
469
|
export type MessengerNavigation =
|
|
470
470
|
| { id: string | number; view: 'list' }
|
|
471
|
-
| { id: string | number; view: 'chat'; sessionKey: string }
|
|
471
|
+
| { id: string | number; view: 'chat'; sessionKey: string; draft?: string; context?: TranscriptContext[]; images?: Array<TranscriptImage & { url: string }> }
|
|
472
472
|
| { id: string | number; view: 'new'; harness?: HarnessId; draft?: string; context?: TranscriptContext[]; images?: Array<TranscriptImage & { url: string }> };
|
|
473
473
|
|
|
474
474
|
export interface MessengerProps {
|
package/messenger.mjs
CHANGED
|
@@ -2544,7 +2544,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2544
2544
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2545
2545
|
] });
|
|
2546
2546
|
}
|
|
2547
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2547
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2548
2548
|
const Header = slots.header;
|
|
2549
2549
|
const HeaderActions = slots.headerActions;
|
|
2550
2550
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2554,6 +2554,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2554
2554
|
const [settings, setSettings] = useState6(null);
|
|
2555
2555
|
const restoreSequence = useRef7(0);
|
|
2556
2556
|
const actionSequence = useRef7(0);
|
|
2557
|
+
const lastNavigation = useRef7(null);
|
|
2557
2558
|
const acknowledged = useRef7(/* @__PURE__ */ new Set());
|
|
2558
2559
|
const setPending = (update) => setPendingState((current) => {
|
|
2559
2560
|
const next = typeof update === "function" ? update(current) : update;
|
|
@@ -2566,6 +2567,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2566
2567
|
setPendingAction(null);
|
|
2567
2568
|
setRestoreDraft(null);
|
|
2568
2569
|
}, [memoryKey]);
|
|
2570
|
+
useEffect8(() => {
|
|
2571
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2572
|
+
lastNavigation.current = navigation.id;
|
|
2573
|
+
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
2574
|
+
setRestoreDraft({
|
|
2575
|
+
id: `host:${String(navigation.id)}`,
|
|
2576
|
+
text: navigation.draft ?? "",
|
|
2577
|
+
context: navigation.context,
|
|
2578
|
+
images: navigation.images
|
|
2579
|
+
});
|
|
2580
|
+
}, [navigation]);
|
|
2569
2581
|
useEffect8(() => {
|
|
2570
2582
|
if (!pending) return;
|
|
2571
2583
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
@@ -2890,6 +2902,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2890
2902
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2891
2903
|
const [opening, setOpening] = useState6(null);
|
|
2892
2904
|
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2905
|
+
const [chatNavigation, setChatNavigation] = useState6(null);
|
|
2893
2906
|
const [listFocus, setListFocus] = useState6(null);
|
|
2894
2907
|
const lastNavigation = useRef7(null);
|
|
2895
2908
|
const setView = (next) => {
|
|
@@ -2902,17 +2915,21 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2902
2915
|
lastNavigation.current = navigation.id;
|
|
2903
2916
|
if (navigation.view === "list") {
|
|
2904
2917
|
setOpening(null);
|
|
2918
|
+
setChatNavigation(null);
|
|
2905
2919
|
setView("list");
|
|
2906
2920
|
return;
|
|
2907
2921
|
}
|
|
2908
2922
|
if (navigation.view === "new") {
|
|
2909
2923
|
setListFocus("@new");
|
|
2924
|
+
setChatNavigation(null);
|
|
2910
2925
|
setNewNavigation(navigation);
|
|
2911
2926
|
setView("new");
|
|
2912
2927
|
return;
|
|
2913
2928
|
}
|
|
2914
2929
|
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2915
2930
|
setListFocus(navigation.sessionKey);
|
|
2931
|
+
setNewNavigation(null);
|
|
2932
|
+
setChatNavigation(navigation);
|
|
2916
2933
|
if (state.attached?.key === navigation.sessionKey) {
|
|
2917
2934
|
setOpening(null);
|
|
2918
2935
|
setView("chat");
|
|
@@ -2934,6 +2951,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2934
2951
|
}, [opening, state.attachError?.key, state.attached?.key, state.error, state.operation]);
|
|
2935
2952
|
const open = (row) => {
|
|
2936
2953
|
setListFocus(row.key);
|
|
2954
|
+
setChatNavigation(null);
|
|
2937
2955
|
setOpening(row);
|
|
2938
2956
|
adapter.onIntent({ action: "attach", key: row.key });
|
|
2939
2957
|
};
|
|
@@ -2943,6 +2961,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2943
2961
|
return /* @__PURE__ */ jsxs8("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2944
2962
|
view === "list" ? /* @__PURE__ */ jsx9(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2945
2963
|
setListFocus("@new");
|
|
2964
|
+
setChatNavigation(null);
|
|
2946
2965
|
setNewNavigation(null);
|
|
2947
2966
|
setView("new");
|
|
2948
2967
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
@@ -2952,9 +2971,10 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2952
2971
|
setView("list");
|
|
2953
2972
|
}, onNew: () => {
|
|
2954
2973
|
setListFocus("@new");
|
|
2974
|
+
setChatNavigation(null);
|
|
2955
2975
|
setNewNavigation(null);
|
|
2956
2976
|
setView("new");
|
|
2957
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
2977
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
2958
2978
|
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2959
2979
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2960
2980
|
/* @__PURE__ */ jsxs8("span", { children: [
|
package/package.json
CHANGED
package/react/components.mjs
CHANGED
|
@@ -2627,7 +2627,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2627
2627
|
onClose ? /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx10(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2628
2628
|
] });
|
|
2629
2629
|
}
|
|
2630
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2630
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2631
2631
|
const Header = slots.header;
|
|
2632
2632
|
const HeaderActions = slots.headerActions;
|
|
2633
2633
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2637,6 +2637,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2637
2637
|
const [settings, setSettings] = useState6(null);
|
|
2638
2638
|
const restoreSequence = useRef7(0);
|
|
2639
2639
|
const actionSequence = useRef7(0);
|
|
2640
|
+
const lastNavigation = useRef7(null);
|
|
2640
2641
|
const acknowledged = useRef7(/* @__PURE__ */ new Set());
|
|
2641
2642
|
const setPending = (update) => setPendingState((current) => {
|
|
2642
2643
|
const next = typeof update === "function" ? update(current) : update;
|
|
@@ -2649,6 +2650,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2649
2650
|
setPendingAction(null);
|
|
2650
2651
|
setRestoreDraft(null);
|
|
2651
2652
|
}, [memoryKey]);
|
|
2653
|
+
useEffect8(() => {
|
|
2654
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2655
|
+
lastNavigation.current = navigation.id;
|
|
2656
|
+
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
2657
|
+
setRestoreDraft({
|
|
2658
|
+
id: `host:${String(navigation.id)}`,
|
|
2659
|
+
text: navigation.draft ?? "",
|
|
2660
|
+
context: navigation.context,
|
|
2661
|
+
images: navigation.images
|
|
2662
|
+
});
|
|
2663
|
+
}, [navigation]);
|
|
2652
2664
|
useEffect8(() => {
|
|
2653
2665
|
if (!pending) return;
|
|
2654
2666
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
@@ -2973,6 +2985,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2973
2985
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2974
2986
|
const [opening, setOpening] = useState6(null);
|
|
2975
2987
|
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2988
|
+
const [chatNavigation, setChatNavigation] = useState6(null);
|
|
2976
2989
|
const [listFocus, setListFocus] = useState6(null);
|
|
2977
2990
|
const lastNavigation = useRef7(null);
|
|
2978
2991
|
const setView = (next) => {
|
|
@@ -2985,17 +2998,21 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2985
2998
|
lastNavigation.current = navigation.id;
|
|
2986
2999
|
if (navigation.view === "list") {
|
|
2987
3000
|
setOpening(null);
|
|
3001
|
+
setChatNavigation(null);
|
|
2988
3002
|
setView("list");
|
|
2989
3003
|
return;
|
|
2990
3004
|
}
|
|
2991
3005
|
if (navigation.view === "new") {
|
|
2992
3006
|
setListFocus("@new");
|
|
3007
|
+
setChatNavigation(null);
|
|
2993
3008
|
setNewNavigation(navigation);
|
|
2994
3009
|
setView("new");
|
|
2995
3010
|
return;
|
|
2996
3011
|
}
|
|
2997
3012
|
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2998
3013
|
setListFocus(navigation.sessionKey);
|
|
3014
|
+
setNewNavigation(null);
|
|
3015
|
+
setChatNavigation(navigation);
|
|
2999
3016
|
if (state.attached?.key === navigation.sessionKey) {
|
|
3000
3017
|
setOpening(null);
|
|
3001
3018
|
setView("chat");
|
|
@@ -3017,6 +3034,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3017
3034
|
}, [opening, state.attachError?.key, state.attached?.key, state.error, state.operation]);
|
|
3018
3035
|
const open = (row) => {
|
|
3019
3036
|
setListFocus(row.key);
|
|
3037
|
+
setChatNavigation(null);
|
|
3020
3038
|
setOpening(row);
|
|
3021
3039
|
adapter.onIntent({ action: "attach", key: row.key });
|
|
3022
3040
|
};
|
|
@@ -3026,6 +3044,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3026
3044
|
return /* @__PURE__ */ jsxs9("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
3027
3045
|
view === "list" ? /* @__PURE__ */ jsx10(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
3028
3046
|
setListFocus("@new");
|
|
3047
|
+
setChatNavigation(null);
|
|
3029
3048
|
setNewNavigation(null);
|
|
3030
3049
|
setView("new");
|
|
3031
3050
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
@@ -3035,9 +3054,10 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3035
3054
|
setView("list");
|
|
3036
3055
|
}, onNew: () => {
|
|
3037
3056
|
setListFocus("@new");
|
|
3057
|
+
setChatNavigation(null);
|
|
3038
3058
|
setNewNavigation(null);
|
|
3039
3059
|
setView("new");
|
|
3040
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
3060
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
3041
3061
|
opening ? /* @__PURE__ */ jsxs9("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
3042
3062
|
/* @__PURE__ */ jsx10(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
3043
3063
|
/* @__PURE__ */ jsxs9("span", { children: [
|
package/react/messenger.mjs
CHANGED
|
@@ -2544,7 +2544,7 @@ function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNe
|
|
|
2544
2544
|
onClose ? /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx9(UiIcon, { name: "close", size: 18 }) }) : null
|
|
2545
2545
|
] });
|
|
2546
2546
|
}
|
|
2547
|
-
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates }) {
|
|
2547
|
+
function Chat({ state, adapter, onBack, onNew, onClose, components, slots, labels, contextCandidates, navigation }) {
|
|
2548
2548
|
const Header = slots.header;
|
|
2549
2549
|
const HeaderActions = slots.headerActions;
|
|
2550
2550
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
@@ -2554,6 +2554,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2554
2554
|
const [settings, setSettings] = useState6(null);
|
|
2555
2555
|
const restoreSequence = useRef7(0);
|
|
2556
2556
|
const actionSequence = useRef7(0);
|
|
2557
|
+
const lastNavigation = useRef7(null);
|
|
2557
2558
|
const acknowledged = useRef7(/* @__PURE__ */ new Set());
|
|
2558
2559
|
const setPending = (update) => setPendingState((current) => {
|
|
2559
2560
|
const next = typeof update === "function" ? update(current) : update;
|
|
@@ -2566,6 +2567,17 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2566
2567
|
setPendingAction(null);
|
|
2567
2568
|
setRestoreDraft(null);
|
|
2568
2569
|
}, [memoryKey]);
|
|
2570
|
+
useEffect8(() => {
|
|
2571
|
+
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2572
|
+
lastNavigation.current = navigation.id;
|
|
2573
|
+
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
2574
|
+
setRestoreDraft({
|
|
2575
|
+
id: `host:${String(navigation.id)}`,
|
|
2576
|
+
text: navigation.draft ?? "",
|
|
2577
|
+
context: navigation.context,
|
|
2578
|
+
images: navigation.images
|
|
2579
|
+
});
|
|
2580
|
+
}, [navigation]);
|
|
2569
2581
|
useEffect8(() => {
|
|
2570
2582
|
if (!pending) return;
|
|
2571
2583
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
@@ -2890,6 +2902,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2890
2902
|
const [view, setViewState] = useState6(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
2891
2903
|
const [opening, setOpening] = useState6(null);
|
|
2892
2904
|
const [newNavigation, setNewNavigation] = useState6(null);
|
|
2905
|
+
const [chatNavigation, setChatNavigation] = useState6(null);
|
|
2893
2906
|
const [listFocus, setListFocus] = useState6(null);
|
|
2894
2907
|
const lastNavigation = useRef7(null);
|
|
2895
2908
|
const setView = (next) => {
|
|
@@ -2902,17 +2915,21 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2902
2915
|
lastNavigation.current = navigation.id;
|
|
2903
2916
|
if (navigation.view === "list") {
|
|
2904
2917
|
setOpening(null);
|
|
2918
|
+
setChatNavigation(null);
|
|
2905
2919
|
setView("list");
|
|
2906
2920
|
return;
|
|
2907
2921
|
}
|
|
2908
2922
|
if (navigation.view === "new") {
|
|
2909
2923
|
setListFocus("@new");
|
|
2924
|
+
setChatNavigation(null);
|
|
2910
2925
|
setNewNavigation(navigation);
|
|
2911
2926
|
setView("new");
|
|
2912
2927
|
return;
|
|
2913
2928
|
}
|
|
2914
2929
|
if (navigation.view === "chat" && typeof navigation.sessionKey === "string" && navigation.sessionKey) {
|
|
2915
2930
|
setListFocus(navigation.sessionKey);
|
|
2931
|
+
setNewNavigation(null);
|
|
2932
|
+
setChatNavigation(navigation);
|
|
2916
2933
|
if (state.attached?.key === navigation.sessionKey) {
|
|
2917
2934
|
setOpening(null);
|
|
2918
2935
|
setView("chat");
|
|
@@ -2934,6 +2951,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2934
2951
|
}, [opening, state.attachError?.key, state.attached?.key, state.error, state.operation]);
|
|
2935
2952
|
const open = (row) => {
|
|
2936
2953
|
setListFocus(row.key);
|
|
2954
|
+
setChatNavigation(null);
|
|
2937
2955
|
setOpening(row);
|
|
2938
2956
|
adapter.onIntent({ action: "attach", key: row.key });
|
|
2939
2957
|
};
|
|
@@ -2943,6 +2961,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2943
2961
|
return /* @__PURE__ */ jsxs8("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
2944
2962
|
view === "list" ? /* @__PURE__ */ jsx9(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onNew: () => {
|
|
2945
2963
|
setListFocus("@new");
|
|
2964
|
+
setChatNavigation(null);
|
|
2946
2965
|
setNewNavigation(null);
|
|
2947
2966
|
setView("new");
|
|
2948
2967
|
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
@@ -2952,9 +2971,10 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
2952
2971
|
setView("list");
|
|
2953
2972
|
}, onNew: () => {
|
|
2954
2973
|
setListFocus("@new");
|
|
2974
|
+
setChatNavigation(null);
|
|
2955
2975
|
setNewNavigation(null);
|
|
2956
2976
|
setView("new");
|
|
2957
|
-
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates }) : null,
|
|
2977
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null }) : null,
|
|
2958
2978
|
opening ? /* @__PURE__ */ jsxs8("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
2959
2979
|
/* @__PURE__ */ jsx9(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
2960
2980
|
/* @__PURE__ */ jsxs8("span", { children: [
|