@volter-ai-dev/supercode-ui 0.1.67 → 0.1.68

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.
@@ -32,6 +32,10 @@ var EMPTY_UI_STATE = Object.freeze({
32
32
  harness: "",
33
33
  mode: "none",
34
34
  strategy: null,
35
+ participant: Object.freeze({ kind: "local-user", label: null, origin: null }),
36
+ workspaceRef: Object.freeze({ kind: "none", value: null }),
37
+ mirror: null,
38
+ holder: null,
35
39
  canSend: false,
36
40
  canSteer: false,
37
41
  canResume: false,
@@ -641,12 +645,40 @@ function readToolPresentation(value, entry) {
641
645
  matches: nullableNumber(item.matches) ?? generated.matches
642
646
  };
643
647
  }
648
+ var OPAQUE_RAW_CHARS = 4e3;
649
+ function opaqueEntry(item) {
650
+ const previouslyOpaque = item.role === "opaque";
651
+ let raw;
652
+ if (previouslyOpaque && typeof item.raw === "string") {
653
+ raw = item.raw;
654
+ } else {
655
+ try {
656
+ raw = JSON.stringify(item, null, 2) ?? "";
657
+ } catch {
658
+ raw = "[unserializable entry payload]";
659
+ }
660
+ }
661
+ const kind = previouslyOpaque && typeof item.kind === "string" ? item.kind : typeof item.role === "string" ? item.role : "";
662
+ return {
663
+ id: item.id,
664
+ role: "opaque",
665
+ kind: boundedString(kind, 120) || "unknown",
666
+ text: typeof item.text === "string" ? boundedString(item.text, OPAQUE_RAW_CHARS) : "",
667
+ ts: nullableNumber(item.ts),
668
+ truncated: item.truncated === true || raw.length > OPAQUE_RAW_CHARS,
669
+ raw: boundedString(raw, OPAQUE_RAW_CHARS)
670
+ };
671
+ }
644
672
  function readTranscript(value) {
645
673
  if (!Array.isArray(value)) return [];
646
674
  const result = [];
647
675
  for (const candidate of value) {
648
676
  const item = record(candidate);
649
- if (!item || typeof item.id !== "string" || typeof item.text !== "string" || !ROLES.has(item.role)) continue;
677
+ if (!item || typeof item.id !== "string") continue;
678
+ if (typeof item.text !== "string" || !ROLES.has(item.role)) {
679
+ result.push(opaqueEntry(item));
680
+ continue;
681
+ }
650
682
  const entry = {
651
683
  id: item.id,
652
684
  role: item.role,
@@ -704,6 +736,75 @@ function readTranscript(value) {
704
736
  }
705
737
  return result;
706
738
  }
739
+ function readParticipant(value) {
740
+ const participant = record(value);
741
+ if (!participant) return { kind: "local-user", label: null, origin: null };
742
+ return {
743
+ kind: ["local-user", "foreign", "unknown"].includes(participant.kind) ? participant.kind : "unknown",
744
+ label: typeof participant.label === "string" && participant.label ? boundedString(participant.label, 200) : null,
745
+ origin: typeof participant.origin === "string" && participant.origin ? boundedString(participant.origin, 100) : null
746
+ };
747
+ }
748
+ function readWorkspaceRef(value, fallbackPath = "") {
749
+ const ref = record(value);
750
+ if (ref && ["repo", "none", "channel"].includes(ref.kind)) {
751
+ return {
752
+ kind: ref.kind,
753
+ value: ref.kind === "none" ? null : typeof ref.value === "string" && ref.value ? boundedString(ref.value, 500) : null
754
+ };
755
+ }
756
+ return fallbackPath ? { kind: "repo", value: boundedString(fallbackPath, 500) } : { kind: "none", value: null };
757
+ }
758
+ function readMirror(value) {
759
+ const mirror = record(value);
760
+ if (!mirror || typeof mirror.canonicalHarness !== "string" || !mirror.canonicalHarness) return null;
761
+ return {
762
+ canonicalHarness: boundedString(mirror.canonicalHarness, 100),
763
+ canonicalKey: typeof mirror.canonicalKey === "string" && mirror.canonicalKey ? boundedString(mirror.canonicalKey, 300) : null,
764
+ bounded: mirror.bounded === true,
765
+ truncated: mirror.truncated === true,
766
+ origin: typeof mirror.origin === "string" && mirror.origin ? boundedString(mirror.origin, 200) : null
767
+ };
768
+ }
769
+ function readHolder(value) {
770
+ const holder = record(value);
771
+ if (!holder) return null;
772
+ const surface = typeof holder.surface === "string" && holder.surface ? boundedString(holder.surface, 100) : null;
773
+ return {
774
+ surface,
775
+ canTakeOver: holder.canTakeOver === true && surface !== null && surface !== "supercode"
776
+ };
777
+ }
778
+ var TRIGGER_KINDS = ["human", "channel", "cron", "heartbeat", "webhook", "parent", "api", "unknown"];
779
+ function readTrigger(value) {
780
+ const trigger = record(value);
781
+ if (!trigger) return null;
782
+ const kind = trigger.kind === "manual" ? "human" : trigger.kind;
783
+ return {
784
+ kind: TRIGGER_KINDS.includes(kind) ? kind : "unknown",
785
+ label: typeof trigger.label === "string" && trigger.label ? boundedString(trigger.label, 200) : null,
786
+ surface: typeof trigger.surface === "string" && trigger.surface ? boundedString(trigger.surface, 300) : null
787
+ };
788
+ }
789
+ function readCrossSurface(value) {
790
+ const moved = record(value);
791
+ if (!moved || typeof moved.state !== "string" || !moved.state) return null;
792
+ return {
793
+ state: boundedString(moved.state, 100),
794
+ platform: typeof moved.platform === "string" && moved.platform ? boundedString(moved.platform, 100) : null,
795
+ error: typeof moved.error === "string" && moved.error ? boundedString(moved.error, 500) : null
796
+ };
797
+ }
798
+ function readRecurring(value) {
799
+ const recurring = record(value);
800
+ if (!recurring || typeof recurring.groupKey !== "string" || !recurring.groupKey) return null;
801
+ const runs = Number.isSafeInteger(recurring.runs) && recurring.runs > 0 ? recurring.runs : 1;
802
+ return {
803
+ groupKey: boundedString(recurring.groupKey, 300),
804
+ runs,
805
+ lastStatus: ["ok", "failed", "mixed"].includes(recurring.lastStatus) ? recurring.lastStatus : null
806
+ };
807
+ }
707
808
  function readSessions(value) {
708
809
  if (!Array.isArray(value)) return [];
709
810
  return value.flatMap((raw) => {
@@ -725,7 +826,13 @@ function readSessions(value) {
725
826
  live: row.live === true,
726
827
  runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null,
727
828
  ...Number.isSafeInteger(row.subagentCount) && row.subagentCount > 0 ? { subagentCount: row.subagentCount } : {},
728
- activity: ACTIVITY_PRIORITY[row.activity] !== void 0 ? row.activity : void 0
829
+ activity: ACTIVITY_PRIORITY[row.activity] !== void 0 ? row.activity : void 0,
830
+ ...row.participant !== void 0 ? { participant: readParticipant(row.participant) } : {},
831
+ workspaceRef: readWorkspaceRef(row.workspaceRef, string(row.cwd)),
832
+ ...readMirror(row.mirror) ? { mirror: readMirror(row.mirror) } : {},
833
+ ...readTrigger(row.trigger) ? { trigger: readTrigger(row.trigger) } : {},
834
+ ...readRecurring(row.recurring) ? { recurring: readRecurring(row.recurring) } : {},
835
+ ...readCrossSurface(row.crossSurface) ? { crossSurface: readCrossSurface(row.crossSurface) } : {}
729
836
  }];
730
837
  });
731
838
  }
@@ -909,6 +1016,10 @@ function normalizeUiState(value) {
909
1016
  canConfigureSettings: raw.canConfigureSettings === true,
910
1017
  messaging: raw.messaging === "live_peer" ? "live_peer" : null,
911
1018
  workspace: string(raw.workspace),
1019
+ workspaceRef: readWorkspaceRef(raw.workspaceRef, string(raw.workspace)),
1020
+ participant: readParticipant(raw.participant),
1021
+ mirror: readMirror(raw.mirror),
1022
+ holder: readHolder(raw.holder),
912
1023
  taskPlan: readTaskPlan(raw.taskPlan),
913
1024
  semantics: readSemantics(raw.semantics),
914
1025
  terminalHandoff: readTerminalHandoff(raw.terminalHandoff),
@@ -1070,6 +1181,12 @@ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } fro
1070
1181
 
1071
1182
  // src/memory.js
1072
1183
  var MEMORY_LIMIT = 100;
1184
+ var registry = /* @__PURE__ */ new Set();
1185
+ function uiMemory() {
1186
+ const map = /* @__PURE__ */ new Map();
1187
+ registry.add(map);
1188
+ return map;
1189
+ }
1073
1190
  function boundedSet(map, key, value) {
1074
1191
  map.delete(key);
1075
1192
  map.set(key, value);
@@ -1423,7 +1540,7 @@ function MessageImages({ items, adapter }) {
1423
1540
  }
1424
1541
 
1425
1542
  // src/intent.js
1426
- var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
1543
+ var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export", "take_over"]);
1427
1544
  async function dispatchConfirmedIntent(adapter, intent) {
1428
1545
  if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
1429
1546
  const confirmed = await adapter.confirmIntent(intent);
@@ -1448,7 +1565,7 @@ function useAutosizeTextarea(ref, value) {
1448
1565
 
1449
1566
  // src/composer.jsx
1450
1567
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1451
- var composerMemory = /* @__PURE__ */ new Map();
1568
+ var composerMemory = uiMemory();
1452
1569
  function ExecutionModeSelect({ modes = [], value, onChange, disabled = false, label = "Run in" }) {
1453
1570
  if (modes.length < 2) return null;
1454
1571
  return /* @__PURE__ */ jsxs3("label", { className: "scui-execution-mode", title: disabled ? void 0 : `${label}: ${value}`, children: [
@@ -1744,7 +1861,11 @@ function languageLabel(info) {
1744
1861
  }
1745
1862
  function frameCode(render, tokens, index, options, env, self) {
1746
1863
  const label = markdown.utils.escapeHtml(languageLabel(tokens[index]?.info ?? ""));
1747
- return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${render(tokens, index, options, env, self)}</div>`;
1864
+ const body = render(tokens, index, options, env, self).replace(
1865
+ "<pre>",
1866
+ `<pre tabindex="0" role="region" aria-label="${label} code">`
1867
+ );
1868
+ return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${body}</div>`;
1748
1869
  }
1749
1870
  for (const kind of ["fence", "code_block"]) {
1750
1871
  const render = markdown.renderer.rules[kind];
@@ -2081,6 +2202,26 @@ function TechnicalDetails({ entry }) {
2081
2202
  ] });
2082
2203
  }
2083
2204
  function TranscriptEntry({ entry, state, adapter }) {
2205
+ if (entry.role === "opaque") {
2206
+ return /* @__PURE__ */ jsxs4("article", { className: "scui-message scui-opaque", "data-role": "opaque", "data-kind": entry.kind, "aria-label": "Unrecognized entry", children: [
2207
+ /* @__PURE__ */ jsxs4("div", { className: "scui-notice", "data-code": "opaque-entry", children: [
2208
+ "Unrecognized entry kind ",
2209
+ /* @__PURE__ */ jsx5("code", { children: entry.kind }),
2210
+ " \u2014 kept as-is, nothing dropped"
2211
+ ] }),
2212
+ entry.text ? /* @__PURE__ */ jsx5(Markdown, { value: entry.text, copyText: adapter?.copyText }) : null,
2213
+ entry.raw ? /* @__PURE__ */ jsxs4("details", { className: "scui-tool-technical", children: [
2214
+ /* @__PURE__ */ jsx5("summary", { children: "Technical details" }),
2215
+ /* @__PURE__ */ jsx5("div", { children: /* @__PURE__ */ jsxs4("section", { children: [
2216
+ /* @__PURE__ */ jsx5("strong", { children: "Raw entry" }),
2217
+ /* @__PURE__ */ jsxs4("pre", { children: [
2218
+ entry.raw,
2219
+ entry.truncated ? "\n[truncated]" : ""
2220
+ ] })
2221
+ ] }) })
2222
+ ] }) : null
2223
+ ] });
2224
+ }
2084
2225
  if (entry.role === "request") return /* @__PURE__ */ jsx5(RequestCard, { entry, adapter, canRespond: state.canRespond });
2085
2226
  if (entry.role === "reasoning") {
2086
2227
  return /* @__PURE__ */ jsxs4("details", { className: "scui-reasoning", open: entry.streaming, children: [
@@ -2210,7 +2351,7 @@ function SessionDetails({ semantics }) {
2210
2351
  ] })
2211
2352
  ] });
2212
2353
  }
2213
- var conversationMemory = /* @__PURE__ */ new Map();
2354
+ var conversationMemory = uiMemory();
2214
2355
  function ConversationAnnouncements({ state }) {
2215
2356
  const previousBusy = useRef4(state.busy);
2216
2357
  const [announcement, setAnnouncement] = useState3("");
@@ -2390,7 +2531,7 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
2390
2531
  // src/sessions.jsx
2391
2532
  import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect3, useRef as useRef5, useState as useState4 } from "react";
2392
2533
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2393
- var sessionListMemory = /* @__PURE__ */ new Map();
2534
+ var sessionListMemory = uiMemory();
2394
2535
  function sessionPathParts(value) {
2395
2536
  const complete = String(value ?? "").replaceAll("\\", "/");
2396
2537
  const boundary = complete.lastIndexOf("/");
@@ -2412,11 +2553,55 @@ function SessionRow({ row, state, onOpen, onOpenSubagents, now = Date.now() }) {
2412
2553
  const unreadCount = attention?.unreadCount ?? 0;
2413
2554
  const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
2414
2555
  const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
2415
- return /* @__PURE__ */ jsxs6("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, children: [
2556
+ const nounBadges = [];
2557
+ if (row.trigger && row.trigger.kind !== "manual" && row.trigger.kind !== "human") {
2558
+ const runs = row.recurring?.runs;
2559
+ const detail = row.trigger.label || row.trigger.surface || "";
2560
+ nounBadges.push(
2561
+ /* @__PURE__ */ jsxs6("small", { className: "scui-session-noun", "data-noun": "trigger", "data-kind": row.trigger.kind, "data-surface": row.trigger.surface ?? void 0, "data-status": row.recurring?.lastStatus ?? void 0, children: [
2562
+ row.trigger.kind,
2563
+ detail ? ` \xB7 ${detail}` : "",
2564
+ runs && runs > 1 ? ` \xB7 \xD7${runs}` : ""
2565
+ ] }, "trigger")
2566
+ );
2567
+ }
2568
+ if (row.crossSurface) {
2569
+ nounBadges.push(
2570
+ /* @__PURE__ */ jsxs6("small", { className: "scui-session-noun", "data-noun": "cross-surface", "data-state": row.crossSurface.state, title: row.crossSurface.error ?? void 0, children: [
2571
+ "\u2192",
2572
+ row.crossSurface.platform ?? "elsewhere",
2573
+ " \xB7 ",
2574
+ row.crossSurface.state
2575
+ ] }, "cross-surface")
2576
+ );
2577
+ }
2578
+ if (row.participant && row.participant.kind !== "local-user") {
2579
+ nounBadges.push(
2580
+ /* @__PURE__ */ jsx7("small", { className: "scui-session-noun", "data-noun": "participant", "data-kind": row.participant.kind, children: row.participant.kind === "foreign" ? `${row.participant.label ?? "someone else"}${row.participant.origin ? ` via ${row.participant.origin}` : ""}` : "unknown participant" }, "participant")
2581
+ );
2582
+ }
2583
+ if (row.mirror) {
2584
+ nounBadges.push(
2585
+ /* @__PURE__ */ jsxs6("small", { className: "scui-session-noun", "data-noun": "mirror", "data-truncated": row.mirror.truncated, children: [
2586
+ "mirror of ",
2587
+ harnessDisplayName(row.mirror.canonicalHarness)
2588
+ ] }, "mirror")
2589
+ );
2590
+ }
2591
+ if (row.workspaceRef?.kind === "channel") {
2592
+ nounBadges.push(
2593
+ /* @__PURE__ */ jsxs6("small", { className: "scui-session-noun", "data-noun": "workspace", "data-kind": "channel", children: [
2594
+ "#",
2595
+ row.workspaceRef.value ?? "channel"
2596
+ ] }, "workspace")
2597
+ );
2598
+ }
2599
+ return /* @__PURE__ */ jsxs6("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-workspace-kind": row.workspaceRef?.kind, children: [
2416
2600
  /* @__PURE__ */ jsxs6("button", { className: "scui-session-main", "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
2417
2601
  /* @__PURE__ */ jsx7(HarnessLogo, { id: row.harness, activity, size: 34 }),
2418
2602
  /* @__PURE__ */ jsxs6("span", { className: "scui-session-copy", children: [
2419
2603
  /* @__PURE__ */ jsx7("span", { className: "scui-session-title", children: /* @__PURE__ */ jsx7("strong", { children: title }) }),
2604
+ nounBadges.length ? /* @__PURE__ */ jsx7("span", { className: "scui-session-nouns", children: nounBadges }) : null,
2420
2605
  path.complete ? /* @__PURE__ */ jsxs6("small", { className: "scui-session-path", title: row.cwd, children: [
2421
2606
  /* @__PURE__ */ jsx7("span", { className: "scui-session-path-leading", children: path.leading }),
2422
2607
  path.separator ? /* @__PURE__ */ jsx7("span", { className: "scui-session-path-separator", children: path.separator }) : null,
@@ -2831,10 +3016,54 @@ function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onC
2831
3016
 
2832
3017
  // src/messenger.jsx
2833
3018
  import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2834
- var pendingMessageMemory = /* @__PURE__ */ new Map();
2835
- var messengerViewMemory = /* @__PURE__ */ new Map();
2836
- var newChatMemory = /* @__PURE__ */ new Map();
3019
+ var pendingMessageMemory = uiMemory();
3020
+ var messengerViewMemory = uiMemory();
3021
+ var newChatMemory = uiMemory();
2837
3022
  var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "steer", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
3023
+ function UniversalNouns({ state, adapter }) {
3024
+ const banners = [];
3025
+ if (state.participant && state.participant.kind !== "local-user") {
3026
+ banners.push(
3027
+ /* @__PURE__ */ jsx10("div", { className: "scui-notice scui-noun-banner", "data-noun": "participant", "data-kind": state.participant.kind, children: state.participant.kind === "foreign" ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
3028
+ "This is ",
3029
+ /* @__PURE__ */ jsx10("strong", { children: state.participant.label ?? "someone else's" }),
3030
+ " conversation",
3031
+ state.participant.origin ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
3032
+ " via ",
3033
+ state.participant.origin
3034
+ ] }) : null,
3035
+ "."
3036
+ ] }) : /* @__PURE__ */ jsx10(Fragment5, { children: "Unknown participant \u2014 this conversation was not started here." }) }, "participant")
3037
+ );
3038
+ }
3039
+ if (state.mirror) {
3040
+ banners.push(
3041
+ /* @__PURE__ */ jsxs9("div", { className: "scui-notice scui-noun-banner", "data-noun": "mirror", "data-truncated": state.mirror.truncated, children: [
3042
+ state.mirror.bounded ? "Bounded mirror" : "Mirror",
3043
+ " of a ",
3044
+ /* @__PURE__ */ jsx10("strong", { children: harnessDisplayName(state.mirror.canonicalHarness) }),
3045
+ " session \u2014 the canonical record lives in its own store",
3046
+ state.mirror.truncated ? " (truncated here)" : "",
3047
+ ".",
3048
+ state.mirror.canonicalKey ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => adapter.onIntent({ action: "open_session", key: state.mirror.canonicalKey }), children: "Open canonical session" }) : null
3049
+ ] }, "mirror")
3050
+ );
3051
+ }
3052
+ if (state.holder && state.holder.surface !== "supercode") {
3053
+ banners.push(
3054
+ /* @__PURE__ */ jsxs9("div", { className: "scui-notice scui-noun-banner", "data-noun": "holder", "data-surface": state.holder.surface ?? "unheld", children: [
3055
+ state.holder.surface ? /* @__PURE__ */ jsxs9(Fragment5, { children: [
3056
+ "Held by ",
3057
+ /* @__PURE__ */ jsx10("strong", { children: state.holder.surface }),
3058
+ " right now."
3059
+ ] }) : /* @__PURE__ */ jsx10(Fragment5, { children: "No surface holds this session right now." }),
3060
+ state.holder.canTakeOver ? /* @__PURE__ */ jsx10("button", { type: "button", onClick: () => dispatchConfirmedIntent(adapter, { action: "take_over" }), children: "Take over" }) : null
3061
+ ] }, "holder")
3062
+ );
3063
+ }
3064
+ if (!banners.length) return null;
3065
+ return /* @__PURE__ */ jsx10("div", { className: "scui-noun-banners", children: banners });
3066
+ }
2838
3067
  function Receipt({ state, adapter }) {
2839
3068
  const receipt = state.reductionReceipt;
2840
3069
  if (receipt) return /* @__PURE__ */ jsx10("div", { className: "scui-receipt", children: /* @__PURE__ */ jsxs9("span", { children: [
@@ -3098,6 +3327,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
3098
3327
  state.recoverable ? /* @__PURE__ */ jsx10("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
3099
3328
  ] }) : null,
3100
3329
  /* @__PURE__ */ jsx10(Receipt, { state, adapter }),
3330
+ /* @__PURE__ */ jsx10(UniversalNouns, { state: actionState, adapter: trackedAdapter }),
3101
3331
  /* @__PURE__ */ jsx10(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
3102
3332
  /* @__PURE__ */ jsx10(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
3103
3333
  /* @__PURE__ */ jsx10(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
@@ -32,6 +32,10 @@ var EMPTY_UI_STATE = Object.freeze({
32
32
  harness: "",
33
33
  mode: "none",
34
34
  strategy: null,
35
+ participant: Object.freeze({ kind: "local-user", label: null, origin: null }),
36
+ workspaceRef: Object.freeze({ kind: "none", value: null }),
37
+ mirror: null,
38
+ holder: null,
35
39
  canSend: false,
36
40
  canSteer: false,
37
41
  canResume: false,
@@ -160,7 +164,11 @@ function languageLabel(info) {
160
164
  }
161
165
  function frameCode(render, tokens, index, options, env, self) {
162
166
  const label = markdown.utils.escapeHtml(languageLabel(tokens[index]?.info ?? ""));
163
- return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${render(tokens, index, options, env, self)}</div>`;
167
+ const body = render(tokens, index, options, env, self).replace(
168
+ "<pre>",
169
+ `<pre tabindex="0" role="region" aria-label="${label} code">`
170
+ );
171
+ return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${body}</div>`;
164
172
  }
165
173
  for (const kind of ["fence", "code_block"]) {
166
174
  const render = markdown.renderer.rules[kind];
@@ -175,6 +183,12 @@ markdown.renderer.rules.link_open = (tokens, index, options, env, self) => {
175
183
 
176
184
  // src/memory.js
177
185
  var MEMORY_LIMIT = 100;
186
+ var registry = /* @__PURE__ */ new Set();
187
+ function uiMemory() {
188
+ const map = /* @__PURE__ */ new Map();
189
+ registry.add(map);
190
+ return map;
191
+ }
178
192
  function boundedSet(map, key, value) {
179
193
  map.delete(key);
180
194
  map.set(key, value);
@@ -264,6 +278,7 @@ function LoadingStatus({ state, compact = false }) {
264
278
  /* @__PURE__ */ jsx4("span", { className: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx4("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
265
279
  ] });
266
280
  }
281
+ var conversationMemory = uiMemory();
267
282
 
268
283
  // src/logo.jsx
269
284
  import { useEffect as useEffect4 } from "react";
@@ -331,7 +346,7 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
331
346
 
332
347
  // src/sessions.jsx
333
348
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
334
- var sessionListMemory = /* @__PURE__ */ new Map();
349
+ var sessionListMemory = uiMemory();
335
350
  function sessionPathParts(value) {
336
351
  const complete = String(value ?? "").replaceAll("\\", "/");
337
352
  const boundary = complete.lastIndexOf("/");
@@ -353,11 +368,55 @@ function SessionRow({ row, state, onOpen, onOpenSubagents, now = Date.now() }) {
353
368
  const unreadCount = attention?.unreadCount ?? 0;
354
369
  const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
355
370
  const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
356
- return /* @__PURE__ */ jsxs5("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, children: [
371
+ const nounBadges = [];
372
+ if (row.trigger && row.trigger.kind !== "manual" && row.trigger.kind !== "human") {
373
+ const runs = row.recurring?.runs;
374
+ const detail = row.trigger.label || row.trigger.surface || "";
375
+ nounBadges.push(
376
+ /* @__PURE__ */ jsxs5("small", { className: "scui-session-noun", "data-noun": "trigger", "data-kind": row.trigger.kind, "data-surface": row.trigger.surface ?? void 0, "data-status": row.recurring?.lastStatus ?? void 0, children: [
377
+ row.trigger.kind,
378
+ detail ? ` \xB7 ${detail}` : "",
379
+ runs && runs > 1 ? ` \xB7 \xD7${runs}` : ""
380
+ ] }, "trigger")
381
+ );
382
+ }
383
+ if (row.crossSurface) {
384
+ nounBadges.push(
385
+ /* @__PURE__ */ jsxs5("small", { className: "scui-session-noun", "data-noun": "cross-surface", "data-state": row.crossSurface.state, title: row.crossSurface.error ?? void 0, children: [
386
+ "\u2192",
387
+ row.crossSurface.platform ?? "elsewhere",
388
+ " \xB7 ",
389
+ row.crossSurface.state
390
+ ] }, "cross-surface")
391
+ );
392
+ }
393
+ if (row.participant && row.participant.kind !== "local-user") {
394
+ nounBadges.push(
395
+ /* @__PURE__ */ jsx6("small", { className: "scui-session-noun", "data-noun": "participant", "data-kind": row.participant.kind, children: row.participant.kind === "foreign" ? `${row.participant.label ?? "someone else"}${row.participant.origin ? ` via ${row.participant.origin}` : ""}` : "unknown participant" }, "participant")
396
+ );
397
+ }
398
+ if (row.mirror) {
399
+ nounBadges.push(
400
+ /* @__PURE__ */ jsxs5("small", { className: "scui-session-noun", "data-noun": "mirror", "data-truncated": row.mirror.truncated, children: [
401
+ "mirror of ",
402
+ harnessDisplayName(row.mirror.canonicalHarness)
403
+ ] }, "mirror")
404
+ );
405
+ }
406
+ if (row.workspaceRef?.kind === "channel") {
407
+ nounBadges.push(
408
+ /* @__PURE__ */ jsxs5("small", { className: "scui-session-noun", "data-noun": "workspace", "data-kind": "channel", children: [
409
+ "#",
410
+ row.workspaceRef.value ?? "channel"
411
+ ] }, "workspace")
412
+ );
413
+ }
414
+ return /* @__PURE__ */ jsxs5("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-workspace-kind": row.workspaceRef?.kind, children: [
357
415
  /* @__PURE__ */ jsxs5("button", { className: "scui-session-main", "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${row.writable ? "" : " \xB7 Read-only"}${working ? " \xB7 Working" : ""}${path.complete ? ` \xB7 ${path.complete}` : ""}${preview ? ` \xB7 ${preview}` : ""}${unreadCount ? ` \xB7 ${unreadCount} unread` : ""}${age ? ` \xB7 ${age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
358
416
  /* @__PURE__ */ jsx6(HarnessLogo, { id: row.harness, activity, size: 34 }),
359
417
  /* @__PURE__ */ jsxs5("span", { className: "scui-session-copy", children: [
360
418
  /* @__PURE__ */ jsx6("span", { className: "scui-session-title", children: /* @__PURE__ */ jsx6("strong", { children: title }) }),
419
+ nounBadges.length ? /* @__PURE__ */ jsx6("span", { className: "scui-session-nouns", children: nounBadges }) : null,
361
420
  path.complete ? /* @__PURE__ */ jsxs5("small", { className: "scui-session-path", title: row.cwd, children: [
362
421
  /* @__PURE__ */ jsx6("span", { className: "scui-session-path-leading", children: path.leading }),
363
422
  path.separator ? /* @__PURE__ */ jsx6("span", { className: "scui-session-path-separator", children: path.separator }) : null,
@@ -32,6 +32,10 @@ var EMPTY_UI_STATE = Object.freeze({
32
32
  harness: "",
33
33
  mode: "none",
34
34
  strategy: null,
35
+ participant: Object.freeze({ kind: "local-user", label: null, origin: null }),
36
+ workspaceRef: Object.freeze({ kind: "none", value: null }),
37
+ mirror: null,
38
+ holder: null,
35
39
  canSend: false,
36
40
  canSteer: false,
37
41
  canResume: false,
@@ -32,6 +32,10 @@ var EMPTY_UI_STATE = Object.freeze({
32
32
  harness: "",
33
33
  mode: "none",
34
34
  strategy: null,
35
+ participant: Object.freeze({ kind: "local-user", label: null, origin: null }),
36
+ workspaceRef: Object.freeze({ kind: "none", value: null }),
37
+ mirror: null,
38
+ holder: null,
35
39
  canSend: false,
36
40
  canSteer: false,
37
41
  canResume: false,
@@ -542,7 +546,11 @@ function languageLabel(info) {
542
546
  }
543
547
  function frameCode(render, tokens, index, options, env, self) {
544
548
  const label = markdown.utils.escapeHtml(languageLabel(tokens[index]?.info ?? ""));
545
- return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${render(tokens, index, options, env, self)}</div>`;
549
+ const body = render(tokens, index, options, env, self).replace(
550
+ "<pre>",
551
+ `<pre tabindex="0" role="region" aria-label="${label} code">`
552
+ );
553
+ return `<div class="scui-code-block"><div class="scui-code-head"><span>${label}</span><button class="scui-code-copy" type="button" aria-label="Copy code" title="Copy code">${COPY_ICON}<span>Copy</span></button></div>${body}</div>`;
546
554
  }
547
555
  for (const kind of ["fence", "code_block"]) {
548
556
  const render = markdown.renderer.rules[kind];
@@ -600,6 +608,12 @@ function Markdown({ value, copyText }) {
600
608
 
601
609
  // src/memory.js
602
610
  var MEMORY_LIMIT = 100;
611
+ var registry = /* @__PURE__ */ new Set();
612
+ function uiMemory() {
613
+ const map = /* @__PURE__ */ new Map();
614
+ registry.add(map);
615
+ return map;
616
+ }
603
617
  function boundedSet(map, key, value) {
604
618
  map.delete(key);
605
619
  map.set(key, value);
@@ -1103,6 +1117,26 @@ function TechnicalDetails({ entry }) {
1103
1117
  ] });
1104
1118
  }
1105
1119
  function TranscriptEntry({ entry, state, adapter }) {
1120
+ if (entry.role === "opaque") {
1121
+ return /* @__PURE__ */ jsxs3("article", { className: "scui-message scui-opaque", "data-role": "opaque", "data-kind": entry.kind, "aria-label": "Unrecognized entry", children: [
1122
+ /* @__PURE__ */ jsxs3("div", { className: "scui-notice", "data-code": "opaque-entry", children: [
1123
+ "Unrecognized entry kind ",
1124
+ /* @__PURE__ */ jsx4("code", { children: entry.kind }),
1125
+ " \u2014 kept as-is, nothing dropped"
1126
+ ] }),
1127
+ entry.text ? /* @__PURE__ */ jsx4(Markdown, { value: entry.text, copyText: adapter?.copyText }) : null,
1128
+ entry.raw ? /* @__PURE__ */ jsxs3("details", { className: "scui-tool-technical", children: [
1129
+ /* @__PURE__ */ jsx4("summary", { children: "Technical details" }),
1130
+ /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsxs3("section", { children: [
1131
+ /* @__PURE__ */ jsx4("strong", { children: "Raw entry" }),
1132
+ /* @__PURE__ */ jsxs3("pre", { children: [
1133
+ entry.raw,
1134
+ entry.truncated ? "\n[truncated]" : ""
1135
+ ] })
1136
+ ] }) })
1137
+ ] }) : null
1138
+ ] });
1139
+ }
1106
1140
  if (entry.role === "request") return /* @__PURE__ */ jsx4(RequestCard, { entry, adapter, canRespond: state.canRespond });
1107
1141
  if (entry.role === "reasoning") {
1108
1142
  return /* @__PURE__ */ jsxs3("details", { className: "scui-reasoning", open: entry.streaming, children: [
@@ -1232,7 +1266,7 @@ function SessionDetails({ semantics }) {
1232
1266
  ] })
1233
1267
  ] });
1234
1268
  }
1235
- var conversationMemory = /* @__PURE__ */ new Map();
1269
+ var conversationMemory = uiMemory();
1236
1270
  function ConversationAnnouncements({ state }) {
1237
1271
  const previousBusy = useRef3(state.busy);
1238
1272
  const [announcement, setAnnouncement] = useState2("");