@volter-ai-dev/supercode-ui 0.1.36 → 0.1.37

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/icon.mjs CHANGED
@@ -44,7 +44,7 @@ var ICONS = {
44
44
  function UiIcon({ name, size = 16, class: className = "" }) {
45
45
  const Glyph = ICONS[name];
46
46
  if (!Glyph) return null;
47
- return /* @__PURE__ */ jsx("svg", { class: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Glyph, {}) });
47
+ return /* @__PURE__ */ jsx("svg", { className: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Glyph, {}) });
48
48
  }
49
49
  export {
50
50
  UiIcon
package/index.d.ts CHANGED
@@ -10,12 +10,34 @@ export type ExecutionMode = 'headless' | 'terminal';
10
10
  export type ContinuationMode = ExecutionMode;
11
11
  export type SessionActivity = 'idle' | 'recent' | 'running' | 'working' | 'needs-input' | 'finished' | 'failed' | 'unseen';
12
12
 
13
+ export interface AgentActivityModel {
14
+ harness: HarnessId | '';
15
+ sessionKey: string | null;
16
+ title: string;
17
+ detail: string;
18
+ activity: SessionActivity;
19
+ unreadCount: number;
20
+ }
21
+
13
22
  export interface HarnessOption {
14
23
  id: HarnessId;
15
24
  label: string;
16
25
  installed: boolean;
17
26
  startable: boolean;
18
27
  reason: string | null;
28
+ auth?: 'ready' | 'configured' | 'required' | 'unknown';
29
+ runtime?: 'ready' | 'degraded' | 'unavailable';
30
+ protocol?: string;
31
+ repair?: string | null;
32
+ capabilities?: {
33
+ start: boolean;
34
+ resume: boolean;
35
+ attach: boolean;
36
+ send: boolean;
37
+ interrupt: boolean;
38
+ steer: boolean;
39
+ respond: boolean;
40
+ };
19
41
  /** Host-supported ways to start this harness. Omitted means headless when startable. */
20
42
  launchModes?: ExecutionMode[];
21
43
  /** Host preference, used unless this browser has a remembered choice for the harness. */
@@ -240,6 +262,7 @@ export interface SupercodeUiState {
240
262
  mode: SessionMode;
241
263
  strategy: ControlStrategy;
242
264
  canSend: boolean;
265
+ canSteer: boolean;
243
266
  canResume: boolean;
244
267
  /** Execution strategies the current host can actually provide. Headless is the default. */
245
268
  continuationModes: ContinuationMode[];
@@ -293,6 +316,7 @@ export type SupercodeUiIntent =
293
316
  | { action: 'loadEarlier' }
294
317
  | { action: 'draft'; text: string }
295
318
  | { action: 'send'; text: string; context?: TranscriptContext[]; images?: Array<TranscriptImage & { url: string }> }
319
+ | { action: 'steer'; text: string }
296
320
  | { action: 'new'; harness: HarnessId; mode?: ExecutionMode; text: string; context?: TranscriptContext[]; images?: Array<TranscriptImage & { url: string }> }
297
321
  | { action: 'resume'; mode?: ContinuationMode }
298
322
  | { action: 'join' }
@@ -309,6 +333,8 @@ export type SupercodeUiIntent =
309
333
 
310
334
  export interface UiAdapter {
311
335
  onIntent(intent: SupercodeUiIntent): void | Promise<void>;
336
+ /** Confirm a takeover or migration intent. Returning false cancels it before dispatch. */
337
+ confirmIntent?(intent: Extract<SupercodeUiIntent, { action: 'resume' | 'join' | 'branch' | 'reduce' | 'export' }>): boolean | Promise<boolean>;
312
338
  /** Ask the embedding host for explicit user-selected text or image context. */
313
339
  pickContext?(): TranscriptAttachment | TranscriptAttachment[] | null | Promise<TranscriptAttachment | TranscriptAttachment[] | null>;
314
340
  /** Resolve one projected historical image on demand. The UI owns and revokes its object URL. */
@@ -345,6 +371,16 @@ export interface ComponentOverrideProps<T = unknown> {
345
371
  value: T;
346
372
  }
347
373
 
374
+ export interface ContextCandidateProps {
375
+ attachment: TranscriptAttachment;
376
+ value?: TranscriptAttachment;
377
+ attached: boolean;
378
+ index: number;
379
+ state: SupercodeUiState;
380
+ adapter: UiAdapter;
381
+ onAttach(attachment: TranscriptAttachment): void;
382
+ }
383
+
348
384
  export interface SessionRowProps {
349
385
  row: SessionRowModel;
350
386
  value?: SessionRowModel;
@@ -405,23 +441,46 @@ export interface MessengerComponents {
405
441
  HarnessLogo?: ComponentType<{ id: HarnessId; activity?: SessionActivity; size?: number }>;
406
442
  HarnessAdvisory?: ComponentType<HarnessAdvisoryProps>;
407
443
  HarnessSettingsPanel?: ComponentType<HarnessSettingsPanelProps>;
444
+ ContextCandidate?: ComponentType<ContextCandidateProps>;
445
+ HarnessReadiness?: ComponentType<{ harnesses: HarnessOption[]; state: SupercodeUiState; adapter: UiAdapter }>;
446
+ }
447
+
448
+ export interface AgentActivityLauncherProps {
449
+ state: SupercodeUiState | unknown;
450
+ onOpen?(activity: AgentActivityModel): void;
451
+ class?: string;
452
+ showSummary?: boolean;
453
+ components?: Pick<MessengerComponents, 'HarnessLogo'>;
408
454
  }
409
455
 
410
456
  export interface MessengerSlots {
411
457
  header?: ComponentType<ComponentOverrideProps>;
412
458
  /** Add a compact consumer control to every default messenger header. `value` is the current view. */
413
459
  headerActions?: ComponentType<ComponentOverrideProps<'list' | 'chat' | 'new'>>;
460
+ /** Host-owned rows rendered inside the searchable conversation scroller. */
461
+ beforeSessions?: ComponentType<ComponentOverrideProps<{ query: string; rows: SessionRowModel[] }>>;
462
+ afterSessions?: ComponentType<ComponentOverrideProps<{ query: string; rows: SessionRowModel[] }>>;
414
463
  emptyConversation?: ComponentType<ComponentOverrideProps>;
415
464
  beforeConversation?: ComponentType<ComponentOverrideProps>;
416
465
  afterConversation?: ComponentType<ComponentOverrideProps>;
417
466
  footer?: ComponentType<ComponentOverrideProps>;
418
467
  }
419
468
 
469
+ export type MessengerNavigation =
470
+ | { id: string | number; view: 'list' }
471
+ | { id: string | number; view: 'chat'; sessionKey: string }
472
+ | { id: string | number; view: 'new'; harness?: HarnessId; draft?: string; context?: TranscriptContext[]; images?: Array<TranscriptImage & { url: string }> };
473
+
420
474
  export interface MessengerProps {
421
475
  state: SupercodeUiState | unknown;
422
476
  adapter: UiAdapter;
423
477
  class?: string;
424
478
  initialView?: 'list' | 'chat' | 'new';
479
+ /** Event-like host navigation. Change `id` to issue a new request. */
480
+ navigation?: MessengerNavigation | null;
481
+ onViewChange?(view: 'list' | 'chat' | 'new'): void;
482
+ /** Deliberate host-provided items that can be attached without opening a picker. */
483
+ contextCandidates?: TranscriptAttachment[];
425
484
  labels?: Partial<MessengerLabels>;
426
485
  components?: MessengerComponents;
427
486
  slots?: MessengerSlots;
@@ -435,6 +494,7 @@ export function harnessDisplayName(id: string): string;
435
494
  export function sessionDisplayName(session: Pick<SessionRowModel, 'name' | 'title'>): string;
436
495
  export function relativeAge(updatedAt: number | null | undefined, now?: number): string;
437
496
  export function sessionActivity(state: SupercodeUiState, row: SessionRowModel): SessionActivity;
497
+ export function projectAgentActivity(state: SupercodeUiState | unknown): AgentActivityModel;
438
498
  export function filterSessions(rows: readonly SessionRowModel[], query: string): SessionRowModel[];
439
499
  export function groupConversation(entries: readonly TranscriptEntryModel[]): Array<
440
500
  | { kind: 'entry'; id: string; entry: TranscriptEntryModel }
@@ -453,12 +513,15 @@ export function isSendKey(event: Pick<KeyboardEvent, 'key' | 'shiftKey' | 'isCom
453
513
  export function parseSupercodeUiIntent(value: unknown): SupercodeUiIntent | null;
454
514
 
455
515
  export function HarnessLogo(props: { id: HarnessId; activity?: SessionActivity; size?: number; onMissingLogo?(id: string): void }): VNode | null;
516
+ export function AgentActivityLauncher(props: AgentActivityLauncherProps): VNode;
456
517
  export type UiIconName = 'attach' | 'back' | 'check' | 'chevron' | 'close' | 'copy' | 'down' | 'menu' | 'plus' | 'search' | 'send' | 'stop';
457
518
  export function UiIcon(props: { name: UiIconName; size?: number; class?: string }): VNode | null;
458
519
  export function hasHarnessLogo(id: string): boolean;
459
520
  export function harnessLogoDataUrl(id: string): string | null;
460
521
  export function ImageViewer(props: { items: TranscriptImage[]; index: number; adapter?: Pick<UiAdapter, 'copyText' | 'resolveImage'>; onChange(index: number): void; onClose(): void }): VNode | null;
461
522
  export function MessageImages(props: { items?: TranscriptImage[]; adapter?: Pick<UiAdapter, 'copyText' | 'resolveImage'> }): VNode | null;
523
+ export function ContextCandidate(props: ContextCandidateProps): VNode;
524
+ export function ContextCandidates(props: { items: TranscriptAttachment[]; context: TranscriptContext[]; images: Array<TranscriptImage & { url: string }>; state: SupercodeUiState; adapter: UiAdapter; onAttach(attachment: TranscriptAttachment): void; component?: ComponentType<ContextCandidateProps> }): VNode | null;
462
525
  export function LoadingStatus(props: { state: SupercodeUiState; compact?: boolean }): VNode;
463
526
  export function RequestCard(props: { entry: TranscriptEntryModel; adapter: UiAdapter; canRespond: boolean }): VNode | null;
464
527
  export function TranscriptEntry(props: { entry: TranscriptEntryModel; state: SupercodeUiState; adapter: UiAdapter }): VNode;
@@ -467,12 +530,13 @@ export function ToolRow(props: ToolRowProps): VNode;
467
530
  export function TaskPlan(props: { plan: TaskPlanModel }): VNode | null;
468
531
  export function HarnessAdvisory(props: HarnessAdvisoryProps): VNode | null;
469
532
  export function HarnessSettingsPanel(props: HarnessSettingsPanelProps): VNode;
533
+ export function HarnessReadiness(props: { harnesses: HarnessOption[]; state: SupercodeUiState; adapter: UiAdapter }): VNode | null;
470
534
  export function SessionDetails(props: { semantics: SessionSemanticsModel }): VNode | null;
471
535
  export function Conversation(props: { state: SupercodeUiState; adapter: UiAdapter; components?: MessengerComponents; slots?: MessengerSlots; memoryKey?: string; pending?: string | PendingMessageModel | null; unreadAfterMessages?: number | null }): VNode;
472
536
  export function SessionRow(props: { row: SessionRowModel; state: SupercodeUiState; adapter: UiAdapter; now?: number; onOpen(row: SessionRowModel): void }): VNode;
473
- export function SessionList(props: { state: SupercodeUiState; adapter: UiAdapter; onOpen(row: SessionRowModel): void; onNew?(): void; onClose?(): void; components?: MessengerComponents; labels?: MessengerLabels; focusKey?: string | null; memoryKey?: string; headerActions?: MessengerSlots['headerActions'] }): VNode;
537
+ export function SessionList(props: { state: SupercodeUiState; adapter: UiAdapter; onOpen(row: SessionRowModel): void; onNew?(): void; onClose?(): void; components?: MessengerComponents; slots?: MessengerSlots; labels?: MessengerLabels; focusKey?: string | null; memoryKey?: string; headerActions?: MessengerSlots['headerActions'] }): VNode;
474
538
  export function ContinuationBar(props: { state: SupercodeUiState; adapter: UiAdapter; labels?: MessengerLabels }): VNode | null;
475
- export function Composer(props: { state: SupercodeUiState; adapter: UiAdapter; labels?: MessengerLabels; memoryKey?: string; pendingStatus?: PendingMessageModel['status'] | 'editing' | null; restoreDraft?: { id: string | number; text: string; context?: TranscriptContext[]; images?: TranscriptImage[] } | null; onPending?(text: string, context?: TranscriptContext[], images?: TranscriptImage[]): void; onDraftRestored?(id: string | number): void }): VNode;
539
+ export function Composer(props: { state: SupercodeUiState; adapter: UiAdapter; labels?: MessengerLabels; memoryKey?: string; pendingStatus?: PendingMessageModel['status'] | 'editing' | null; restoreDraft?: { id: string | number; text: string; context?: TranscriptContext[]; images?: TranscriptImage[] } | null; contextCandidates?: TranscriptAttachment[]; components?: Pick<MessengerComponents, 'ContextCandidate'>; onPending?(text: string, context?: TranscriptContext[], images?: TranscriptImage[]): void; onDraftRestored?(id: string | number): void }): VNode;
476
540
  export function SupercodeMessenger(props: MessengerProps): VNode;
477
541
 
478
542
  export interface MountedMessenger {
package/logo.mjs CHANGED
@@ -5,13 +5,13 @@ var LOGOS = {
5
5
  "claude-code": {
6
6
  viewBox: "-1 3.5 26 18",
7
7
  paths: [
8
- ["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z" }]
8
+ ["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z" }]
9
9
  ]
10
10
  },
11
11
  codex: {
12
12
  viewBox: "-1 -1 26 26",
13
13
  paths: [
14
- ["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z" }]
14
+ ["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z" }]
15
15
  ]
16
16
  },
17
17
  gemini: {
@@ -31,7 +31,7 @@ var LOGOS = {
31
31
  pi: {
32
32
  viewBox: "0 0 24 24",
33
33
  paths: [
34
- ["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
34
+ ["path", { fillRule: "evenodd", clipRule: "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
35
35
  ["path", { d: "M17.5 12H23v11h-5.5V12z" }]
36
36
  ]
37
37
  },
@@ -41,7 +41,7 @@ var LOGOS = {
41
41
  paths: [
42
42
  ["rect", { width: "64", height: "64", rx: "14", fill: "#111923" }],
43
43
  ["path", { d: "M18 21h28v6H18zm0 13h18v6H18z", fill: "#5f8fff" }],
44
- ["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", "stroke-width": "4" }]
44
+ ["circle", { cx: "46", cy: "37", r: "7", fill: "none", stroke: "#8ce0aa", strokeWidth: "4" }]
45
45
  ]
46
46
  }
47
47
  };
@@ -58,12 +58,17 @@ var LOGO_CHROME = {
58
58
  function escapeSvgAttribute(value) {
59
59
  return String(value).replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
60
60
  }
61
+ var SVG_ATTRIBUTE_NAMES = Object.freeze({
62
+ clipRule: "clip-rule",
63
+ fillRule: "fill-rule",
64
+ strokeWidth: "stroke-width"
65
+ });
61
66
  function harnessLogoDataUrl(id) {
62
67
  const logo = LOGOS[id];
63
68
  if (!logo) return null;
64
69
  const chrome = LOGO_CHROME[id] ?? { background: "#111", color: id === "claude-code" ? "#d97757" : "#f7f7f5" };
65
70
  const glyph = logo.paths.map(([tag, attributes]) => {
66
- const serialized = Object.entries(attributes).map(([name, value]) => `${name}="${escapeSvgAttribute(value)}"`).join(" ");
71
+ const serialized = Object.entries(attributes).map(([name, value]) => `${SVG_ATTRIBUTE_NAMES[name] ?? name}="${escapeSvgAttribute(value)}"`).join(" ");
67
72
  return `<${tag} ${serialized}/>`;
68
73
  }).join("");
69
74
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle cx="20" cy="20" r="19" fill="${chrome.background}" stroke="#383a42"/><svg x="7" y="7" width="26" height="26" viewBox="${logo.viewBox}" color="${chrome.color}" fill="currentColor" preserveAspectRatio="xMidYMid meet">${glyph}</svg></svg>`;
@@ -75,7 +80,7 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
75
80
  if (!logo) onMissingLogo?.(id);
76
81
  }, [id, logo, onMissingLogo]);
77
82
  if (!logo) return null;
78
- return /* @__PURE__ */ jsxs("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
83
+ return /* @__PURE__ */ jsxs("span", { className: "scui-logo", "data-harness": id, "data-activity": activity, style: { "--scui-logo-size": `${size}px` }, "aria-hidden": "true", children: [
79
84
  /* @__PURE__ */ jsx("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx(Tag, { ...props }, index)) }),
80
85
  activity && activity !== "idle" ? /* @__PURE__ */ jsx("i", {}) : null
81
86
  ] });