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