@robota-sdk/agent-ui-web 3.0.0-beta.96 → 3.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robota-sdk/agent-ui-web",
3
- "version": "3.0.0-beta.96",
3
+ "version": "3.0.1",
4
4
  "description": "Browser-safe React session presentation, wire reducer, WebSocket client and runtime-host contract for consumer-owned agent renderers.",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "type": "module",
@@ -58,11 +58,11 @@
58
58
  "pretendard": "^1.3.9",
59
59
  "react-markdown": "^10.1.0",
60
60
  "remark-gfm": "^4.0.1",
61
- "@robota-sdk/agent-interface-command": "3.0.0-beta.96",
62
- "@robota-sdk/agent-interface-execution": "3.0.0-beta.96",
63
- "@robota-sdk/agent-transport": "3.0.0-beta.96",
64
- "@robota-sdk/agent-interface-transport": "3.0.0-beta.96",
65
- "@robota-sdk/agent-interface-session": "3.0.0-beta.96"
61
+ "@robota-sdk/agent-interface-command": "3.0.1",
62
+ "@robota-sdk/agent-interface-session": "3.0.1",
63
+ "@robota-sdk/agent-transport": "3.0.1",
64
+ "@robota-sdk/agent-interface-transport": "3.0.1",
65
+ "@robota-sdk/agent-interface-execution": "3.0.1"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "react": ">=18"
@@ -268,7 +268,7 @@ function noticeSentence(notice: ISessionNotice): string | null {
268
268
  }
269
269
 
270
270
  /**
271
- * Session and protocol failures, as dismissible toasts over the top-right corner: they stay until
271
+ * Session outcomes and protocol failures, as dismissible toasts over the top-right corner: they stay until
272
272
  * dismissed, and never push the conversation or the composer out of view. Command output is not
273
273
  * here — it belongs to the conversation. A provider error classified at the wire boundary shows one
274
274
  * plain sentence with the next step; its raw text sits behind "Details" rather than as the headline.
@@ -280,13 +280,16 @@ export function SessionNotices({ state }: { state: IWsSessionState }): React.Rea
280
280
  <div className="pointer-events-none absolute right-4 top-16 z-40 flex w-[min(400px,calc(100%-32px))] flex-col gap-2">
281
281
  {notices.slice(-3).map((notice) => {
282
282
  const sentence = noticeSentence(notice);
283
+ const compacted = notice.kind === 'context-compacted';
283
284
  return (
284
285
  <div
285
286
  key={notice.id}
286
- role="alert"
287
+ role={compacted ? 'status' : 'alert'}
287
288
  className="gui-rise pointer-events-auto flex items-start gap-3 rounded-xl bg-popover px-4 py-3 text-[14px] leading-snug text-popover-foreground shadow-xl shadow-black/30"
288
289
  >
289
- <span className="mt-[7px] h-2 w-2 flex-shrink-0 rounded-full bg-destructive" />
290
+ <span
291
+ className={`mt-[7px] h-2 w-2 flex-shrink-0 rounded-full ${compacted ? 'bg-primary' : 'bg-destructive'}`}
292
+ />
290
293
  <span className="max-h-40 flex-1 overflow-y-auto whitespace-pre-wrap break-words">
291
294
  {sentence ?? notice.message}
292
295
  {sentence && (
@@ -20,11 +20,11 @@ export const SERVER_MESSAGE_HANDLING = {
20
20
  error: 'visible-notice',
21
21
  command_result: 'reducer-state',
22
22
  messages: 'reducer-state',
23
- // #3189: the full history and its change signal serve a client that renders the whole session
24
- // (the TUI); this surface builds its transcript from `messages` and the streamed turn.
23
+ // The full system history serves the TUI; this transcript uses `messages` and streamed turns.
24
+ // A history change carries optional compaction metadata for a notice without replacing the turn.
25
25
  history: 'intentionally-not-rendered',
26
- history_changed: 'intentionally-not-rendered',
27
- context: 'intentionally-not-rendered',
26
+ history_changed: 'visible-notice',
27
+ context: 'reducer-state',
28
28
  turn_source: 'intentionally-not-rendered',
29
29
  commands: 'reducer-state',
30
30
  session_status: 'reducer-state',
@@ -157,7 +157,8 @@ export interface ISessionNotice {
157
157
  | 'protocol-error'
158
158
  | 'session-change-refused'
159
159
  | 'background-task-control-failed'
160
- | 'command-failed';
160
+ | 'command-failed'
161
+ | 'context-compacted';
161
162
  message: string;
162
163
  /**
163
164
  * A `session-error` classified at the wire boundary (#3289 §3) — present only when the host could
@@ -464,6 +464,10 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
464
464
  } = useAgentSwitcherState(send);
465
465
  const { handleSchedulesMessage, requestSchedules, ...schedulesState } = useSchedulesState(send);
466
466
 
467
+ const clearCompactionNotices = useCallback((): void => {
468
+ setSessionNotices((previous) => previous.filter((notice) => notice.kind !== 'context-compacted'));
469
+ }, []);
470
+
467
471
  const handleMessage = useCallback(
468
472
  (msg: TServerMessage): void => {
469
473
  // ARCH-2164: touching the exhaustive registry here keeps every decoded variant tied to an
@@ -663,6 +667,7 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
663
667
  // Nothing of the old session stays on screen until the new one's answers arrive.
664
668
  sessionStatusRef.current = null;
665
669
  setSessionStatus(null);
670
+ clearCompactionNotices();
666
671
  streamingTextRef.current = '';
667
672
  turnSegmentsRef.current = [];
668
673
  setStreamingText('');
@@ -685,6 +690,7 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
685
690
  break;
686
691
  }
687
692
  case 'history_cleared': {
693
+ clearCompactionNotices();
688
694
  rejectPendingAppRequests('The session history was cleared.');
689
695
  streamingTextRef.current = '';
690
696
  turnSegmentsRef.current = [];
@@ -793,6 +799,29 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
793
799
  setCommandCatalog(catalog);
794
800
  break;
795
801
  }
802
+ case 'context': {
803
+ // A later status snapshot supplies identity and the latest context when none is known yet.
804
+ if (sessionStatusRef.current !== null) {
805
+ const next = { ...sessionStatusRef.current, context: msg.state };
806
+ sessionStatusRef.current = next;
807
+ setSessionStatus(next);
808
+ }
809
+ break;
810
+ }
811
+ case 'history_changed': {
812
+ const compact = msg.compact;
813
+ if (compact?.trigger === 'auto') {
814
+ setSessionNotices((previous) => [
815
+ ...previous,
816
+ {
817
+ id: nextId(),
818
+ kind: 'context-compacted',
819
+ message: `Auto compacted context: ${Math.round(compact.beforeUsedPercentage)}% → ${Math.round(compact.afterUsedPercentage)}%`,
820
+ },
821
+ ]);
822
+ }
823
+ break;
824
+ }
796
825
  case 'session_status': {
797
826
  sessionStatusRef.current = msg.status;
798
827
  setSessionStatus(msg.status);
@@ -877,6 +906,7 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
877
906
  appendEntry,
878
907
  canListSessions,
879
908
  closeExecutionDetail,
909
+ clearCompactionNotices,
880
910
  finishTurn,
881
911
  handleAgentDefinitionsMessage,
882
912
  handleAppViewMessage,
@@ -921,7 +951,10 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
921
951
  statusRef.current = next;
922
952
  setStatus(next);
923
953
  // A reply lost with the connection never arrives; the views waiting on one learn that now.
924
- if (next !== 'connected') rejectPendingAppRequests();
954
+ if (next !== 'connected') {
955
+ rejectPendingAppRequests();
956
+ clearCompactionNotices();
957
+ }
925
958
  // Every client learns what it can offer and what is in effect as soon as it is attached.
926
959
  if (next === 'connected') {
927
960
  // A reply lost with the old connection never arrives; stop waiting for it.
@@ -954,6 +987,7 @@ export function useSessionClient<TStatus extends string = TConnectionStatus>(
954
987
  }, [
955
988
  makeClient,
956
989
  handleMessage,
990
+ clearCompactionNotices,
957
991
  requestSessions,
958
992
  requestSchedules,
959
993
  armRestore,