@volter-ai-dev/supercode-ui 0.1.55 → 0.1.57
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/components.mjs +155 -112
- package/embed.mjs +155 -112
- package/messenger.mjs +155 -112
- package/package.json +1 -1
- package/react/components.mjs +155 -112
- package/react/messenger.mjs +155 -112
- package/react/sessions.mjs +3 -4
- package/react/subagents.mjs +66 -21
- package/sessions.mjs +3 -4
- package/styles.css +2 -2
- package/subagents.mjs +66 -21
package/messenger.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/messenger.jsx
|
|
2
|
-
import { useEffect as
|
|
2
|
+
import { useEffect as useEffect9, useId as useId3, useMemo as useMemo3, useRef as useRef8, useState as useState7 } from "preact/hooks";
|
|
3
3
|
|
|
4
4
|
// core.mjs
|
|
5
5
|
var HARNESS_NAMES = Object.freeze({
|
|
@@ -2280,11 +2280,10 @@ function SessionRow({ row, state, onOpen, onOpenSubagents, now = Date.now() }) {
|
|
|
2280
2280
|
state.attachError?.key === row.key ? /* @__PURE__ */ jsx7("em", { children: state.attachError.message }) : null
|
|
2281
2281
|
] })
|
|
2282
2282
|
] }),
|
|
2283
|
-
row.subagentCount ? /* @__PURE__ */ jsxs6("button", { className: "scui-session-agents", type: "button", "aria-label": `
|
|
2283
|
+
row.subagentCount ? /* @__PURE__ */ jsxs6("button", { className: "scui-session-agents", type: "button", "aria-label": `Open ${row.subagentCount} agent sessions in ${title}`, onClick: () => onOpenSubagents?.(row), children: [
|
|
2284
2284
|
/* @__PURE__ */ jsx7(UiIcon, { name: "agents", size: 14 }),
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
row.subagentCount === 1 ? "agent" : "agents"
|
|
2285
|
+
"Agents \xB7 ",
|
|
2286
|
+
row.subagentCount
|
|
2288
2287
|
] }) : null
|
|
2289
2288
|
] });
|
|
2290
2289
|
}
|
|
@@ -2362,11 +2361,51 @@ function SessionList({ state, adapter, onOpen, onOpenSubagents, onNew, onClose,
|
|
|
2362
2361
|
}
|
|
2363
2362
|
|
|
2364
2363
|
// src/subagents.jsx
|
|
2364
|
+
import { useEffect as useEffect7, useRef as useRef6, useState as useState5 } from "preact/hooks";
|
|
2365
2365
|
import { jsx as jsx8, jsxs as jsxs7 } from "preact/jsx-runtime";
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
if (
|
|
2366
|
+
var ACTIVE_ACTIVITY = /* @__PURE__ */ new Set(["working", "running", "recent"]);
|
|
2367
|
+
function activityLabel(activity, age) {
|
|
2368
|
+
if (activity === "needs-input") return "Needs input";
|
|
2369
|
+
if (activity === "failed") return "Failed";
|
|
2370
|
+
if (activity === "unseen") return "New update";
|
|
2371
|
+
if (activity === "working") return "Working";
|
|
2372
|
+
if (activity === "running") return "Running";
|
|
2373
|
+
if (activity === "recent") return "Recent";
|
|
2374
|
+
if (activity === "finished") return "Finished";
|
|
2375
|
+
return age;
|
|
2376
|
+
}
|
|
2377
|
+
function SubagentRow({ row, inspector, adapter }) {
|
|
2378
|
+
return /* @__PURE__ */ jsxs7("button", { className: "scui-subagent-row", type: "button", "data-activity": row.activity ?? "idle", onClick: () => adapter.onIntent({ action: "openSubagent", parentKey: inspector.parentKey, key: row.key }), children: [
|
|
2379
|
+
/* @__PURE__ */ jsx8(HarnessLogo, { id: row.harness, activity: row.activity, size: 30 }),
|
|
2380
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2381
|
+
/* @__PURE__ */ jsx8("strong", { children: sessionDisplayName(row) }),
|
|
2382
|
+
/* @__PURE__ */ jsx8("small", { children: row.preview || (row.activity === "working" ? "Working\u2026" : row.cwd) })
|
|
2383
|
+
] }),
|
|
2384
|
+
/* @__PURE__ */ jsxs7("span", { children: [
|
|
2385
|
+
/* @__PURE__ */ jsx8("small", { children: activityLabel(row.activity, row.age) }),
|
|
2386
|
+
/* @__PURE__ */ jsx8(UiIcon, { name: "chevron", size: 14 })
|
|
2387
|
+
] })
|
|
2388
|
+
] });
|
|
2389
|
+
}
|
|
2390
|
+
function SubagentSection({ label, rows, inspector, adapter }) {
|
|
2391
|
+
if (!rows.length) return null;
|
|
2392
|
+
return /* @__PURE__ */ jsxs7("section", { className: "scui-subagent-section", "aria-labelledby": `scui-subagents-${label.toLowerCase().replaceAll(" ", "-")}`, children: [
|
|
2393
|
+
/* @__PURE__ */ jsx8("h2", { id: `scui-subagents-${label.toLowerCase().replaceAll(" ", "-")}`, children: label }),
|
|
2394
|
+
rows.map((row) => /* @__PURE__ */ jsx8(SubagentRow, { row, inspector, adapter }, row.key))
|
|
2395
|
+
] });
|
|
2396
|
+
}
|
|
2397
|
+
function SubagentInspectorContent({ state, adapter, onClose, inspector }) {
|
|
2369
2398
|
const selected = inspector.items.find((row) => row.key === inspector.selectedKey) ?? null;
|
|
2399
|
+
const active = inspector.items.filter((row) => ACTIVE_ACTIVITY.has(row.activity));
|
|
2400
|
+
const history = inspector.items.filter((row) => !ACTIVE_ACTIVITY.has(row.activity));
|
|
2401
|
+
const [historyOpen, setHistoryOpen] = useState5(false);
|
|
2402
|
+
const backButton = useRef6(null);
|
|
2403
|
+
useEffect7(() => {
|
|
2404
|
+
if (inspector.status === "ready" && !active.length) setHistoryOpen(true);
|
|
2405
|
+
}, [inspector.parentKey, inspector.status]);
|
|
2406
|
+
useEffect7(() => {
|
|
2407
|
+
backButton.current?.focus({ preventScroll: true });
|
|
2408
|
+
}, [selected?.key]);
|
|
2370
2409
|
const detailState = selected ? {
|
|
2371
2410
|
...state,
|
|
2372
2411
|
transcript: inspector.transcript,
|
|
@@ -2387,15 +2426,14 @@ function SubagentInspector({ state, adapter, onClose }) {
|
|
|
2387
2426
|
onClose();
|
|
2388
2427
|
};
|
|
2389
2428
|
const back = () => selected ? adapter.onIntent({ action: "openSubagents", key: inspector.parentKey }) : leave();
|
|
2390
|
-
return /* @__PURE__ */ jsxs7("section", { className: "scui-subagents", "aria-label": `
|
|
2429
|
+
return /* @__PURE__ */ jsxs7("section", { className: "scui-subagents", "aria-label": `Agents for ${inspector.parentTitle}`, children: [
|
|
2391
2430
|
/* @__PURE__ */ jsxs7("header", { className: "scui-head", children: [
|
|
2392
|
-
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": selected ? "Back to
|
|
2393
|
-
/* @__PURE__ */ jsx8(UiIcon, { name: "agents", size: 20 }),
|
|
2431
|
+
/* @__PURE__ */ jsx8("button", { ref: backButton, type: "button", "aria-label": selected ? "Back to agents" : "Back to chats", onClick: back, children: /* @__PURE__ */ jsx8(UiIcon, { name: "back", size: 17 }) }),
|
|
2432
|
+
selected ? /* @__PURE__ */ jsx8(HarnessLogo, { id: selected.harness, activity: selected.activity, size: 24 }) : /* @__PURE__ */ jsx8(UiIcon, { name: "agents", size: 20 }),
|
|
2394
2433
|
/* @__PURE__ */ jsxs7("span", { className: "scui-head-copy", children: [
|
|
2395
|
-
/* @__PURE__ */ jsx8("strong", { children: selected ? sessionDisplayName(selected) :
|
|
2396
|
-
/* @__PURE__ */ jsx8("small", { children: selected ? `${harnessDisplayName(selected.harness)} \xB7 Read-only` : inspector.parentTitle })
|
|
2397
|
-
] })
|
|
2398
|
-
/* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Close subagent inspector", onClick: leave, children: /* @__PURE__ */ jsx8(UiIcon, { name: "close", size: 18 }) })
|
|
2434
|
+
/* @__PURE__ */ jsx8("strong", { children: selected ? sessionDisplayName(selected) : "Agents" }),
|
|
2435
|
+
/* @__PURE__ */ jsx8("small", { children: selected ? `${harnessDisplayName(selected.harness)} \xB7 Read-only` : `${inspector.items.length} ${inspector.items.length === 1 ? "session" : "sessions"} \xB7 ${inspector.parentTitle}` })
|
|
2436
|
+
] })
|
|
2399
2437
|
] }),
|
|
2400
2438
|
inspector.status === "loading" ? /* @__PURE__ */ jsxs7("div", { className: "scui-subagents-loading", role: "status", children: [
|
|
2401
2439
|
/* @__PURE__ */ jsx8("i", {}),
|
|
@@ -2405,24 +2443,28 @@ function SubagentInspector({ state, adapter, onClose }) {
|
|
|
2405
2443
|
] })
|
|
2406
2444
|
] }) : null,
|
|
2407
2445
|
inspector.error ? /* @__PURE__ */ jsx8("div", { className: "scui-error", role: "alert", children: inspector.error }) : null,
|
|
2408
|
-
!selected && inspector.status === "ready" ? /* @__PURE__ */
|
|
2409
|
-
/* @__PURE__ */ jsx8(
|
|
2410
|
-
/* @__PURE__ */ jsxs7("
|
|
2411
|
-
/* @__PURE__ */
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
/* @__PURE__ */ jsx8(
|
|
2417
|
-
] })
|
|
2418
|
-
] }
|
|
2446
|
+
!selected && inspector.status === "ready" && inspector.items.length ? /* @__PURE__ */ jsxs7("div", { className: "scui-subagent-rows", children: [
|
|
2447
|
+
/* @__PURE__ */ jsx8(SubagentSection, { label: "Active", rows: active, inspector, adapter }),
|
|
2448
|
+
history.length ? /* @__PURE__ */ jsxs7("details", { className: "scui-subagent-history", open: historyOpen, onToggle: (event) => setHistoryOpen(event.currentTarget.open), children: [
|
|
2449
|
+
/* @__PURE__ */ jsxs7("summary", { children: [
|
|
2450
|
+
/* @__PURE__ */ jsx8("span", { children: "History" }),
|
|
2451
|
+
/* @__PURE__ */ jsx8("small", { children: history.length }),
|
|
2452
|
+
/* @__PURE__ */ jsx8(UiIcon, { name: "chevron", size: 14 })
|
|
2453
|
+
] }),
|
|
2454
|
+
/* @__PURE__ */ jsx8("div", { children: history.map((row) => /* @__PURE__ */ jsx8(SubagentRow, { row, inspector, adapter }, row.key)) })
|
|
2455
|
+
] }) : null
|
|
2456
|
+
] }) : null,
|
|
2419
2457
|
!selected && inspector.status === "ready" && !inspector.items.length ? /* @__PURE__ */ jsx8("div", { className: "scui-empty", children: "No native child sessions were found." }) : null,
|
|
2420
2458
|
selected && inspector.status === "ready" && detailState ? /* @__PURE__ */ jsx8(Conversation, { state: detailState, adapter, memoryKey: `subagent:${selected.key}` }) : null
|
|
2421
2459
|
] });
|
|
2422
2460
|
}
|
|
2461
|
+
function SubagentInspector({ state, adapter, onClose }) {
|
|
2462
|
+
if (!state.subagentInspector) return null;
|
|
2463
|
+
return /* @__PURE__ */ jsx8(SubagentInspectorContent, { state, adapter, onClose, inspector: state.subagentInspector });
|
|
2464
|
+
}
|
|
2423
2465
|
|
|
2424
2466
|
// src/settings.jsx
|
|
2425
|
-
import { useEffect as
|
|
2467
|
+
import { useEffect as useEffect8, useId as useId2, useMemo as useMemo2, useRef as useRef7, useState as useState6 } from "preact/hooks";
|
|
2426
2468
|
import { jsx as jsx9, jsxs as jsxs8 } from "preact/jsx-runtime";
|
|
2427
2469
|
function HarnessAdvisory({ state, onReview }) {
|
|
2428
2470
|
const advisory = state.interopSettings?.advisories[0];
|
|
@@ -2445,12 +2487,12 @@ function initialValues(report, recommendedChange) {
|
|
|
2445
2487
|
function HarnessSettingsPanel({ state, adapter, onClose, recommendedChange = null }) {
|
|
2446
2488
|
const report = state.interopSettings;
|
|
2447
2489
|
const titleId = useId2();
|
|
2448
|
-
const panel =
|
|
2490
|
+
const panel = useRef7(null);
|
|
2449
2491
|
const valuesKey = `${report?.revision ?? ""}:${recommendedChange?.key ?? ""}:${recommendedChange?.value ?? ""}`;
|
|
2450
2492
|
const defaults = useMemo2(() => report ? initialValues(report, recommendedChange) : {}, [valuesKey]);
|
|
2451
|
-
const [values, setValues] =
|
|
2452
|
-
|
|
2453
|
-
|
|
2493
|
+
const [values, setValues] = useState6(defaults);
|
|
2494
|
+
useEffect8(() => setValues(defaults), [defaults]);
|
|
2495
|
+
useEffect8(() => {
|
|
2454
2496
|
panel.current?.querySelector("select, button")?.focus({ preventScroll: true });
|
|
2455
2497
|
const dismiss = (event) => {
|
|
2456
2498
|
if (event.key === "Escape") {
|
|
@@ -2538,11 +2580,11 @@ function HarnessReadiness({ harnesses, adapter }) {
|
|
|
2538
2580
|
] });
|
|
2539
2581
|
}
|
|
2540
2582
|
function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange, logo: Logo = HarnessLogo }) {
|
|
2541
|
-
const [open, setOpen] =
|
|
2583
|
+
const [open, setOpen] = useState6(false);
|
|
2542
2584
|
const menuId = useId2();
|
|
2543
|
-
const root =
|
|
2544
|
-
const trigger =
|
|
2545
|
-
const panel =
|
|
2585
|
+
const root = useRef7(null);
|
|
2586
|
+
const trigger = useRef7(null);
|
|
2587
|
+
const panel = useRef7(null);
|
|
2546
2588
|
const available = harnesses.filter((item) => item.startable);
|
|
2547
2589
|
const unavailable = harnesses.filter((item) => !item.startable);
|
|
2548
2590
|
const selected = available.find((item) => item.id === value) ?? available[0] ?? null;
|
|
@@ -2550,7 +2592,7 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2550
2592
|
setOpen(false);
|
|
2551
2593
|
trigger.current?.focus({ preventScroll: true });
|
|
2552
2594
|
};
|
|
2553
|
-
|
|
2595
|
+
useEffect8(() => {
|
|
2554
2596
|
if (!open) return;
|
|
2555
2597
|
panel.current?.querySelector('[aria-selected="true"], [role="option"]')?.focus({ preventScroll: true });
|
|
2556
2598
|
const dismiss = (event) => {
|
|
@@ -2612,7 +2654,7 @@ function HarnessPicker({ harnesses, value, disabled = false, adapter, onChange,
|
|
|
2612
2654
|
}
|
|
2613
2655
|
|
|
2614
2656
|
// src/messenger.jsx
|
|
2615
|
-
import { jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
2657
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "preact/jsx-runtime";
|
|
2616
2658
|
var pendingMessageMemory = /* @__PURE__ */ new Map();
|
|
2617
2659
|
var messengerViewMemory = /* @__PURE__ */ new Map();
|
|
2618
2660
|
var newChatMemory = /* @__PURE__ */ new Map();
|
|
@@ -2655,10 +2697,10 @@ function Receipt({ state, adapter }) {
|
|
|
2655
2697
|
return null;
|
|
2656
2698
|
}
|
|
2657
2699
|
function ConversationActions({ state, adapter, actionPending, onNew, onSettings }) {
|
|
2658
|
-
const [open, setOpen] =
|
|
2659
|
-
const root =
|
|
2660
|
-
const panel =
|
|
2661
|
-
const trigger =
|
|
2700
|
+
const [open, setOpen] = useState7(false);
|
|
2701
|
+
const root = useRef8(null);
|
|
2702
|
+
const panel = useRef8(null);
|
|
2703
|
+
const trigger = useRef8(null);
|
|
2662
2704
|
const menuId = useId3();
|
|
2663
2705
|
const targets = state.harnesses.filter((item) => item.startable);
|
|
2664
2706
|
const groups = [
|
|
@@ -2682,7 +2724,7 @@ function ConversationActions({ state, adapter, actionPending, onNew, onSettings
|
|
|
2682
2724
|
items: state.canBranch ? targets.map((target) => ({ key: `branch:${target.id}`, label: target.id === state.harness ? `Fork in ${target.label}` : `Continue with ${target.label}`, intent: { action: "branch", targetHarness: target.id } })) : []
|
|
2683
2725
|
}
|
|
2684
2726
|
].filter((group) => group.items.length);
|
|
2685
|
-
|
|
2727
|
+
useEffect9(() => {
|
|
2686
2728
|
if (!open) return;
|
|
2687
2729
|
panel.current?.querySelector("button:not(:disabled)")?.focus({ preventScroll: true });
|
|
2688
2730
|
const dismiss = (event) => {
|
|
@@ -2733,11 +2775,11 @@ function ConversationActions({ state, adapter, actionPending, onNew, onSettings
|
|
|
2733
2775
|
] });
|
|
2734
2776
|
}
|
|
2735
2777
|
function ChatHeader({ state, adapter, pendingStatus, actionPending, onBack, onNew, onClose, onSettings, headerActions: HeaderActions }) {
|
|
2736
|
-
const back =
|
|
2778
|
+
const back = useRef8(null);
|
|
2737
2779
|
const harness = state.attached?.harness ?? state.harness;
|
|
2738
2780
|
const title = state.attached ? sessionDisplayName(state.attached) : harnessDisplayName(harness) || "Agent chat";
|
|
2739
2781
|
const status = state.needsInput ? "Needs input" : pendingStatus === "failed" ? "Send failed" : state.busy ? "Working" : pendingStatus === "sending" ? "Sending" : pendingStatus === "editing" ? "Editing message" : state.messaging === "live_peer" ? "Live" : state.mode === "mirror" ? "Read-only" : "Ready";
|
|
2740
|
-
|
|
2782
|
+
useEffect9(() => {
|
|
2741
2783
|
if (state.mode === "mirror" && !state.canSend) back.current?.focus({ preventScroll: true });
|
|
2742
2784
|
}, []);
|
|
2743
2785
|
return /* @__PURE__ */ jsxs9("header", { className: "scui-head scui-chat-head", children: [
|
|
@@ -2760,26 +2802,26 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2760
2802
|
const Header = slots.header;
|
|
2761
2803
|
const HeaderActions = slots.headerActions;
|
|
2762
2804
|
const memoryKey = state.attached?.key || `${state.harness}:${state.workspace}`;
|
|
2763
|
-
const [pending, setPendingState] =
|
|
2764
|
-
const [pendingAction, setPendingAction] =
|
|
2765
|
-
const [restoreDraft, setRestoreDraft] =
|
|
2766
|
-
const [settings, setSettings] =
|
|
2767
|
-
const restoreSequence =
|
|
2768
|
-
const actionSequence =
|
|
2769
|
-
const lastNavigation =
|
|
2770
|
-
const acknowledged =
|
|
2805
|
+
const [pending, setPendingState] = useState7(() => pendingMessageMemory.get(memoryKey) ?? null);
|
|
2806
|
+
const [pendingAction, setPendingAction] = useState7(null);
|
|
2807
|
+
const [restoreDraft, setRestoreDraft] = useState7(null);
|
|
2808
|
+
const [settings, setSettings] = useState7(null);
|
|
2809
|
+
const restoreSequence = useRef8(0);
|
|
2810
|
+
const actionSequence = useRef8(0);
|
|
2811
|
+
const lastNavigation = useRef8(null);
|
|
2812
|
+
const acknowledged = useRef8(/* @__PURE__ */ new Set());
|
|
2771
2813
|
const setPending = (update) => setPendingState((current) => {
|
|
2772
2814
|
const next = typeof update === "function" ? update(current) : update;
|
|
2773
2815
|
if (next) boundedSet(pendingMessageMemory, memoryKey, next);
|
|
2774
2816
|
else pendingMessageMemory.delete(memoryKey);
|
|
2775
2817
|
return next;
|
|
2776
2818
|
});
|
|
2777
|
-
|
|
2819
|
+
useEffect9(() => {
|
|
2778
2820
|
setPendingState(pendingMessageMemory.get(memoryKey) ?? null);
|
|
2779
2821
|
setPendingAction(null);
|
|
2780
2822
|
setRestoreDraft(null);
|
|
2781
2823
|
}, [memoryKey]);
|
|
2782
|
-
|
|
2824
|
+
useEffect9(() => {
|
|
2783
2825
|
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
2784
2826
|
lastNavigation.current = navigation.id;
|
|
2785
2827
|
if (navigation.draft === void 0 && !navigation.context?.length && !navigation.images?.length) return;
|
|
@@ -2790,7 +2832,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2790
2832
|
images: navigation.images
|
|
2791
2833
|
});
|
|
2792
2834
|
}, [navigation]);
|
|
2793
|
-
|
|
2835
|
+
useEffect9(() => {
|
|
2794
2836
|
if (!pending) return;
|
|
2795
2837
|
if (state.transcript.some((entry) => entry.role === "user" && entry.text.trim() === pending.text.trim() && !pending.baselineIds.includes(entry.id))) {
|
|
2796
2838
|
setPending(null);
|
|
@@ -2819,7 +2861,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2819
2861
|
setRestoreDraft({ id: restoreSequence.current, text: pending.text, context: pending.context, images: pending.images });
|
|
2820
2862
|
setPending({ ...pending, status: "editing" });
|
|
2821
2863
|
};
|
|
2822
|
-
|
|
2864
|
+
useEffect9(() => {
|
|
2823
2865
|
const key = state.attached?.key;
|
|
2824
2866
|
if (!key || !state.attention.some((item) => item.key === key)) {
|
|
2825
2867
|
if (key) acknowledged.current.delete(key);
|
|
@@ -2854,7 +2896,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
|
|
|
2854
2896
|
return result;
|
|
2855
2897
|
}
|
|
2856
2898
|
}), [adapter, state.error]);
|
|
2857
|
-
|
|
2899
|
+
useEffect9(() => {
|
|
2858
2900
|
if (!pendingAction) return;
|
|
2859
2901
|
if (state.operation && !pendingAction.seenOperation) {
|
|
2860
2902
|
setPendingAction({ ...pendingAction, seenOperation: true });
|
|
@@ -2891,18 +2933,18 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2891
2933
|
const startable = state.harnesses.filter((item) => item.startable);
|
|
2892
2934
|
const startableKey = startable.map((item) => `${item.id}:${item.launchModes?.join(",")}:${item.preferredLaunchMode ?? ""}`).join("\0");
|
|
2893
2935
|
const remembered = newChatMemory.get(memoryKey) ?? { harness: startable[0]?.id ?? "", draft: "", context: [], images: [], modes: {} };
|
|
2894
|
-
const [harness, setHarness] =
|
|
2895
|
-
const [draft, setDraft] =
|
|
2896
|
-
const [context, setContext] =
|
|
2897
|
-
const [images, setImages] =
|
|
2898
|
-
const [modes, setModes] =
|
|
2899
|
-
const [starting, setStarting] =
|
|
2900
|
-
const [picking, setPicking] =
|
|
2901
|
-
const [dragging, setDragging] =
|
|
2902
|
-
const [pickerError, setPickerError] =
|
|
2903
|
-
const startSequence =
|
|
2904
|
-
const lastComposerCommand =
|
|
2905
|
-
const textarea =
|
|
2936
|
+
const [harness, setHarness] = useState7(remembered.harness);
|
|
2937
|
+
const [draft, setDraft] = useState7(remembered.draft);
|
|
2938
|
+
const [context, setContext] = useState7(remembered.context);
|
|
2939
|
+
const [images, setImages] = useState7(remembered.images ?? []);
|
|
2940
|
+
const [modes, setModes] = useState7(remembered.modes ?? {});
|
|
2941
|
+
const [starting, setStarting] = useState7(null);
|
|
2942
|
+
const [picking, setPicking] = useState7(false);
|
|
2943
|
+
const [dragging, setDragging] = useState7(false);
|
|
2944
|
+
const [pickerError, setPickerError] = useState7(null);
|
|
2945
|
+
const startSequence = useRef8(0);
|
|
2946
|
+
const lastComposerCommand = useRef8(null);
|
|
2947
|
+
const textarea = useRef8(null);
|
|
2906
2948
|
const selectedHarness = startable.find((item) => item.id === harness) ?? null;
|
|
2907
2949
|
const Picker = components.HarnessPicker ?? HarnessPicker;
|
|
2908
2950
|
const Readiness = components.HarnessReadiness ?? HarnessReadiness;
|
|
@@ -2913,13 +2955,13 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2913
2955
|
const terminalAttachments = mode === "terminal" && (context.length > 0 || images.length > 0);
|
|
2914
2956
|
const remember = (overrides = {}) => boundedSet(newChatMemory, memoryKey, { harness, draft, context, images, modes, ...overrides });
|
|
2915
2957
|
useAutosizeTextarea(textarea, draft);
|
|
2916
|
-
|
|
2958
|
+
useEffect9(() => {
|
|
2917
2959
|
if (startable.some((item) => item.id === harness)) return;
|
|
2918
2960
|
const next = startable[0]?.id ?? "";
|
|
2919
2961
|
setHarness(next);
|
|
2920
2962
|
remember({ harness: next });
|
|
2921
2963
|
}, [harness, startableKey]);
|
|
2922
|
-
|
|
2964
|
+
useEffect9(() => {
|
|
2923
2965
|
if (!starting || starting.mode === "terminal") return;
|
|
2924
2966
|
const sessionChanged = (state.attached?.key ?? null) !== starting.attachedKey;
|
|
2925
2967
|
const beganWorking = !starting.busy && state.busy;
|
|
@@ -2927,13 +2969,13 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2927
2969
|
newChatMemory.delete(memoryKey);
|
|
2928
2970
|
onStarted("headless");
|
|
2929
2971
|
}, [memoryKey, onStarted, starting, state.attached?.key, state.busy]);
|
|
2930
|
-
|
|
2972
|
+
useEffect9(() => {
|
|
2931
2973
|
if (starting && state.error !== starting.initialError && !state.busy && !state.operation) setStarting(null);
|
|
2932
2974
|
}, [starting, state.busy, state.error, state.operation]);
|
|
2933
|
-
|
|
2975
|
+
useEffect9(() => {
|
|
2934
2976
|
textarea.current?.focus({ preventScroll: true });
|
|
2935
2977
|
}, []);
|
|
2936
|
-
|
|
2978
|
+
useEffect9(() => {
|
|
2937
2979
|
if (!navigation) return;
|
|
2938
2980
|
const nextHarness = startable.some((item) => item.id === navigation.harness) ? navigation.harness : harness;
|
|
2939
2981
|
const nextDraft = typeof navigation.draft === "string" ? navigation.draft : draft;
|
|
@@ -2946,7 +2988,7 @@ function NewChat({ state, adapter, onBack, onClose, onStarted, labels, memoryKey
|
|
|
2946
2988
|
remember({ harness: nextHarness, draft: nextDraft, context: nextContext, images: nextImages });
|
|
2947
2989
|
textarea.current?.focus({ preventScroll: true });
|
|
2948
2990
|
}, [navigation?.id]);
|
|
2949
|
-
|
|
2991
|
+
useEffect9(() => {
|
|
2950
2992
|
if (!composerCommand || composerCommand.id === lastComposerCommand.current) return;
|
|
2951
2993
|
lastComposerCommand.current = composerCommand.id;
|
|
2952
2994
|
if (composerCommand.action === "attach") {
|
|
@@ -3123,19 +3165,19 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3123
3165
|
const contextCandidates = useMemo3(() => normalizeAttachmentCandidates(candidatesInput), [candidatesInput]);
|
|
3124
3166
|
const copy = { ...DEFAULT_LABELS, ...labels };
|
|
3125
3167
|
const memoryKey = state.workspace || "@default";
|
|
3126
|
-
const [view, setViewState] =
|
|
3127
|
-
const [opening, setOpening] =
|
|
3128
|
-
const [newNavigation, setNewNavigation] =
|
|
3129
|
-
const [chatNavigation, setChatNavigation] =
|
|
3130
|
-
const [listFocus, setListFocus] =
|
|
3131
|
-
const [inspecting, setInspecting] =
|
|
3132
|
-
const lastNavigation =
|
|
3168
|
+
const [view, setViewState] = useState7(initialView ?? (state.attention.length ? "list" : messengerViewMemory.get(memoryKey) ?? (state.attached || state.transcript.length ? "chat" : "list")));
|
|
3169
|
+
const [opening, setOpening] = useState7(null);
|
|
3170
|
+
const [newNavigation, setNewNavigation] = useState7(null);
|
|
3171
|
+
const [chatNavigation, setChatNavigation] = useState7(null);
|
|
3172
|
+
const [listFocus, setListFocus] = useState7(null);
|
|
3173
|
+
const [inspecting, setInspecting] = useState7(null);
|
|
3174
|
+
const lastNavigation = useRef8(null);
|
|
3133
3175
|
const setView = (next) => {
|
|
3134
3176
|
boundedSet(messengerViewMemory, memoryKey, next);
|
|
3135
3177
|
setViewState(next);
|
|
3136
3178
|
onViewChange?.(next);
|
|
3137
3179
|
};
|
|
3138
|
-
|
|
3180
|
+
useEffect9(() => {
|
|
3139
3181
|
if (!navigation || navigation.id === lastNavigation.current) return;
|
|
3140
3182
|
lastNavigation.current = navigation.id;
|
|
3141
3183
|
if (navigation.view === "list") {
|
|
@@ -3165,7 +3207,7 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3165
3207
|
adapter.onIntent({ action: "attach", key: navigation.sessionKey });
|
|
3166
3208
|
}
|
|
3167
3209
|
}, [adapter, navigation, state.attached?.key, state.sessions]);
|
|
3168
|
-
|
|
3210
|
+
useEffect9(() => {
|
|
3169
3211
|
if (!opening) return;
|
|
3170
3212
|
if (state.attached?.key === opening.key) {
|
|
3171
3213
|
setOpening(null);
|
|
@@ -3193,35 +3235,36 @@ function SupercodeMessenger({ state: stateInput, adapter, class: className = "",
|
|
|
3193
3235
|
...state,
|
|
3194
3236
|
subagentInspector: state.subagentInspector?.parentKey === inspectorParent.key ? state.subagentInspector : { parentKey: inspectorParent.key, parentTitle: sessionDisplayName(inspectorParent), status: "loading", items: [], selectedKey: null, transcript: [], error: null }
|
|
3195
3237
|
} : null;
|
|
3196
|
-
return /* @__PURE__ */ jsxs9("main", { className: `scui-root ${className}`, "data-view": view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
/* @__PURE__ */
|
|
3215
|
-
|
|
3216
|
-
/* @__PURE__ */ jsxs9("
|
|
3217
|
-
|
|
3218
|
-
|
|
3238
|
+
return /* @__PURE__ */ jsxs9("main", { className: `scui-root ${className}`, "data-view": inspectorState ? "agents" : view, "data-mode": state.mode, "aria-label": "Supercode messenger", children: [
|
|
3239
|
+
inspectorState ? /* @__PURE__ */ jsx10(SubagentInspector, { state: inspectorState, adapter, onClose: () => setInspecting(null) }) : /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3240
|
+
view === "list" ? /* @__PURE__ */ jsx10(SessionList, { state, adapter, focusKey: listFocus, onOpen: open, onOpenSubagents: openSubagents, onNew: () => {
|
|
3241
|
+
setListFocus("@new");
|
|
3242
|
+
setChatNavigation(null);
|
|
3243
|
+
setNewNavigation(null);
|
|
3244
|
+
setView("new");
|
|
3245
|
+
}, onClose: adapter.onClose ? close : void 0, components, labels: copy, memoryKey, slots, headerActions: HeaderActions }) : null,
|
|
3246
|
+
view === "new" ? /* @__PURE__ */ jsx10(NewChat, { state, adapter, onBack: () => setView("list"), onClose: adapter.onClose ? close : void 0, onStarted: (mode) => setView(mode === "terminal" ? "list" : "chat"), labels: copy, memoryKey, headerActions: HeaderActions, contextCandidates, components, navigation: newNavigation, composerCommand }) : null,
|
|
3247
|
+
view === "chat" ? /* @__PURE__ */ jsx10(Chat, { state, adapter, onBack: () => {
|
|
3248
|
+
setListFocus(state.attached?.key ?? listFocus);
|
|
3249
|
+
setView("list");
|
|
3250
|
+
}, onNew: () => {
|
|
3251
|
+
setListFocus("@new");
|
|
3252
|
+
setChatNavigation(null);
|
|
3253
|
+
setNewNavigation(null);
|
|
3254
|
+
setView("new");
|
|
3255
|
+
}, onClose: adapter.onClose ? close : void 0, components, slots, labels: copy, contextCandidates, navigation: chatNavigation?.sessionKey === state.attached?.key ? chatNavigation : null, composerCommand }) : null,
|
|
3256
|
+
opening ? /* @__PURE__ */ jsxs9("div", { className: "scui-opening", role: "status", "aria-busy": "true", children: [
|
|
3257
|
+
/* @__PURE__ */ jsx10(HarnessLogo, { id: opening.harness, size: 34 }),
|
|
3258
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
3259
|
+
/* @__PURE__ */ jsxs9("strong", { children: [
|
|
3260
|
+
"Opening ",
|
|
3261
|
+
sessionDisplayName(opening)
|
|
3262
|
+
] }),
|
|
3263
|
+
/* @__PURE__ */ jsx10("small", { children: "Loading the latest transcript window\u2026" })
|
|
3219
3264
|
] }),
|
|
3220
|
-
/* @__PURE__ */ jsx10("
|
|
3221
|
-
] })
|
|
3222
|
-
|
|
3223
|
-
] }) : null,
|
|
3224
|
-
inspectorState ? /* @__PURE__ */ jsx10(SubagentInspector, { state: inspectorState, adapter, onClose: () => setInspecting(null) }) : null,
|
|
3265
|
+
/* @__PURE__ */ jsx10("i", {})
|
|
3266
|
+
] }) : null
|
|
3267
|
+
] }),
|
|
3225
3268
|
Footer ? /* @__PURE__ */ jsx10(Footer, { state, adapter, value: copy }) : null
|
|
3226
3269
|
] });
|
|
3227
3270
|
}
|