@aomi-labs/react 0.3.5 → 0.3.6

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/dist/index.js CHANGED
@@ -560,62 +560,8 @@ import {
560
560
  createContext as createContext2,
561
561
  useCallback as useCallback2,
562
562
  useContext as useContext2,
563
- useEffect as useEffect2,
564
- useRef as useRef2,
565
- useState as useState2
563
+ useRef as useRef2
566
564
  } from "react";
567
- import {
568
- isInlineCall,
569
- isSystemNotice,
570
- isSystemError,
571
- isAsyncCallback
572
- } from "@aomi-labs/client";
573
-
574
- // packages/react/src/state/event-buffer.ts
575
- function createEventBuffer() {
576
- return {
577
- inboundQueue: [],
578
- outboundQueue: [],
579
- sseStatus: "disconnected",
580
- lastEventId: null,
581
- subscribers: /* @__PURE__ */ new Map()
582
- };
583
- }
584
- function enqueueInbound(state, event) {
585
- state.inboundQueue.push(__spreadProps(__spreadValues({}, event), {
586
- status: "pending",
587
- timestamp: Date.now()
588
- }));
589
- }
590
- function subscribe(state, type, callback) {
591
- if (!state.subscribers.has(type)) {
592
- state.subscribers.set(type, /* @__PURE__ */ new Set());
593
- }
594
- state.subscribers.get(type).add(callback);
595
- return () => {
596
- var _a;
597
- (_a = state.subscribers.get(type)) == null ? void 0 : _a.delete(callback);
598
- };
599
- }
600
- function dispatch(state, event) {
601
- const typeSubscribers = state.subscribers.get(event.type);
602
- if (typeSubscribers) {
603
- for (const callback of typeSubscribers) {
604
- callback(event);
605
- }
606
- }
607
- const allSubscribers = state.subscribers.get("*");
608
- if (allSubscribers) {
609
- for (const callback of allSubscribers) {
610
- callback(event);
611
- }
612
- }
613
- }
614
- function setSSEStatus(state, status) {
615
- state.sseStatus = status;
616
- }
617
-
618
- // packages/react/src/contexts/event-context.tsx
619
565
  import { jsx as jsx2 } from "react/jsx-runtime";
620
566
  var EventContextState = createContext2(null);
621
567
  function useEventContext() {
@@ -632,52 +578,32 @@ function EventContextProvider({
632
578
  aomiClient,
633
579
  sessionId
634
580
  }) {
635
- const bufferRef = useRef2(null);
636
- if (!bufferRef.current) {
637
- bufferRef.current = createEventBuffer();
638
- }
639
- const buffer = bufferRef.current;
640
- const [sseStatus, setSseStatus] = useState2("disconnected");
641
- useEffect2(() => {
642
- setSSEStatus(buffer, "connecting");
643
- setSseStatus("connecting");
644
- const unsubscribe = aomiClient.subscribeSSE(
645
- sessionId,
646
- (event) => {
647
- enqueueInbound(buffer, {
648
- type: event.type,
649
- sessionId: event.session_id,
650
- payload: event
651
- });
652
- const inboundEvent = {
653
- type: event.type,
654
- sessionId: event.session_id,
655
- payload: event,
656
- status: "fetched",
657
- timestamp: Date.now()
658
- };
659
- dispatch(buffer, inboundEvent);
660
- },
661
- (error) => {
662
- console.error("SSE error:", error);
663
- setSSEStatus(buffer, "disconnected");
664
- setSseStatus("disconnected");
665
- }
666
- );
667
- setSSEStatus(buffer, "connected");
668
- setSseStatus("connected");
669
- return () => {
670
- unsubscribe();
671
- setSSEStatus(buffer, "disconnected");
672
- setSseStatus("disconnected");
673
- };
674
- }, [aomiClient, sessionId, buffer]);
675
- const subscribeCallback = useCallback2(
581
+ const subscribersRef = useRef2(/* @__PURE__ */ new Map());
582
+ const subscribe = useCallback2(
676
583
  (type, callback) => {
677
- return subscribe(buffer, type, callback);
584
+ const subs = subscribersRef.current;
585
+ if (!subs.has(type)) {
586
+ subs.set(type, /* @__PURE__ */ new Set());
587
+ }
588
+ subs.get(type).add(callback);
589
+ return () => {
590
+ var _a;
591
+ (_a = subs.get(type)) == null ? void 0 : _a.delete(callback);
592
+ };
678
593
  },
679
- [buffer]
594
+ []
680
595
  );
596
+ const dispatchEvent = useCallback2((event) => {
597
+ const subs = subscribersRef.current;
598
+ const typeSubs = subs.get(event.type);
599
+ if (typeSubs) {
600
+ for (const cb of typeSubs) cb(event);
601
+ }
602
+ const wildcardSubs = subs.get("*");
603
+ if (wildcardSubs) {
604
+ for (const cb of wildcardSubs) cb(event);
605
+ }
606
+ }, []);
681
607
  const sendOutbound = useCallback2(
682
608
  async (event) => {
683
609
  try {
@@ -692,50 +618,14 @@ function EventContextProvider({
692
618
  },
693
619
  [aomiClient]
694
620
  );
695
- const dispatchSystemEvents = useCallback2(
696
- (sessionId2, events) => {
697
- var _a;
698
- for (const event of events) {
699
- let eventType;
700
- let payload;
701
- if (isInlineCall(event)) {
702
- eventType = event.InlineCall.type;
703
- payload = (_a = event.InlineCall.payload) != null ? _a : event.InlineCall;
704
- } else if (isSystemNotice(event)) {
705
- eventType = "system_notice";
706
- payload = { message: event.SystemNotice };
707
- } else if (isSystemError(event)) {
708
- eventType = "system_error";
709
- payload = { message: event.SystemError };
710
- } else if (isAsyncCallback(event)) {
711
- eventType = "async_callback";
712
- payload = event.AsyncCallback;
713
- } else {
714
- console.warn("Unknown system event type:", event);
715
- continue;
716
- }
717
- const inboundEvent = {
718
- type: eventType,
719
- sessionId: sessionId2,
720
- payload,
721
- status: "fetched",
722
- timestamp: Date.now()
723
- };
724
- enqueueInbound(buffer, {
725
- type: eventType,
726
- sessionId: sessionId2,
727
- payload
728
- });
729
- dispatch(buffer, inboundEvent);
730
- }
731
- },
732
- [buffer]
733
- );
734
621
  const contextValue = {
735
- subscribe: subscribeCallback,
622
+ subscribe,
623
+ dispatch: dispatchEvent,
736
624
  sendOutboundSystem: sendOutbound,
737
- dispatchInboundSystem: dispatchSystemEvents,
738
- sseStatus
625
+ // SSE is managed by ClientSession now — status is always "connected"
626
+ // when sessions are active. Individual session status can be queried
627
+ // from the session manager if needed.
628
+ sseStatus: "connected"
739
629
  };
740
630
  return /* @__PURE__ */ jsx2(EventContextState.Provider, { value: contextValue, children });
741
631
  }
@@ -745,7 +635,7 @@ import {
745
635
  createContext as createContext3,
746
636
  useCallback as useCallback3,
747
637
  useContext as useContext3,
748
- useState as useState3
638
+ useState as useState2
749
639
  } from "react";
750
640
  import { jsx as jsx3 } from "react/jsx-runtime";
751
641
  var NotificationContext = createContext3(null);
@@ -765,7 +655,7 @@ function generateId() {
765
655
  function NotificationContextProvider({
766
656
  children
767
657
  }) {
768
- const [notifications, setNotifications] = useState3([]);
658
+ const [notifications, setNotifications] = useState2([]);
769
659
  const showNotification = useCallback3((params) => {
770
660
  const id = generateId();
771
661
  const notification = __spreadProps(__spreadValues({}, params), {
@@ -846,7 +736,7 @@ import {
846
736
  useCallback as useCallback4,
847
737
  useContext as useContext5,
848
738
  useRef as useRef4,
849
- useState as useState4
739
+ useState as useState3
850
740
  } from "react";
851
741
  import { jsx as jsx5 } from "react/jsx-runtime";
852
742
  var UserContext = createContext5(void 0);
@@ -865,7 +755,7 @@ function useUser() {
865
755
  };
866
756
  }
867
757
  function UserContextProvider({ children }) {
868
- const [user, setUserState] = useState4({
758
+ const [user, setUserState] = useState3({
869
759
  isConnected: false,
870
760
  address: void 0,
871
761
  chainId: void 0,
@@ -943,14 +833,48 @@ function UserContextProvider({ children }) {
943
833
  }
944
834
 
945
835
  // packages/react/src/runtime/core.tsx
946
- import { useCallback as useCallback7, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef7 } from "react";
836
+ import { useCallback as useCallback7, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef7 } from "react";
947
837
  import {
948
838
  AssistantRuntimeProvider,
949
839
  useExternalStoreRuntime
950
840
  } from "@assistant-ui/react";
951
841
 
952
842
  // packages/react/src/runtime/orchestrator.ts
953
- import { useCallback as useCallback5, useRef as useRef5, useState as useState5 } from "react";
843
+ import { useCallback as useCallback5, useEffect as useEffect2, useRef as useRef5, useState as useState4 } from "react";
844
+
845
+ // packages/react/src/runtime/session-manager.ts
846
+ import { Session as ClientSession } from "@aomi-labs/client";
847
+ var SessionManager = class {
848
+ constructor(clientFactory) {
849
+ this.clientFactory = clientFactory;
850
+ this.sessions = /* @__PURE__ */ new Map();
851
+ }
852
+ getOrCreate(threadId, opts) {
853
+ let session = this.sessions.get(threadId);
854
+ if (session) return session;
855
+ session = new ClientSession(this.clientFactory(), __spreadProps(__spreadValues({}, opts), {
856
+ sessionId: threadId
857
+ }));
858
+ this.sessions.set(threadId, session);
859
+ return session;
860
+ }
861
+ get(threadId) {
862
+ return this.sessions.get(threadId);
863
+ }
864
+ close(threadId) {
865
+ const session = this.sessions.get(threadId);
866
+ if (session) {
867
+ session.close();
868
+ this.sessions.delete(threadId);
869
+ }
870
+ }
871
+ closeAll() {
872
+ for (const [threadId, session] of this.sessions) {
873
+ session.close();
874
+ }
875
+ this.sessions.clear();
876
+ }
877
+ };
954
878
 
955
879
  // packages/react/src/runtime/utils.ts
956
880
  import { clsx } from "clsx";
@@ -1054,194 +978,6 @@ var SUPPORTED_CHAINS = [
1054
978
  ];
1055
979
  var getChainInfo = (chainId) => chainId === void 0 ? void 0 : SUPPORTED_CHAINS.find((c) => c.id === chainId);
1056
980
 
1057
- // packages/react/src/state/backend-state.ts
1058
- function createBackendState() {
1059
- return {
1060
- runningThreads: /* @__PURE__ */ new Set()
1061
- };
1062
- }
1063
- function resolveThreadId(_state, threadId) {
1064
- return threadId;
1065
- }
1066
- function setThreadRunning(state, threadId, running) {
1067
- if (running) {
1068
- state.runningThreads.add(threadId);
1069
- } else {
1070
- state.runningThreads.delete(threadId);
1071
- }
1072
- }
1073
- function isThreadRunning(state, threadId) {
1074
- return state.runningThreads.has(threadId);
1075
- }
1076
-
1077
- // packages/react/src/runtime/message-controller.ts
1078
- var MessageController = class {
1079
- constructor(config) {
1080
- this.config = config;
1081
- }
1082
- inbound(threadId, msgs) {
1083
- if (!msgs) return;
1084
- const threadMessages = [];
1085
- for (const msg of msgs) {
1086
- const threadMessage = toInboundMessage(msg);
1087
- if (threadMessage) {
1088
- threadMessages.push(threadMessage);
1089
- }
1090
- }
1091
- this.getThreadContextApi().setThreadMessages(threadId, threadMessages);
1092
- }
1093
- async outbound(message, threadId) {
1094
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1095
- const backendState = this.config.backendStateRef.current;
1096
- const text = message.content.filter(
1097
- (part) => part.type === "text"
1098
- ).map(
1099
- (part) => part.text
1100
- ).join("\n");
1101
- if (!text) return;
1102
- const threadState = this.getThreadContextApi();
1103
- const existingMessages = threadState.getThreadMessages(threadId);
1104
- const userMessage = {
1105
- role: "user",
1106
- content: [{ type: "text", text }],
1107
- createdAt: /* @__PURE__ */ new Date()
1108
- };
1109
- threadState.setThreadMessages(threadId, [...existingMessages, userMessage]);
1110
- threadState.updateThreadMetadata(threadId, {
1111
- lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1112
- });
1113
- const backendThreadId = resolveThreadId(backendState, threadId);
1114
- const app = this.config.getApp();
1115
- const publicKey = (_b = (_a = this.config).getPublicKey) == null ? void 0 : _b.call(_a);
1116
- const apiKey = (_e = (_d = (_c = this.config).getApiKey) == null ? void 0 : _d.call(_c)) != null ? _e : void 0;
1117
- const clientId = (_g = (_f = this.config).getClientId) == null ? void 0 : _g.call(_f);
1118
- const userState = (_i = (_h = this.config).getUserState) == null ? void 0 : _i.call(_h);
1119
- try {
1120
- this.markRunning(threadId, true);
1121
- const response = await this.config.aomiClientRef.current.sendMessage(
1122
- backendThreadId,
1123
- text,
1124
- { app, publicKey, apiKey, userState, clientId }
1125
- );
1126
- if (response == null ? void 0 : response.messages) {
1127
- this.inbound(threadId, response.messages);
1128
- }
1129
- if (((_j = response == null ? void 0 : response.system_events) == null ? void 0 : _j.length) && this.config.onSyncEvents) {
1130
- this.config.onSyncEvents(backendThreadId, response.system_events);
1131
- }
1132
- if (response == null ? void 0 : response.is_processing) {
1133
- this.config.polling.start(threadId);
1134
- } else if (!this.config.polling.isPolling(threadId)) {
1135
- this.markRunning(threadId, false);
1136
- }
1137
- } catch (error) {
1138
- console.error("Failed to send message:", error);
1139
- this.markRunning(threadId, false);
1140
- }
1141
- }
1142
- async cancel(threadId) {
1143
- var _a;
1144
- this.config.polling.stop(threadId);
1145
- const backendState = this.config.backendStateRef.current;
1146
- const backendThreadId = resolveThreadId(backendState, threadId);
1147
- try {
1148
- const response = await this.config.aomiClientRef.current.interrupt(backendThreadId);
1149
- if (response == null ? void 0 : response.messages) {
1150
- this.inbound(threadId, response.messages);
1151
- }
1152
- if (((_a = response == null ? void 0 : response.system_events) == null ? void 0 : _a.length) && this.config.onSyncEvents) {
1153
- this.config.onSyncEvents(backendThreadId, response.system_events);
1154
- }
1155
- this.markRunning(threadId, false);
1156
- } catch (error) {
1157
- console.error("Failed to cancel:", error);
1158
- }
1159
- }
1160
- markRunning(threadId, running) {
1161
- var _a, _b;
1162
- setThreadRunning(this.config.backendStateRef.current, threadId, running);
1163
- if (this.config.threadContextRef.current.currentThreadId === threadId) {
1164
- (_b = (_a = this.config).setGlobalIsRunning) == null ? void 0 : _b.call(_a, running);
1165
- }
1166
- }
1167
- getThreadContextApi() {
1168
- const { getThreadMessages, setThreadMessages, updateThreadMetadata } = this.config.threadContextRef.current;
1169
- return { getThreadMessages, setThreadMessages, updateThreadMetadata };
1170
- }
1171
- };
1172
-
1173
- // packages/react/src/runtime/polling-controller.ts
1174
- var PollingController = class {
1175
- constructor(config) {
1176
- this.config = config;
1177
- this.intervals = /* @__PURE__ */ new Map();
1178
- var _a;
1179
- this.intervalMs = (_a = config.intervalMs) != null ? _a : 500;
1180
- }
1181
- start(threadId) {
1182
- var _a, _b;
1183
- const backendState = this.config.backendStateRef.current;
1184
- if (this.intervals.has(threadId)) return;
1185
- const backendThreadId = resolveThreadId(backendState, threadId);
1186
- setThreadRunning(backendState, threadId, true);
1187
- const tick = async () => {
1188
- var _a2, _b2, _c, _d;
1189
- if (!this.intervals.has(threadId)) return;
1190
- try {
1191
- console.log(
1192
- "[PollingController] Fetching state for threadId:",
1193
- threadId
1194
- );
1195
- const userState = (_b2 = (_a2 = this.config).getUserState) == null ? void 0 : _b2.call(_a2);
1196
- const clientId = (_d = (_c = this.config).getClientId) == null ? void 0 : _d.call(_c);
1197
- const state = await this.config.aomiClientRef.current.fetchState(
1198
- backendThreadId,
1199
- userState,
1200
- clientId
1201
- );
1202
- if (!this.intervals.has(threadId)) return;
1203
- this.handleState(threadId, state);
1204
- } catch (error) {
1205
- console.error("Polling error:", error);
1206
- this.stop(threadId);
1207
- }
1208
- };
1209
- const intervalId = setInterval(tick, this.intervalMs);
1210
- this.intervals.set(threadId, intervalId);
1211
- (_b = (_a = this.config).onStart) == null ? void 0 : _b.call(_a, threadId);
1212
- }
1213
- stop(threadId) {
1214
- var _a, _b;
1215
- const intervalId = this.intervals.get(threadId);
1216
- if (intervalId) {
1217
- clearInterval(intervalId);
1218
- this.intervals.delete(threadId);
1219
- }
1220
- setThreadRunning(this.config.backendStateRef.current, threadId, false);
1221
- (_b = (_a = this.config).onStop) == null ? void 0 : _b.call(_a, threadId);
1222
- }
1223
- isPolling(threadId) {
1224
- return this.intervals.has(threadId);
1225
- }
1226
- stopAll() {
1227
- for (const threadId of this.intervals.keys()) {
1228
- this.stop(threadId);
1229
- }
1230
- }
1231
- handleState(threadId, state) {
1232
- var _a;
1233
- if (((_a = state.system_events) == null ? void 0 : _a.length) && this.config.onSyncEvents) {
1234
- const backendState = this.config.backendStateRef.current;
1235
- const sessionId = resolveThreadId(backendState, threadId);
1236
- this.config.onSyncEvents(sessionId, state.system_events);
1237
- }
1238
- this.config.applyMessages(threadId, state.messages);
1239
- if (!state.is_processing) {
1240
- this.stop(threadId);
1241
- }
1242
- }
1243
- };
1244
-
1245
981
  // packages/react/src/runtime/orchestrator.ts
1246
982
  function useRuntimeOrchestrator(aomiClient, options) {
1247
983
  const threadContext = useThreadContext();
@@ -1249,90 +985,160 @@ function useRuntimeOrchestrator(aomiClient, options) {
1249
985
  threadContextRef.current = threadContext;
1250
986
  const aomiClientRef = useRef5(aomiClient);
1251
987
  aomiClientRef.current = aomiClient;
1252
- const backendStateRef = useRef5(createBackendState());
1253
- const [isRunning, setIsRunning] = useState5(false);
1254
- const messageControllerRef = useRef5(null);
1255
- const pollingRef = useRef5(null);
988
+ const [isRunning, setIsRunning] = useState4(false);
989
+ const sessionManagerRef = useRef5(null);
990
+ if (!sessionManagerRef.current) {
991
+ sessionManagerRef.current = new SessionManager(() => aomiClientRef.current);
992
+ }
1256
993
  const pendingFetches = useRef5(/* @__PURE__ */ new Set());
1257
- if (!pollingRef.current) {
1258
- pollingRef.current = new PollingController({
1259
- aomiClientRef,
1260
- backendStateRef,
1261
- applyMessages: (threadId, msgs) => {
1262
- var _a;
1263
- (_a = messageControllerRef.current) == null ? void 0 : _a.inbound(threadId, msgs);
1264
- },
1265
- onSyncEvents: options.onSyncEvents,
1266
- getUserState: options.getUserState,
1267
- getClientId: options.getClientId,
1268
- onStart: (threadId) => {
994
+ const listenerCleanups = useRef5(/* @__PURE__ */ new Map());
995
+ const getSession = useCallback5(
996
+ (threadId) => {
997
+ var _a, _b, _c, _d, _e;
998
+ const manager = sessionManagerRef.current;
999
+ const existing = manager.get(threadId);
1000
+ if (existing) return existing;
1001
+ const session = manager.getOrCreate(threadId, {
1002
+ app: options.getApp(),
1003
+ publicKey: (_a = options.getPublicKey) == null ? void 0 : _a.call(options),
1004
+ apiKey: (_c = (_b = options.getApiKey) == null ? void 0 : _b.call(options)) != null ? _c : void 0,
1005
+ clientId: (_d = options.getClientId) == null ? void 0 : _d.call(options),
1006
+ userState: (_e = options.getUserState) == null ? void 0 : _e.call(options)
1007
+ });
1008
+ const cleanups = [];
1009
+ cleanups.push(
1010
+ session.on("messages", (msgs) => {
1011
+ const threadMessages = [];
1012
+ for (const msg of msgs) {
1013
+ const converted = toInboundMessage(msg);
1014
+ if (converted) threadMessages.push(converted);
1015
+ }
1016
+ threadContextRef.current.setThreadMessages(threadId, threadMessages);
1017
+ })
1018
+ );
1019
+ cleanups.push(
1020
+ session.on("processing_start", () => {
1021
+ if (threadContextRef.current.currentThreadId === threadId) {
1022
+ setIsRunning(true);
1023
+ }
1024
+ })
1025
+ );
1026
+ cleanups.push(
1027
+ session.on("processing_end", () => {
1028
+ if (threadContextRef.current.currentThreadId === threadId) {
1029
+ setIsRunning(false);
1030
+ }
1031
+ })
1032
+ );
1033
+ cleanups.push(
1034
+ session.on("wallet_tx_request", (req) => {
1035
+ var _a2;
1036
+ return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
1037
+ })
1038
+ );
1039
+ cleanups.push(
1040
+ session.on("wallet_eip712_request", (req) => {
1041
+ var _a2;
1042
+ return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
1043
+ })
1044
+ );
1045
+ cleanups.push(
1046
+ session.on("title_changed", ({ title }) => {
1047
+ threadContextRef.current.updateThreadMetadata(threadId, { title });
1048
+ })
1049
+ );
1050
+ const forwardEvent = (type) => session.on(type, (payload) => {
1051
+ var _a2;
1052
+ (_a2 = options.onEvent) == null ? void 0 : _a2.call(options, { type, payload, sessionId: threadId });
1053
+ });
1054
+ cleanups.push(forwardEvent("tool_update"));
1055
+ cleanups.push(forwardEvent("tool_complete"));
1056
+ cleanups.push(forwardEvent("system_notice"));
1057
+ cleanups.push(forwardEvent("system_error"));
1058
+ cleanups.push(forwardEvent("async_callback"));
1059
+ listenerCleanups.current.set(threadId, () => {
1060
+ for (const cleanup of cleanups) cleanup();
1061
+ });
1062
+ return session;
1063
+ },
1064
+ // Stable deps — option getters are refs
1065
+ []
1066
+ );
1067
+ const ensureInitialState = useCallback5(
1068
+ async (threadId) => {
1069
+ var _a;
1070
+ if (pendingFetches.current.has(threadId)) return;
1071
+ pendingFetches.current.add(threadId);
1072
+ try {
1073
+ const session = getSession(threadId);
1074
+ const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
1075
+ if (userState) session.resolveUserState(userState);
1076
+ await session.fetchCurrentState();
1269
1077
  if (threadContextRef.current.currentThreadId === threadId) {
1270
- setIsRunning(true);
1078
+ setIsRunning(session.getIsProcessing());
1271
1079
  }
1272
- },
1273
- onStop: (threadId) => {
1080
+ } catch (error) {
1081
+ console.error("Failed to fetch initial state:", error);
1274
1082
  if (threadContextRef.current.currentThreadId === threadId) {
1275
1083
  setIsRunning(false);
1276
1084
  }
1085
+ } finally {
1086
+ pendingFetches.current.delete(threadId);
1277
1087
  }
1278
- });
1279
- }
1280
- if (!messageControllerRef.current) {
1281
- messageControllerRef.current = new MessageController({
1282
- aomiClientRef,
1283
- backendStateRef,
1284
- threadContextRef,
1285
- polling: pollingRef.current,
1286
- setGlobalIsRunning: setIsRunning,
1287
- getPublicKey: options.getPublicKey,
1288
- getApp: options.getApp,
1289
- getApiKey: options.getApiKey,
1290
- getClientId: options.getClientId,
1291
- getUserState: options.getUserState,
1292
- onSyncEvents: options.onSyncEvents
1293
- });
1294
- }
1295
- const ensureInitialState = useCallback5(async (threadId) => {
1296
- var _a, _b, _c, _d, _e;
1297
- if (pendingFetches.current.has(threadId)) return;
1298
- const backendThreadId = resolveThreadId(backendStateRef.current, threadId);
1299
- pendingFetches.current.add(threadId);
1300
- try {
1088
+ },
1089
+ [getSession]
1090
+ );
1091
+ const sendMessage = useCallback5(
1092
+ async (text, threadId) => {
1093
+ var _a;
1094
+ const session = getSession(threadId);
1301
1095
  const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
1302
- const clientId = (_b = options.getClientId) == null ? void 0 : _b.call(options);
1303
- const state = await aomiClientRef.current.fetchState(
1304
- backendThreadId,
1305
- userState,
1306
- clientId
1307
- );
1308
- (_c = messageControllerRef.current) == null ? void 0 : _c.inbound(threadId, state.messages);
1309
- if (((_d = state.system_events) == null ? void 0 : _d.length) && options.onSyncEvents) {
1310
- options.onSyncEvents(backendThreadId, state.system_events);
1311
- }
1312
- if (threadContextRef.current.currentThreadId === threadId) {
1313
- if (state.is_processing) {
1314
- setIsRunning(true);
1315
- (_e = pollingRef.current) == null ? void 0 : _e.start(threadId);
1316
- } else {
1317
- setIsRunning(false);
1318
- }
1096
+ if (userState) session.resolveUserState(userState);
1097
+ const existingMessages = threadContextRef.current.getThreadMessages(threadId);
1098
+ const userMessage = {
1099
+ role: "user",
1100
+ content: [{ type: "text", text }],
1101
+ createdAt: /* @__PURE__ */ new Date()
1102
+ };
1103
+ threadContextRef.current.setThreadMessages(threadId, [
1104
+ ...existingMessages,
1105
+ userMessage
1106
+ ]);
1107
+ threadContextRef.current.updateThreadMetadata(threadId, {
1108
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1109
+ });
1110
+ await session.sendAsync(text);
1111
+ },
1112
+ [getSession]
1113
+ );
1114
+ const cancelGeneration = useCallback5(
1115
+ async (threadId) => {
1116
+ var _a;
1117
+ const session = (_a = sessionManagerRef.current) == null ? void 0 : _a.get(threadId);
1118
+ if (session) {
1119
+ await session.interrupt();
1319
1120
  }
1320
- } catch (error) {
1321
- console.error("Failed to fetch initial state:", error);
1322
- if (threadContextRef.current.currentThreadId === threadId) {
1323
- setIsRunning(false);
1121
+ },
1122
+ []
1123
+ );
1124
+ useEffect2(() => {
1125
+ return () => {
1126
+ var _a;
1127
+ (_a = sessionManagerRef.current) == null ? void 0 : _a.closeAll();
1128
+ for (const cleanup of listenerCleanups.current.values()) {
1129
+ cleanup();
1324
1130
  }
1325
- } finally {
1326
- pendingFetches.current.delete(threadId);
1327
- }
1131
+ listenerCleanups.current.clear();
1132
+ };
1328
1133
  }, []);
1329
1134
  return {
1330
- backendStateRef,
1331
- polling: pollingRef.current,
1332
- messageController: messageControllerRef.current,
1135
+ sessionManager: sessionManagerRef.current,
1136
+ getSession,
1333
1137
  isRunning,
1334
1138
  setIsRunning,
1335
1139
  ensureInitialState,
1140
+ sendMessage,
1141
+ cancelGeneration,
1336
1142
  aomiClientRef
1337
1143
  };
1338
1144
  }
@@ -1484,154 +1290,49 @@ function useAomiRuntime() {
1484
1290
  }
1485
1291
 
1486
1292
  // packages/react/src/handlers/wallet-handler.ts
1487
- import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef6, useState as useState6 } from "react";
1488
- import {
1489
- normalizeEip712Payload,
1490
- normalizeTxPayload
1491
- } from "@aomi-labs/client";
1492
-
1493
- // packages/react/src/state/wallet-buffer.ts
1494
- function createWalletBuffer() {
1495
- return { queue: [], nextId: 1 };
1496
- }
1497
- function enqueue(buffer, kind, payload) {
1498
- const request = {
1499
- id: `wreq-${buffer.nextId++}`,
1500
- kind,
1501
- payload,
1502
- status: "pending",
1503
- timestamp: Date.now()
1504
- };
1505
- buffer.queue.push(request);
1506
- return request;
1507
- }
1508
- function dequeue(buffer, id) {
1509
- const index = buffer.queue.findIndex((r) => r.id === id);
1510
- if (index === -1) return null;
1511
- return buffer.queue.splice(index, 1)[0];
1512
- }
1513
- function markProcessing(buffer, id) {
1514
- const request = buffer.queue.find((r) => r.id === id);
1515
- if (!request || request.status !== "pending") return false;
1516
- request.status = "processing";
1517
- return true;
1518
- }
1519
- function getAll(buffer) {
1520
- return [...buffer.queue];
1521
- }
1522
-
1523
- // packages/react/src/handlers/wallet-handler.ts
1293
+ import { useCallback as useCallback6, useRef as useRef6, useState as useState5 } from "react";
1524
1294
  function useWalletHandler({
1525
- sessionId,
1526
- onRequestComplete
1295
+ getSession
1527
1296
  }) {
1528
- const { subscribe: subscribe2, sendOutboundSystem: sendOutbound } = useEventContext();
1529
- const bufferRef = useRef6(createWalletBuffer());
1530
- const [pendingRequests, setPendingRequests] = useState6([]);
1531
- const syncState = useCallback6(() => {
1532
- setPendingRequests(getAll(bufferRef.current));
1297
+ const [pendingRequests, setPendingRequests] = useState5([]);
1298
+ const requestsRef = useRef6([]);
1299
+ const enqueueRequest = useCallback6((request) => {
1300
+ requestsRef.current = [...requestsRef.current, request];
1301
+ setPendingRequests(requestsRef.current);
1533
1302
  }, []);
1534
- useEffect3(() => {
1535
- const unsubscribe = subscribe2(
1536
- "wallet_tx_request",
1537
- (event) => {
1538
- const payload = normalizeTxPayload(event.payload);
1539
- if (!payload) {
1540
- console.warn("[aomi][wallet] Ignoring tx request with invalid payload", event.payload);
1541
- return;
1542
- }
1543
- enqueue(bufferRef.current, "transaction", payload);
1544
- syncState();
1545
- }
1546
- );
1547
- return unsubscribe;
1548
- }, [subscribe2, syncState]);
1549
- useEffect3(() => {
1550
- const unsubscribe = subscribe2(
1551
- "wallet_eip712_request",
1552
- (event) => {
1553
- var _a;
1554
- const payload = normalizeEip712Payload((_a = event.payload) != null ? _a : {});
1555
- enqueue(bufferRef.current, "eip712_sign", payload);
1556
- syncState();
1557
- }
1558
- );
1559
- return unsubscribe;
1560
- }, [subscribe2, syncState]);
1561
- const startProcessingCb = useCallback6(
1562
- (id) => {
1563
- markProcessing(bufferRef.current, id);
1564
- syncState();
1565
- },
1566
- [syncState]
1567
- );
1568
1303
  const resolveRequest = useCallback6(
1569
1304
  (id, result) => {
1570
- var _a;
1571
- const removed = dequeue(bufferRef.current, id);
1572
- if (!removed) return;
1573
- let outbound;
1574
- if (removed.kind === "transaction") {
1575
- outbound = sendOutbound({
1576
- type: "wallet:tx_complete",
1577
- sessionId,
1578
- payload: {
1579
- txHash: (_a = result.txHash) != null ? _a : "",
1580
- status: "success",
1581
- amount: result.amount
1582
- }
1583
- });
1584
- } else {
1585
- const eip712Payload = removed.payload;
1586
- outbound = sendOutbound({
1587
- type: "wallet_eip712_response",
1588
- sessionId,
1589
- payload: {
1590
- status: "success",
1591
- signature: result.signature,
1592
- description: eip712Payload.description
1593
- }
1594
- });
1305
+ const session = getSession();
1306
+ if (!session) {
1307
+ console.error("[wallet-handler] No session available to resolve request");
1308
+ return;
1595
1309
  }
1596
- outbound.then(() => onRequestComplete == null ? void 0 : onRequestComplete());
1597
- syncState();
1310
+ requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
1311
+ setPendingRequests(requestsRef.current);
1312
+ void session.resolve(id, result).catch((err) => {
1313
+ console.error("[wallet-handler] Failed to resolve request:", err);
1314
+ });
1598
1315
  },
1599
- [sendOutbound, sessionId, syncState, onRequestComplete]
1316
+ [getSession]
1600
1317
  );
1601
1318
  const rejectRequest = useCallback6(
1602
1319
  (id, error) => {
1603
- const removed = dequeue(bufferRef.current, id);
1604
- if (!removed) return;
1605
- let outbound;
1606
- if (removed.kind === "transaction") {
1607
- outbound = sendOutbound({
1608
- type: "wallet:tx_complete",
1609
- sessionId,
1610
- payload: {
1611
- txHash: "",
1612
- status: "failed"
1613
- }
1614
- });
1615
- } else {
1616
- const eip712Payload = removed.payload;
1617
- outbound = sendOutbound({
1618
- type: "wallet_eip712_response",
1619
- sessionId,
1620
- payload: {
1621
- status: "failed",
1622
- error: error != null ? error : "EIP-712 signing failed",
1623
- description: eip712Payload.description
1624
- }
1625
- });
1320
+ const session = getSession();
1321
+ if (!session) {
1322
+ console.error("[wallet-handler] No session available to reject request");
1323
+ return;
1626
1324
  }
1627
- outbound.then(() => onRequestComplete == null ? void 0 : onRequestComplete());
1628
- syncState();
1325
+ requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
1326
+ setPendingRequests(requestsRef.current);
1327
+ void session.reject(id, error).catch((err) => {
1328
+ console.error("[wallet-handler] Failed to reject request:", err);
1329
+ });
1629
1330
  },
1630
- [sendOutbound, sessionId, syncState, onRequestComplete]
1331
+ [getSession]
1631
1332
  );
1632
1333
  return {
1633
1334
  pendingRequests,
1634
- startProcessing: startProcessingCb,
1335
+ enqueueRequest,
1635
1336
  resolveRequest,
1636
1337
  rejectRequest
1637
1338
  };
@@ -1646,19 +1347,25 @@ function AomiRuntimeCore({
1646
1347
  const threadContext = useThreadContext();
1647
1348
  const eventContext = useEventContext();
1648
1349
  const notificationContext = useNotification();
1649
- const { dispatchInboundSystem: dispatchSystemEvents } = eventContext;
1650
1350
  const { user, onUserStateChange, getUserState } = useUser();
1651
1351
  const { getControlState, getCurrentThreadApp, clearSecrets } = useControl();
1352
+ const sessionManagerRef = useRef7(null);
1353
+ const walletHandler = useWalletHandler({
1354
+ getSession: () => {
1355
+ var _a;
1356
+ return (_a = sessionManagerRef.current) == null ? void 0 : _a.get(threadContext.currentThreadId);
1357
+ }
1358
+ });
1652
1359
  const {
1653
- backendStateRef,
1654
- polling,
1655
- messageController,
1360
+ sessionManager,
1361
+ getSession,
1656
1362
  isRunning,
1657
1363
  setIsRunning,
1658
1364
  ensureInitialState,
1365
+ sendMessage: orchestratorSendMessage,
1366
+ cancelGeneration: orchestratorCancel,
1659
1367
  aomiClientRef
1660
1368
  } = useRuntimeOrchestrator(aomiClient, {
1661
- onSyncEvents: dispatchSystemEvents,
1662
1369
  getPublicKey: () => getUserState().address,
1663
1370
  getUserState,
1664
1371
  getApp: getCurrentThreadApp,
@@ -1666,8 +1373,11 @@ function AomiRuntimeCore({
1666
1373
  getClientId: () => {
1667
1374
  var _a;
1668
1375
  return (_a = getControlState().clientId) != null ? _a : void 0;
1669
- }
1376
+ },
1377
+ onWalletRequest: (request) => walletHandler.enqueueRequest(request),
1378
+ onEvent: (event) => eventContext.dispatch(event)
1670
1379
  });
1380
+ sessionManagerRef.current = sessionManager;
1671
1381
  const walletSnapshot = useCallback7(
1672
1382
  (nextUser) => ({
1673
1383
  address: nextUser.address,
@@ -1678,7 +1388,7 @@ function AomiRuntimeCore({
1678
1388
  [getUserState]
1679
1389
  );
1680
1390
  const lastWalletStateRef = useRef7(walletSnapshot(getUserState()));
1681
- useEffect4(() => {
1391
+ useEffect3(() => {
1682
1392
  lastWalletStateRef.current = walletSnapshot(getUserState());
1683
1393
  const unsubscribe = onUserStateChange(async (newUser) => {
1684
1394
  const nextWalletState = walletSnapshot(newUser);
@@ -1705,17 +1415,10 @@ function AomiRuntimeCore({
1705
1415
  const threadContextRef = useRef7(threadContext);
1706
1416
  threadContextRef.current = threadContext;
1707
1417
  const currentThreadIdRef = useRef7(threadContext.currentThreadId);
1708
- useEffect4(() => {
1418
+ useEffect3(() => {
1709
1419
  currentThreadIdRef.current = threadContext.currentThreadId;
1710
1420
  }, [threadContext.currentThreadId]);
1711
- const onWalletRequestComplete = useCallback7(() => {
1712
- polling.start(currentThreadIdRef.current);
1713
- }, [polling]);
1714
- const walletHandler = useWalletHandler({
1715
- sessionId: threadContext.currentThreadId,
1716
- onRequestComplete: onWalletRequestComplete
1717
- });
1718
- useEffect4(() => {
1421
+ useEffect3(() => {
1719
1422
  const unsubscribe = eventContext.subscribe(
1720
1423
  "user_state_request",
1721
1424
  () => {
@@ -1728,14 +1431,10 @@ function AomiRuntimeCore({
1728
1431
  );
1729
1432
  return unsubscribe;
1730
1433
  }, [eventContext, threadContext.currentThreadId, getUserState]);
1731
- useEffect4(() => {
1434
+ useEffect3(() => {
1732
1435
  void ensureInitialState(threadContext.currentThreadId);
1733
1436
  }, [ensureInitialState, threadContext.currentThreadId]);
1734
- useEffect4(() => {
1735
- const threadId = threadContext.currentThreadId;
1736
- setIsRunning(isThreadRunning(backendStateRef.current, threadId));
1737
- }, [backendStateRef, setIsRunning, threadContext.currentThreadId]);
1738
- useEffect4(() => {
1437
+ useEffect3(() => {
1739
1438
  const threadId = threadContext.currentThreadId;
1740
1439
  const currentMeta = threadContext.getThreadMetadata(threadId);
1741
1440
  if (currentMeta && currentMeta.control.isProcessing !== isRunning) {
@@ -1749,7 +1448,7 @@ function AomiRuntimeCore({
1749
1448
  const currentMessages = threadContext.getThreadMessages(
1750
1449
  threadContext.currentThreadId
1751
1450
  );
1752
- useEffect4(() => {
1451
+ useEffect3(() => {
1753
1452
  const userAddress = user.address;
1754
1453
  if (!userAddress) return;
1755
1454
  const fetchThreadList = async () => {
@@ -1790,66 +1489,19 @@ function AomiRuntimeCore({
1790
1489
  }, [user.address, aomiClientRef]);
1791
1490
  const threadListAdapter = useMemo2(
1792
1491
  () => buildThreadListAdapter({
1793
- backendStateRef,
1794
1492
  aomiClientRef,
1795
1493
  threadContext,
1796
- currentThreadIdRef,
1797
- polling,
1798
- userAddress: user.address,
1799
- setIsRunning,
1800
- getApp: getCurrentThreadApp,
1801
- getApiKey: () => getControlState().apiKey,
1802
- getUserState
1494
+ setIsRunning
1803
1495
  }),
1804
1496
  [
1805
1497
  aomiClientRef,
1806
- polling,
1807
- user.address,
1808
- backendStateRef,
1809
1498
  setIsRunning,
1810
1499
  threadContext,
1811
1500
  threadContext.currentThreadId,
1812
- threadContext.allThreadsMetadata,
1813
- getControlState,
1814
- getCurrentThreadApp,
1815
- getUserState
1501
+ threadContext.allThreadsMetadata
1816
1502
  ]
1817
1503
  );
1818
- useEffect4(() => {
1819
- const backendState = backendStateRef.current;
1820
- const unsubscribe = eventContext.subscribe("title_changed", (event) => {
1821
- const sessionId = event.sessionId;
1822
- const payload = event.payload;
1823
- const newTitle = payload == null ? void 0 : payload.new_title;
1824
- if (typeof newTitle !== "string") return;
1825
- const targetThreadId = resolveThreadId(backendState, sessionId);
1826
- const normalizedTitle = isPlaceholderTitle(newTitle) ? "" : newTitle;
1827
- if (process.env.NODE_ENV !== "production") {
1828
- console.debug("[aomi][sse] title_changed", {
1829
- sessionId,
1830
- newTitle,
1831
- normalizedTitle,
1832
- currentThreadId: threadContextRef.current.currentThreadId,
1833
- targetThreadId
1834
- });
1835
- }
1836
- threadContextRef.current.setThreadMetadata((prev) => {
1837
- var _a, _b;
1838
- const next = new Map(prev);
1839
- const existing = next.get(targetThreadId);
1840
- const nextStatus = (existing == null ? void 0 : existing.status) === "archived" ? "archived" : "regular";
1841
- next.set(targetThreadId, {
1842
- title: normalizedTitle,
1843
- status: nextStatus,
1844
- lastActiveAt: (_a = existing == null ? void 0 : existing.lastActiveAt) != null ? _a : (/* @__PURE__ */ new Date()).toISOString(),
1845
- control: (_b = existing == null ? void 0 : existing.control) != null ? _b : initThreadControl()
1846
- });
1847
- return next;
1848
- });
1849
- });
1850
- return unsubscribe;
1851
- }, [eventContext, backendStateRef]);
1852
- useEffect4(() => {
1504
+ useEffect3(() => {
1853
1505
  const showToolNotification = (eventType) => (event) => {
1854
1506
  const payload = event.payload;
1855
1507
  const toolName = typeof (payload == null ? void 0 : payload.tool_name) === "string" ? payload.tool_name : void 0;
@@ -1874,10 +1526,8 @@ function AomiRuntimeCore({
1874
1526
  unsubscribeComplete();
1875
1527
  };
1876
1528
  }, [eventContext, notificationContext]);
1877
- useEffect4(() => {
1878
- const unsubscribe = eventContext.subscribe("system_notice", (event) => {
1879
- const payload = event.payload;
1880
- const message = payload == null ? void 0 : payload.message;
1529
+ useEffect3(() => {
1530
+ const unsubscribe = eventContext.subscribe("system_notice", (_event) => {
1881
1531
  });
1882
1532
  return unsubscribe;
1883
1533
  }, [eventContext, notificationContext]);
@@ -1885,34 +1535,36 @@ function AomiRuntimeCore({
1885
1535
  messages: currentMessages,
1886
1536
  setMessages: (msgs) => threadContext.setThreadMessages(threadContext.currentThreadId, [...msgs]),
1887
1537
  isRunning,
1888
- onNew: (message) => messageController.outbound(message, threadContext.currentThreadId),
1889
- onCancel: () => messageController.cancel(threadContext.currentThreadId),
1538
+ onNew: async (message) => {
1539
+ const text = message.content.filter(
1540
+ (part) => part.type === "text"
1541
+ ).map((part) => part.text).join("\n");
1542
+ if (text) {
1543
+ await orchestratorSendMessage(text, threadContext.currentThreadId);
1544
+ }
1545
+ },
1546
+ onCancel: async () => {
1547
+ await orchestratorCancel(threadContext.currentThreadId);
1548
+ },
1890
1549
  convertMessage: (msg) => msg,
1891
1550
  adapters: { threadList: threadListAdapter }
1892
1551
  });
1893
- useEffect4(() => {
1552
+ useEffect3(() => {
1894
1553
  return () => {
1895
- polling.stopAll();
1554
+ sessionManager.closeAll();
1896
1555
  void clearSecrets();
1897
1556
  };
1898
- }, [polling, clearSecrets]);
1557
+ }, [sessionManager, clearSecrets]);
1899
1558
  const userContext = useUser();
1900
1559
  const sendMessage = useCallback7(
1901
1560
  async (text) => {
1902
- const appendMessage = {
1903
- role: "user",
1904
- content: [{ type: "text", text }]
1905
- };
1906
- await messageController.outbound(
1907
- appendMessage,
1908
- threadContext.currentThreadId
1909
- );
1561
+ await orchestratorSendMessage(text, threadContext.currentThreadId);
1910
1562
  },
1911
- [messageController, threadContext.currentThreadId]
1563
+ [orchestratorSendMessage, threadContext.currentThreadId]
1912
1564
  );
1913
1565
  const cancelGeneration = useCallback7(() => {
1914
- messageController.cancel(threadContext.currentThreadId);
1915
- }, [messageController, threadContext.currentThreadId]);
1566
+ void orchestratorCancel(threadContext.currentThreadId);
1567
+ }, [orchestratorCancel, threadContext.currentThreadId]);
1916
1568
  const getMessages = useCallback7(
1917
1569
  (threadId) => {
1918
1570
  const id = threadId != null ? threadId : threadContext.currentThreadId;
@@ -1926,9 +1578,10 @@ function AomiRuntimeCore({
1926
1578
  }, [threadListAdapter]);
1927
1579
  const deleteThread = useCallback7(
1928
1580
  async (threadId) => {
1581
+ sessionManager.close(threadId);
1929
1582
  await threadListAdapter.onDelete(threadId);
1930
1583
  },
1931
- [threadListAdapter]
1584
+ [threadListAdapter, sessionManager]
1932
1585
  );
1933
1586
  const renameThread = useCallback7(
1934
1587
  async (threadId, title) => {
@@ -1983,7 +1636,9 @@ function AomiRuntimeCore({
1983
1636
  clearAllNotifications: notificationContext.clearAll,
1984
1637
  // Wallet API
1985
1638
  pendingWalletRequests: walletHandler.pendingRequests,
1986
- startWalletRequest: walletHandler.startProcessing,
1639
+ startWalletRequest: () => {
1640
+ },
1641
+ // No-op: ClientSession manages processing state
1987
1642
  resolveWalletRequest: walletHandler.resolveRequest,
1988
1643
  rejectWalletRequest: walletHandler.rejectRequest,
1989
1644
  // Event API
@@ -2051,7 +1706,7 @@ function AomiRuntimeInner({
2051
1706
  }
2052
1707
 
2053
1708
  // packages/react/src/handlers/notification-handler.ts
2054
- import { useCallback as useCallback8, useEffect as useEffect5, useState as useState7 } from "react";
1709
+ import { useCallback as useCallback8, useEffect as useEffect4, useState as useState6 } from "react";
2055
1710
  var notificationIdCounter2 = 0;
2056
1711
  function generateNotificationId() {
2057
1712
  return `notif-${Date.now()}-${++notificationIdCounter2}`;
@@ -2059,10 +1714,10 @@ function generateNotificationId() {
2059
1714
  function useNotificationHandler({
2060
1715
  onNotification
2061
1716
  } = {}) {
2062
- const { subscribe: subscribe2 } = useEventContext();
2063
- const [notifications, setNotifications] = useState7([]);
2064
- useEffect5(() => {
2065
- const unsubscribe = subscribe2("notification", (event) => {
1717
+ const { subscribe } = useEventContext();
1718
+ const [notifications, setNotifications] = useState6([]);
1719
+ useEffect4(() => {
1720
+ const unsubscribe = subscribe("notification", (event) => {
2066
1721
  var _a, _b;
2067
1722
  const payload = event.payload;
2068
1723
  const notification = {
@@ -2071,14 +1726,14 @@ function useNotificationHandler({
2071
1726
  title: (_b = payload.title) != null ? _b : "Notification",
2072
1727
  body: payload.body,
2073
1728
  handled: false,
2074
- timestamp: event.timestamp,
1729
+ timestamp: Date.now(),
2075
1730
  sessionId: event.sessionId
2076
1731
  };
2077
1732
  setNotifications((prev) => [notification, ...prev]);
2078
1733
  onNotification == null ? void 0 : onNotification(notification);
2079
1734
  });
2080
1735
  return unsubscribe;
2081
- }, [subscribe2, onNotification]);
1736
+ }, [subscribe, onNotification]);
2082
1737
  const unhandledCount = notifications.filter((n) => !n.handled).length;
2083
1738
  const markHandled = useCallback8((id) => {
2084
1739
  setNotifications(