@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.cjs +276 -611
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -56
- package/dist/index.d.ts +41 -56
- package/dist/index.js +293 -638
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
-
|
|
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
|
|
636
|
-
|
|
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
|
-
|
|
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
|
-
[
|
|
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
|
|
622
|
+
subscribe,
|
|
623
|
+
dispatch: dispatchEvent,
|
|
736
624
|
sendOutboundSystem: sendOutbound,
|
|
737
|
-
|
|
738
|
-
|
|
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
|
|
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] =
|
|
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
|
|
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] =
|
|
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
|
|
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
|
|
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
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
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
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
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(
|
|
1078
|
+
setIsRunning(session.getIsProcessing());
|
|
1271
1079
|
}
|
|
1272
|
-
}
|
|
1273
|
-
|
|
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
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
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
|
-
|
|
1303
|
-
const
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
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
|
-
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
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
|
-
|
|
1326
|
-
|
|
1327
|
-
}
|
|
1131
|
+
listenerCleanups.current.clear();
|
|
1132
|
+
};
|
|
1328
1133
|
}, []);
|
|
1329
1134
|
return {
|
|
1330
|
-
|
|
1331
|
-
|
|
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,
|
|
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
|
-
|
|
1526
|
-
onRequestComplete
|
|
1295
|
+
getSession
|
|
1527
1296
|
}) {
|
|
1528
|
-
const
|
|
1529
|
-
const
|
|
1530
|
-
const
|
|
1531
|
-
|
|
1532
|
-
setPendingRequests(
|
|
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
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
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
|
-
|
|
1597
|
-
|
|
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
|
-
[
|
|
1316
|
+
[getSession]
|
|
1600
1317
|
);
|
|
1601
1318
|
const rejectRequest = useCallback6(
|
|
1602
1319
|
(id, error) => {
|
|
1603
|
-
const
|
|
1604
|
-
if (!
|
|
1605
|
-
|
|
1606
|
-
|
|
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
|
-
|
|
1628
|
-
|
|
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
|
-
[
|
|
1331
|
+
[getSession]
|
|
1631
1332
|
);
|
|
1632
1333
|
return {
|
|
1633
1334
|
pendingRequests,
|
|
1634
|
-
|
|
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
|
-
|
|
1654
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1418
|
+
useEffect3(() => {
|
|
1709
1419
|
currentThreadIdRef.current = threadContext.currentThreadId;
|
|
1710
1420
|
}, [threadContext.currentThreadId]);
|
|
1711
|
-
|
|
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
|
-
|
|
1434
|
+
useEffect3(() => {
|
|
1732
1435
|
void ensureInitialState(threadContext.currentThreadId);
|
|
1733
1436
|
}, [ensureInitialState, threadContext.currentThreadId]);
|
|
1734
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1878
|
-
const unsubscribe = eventContext.subscribe("system_notice", (
|
|
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) =>
|
|
1889
|
-
|
|
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
|
-
|
|
1552
|
+
useEffect3(() => {
|
|
1894
1553
|
return () => {
|
|
1895
|
-
|
|
1554
|
+
sessionManager.closeAll();
|
|
1896
1555
|
void clearSecrets();
|
|
1897
1556
|
};
|
|
1898
|
-
}, [
|
|
1557
|
+
}, [sessionManager, clearSecrets]);
|
|
1899
1558
|
const userContext = useUser();
|
|
1900
1559
|
const sendMessage = useCallback7(
|
|
1901
1560
|
async (text) => {
|
|
1902
|
-
|
|
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
|
-
[
|
|
1563
|
+
[orchestratorSendMessage, threadContext.currentThreadId]
|
|
1912
1564
|
);
|
|
1913
1565
|
const cancelGeneration = useCallback7(() => {
|
|
1914
|
-
|
|
1915
|
-
}, [
|
|
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:
|
|
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
|
|
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
|
|
2063
|
-
const [notifications, setNotifications] =
|
|
2064
|
-
|
|
2065
|
-
const unsubscribe =
|
|
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:
|
|
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
|
-
}, [
|
|
1736
|
+
}, [subscribe, onNotification]);
|
|
2082
1737
|
const unhandledCount = notifications.filter((n) => !n.handled).length;
|
|
2083
1738
|
const markHandled = useCallback8((id) => {
|
|
2084
1739
|
setNotifications(
|