@volter-ai-dev/supercode-ui 0.1.66 → 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,
@@ -69,7 +73,12 @@ var EMPTY_UI_STATE = Object.freeze({
69
73
  subagentInspector: null,
70
74
  attached: null,
71
75
  owned: null,
72
- attachError: null
76
+ attachError: null,
77
+ agentPackage: null,
78
+ contributions: Object.freeze([]),
79
+ agentPackageError: null,
80
+ agentPackageCapabilityState: null,
81
+ agentPackageCapabilityError: null
73
82
  });
74
83
  var ROLES = /* @__PURE__ */ new Set(["system", "user", "assistant", "tool", "reasoning", "request", "notice"]);
75
84
  var MODES = /* @__PURE__ */ new Set(["none", "control", "mirror"]);
@@ -82,6 +91,10 @@ var AUTHENTICATION_PHASES = /* @__PURE__ */ new Set(["idle", "checking", "requir
82
91
  var MAX_TOOL_FIELDS = 8;
83
92
  var MAX_TOOL_FIELD_CHARS = 800;
84
93
  var MAX_TOOL_PREVIEW_CHARS = 4e3;
94
+ var MAX_CONTRIBUTIONS = 64;
95
+ var MAX_CONTRIBUTION_JSON_DEPTH = 12;
96
+ var MAX_CONTRIBUTION_COLLECTION = 100;
97
+ var MAX_CONTRIBUTION_STRING_CHARS = 16e3;
85
98
  function record(value) {
86
99
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
87
100
  }
@@ -114,6 +127,126 @@ function number(value, fallback = 0) {
114
127
  function nullableNumber(value) {
115
128
  return typeof value === "number" && Number.isFinite(value) ? value : null;
116
129
  }
130
+ function relativeContributionPath(value) {
131
+ if (typeof value !== "string" || value.startsWith("/") || /^[a-z]:[\\/]/i.test(value)) return null;
132
+ return value.replaceAll("\\", "/").split("/").some((segment) => segment === "..") ? null : boundedString(value, 1e3);
133
+ }
134
+ function contributionJson(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
135
+ if (value === null || typeof value === "boolean" || typeof value === "string") {
136
+ return typeof value === "string" ? boundedString(value, MAX_CONTRIBUTION_STRING_CHARS) : value;
137
+ }
138
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
139
+ if (depth >= MAX_CONTRIBUTION_JSON_DEPTH || !value || typeof value !== "object" || seen.has(value)) {
140
+ return void 0;
141
+ }
142
+ seen.add(value);
143
+ if (Array.isArray(value)) {
144
+ const result2 = [];
145
+ for (const item of value.slice(0, MAX_CONTRIBUTION_COLLECTION)) {
146
+ const normalized = contributionJson(item, depth + 1, seen);
147
+ if (normalized !== void 0) result2.push(normalized);
148
+ }
149
+ seen.delete(value);
150
+ return result2;
151
+ }
152
+ const source = record(value);
153
+ if (!source) return void 0;
154
+ const result = {};
155
+ for (const [key, item] of Object.entries(source).slice(0, MAX_CONTRIBUTION_COLLECTION)) {
156
+ const normalized = contributionJson(item, depth + 1, seen);
157
+ if (normalized !== void 0) result[boundedString(key, 200)] = normalized;
158
+ }
159
+ seen.delete(value);
160
+ return result;
161
+ }
162
+ function normalizeContributions(value) {
163
+ if (!Array.isArray(value)) return [];
164
+ return value.slice(0, MAX_CONTRIBUTIONS).flatMap((candidate) => {
165
+ const item = record(candidate);
166
+ const placement = record(item?.placement);
167
+ const source = relativeContributionPath(item?.source);
168
+ if (item?.schema !== "supercode/contribution-v1" || typeof item.id !== "string" || !item.id.trim() || typeof item.kind !== "string" || !item.kind.trim() || source === null) return [];
169
+ const data = contributionJson(item.data);
170
+ if (data === void 0) return [];
171
+ return [{
172
+ schema: "supercode/contribution-v1",
173
+ id: boundedString(item.id, 200),
174
+ kind: boundedString(item.kind, 100),
175
+ ...typeof item.title === "string" ? { title: boundedString(item.title, 500) } : {},
176
+ ...placement ? { placement: {
177
+ ...typeof placement.surface === "string" ? { surface: boundedString(placement.surface, 100) } : {},
178
+ ...typeof placement.region === "string" ? { region: boundedString(placement.region, 100) } : {}
179
+ } } : {},
180
+ data,
181
+ source
182
+ }];
183
+ });
184
+ }
185
+ function readAgentPackage(value) {
186
+ const agentPackage = record(value);
187
+ const capabilities = record(agentPackage?.capabilities);
188
+ const storage = record(agentPackage?.storage);
189
+ const relativePath = relativeContributionPath(storage?.relativePath);
190
+ if (agentPackage?.schemaVersion !== 1 || typeof agentPackage.id !== "string" || typeof agentPackage.name !== "string" || typeof agentPackage.version !== "string" || !capabilities || !Array.isArray(capabilities.required) || !Array.isArray(capabilities.optional) || !storage || relativePath === null) return null;
191
+ const resources = record(agentPackage.resources);
192
+ return {
193
+ id: boundedString(agentPackage.id, 200),
194
+ name: boundedString(agentPackage.name, 500),
195
+ version: boundedString(agentPackage.version, 100),
196
+ description: typeof agentPackage.description === "string" ? boundedString(agentPackage.description, 2e3) : null,
197
+ capabilities: {
198
+ required: capabilities.required.filter((item) => typeof item === "string").slice(0, 100).map((item) => boundedString(item, 200)),
199
+ optional: capabilities.optional.filter((item) => typeof item === "string").slice(0, 100).map((item) => boundedString(item, 200))
200
+ },
201
+ storage: { relativePath },
202
+ resources: resources ? Object.fromEntries(Object.entries(resources).flatMap(([id, candidate]) => {
203
+ const state = record(candidate);
204
+ if (state?.schema !== "supercode/package-resource-state-v1") return [];
205
+ if (state.status === "absent" && typeof state.contributionId === "string") {
206
+ return [[boundedString(id, 200), {
207
+ schema: "supercode/package-resource-state-v1",
208
+ status: "absent",
209
+ contributionId: boundedString(state.contributionId, 200)
210
+ }]];
211
+ }
212
+ if (state.status === "error" && typeof state.contributionId === "string" && typeof state.message === "string") {
213
+ return [[boundedString(id, 200), {
214
+ schema: "supercode/package-resource-state-v1",
215
+ status: "error",
216
+ contributionId: boundedString(state.contributionId, 200),
217
+ message: boundedString(state.message)
218
+ }]];
219
+ }
220
+ const resource = record(state?.resource);
221
+ const data = contributionJson(resource?.data);
222
+ if (state?.status !== "ready" || resource?.schema !== "supercode/package-resource-v1" || typeof resource.contributionId !== "string" || !["json", "text"].includes(resource.format) || typeof resource.mediaType !== "string" || data === void 0) return [];
223
+ return [[boundedString(id, 200), {
224
+ schema: "supercode/package-resource-state-v1",
225
+ status: "ready",
226
+ resource: {
227
+ schema: "supercode/package-resource-v1",
228
+ contributionId: boundedString(resource.contributionId, 200),
229
+ format: resource.format,
230
+ mediaType: boundedString(resource.mediaType, 200),
231
+ data
232
+ }
233
+ }]];
234
+ })) : {}
235
+ };
236
+ }
237
+ function readAgentPackageCapabilityState(value) {
238
+ const state = record(value);
239
+ if (!state) return null;
240
+ const fields = ["availableRequired", "missingRequired", "enabledOptional", "unavailableOptional"];
241
+ if (!fields.every((field) => Array.isArray(state[field]))) return null;
242
+ return {
243
+ ready: state.ready === true,
244
+ ...Object.fromEntries(fields.map((field) => [
245
+ field,
246
+ state[field].filter((item) => typeof item === "string").slice(0, 100).map((item) => boundedString(item, 200))
247
+ ]))
248
+ };
249
+ }
117
250
  function relativeAge(updatedAt, now = Date.now()) {
118
251
  if (typeof updatedAt !== "number" || !Number.isFinite(updatedAt) || updatedAt <= 0) return "";
119
252
  const delta = Math.max(0, now - updatedAt);
@@ -512,12 +645,40 @@ function readToolPresentation(value, entry) {
512
645
  matches: nullableNumber(item.matches) ?? generated.matches
513
646
  };
514
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
+ }
515
672
  function readTranscript(value) {
516
673
  if (!Array.isArray(value)) return [];
517
674
  const result = [];
518
675
  for (const candidate of value) {
519
676
  const item = record(candidate);
520
- 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
+ }
521
682
  const entry = {
522
683
  id: item.id,
523
684
  role: item.role,
@@ -575,6 +736,75 @@ function readTranscript(value) {
575
736
  }
576
737
  return result;
577
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
+ }
578
808
  function readSessions(value) {
579
809
  if (!Array.isArray(value)) return [];
580
810
  return value.flatMap((raw) => {
@@ -596,7 +826,13 @@ function readSessions(value) {
596
826
  live: row.live === true,
597
827
  runtimeStatus: row.runtimeStatus === "running" || row.runtimeStatus === "busy" || row.runtimeStatus === "idle" ? row.runtimeStatus : null,
598
828
  ...Number.isSafeInteger(row.subagentCount) && row.subagentCount > 0 ? { subagentCount: row.subagentCount } : {},
599
- 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) } : {}
600
836
  }];
601
837
  });
602
838
  }
@@ -780,6 +1016,10 @@ function normalizeUiState(value) {
780
1016
  canConfigureSettings: raw.canConfigureSettings === true,
781
1017
  messaging: raw.messaging === "live_peer" ? "live_peer" : null,
782
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),
783
1023
  taskPlan: readTaskPlan(raw.taskPlan),
784
1024
  semantics: readSemantics(raw.semantics),
785
1025
  terminalHandoff: readTerminalHandoff(raw.terminalHandoff),
@@ -831,7 +1071,12 @@ function normalizeUiState(value) {
831
1071
  subagentInspector: readSubagentInspector(raw.subagentInspector),
832
1072
  attached: readAttached(raw.attached),
833
1073
  owned: readAttached(raw.owned),
834
- attachError: attachError && typeof attachError.key === "string" && typeof attachError.message === "string" ? { key: attachError.key, message: attachError.message } : null
1074
+ attachError: attachError && typeof attachError.key === "string" && typeof attachError.message === "string" ? { key: attachError.key, message: attachError.message } : null,
1075
+ agentPackage: readAgentPackage(raw.agentPackage),
1076
+ contributions: normalizeContributions(raw.contributions),
1077
+ agentPackageError: typeof raw.agentPackageError === "string" ? boundedString(raw.agentPackageError) : null,
1078
+ agentPackageCapabilityState: readAgentPackageCapabilityState(raw.agentPackageCapabilityState),
1079
+ agentPackageCapabilityError: typeof raw.agentPackageCapabilityError === "string" ? boundedString(raw.agentPackageCapabilityError) : null
835
1080
  };
836
1081
  }
837
1082
  function harnessDisplayName(id) {
@@ -976,6 +1221,15 @@ function isSendKey(event) {
976
1221
 
977
1222
  // src/memory.js
978
1223
  var MEMORY_LIMIT = 100;
1224
+ var registry = /* @__PURE__ */ new Set();
1225
+ function uiMemory() {
1226
+ const map = /* @__PURE__ */ new Map();
1227
+ registry.add(map);
1228
+ return map;
1229
+ }
1230
+ function resetSupercodeUiMemory() {
1231
+ for (const map of registry) map.clear();
1232
+ }
979
1233
  function boundedSet(map, key, value) {
980
1234
  map.delete(key);
981
1235
  map.set(key, value);
@@ -1329,7 +1583,7 @@ function MessageImages({ items, adapter }) {
1329
1583
  }
1330
1584
 
1331
1585
  // src/intent.js
1332
- var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
1586
+ var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export", "take_over"]);
1333
1587
  async function dispatchConfirmedIntent(adapter, intent) {
1334
1588
  if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
1335
1589
  const confirmed = await adapter.confirmIntent(intent);
@@ -1354,7 +1608,7 @@ function useAutosizeTextarea(ref, value) {
1354
1608
 
1355
1609
  // src/composer.jsx
1356
1610
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1357
- var composerMemory = /* @__PURE__ */ new Map();
1611
+ var composerMemory = uiMemory();
1358
1612
  function ExecutionModeSelect({ modes = [], value, onChange, disabled = false, label = "Run in" }) {
1359
1613
  if (modes.length < 2) return null;
1360
1614
  return /* @__PURE__ */ jsxs3("label", { className: "scui-execution-mode", title: disabled ? void 0 : `${label}: ${value}`, children: [
@@ -1757,7 +2011,11 @@ function languageLabel(info) {
1757
2011
  }
1758
2012
  function frameCode(render, tokens, index, options, env, self) {
1759
2013
  const label = markdown.utils.escapeHtml(languageLabel(tokens[index]?.info ?? ""));
1760
- 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>`;
2014
+ const body = render(tokens, index, options, env, self).replace(
2015
+ "<pre>",
2016
+ `<pre tabindex="0" role="region" aria-label="${label} code">`
2017
+ );
2018
+ 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>`;
1761
2019
  }
1762
2020
  for (const kind of ["fence", "code_block"]) {
1763
2021
  const render = markdown.renderer.rules[kind];
@@ -2094,6 +2352,26 @@ function TechnicalDetails({ entry }) {
2094
2352
  ] });
2095
2353
  }
2096
2354
  function TranscriptEntry({ entry, state, adapter }) {
2355
+ if (entry.role === "opaque") {
2356
+ return /* @__PURE__ */ jsxs6("article", { className: "scui-message scui-opaque", "data-role": "opaque", "data-kind": entry.kind, "aria-label": "Unrecognized entry", children: [
2357
+ /* @__PURE__ */ jsxs6("div", { className: "scui-notice", "data-code": "opaque-entry", children: [
2358
+ "Unrecognized entry kind ",
2359
+ /* @__PURE__ */ jsx7("code", { children: entry.kind }),
2360
+ " \u2014 kept as-is, nothing dropped"
2361
+ ] }),
2362
+ entry.text ? /* @__PURE__ */ jsx7(Markdown, { value: entry.text, copyText: adapter?.copyText }) : null,
2363
+ entry.raw ? /* @__PURE__ */ jsxs6("details", { className: "scui-tool-technical", children: [
2364
+ /* @__PURE__ */ jsx7("summary", { children: "Technical details" }),
2365
+ /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsxs6("section", { children: [
2366
+ /* @__PURE__ */ jsx7("strong", { children: "Raw entry" }),
2367
+ /* @__PURE__ */ jsxs6("pre", { children: [
2368
+ entry.raw,
2369
+ entry.truncated ? "\n[truncated]" : ""
2370
+ ] })
2371
+ ] }) })
2372
+ ] }) : null
2373
+ ] });
2374
+ }
2097
2375
  if (entry.role === "request") return /* @__PURE__ */ jsx7(RequestCard, { entry, adapter, canRespond: state.canRespond });
2098
2376
  if (entry.role === "reasoning") {
2099
2377
  return /* @__PURE__ */ jsxs6("details", { className: "scui-reasoning", open: entry.streaming, children: [
@@ -2223,7 +2501,7 @@ function SessionDetails({ semantics }) {
2223
2501
  ] })
2224
2502
  ] });
2225
2503
  }
2226
- var conversationMemory = /* @__PURE__ */ new Map();
2504
+ var conversationMemory = uiMemory();
2227
2505
  function ConversationAnnouncements({ state }) {
2228
2506
  const previousBusy = useRef4(state.busy);
2229
2507
  const [announcement, setAnnouncement] = useState3("");
@@ -2342,7 +2620,7 @@ import { useEffect as useEffect9, useId as useId3, useMemo as useMemo3, useRef a
2342
2620
  // src/sessions.jsx
2343
2621
  import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect3, useRef as useRef5, useState as useState4 } from "react";
2344
2622
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2345
- var sessionListMemory = /* @__PURE__ */ new Map();
2623
+ var sessionListMemory = uiMemory();
2346
2624
  function sessionPathParts(value) {
2347
2625
  const complete = String(value ?? "").replaceAll("\\", "/");
2348
2626
  const boundary = complete.lastIndexOf("/");
@@ -2364,11 +2642,55 @@ function SessionRow({ row, state, onOpen, onOpenSubagents, now = Date.now() }) {
2364
2642
  const unreadCount = attention?.unreadCount ?? 0;
2365
2643
  const unreadLabel = unreadCount > 99 ? "99+" : String(unreadCount);
2366
2644
  const age = relativeAge(row.previewUpdatedAt ?? row.updatedAt, now) || row.age;
2367
- return /* @__PURE__ */ jsxs7("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, children: [
2645
+ const nounBadges = [];
2646
+ if (row.trigger && row.trigger.kind !== "manual" && row.trigger.kind !== "human") {
2647
+ const runs = row.recurring?.runs;
2648
+ const detail = row.trigger.label || row.trigger.surface || "";
2649
+ nounBadges.push(
2650
+ /* @__PURE__ */ jsxs7("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: [
2651
+ row.trigger.kind,
2652
+ detail ? ` \xB7 ${detail}` : "",
2653
+ runs && runs > 1 ? ` \xB7 \xD7${runs}` : ""
2654
+ ] }, "trigger")
2655
+ );
2656
+ }
2657
+ if (row.crossSurface) {
2658
+ nounBadges.push(
2659
+ /* @__PURE__ */ jsxs7("small", { className: "scui-session-noun", "data-noun": "cross-surface", "data-state": row.crossSurface.state, title: row.crossSurface.error ?? void 0, children: [
2660
+ "\u2192",
2661
+ row.crossSurface.platform ?? "elsewhere",
2662
+ " \xB7 ",
2663
+ row.crossSurface.state
2664
+ ] }, "cross-surface")
2665
+ );
2666
+ }
2667
+ if (row.participant && row.participant.kind !== "local-user") {
2668
+ nounBadges.push(
2669
+ /* @__PURE__ */ jsx8("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")
2670
+ );
2671
+ }
2672
+ if (row.mirror) {
2673
+ nounBadges.push(
2674
+ /* @__PURE__ */ jsxs7("small", { className: "scui-session-noun", "data-noun": "mirror", "data-truncated": row.mirror.truncated, children: [
2675
+ "mirror of ",
2676
+ harnessDisplayName(row.mirror.canonicalHarness)
2677
+ ] }, "mirror")
2678
+ );
2679
+ }
2680
+ if (row.workspaceRef?.kind === "channel") {
2681
+ nounBadges.push(
2682
+ /* @__PURE__ */ jsxs7("small", { className: "scui-session-noun", "data-noun": "workspace", "data-kind": "channel", children: [
2683
+ "#",
2684
+ row.workspaceRef.value ?? "channel"
2685
+ ] }, "workspace")
2686
+ );
2687
+ }
2688
+ return /* @__PURE__ */ jsxs7("article", { className: "scui-session", "data-active": row.active, "data-activity": activity, "data-writable": row.writable, "data-workspace-kind": row.workspaceRef?.kind, children: [
2368
2689
  /* @__PURE__ */ jsxs7("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: [
2369
2690
  /* @__PURE__ */ jsx8(HarnessLogo, { id: row.harness, activity, size: 34 }),
2370
2691
  /* @__PURE__ */ jsxs7("span", { className: "scui-session-copy", children: [
2371
2692
  /* @__PURE__ */ jsx8("span", { className: "scui-session-title", children: /* @__PURE__ */ jsx8("strong", { children: title }) }),
2693
+ nounBadges.length ? /* @__PURE__ */ jsx8("span", { className: "scui-session-nouns", children: nounBadges }) : null,
2372
2694
  path.complete ? /* @__PURE__ */ jsxs7("small", { className: "scui-session-path", title: row.cwd, children: [
2373
2695
  /* @__PURE__ */ jsx8("span", { className: "scui-session-path-leading", children: path.leading }),
2374
2696
  path.separator ? /* @__PURE__ */ jsx8("span", { className: "scui-session-path-separator", children: path.separator }) : null,
@@ -2783,10 +3105,54 @@ function HarnessPicker({ harnesses, state, value, disabled = false, adapter, onC
2783
3105
 
2784
3106
  // src/messenger.jsx
2785
3107
  import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2786
- var pendingMessageMemory = /* @__PURE__ */ new Map();
2787
- var messengerViewMemory = /* @__PURE__ */ new Map();
2788
- var newChatMemory = /* @__PURE__ */ new Map();
3108
+ var pendingMessageMemory = uiMemory();
3109
+ var messengerViewMemory = uiMemory();
3110
+ var newChatMemory = uiMemory();
2789
3111
  var TRACKED_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "detach", "branch", "reduce", "terminal", "export", "steer", "interrupt", "respond", "configureHarness", "refresh", "loadEarlier", "loadSessions"]);
3112
+ function UniversalNouns({ state, adapter }) {
3113
+ const banners = [];
3114
+ if (state.participant && state.participant.kind !== "local-user") {
3115
+ banners.push(
3116
+ /* @__PURE__ */ jsx11("div", { className: "scui-notice scui-noun-banner", "data-noun": "participant", "data-kind": state.participant.kind, children: state.participant.kind === "foreign" ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
3117
+ "This is ",
3118
+ /* @__PURE__ */ jsx11("strong", { children: state.participant.label ?? "someone else's" }),
3119
+ " conversation",
3120
+ state.participant.origin ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
3121
+ " via ",
3122
+ state.participant.origin
3123
+ ] }) : null,
3124
+ "."
3125
+ ] }) : /* @__PURE__ */ jsx11(Fragment5, { children: "Unknown participant \u2014 this conversation was not started here." }) }, "participant")
3126
+ );
3127
+ }
3128
+ if (state.mirror) {
3129
+ banners.push(
3130
+ /* @__PURE__ */ jsxs10("div", { className: "scui-notice scui-noun-banner", "data-noun": "mirror", "data-truncated": state.mirror.truncated, children: [
3131
+ state.mirror.bounded ? "Bounded mirror" : "Mirror",
3132
+ " of a ",
3133
+ /* @__PURE__ */ jsx11("strong", { children: harnessDisplayName(state.mirror.canonicalHarness) }),
3134
+ " session \u2014 the canonical record lives in its own store",
3135
+ state.mirror.truncated ? " (truncated here)" : "",
3136
+ ".",
3137
+ state.mirror.canonicalKey ? /* @__PURE__ */ jsx11("button", { type: "button", onClick: () => adapter.onIntent({ action: "open_session", key: state.mirror.canonicalKey }), children: "Open canonical session" }) : null
3138
+ ] }, "mirror")
3139
+ );
3140
+ }
3141
+ if (state.holder && state.holder.surface !== "supercode") {
3142
+ banners.push(
3143
+ /* @__PURE__ */ jsxs10("div", { className: "scui-notice scui-noun-banner", "data-noun": "holder", "data-surface": state.holder.surface ?? "unheld", children: [
3144
+ state.holder.surface ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
3145
+ "Held by ",
3146
+ /* @__PURE__ */ jsx11("strong", { children: state.holder.surface }),
3147
+ " right now."
3148
+ ] }) : /* @__PURE__ */ jsx11(Fragment5, { children: "No surface holds this session right now." }),
3149
+ state.holder.canTakeOver ? /* @__PURE__ */ jsx11("button", { type: "button", onClick: () => dispatchConfirmedIntent(adapter, { action: "take_over" }), children: "Take over" }) : null
3150
+ ] }, "holder")
3151
+ );
3152
+ }
3153
+ if (!banners.length) return null;
3154
+ return /* @__PURE__ */ jsx11("div", { className: "scui-noun-banners", children: banners });
3155
+ }
2790
3156
  function Receipt({ state, adapter }) {
2791
3157
  const receipt = state.reductionReceipt;
2792
3158
  if (receipt) return /* @__PURE__ */ jsx11("div", { className: "scui-receipt", children: /* @__PURE__ */ jsxs10("span", { children: [
@@ -3050,6 +3416,7 @@ function Chat({ state, adapter, onBack, onNew, onClose, components, slots, label
3050
3416
  state.recoverable ? /* @__PURE__ */ jsx11("button", { type: "button", disabled: Boolean(action), onClick: () => trackedAdapter.onIntent({ action: "refresh" }), children: "Retry" }) : null
3051
3417
  ] }) : null,
3052
3418
  /* @__PURE__ */ jsx11(Receipt, { state, adapter }),
3419
+ /* @__PURE__ */ jsx11(UniversalNouns, { state: actionState, adapter: trackedAdapter }),
3053
3420
  /* @__PURE__ */ jsx11(Conversation, { state: actionState, adapter: trackedAdapter, components, slots, memoryKey, pending: pendingMessage, unreadAfterMessages }, memoryKey),
3054
3421
  /* @__PURE__ */ jsx11(ContinuationBar, { state: actionState, adapter: trackedAdapter, labels }),
3055
3422
  /* @__PURE__ */ jsx11(Advisory, { state: actionState, adapter: trackedAdapter, value: state.interopSettings?.advisories[0] ?? null, onReview: (recommendedChange) => setSettings({ recommendedChange }) }),
@@ -3424,5 +3791,6 @@ export {
3424
3791
  TranscriptEntry,
3425
3792
  UiIcon,
3426
3793
  harnessLogoDataUrl,
3427
- hasHarnessLogo
3794
+ hasHarnessLogo,
3795
+ resetSupercodeUiMemory
3428
3796
  };
@@ -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,
@@ -69,7 +73,12 @@ var EMPTY_UI_STATE = Object.freeze({
69
73
  subagentInspector: null,
70
74
  attached: null,
71
75
  owned: null,
72
- attachError: null
76
+ attachError: null,
77
+ agentPackage: null,
78
+ contributions: Object.freeze([]),
79
+ agentPackageError: null,
80
+ agentPackageCapabilityState: null,
81
+ agentPackageCapabilityError: null
73
82
  });
74
83
  function harnessDisplayName(id) {
75
84
  return HARNESS_NAMES[id] ?? id;
@@ -95,6 +104,12 @@ function isSendKey(event) {
95
104
 
96
105
  // src/memory.js
97
106
  var MEMORY_LIMIT = 100;
107
+ var registry = /* @__PURE__ */ new Set();
108
+ function uiMemory() {
109
+ const map = /* @__PURE__ */ new Map();
110
+ registry.add(map);
111
+ return map;
112
+ }
98
113
  function boundedSet(map, key, value) {
99
114
  map.delete(key);
100
115
  map.set(key, value);
@@ -284,7 +299,7 @@ function ImageTray({ items, onRemove }) {
284
299
  }
285
300
 
286
301
  // src/intent.js
287
- var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export"]);
302
+ var CONFIRMABLE_ACTIONS = /* @__PURE__ */ new Set(["resume", "join", "branch", "reduce", "export", "take_over"]);
288
303
  async function dispatchConfirmedIntent(adapter, intent) {
289
304
  if (CONFIRMABLE_ACTIONS.has(intent.action) && adapter.confirmIntent) {
290
305
  const confirmed = await adapter.confirmIntent(intent);
@@ -309,7 +324,7 @@ function useAutosizeTextarea(ref, value) {
309
324
 
310
325
  // src/composer.jsx
311
326
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
312
- var composerMemory = /* @__PURE__ */ new Map();
327
+ var composerMemory = uiMemory();
313
328
  function ExecutionModeSelect({ modes = [], value, onChange, disabled = false, label = "Run in" }) {
314
329
  if (modes.length < 2) return null;
315
330
  return /* @__PURE__ */ jsxs3("label", { className: "scui-execution-mode", title: disabled ? void 0 : `${label}: ${value}`, children: [