@robota-sdk/agent-ui-web 3.0.0-beta.96 → 3.0.0-beta.99
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/CHANGELOG.md +30 -0
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +36 -6
- package/dist/browser/index.js.map +1 -1
- package/dist/node/index.cjs +36 -6
- package/dist/node/index.d.cts +1 -1
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.ts +1 -1
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +36 -6
- package/dist/node/index.js.map +1 -1
- package/package.json +6 -6
- package/src/components/SessionSurfaceChrome.tsx +6 -3
- package/src/hooks/server-message-handling.ts +4 -4
- package/src/hooks/session-client-types.ts +2 -1
- package/src/hooks/useSessionClient.ts +35 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robota-sdk/agent-ui-web",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.99",
|
|
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.
|
|
62
|
-
"@robota-sdk/agent-interface-execution": "3.0.0-beta.
|
|
63
|
-
"@robota-sdk/agent-
|
|
64
|
-
"@robota-sdk/agent-interface-transport": "3.0.0-beta.
|
|
65
|
-
"@robota-sdk/agent-
|
|
61
|
+
"@robota-sdk/agent-interface-command": "3.0.0-beta.99",
|
|
62
|
+
"@robota-sdk/agent-interface-execution": "3.0.0-beta.99",
|
|
63
|
+
"@robota-sdk/agent-interface-session": "3.0.0-beta.99",
|
|
64
|
+
"@robota-sdk/agent-interface-transport": "3.0.0-beta.99",
|
|
65
|
+
"@robota-sdk/agent-transport": "3.0.0-beta.99"
|
|
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=
|
|
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
|
|
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
|
-
//
|
|
24
|
-
//
|
|
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: '
|
|
27
|
-
context: '
|
|
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')
|
|
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,
|