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

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/controller.d.ts CHANGED
@@ -9,6 +9,7 @@ import type {
9
9
  SupercodeController,
10
10
  } from '@volter-ai-dev/supercode-client';
11
11
  import type {
12
+ TranscriptEntryModel,
12
13
  AttachedSessionModel,
13
14
  ContinuationMode,
14
15
  SessionAttention,
@@ -19,6 +20,9 @@ import type {
19
20
  UiAdapter,
20
21
  } from './index.js';
21
22
 
23
+ /** `after`: a conversation entry id (row follows it), `'^'` (before everything), or null/absent (at the end). */
24
+ export type HostTranscriptEntry = TranscriptEntryModel & { after?: string | null };
25
+
22
26
  export interface ClientProjectionOptions {
23
27
  now?: number;
24
28
  /** Maximum rendered conversation rows after hidden context is removed. Default 120. */
@@ -49,6 +53,9 @@ export interface ClientProjectionOptions {
49
53
  continuationModes?: ContinuationMode[];
50
54
  /** Trusted-host inventory and lifecycle overlays (for example a machine-wide session catalog). */
51
55
  sessions?: SessionRowModel[];
56
+ /** Host-owned rows placed inside the conversation: after the conversation entry `after` names,
57
+ * or at the end. The conversation's own order is never changed; ids already present are skipped. */
58
+ hostEntries?: readonly HostTranscriptEntry[];
52
59
  attached?: AttachedSessionModel | null;
53
60
  owned?: AttachedSessionModel | null;
54
61
  attachError?: SupercodeUiState['attachError'];
package/controller.mjs CHANGED
@@ -509,6 +509,39 @@ function projectPill(snapshot) {
509
509
  return { tone: 'live', label: text(`${label(harness)} ready`) };
510
510
  }
511
511
 
512
+ /** A host's own rows — display objects an app printed, notices the host raised —
513
+ * inside the conversation at the position the host names: after a conversation
514
+ * entry by id, or at the end. The conversation's own order is never changed. */
515
+ function withHostEntries(transcript, hostEntries) {
516
+ if (!Array.isArray(hostEntries) || hostEntries.length === 0) return transcript;
517
+ const out = [...transcript];
518
+ const tail = [];
519
+ for (const raw of hostEntries) {
520
+ if (!raw || typeof raw !== 'object' || typeof raw.id !== 'string') continue;
521
+ const { after, ...entry } = raw;
522
+ if (out.some((item) => item.id === entry.id)) continue;
523
+ if (after === '^') {
524
+ // before everything, in the given order
525
+ let at = 0;
526
+ while (at < out.length && out[at].__hostAfter === '^') at += 1;
527
+ out.splice(at, 0, { ...entry, __hostAfter: '^' });
528
+ continue;
529
+ }
530
+ const index = typeof after === 'string' ? out.findIndex((item) => item.id === after) : -1;
531
+ if (index >= 0) {
532
+ // keep host rows that share an anchor in their given order
533
+ let at = index + 1;
534
+ while (at < out.length && out[at].__hostAfter === after) at += 1;
535
+ out.splice(at, 0, { ...entry, __hostAfter: after });
536
+ } else tail.push(entry);
537
+ }
538
+ return [...out, ...tail].map((item) => {
539
+ if (!('__hostAfter' in item)) return item;
540
+ const { __hostAfter: _anchor, ...clean } = item;
541
+ return clean;
542
+ });
543
+ }
544
+
512
545
  function projectClientSnapshotInternal(snapshot, options, imageRegistry) {
513
546
  const now = Number.isFinite(options.now) ? options.now : Date.now();
514
547
  const busy = ['running', 'interrupting', 'reconciling'].includes(snapshot.turn?.state);
@@ -559,7 +592,10 @@ function projectClientSnapshotInternal(snapshot, options, imageRegistry) {
559
592
  ? snapshot.connection?.ownsRuntime ? active : null
560
593
  : options.owned;
561
594
  const maxEntries = positiveInteger(options.maxEntries, DEFAULT_MAX_ENTRIES);
562
- const transcript = projectConversation(snapshot.conversation ?? [], options, imageRegistry);
595
+ const transcript = withHostEntries(
596
+ projectConversation(snapshot.conversation ?? [], options, imageRegistry),
597
+ options.hostEntries,
598
+ );
563
599
  const startup = snapshot.availability === 'loading'
564
600
  ? snapshot.operation === 'start' ? 'starting' : snapshot.operation === 'refresh' ? 'discovering' : 'connecting'
565
601
  : 'ready';
package/host.d.ts CHANGED
@@ -24,7 +24,7 @@ export class RemoteControllerHost {
24
24
  dispatch(intent: unknown): Promise<RemoteUiFrame>;
25
25
  getFrame(): RemoteUiFrame;
26
26
  refreshProjection(): RemoteUiFrame;
27
- restore(identity: string, connection: 'observe' | 'attach'): Promise<RemoteUiFrame>;
27
+ restore(identity: string, connection: 'observe' | 'attach' | 'resume'): Promise<RemoteUiFrame>;
28
28
  subscribe(listener: (frame: RemoteUiFrame) => void): () => void;
29
29
  }
30
30
 
package/host.mjs CHANGED
@@ -119,8 +119,8 @@ export class RemoteControllerHost {
119
119
  if (typeof identity !== 'string' || !identity) {
120
120
  throw new TypeError('RemoteControllerHost restore identity must be a non-empty string.');
121
121
  }
122
- if (connection !== 'observe' && connection !== 'attach') {
123
- throw new TypeError('RemoteControllerHost restore connection must be observe or attach.');
122
+ if (connection !== 'observe' && connection !== 'attach' && connection !== 'resume') {
123
+ throw new TypeError('RemoteControllerHost restore connection must be observe, attach, or resume.');
124
124
  }
125
125
  const sequence = this.#sequence;
126
126
  await this.#controller.dispatch({ type: 'restore', identity, connection });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter-ai-dev/supercode-ui",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "type": "module",
5
5
  "description": "Composable default UI kit for Supercode-powered coding-agent experiences",
6
6
  "exports": {