@aomi-labs/react 0.3.8 → 0.3.10

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/README.md CHANGED
@@ -10,15 +10,15 @@ npm install @aomi-labs/react @assistant-ui/react react react-dom
10
10
  pnpm add @aomi-labs/react @assistant-ui/react react react-dom
11
11
  ```
12
12
 
13
- Optional dependencies for advanced custom wallet adapters:
13
+ Optional dependencies when wiring wallet UI through Para + wagmi:
14
14
 
15
15
  ```bash
16
16
  pnpm add wagmi viem
17
17
  ```
18
18
 
19
- If you use the registry-installed `AomiFrame`, the default Para-backed
20
- `AomiAdapterProvider` is already wired for you. Add `wagmi` only when you want
21
- to bring your own adapter implementation.
19
+ If you use the registry-installed `AomiFrame` from `@aomi-labs/widget-lib`,
20
+ wallet behavior comes from the surrounding Para + wagmi provider tree.
21
+ `@aomi-labs/react` does not ship built-in wallet providers.
22
22
 
23
23
  ## Quick Start
24
24
 
package/dist/index.cjs CHANGED
@@ -50,7 +50,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
50
50
  // packages/react/src/index.ts
51
51
  var index_exports = {};
52
52
  __export(index_exports, {
53
- AomiClient: () => import_client3.AomiClient,
53
+ AomiClient: () => import_client6.AomiClient,
54
54
  AomiRuntimeProvider: () => AomiRuntimeProvider,
55
55
  ControlContextProvider: () => ControlContextProvider,
56
56
  EventContextProvider: () => EventContextProvider,
@@ -63,7 +63,7 @@ __export(index_exports, {
63
63
  getChainInfo: () => getChainInfo,
64
64
  getNetworkName: () => getNetworkName,
65
65
  initThreadControl: () => initThreadControl,
66
- toViemSignTypedDataArgs: () => import_client4.toViemSignTypedDataArgs,
66
+ toViemSignTypedDataArgs: () => import_client7.toViemSignTypedDataArgs,
67
67
  useAomiRuntime: () => useAomiRuntime,
68
68
  useControl: () => useControl,
69
69
  useCurrentThreadMessages: () => useCurrentThreadMessages,
@@ -76,12 +76,12 @@ __export(index_exports, {
76
76
  useWalletHandler: () => useWalletHandler
77
77
  });
78
78
  module.exports = __toCommonJS(index_exports);
79
- var import_client3 = require("@aomi-labs/client");
80
- var import_client4 = require("@aomi-labs/client");
79
+ var import_client6 = require("@aomi-labs/client");
80
+ var import_client7 = require("@aomi-labs/client");
81
81
 
82
82
  // packages/react/src/runtime/aomi-runtime.tsx
83
83
  var import_react11 = require("react");
84
- var import_client2 = require("@aomi-labs/client");
84
+ var import_client5 = require("@aomi-labs/client");
85
85
 
86
86
  // packages/react/src/contexts/control-context.tsx
87
87
  var import_react = require("react");
@@ -895,6 +895,8 @@ function useCurrentThreadMetadata() {
895
895
 
896
896
  // packages/react/src/contexts/user-context.tsx
897
897
  var import_react5 = require("react");
898
+ var import_client = require("@aomi-labs/client");
899
+ var import_client2 = require("@aomi-labs/client");
898
900
  var import_jsx_runtime5 = require("react/jsx-runtime");
899
901
  var UserContext = (0, import_react5.createContext)(void 0);
900
902
  function useUser() {
@@ -913,10 +915,10 @@ function useUser() {
913
915
  }
914
916
  function UserContextProvider({ children }) {
915
917
  const [user, setUserState] = (0, import_react5.useState)({
916
- isConnected: false,
917
918
  address: void 0,
918
- chainId: void 0,
919
- ensName: void 0,
919
+ chain_id: void 0,
920
+ is_connected: false,
921
+ ens_name: void 0,
920
922
  ext: void 0
921
923
  });
922
924
  const userRef = (0, import_react5.useRef)(user);
@@ -926,7 +928,13 @@ function UserContextProvider({ children }) {
926
928
  );
927
929
  const setUser = (0, import_react5.useCallback)((data) => {
928
930
  setUserState((prev) => {
929
- const next = __spreadValues(__spreadValues({}, prev), data);
931
+ var _a, _b, _c;
932
+ const normalizedData = (_a = import_client.UserState.normalize(data)) != null ? _a : {};
933
+ const next = normalizedData.is_connected === false ? __spreadProps(__spreadValues({}, (_b = import_client.UserState.normalize(__spreadValues(__spreadValues({}, prev), normalizedData))) != null ? _b : prev), {
934
+ address: void 0,
935
+ chain_id: void 0,
936
+ ens_name: void 0
937
+ }) : (_c = import_client.UserState.normalize(__spreadValues(__spreadValues({}, prev), normalizedData))) != null ? _c : prev;
930
938
  StateChangeCallbacks.current.forEach((callback) => {
931
939
  callback(next);
932
940
  });
@@ -935,12 +943,7 @@ function UserContextProvider({ children }) {
935
943
  }, []);
936
944
  const addExtValue = (0, import_react5.useCallback)((key, value) => {
937
945
  setUserState((prev) => {
938
- var _a;
939
- const next = __spreadProps(__spreadValues({}, prev), {
940
- ext: __spreadProps(__spreadValues({}, (_a = prev.ext) != null ? _a : {}), {
941
- [key]: value
942
- })
943
- });
946
+ const next = import_client.UserState.withExt(prev, key, value);
944
947
  StateChangeCallbacks.current.forEach((callback) => {
945
948
  callback(next);
946
949
  });
@@ -949,10 +952,11 @@ function UserContextProvider({ children }) {
949
952
  }, []);
950
953
  const removeExtValue = (0, import_react5.useCallback)((key) => {
951
954
  setUserState((prev) => {
952
- if (!prev.ext || !(key in prev.ext)) {
955
+ const ext = prev.ext;
956
+ if (typeof ext !== "object" || ext === null || Array.isArray(ext) || !(key in ext)) {
953
957
  return prev;
954
958
  }
955
- const nextExt = __spreadValues({}, prev.ext);
959
+ const nextExt = __spreadValues({}, ext);
956
960
  delete nextExt[key];
957
961
  const next = __spreadProps(__spreadValues({}, prev), {
958
962
  ext: Object.keys(nextExt).length > 0 ? nextExt : void 0
@@ -992,12 +996,13 @@ function UserContextProvider({ children }) {
992
996
  // packages/react/src/runtime/core.tsx
993
997
  var import_react9 = require("react");
994
998
  var import_react10 = require("@assistant-ui/react");
999
+ var import_client4 = require("@aomi-labs/client");
995
1000
 
996
1001
  // packages/react/src/runtime/orchestrator.ts
997
1002
  var import_react6 = require("react");
998
1003
 
999
1004
  // packages/react/src/runtime/session-manager.ts
1000
- var import_client = require("@aomi-labs/client");
1005
+ var import_client3 = require("@aomi-labs/client");
1001
1006
  var SessionManager = class {
1002
1007
  constructor(clientFactory) {
1003
1008
  this.clientFactory = clientFactory;
@@ -1006,7 +1011,7 @@ var SessionManager = class {
1006
1011
  getOrCreate(threadId, opts) {
1007
1012
  let session = this.sessions.get(threadId);
1008
1013
  if (session) return session;
1009
- session = new import_client.Session(this.clientFactory(), __spreadProps(__spreadValues({}, opts), {
1014
+ session = new import_client3.Session(this.clientFactory(), __spreadProps(__spreadValues({}, opts), {
1010
1015
  sessionId: threadId
1011
1016
  }));
1012
1017
  this.sessions.set(threadId, session);
@@ -1185,16 +1190,13 @@ function useRuntimeOrchestrator(aomiClient, options) {
1185
1190
  })
1186
1191
  );
1187
1192
  cleanups.push(
1188
- session.on("wallet_tx_request", (req) => {
1189
- var _a2;
1190
- return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
1191
- })
1192
- );
1193
- cleanups.push(
1194
- session.on("wallet_eip712_request", (req) => {
1195
- var _a2;
1196
- return (_a2 = options.onWalletRequest) == null ? void 0 : _a2.call(options, req);
1197
- })
1193
+ session.on(
1194
+ "wallet_requests_changed",
1195
+ (requests) => {
1196
+ var _a2;
1197
+ return (_a2 = options.onPendingRequestsChange) == null ? void 0 : _a2.call(options, requests);
1198
+ }
1199
+ )
1198
1200
  );
1199
1201
  cleanups.push(
1200
1202
  session.on("title_changed", ({ title }) => {
@@ -1220,7 +1222,7 @@ function useRuntimeOrchestrator(aomiClient, options) {
1220
1222
  );
1221
1223
  const ensureInitialState = (0, import_react6.useCallback)(
1222
1224
  async (threadId) => {
1223
- var _a;
1225
+ var _a, _b;
1224
1226
  if (pendingFetches.current.has(threadId)) return;
1225
1227
  pendingFetches.current.add(threadId);
1226
1228
  try {
@@ -1228,6 +1230,7 @@ function useRuntimeOrchestrator(aomiClient, options) {
1228
1230
  const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
1229
1231
  if (userState) session.resolveUserState(userState);
1230
1232
  await session.fetchCurrentState();
1233
+ (_b = options.onPendingRequestsChange) == null ? void 0 : _b.call(options, session.getPendingRequests());
1231
1234
  if (threadContextRef.current.currentThreadId === threadId) {
1232
1235
  setIsRunning(session.getIsProcessing());
1233
1236
  }
@@ -1244,7 +1247,7 @@ function useRuntimeOrchestrator(aomiClient, options) {
1244
1247
  );
1245
1248
  const sendMessage = (0, import_react6.useCallback)(
1246
1249
  async (text, threadId) => {
1247
- var _a;
1250
+ var _a, _b;
1248
1251
  const session = getSession(threadId);
1249
1252
  const userState = (_a = options.getUserState) == null ? void 0 : _a.call(options);
1250
1253
  if (userState) session.resolveUserState(userState);
@@ -1262,6 +1265,7 @@ function useRuntimeOrchestrator(aomiClient, options) {
1262
1265
  lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1263
1266
  });
1264
1267
  await session.sendAsync(text);
1268
+ (_b = options.onPendingRequestsChange) == null ? void 0 : _b.call(options, session.getPendingRequests());
1265
1269
  },
1266
1270
  [getSession]
1267
1271
  );
@@ -1449,9 +1453,9 @@ function useWalletHandler({
1449
1453
  getSession
1450
1454
  }) {
1451
1455
  const [pendingRequests, setPendingRequests] = (0, import_react8.useState)([]);
1452
- const requestsRef = (0, import_react8.useRef)([]);
1453
- const enqueueRequest = (0, import_react8.useCallback)((request) => {
1454
- requestsRef.current = [...requestsRef.current, request];
1456
+ const requestsRef = (0, import_react8.useRef)(pendingRequests);
1457
+ const setRequests = (0, import_react8.useCallback)((requests) => {
1458
+ requestsRef.current = [...requests];
1455
1459
  setPendingRequests(requestsRef.current);
1456
1460
  }, []);
1457
1461
  const resolveRequest = (0, import_react8.useCallback)(
@@ -1461,13 +1465,12 @@ function useWalletHandler({
1461
1465
  console.error("[wallet-handler] No session available to resolve request");
1462
1466
  return;
1463
1467
  }
1464
- requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
1465
- setPendingRequests(requestsRef.current);
1468
+ setRequests(requestsRef.current.filter((request) => request.id !== id));
1466
1469
  void session.resolve(id, result).catch((err) => {
1467
1470
  console.error("[wallet-handler] Failed to resolve request:", err);
1468
1471
  });
1469
1472
  },
1470
- [getSession]
1473
+ [getSession, setRequests]
1471
1474
  );
1472
1475
  const rejectRequest = (0, import_react8.useCallback)(
1473
1476
  (id, error) => {
@@ -1476,17 +1479,16 @@ function useWalletHandler({
1476
1479
  console.error("[wallet-handler] No session available to reject request");
1477
1480
  return;
1478
1481
  }
1479
- requestsRef.current = requestsRef.current.filter((r) => r.id !== id);
1480
- setPendingRequests(requestsRef.current);
1482
+ setRequests(requestsRef.current.filter((request) => request.id !== id));
1481
1483
  void session.reject(id, error).catch((err) => {
1482
1484
  console.error("[wallet-handler] Failed to reject request:", err);
1483
1485
  });
1484
1486
  },
1485
- [getSession]
1487
+ [getSession, setRequests]
1486
1488
  );
1487
1489
  return {
1488
1490
  pendingRequests,
1489
- enqueueRequest,
1491
+ setRequests,
1490
1492
  resolveRequest,
1491
1493
  rejectRequest
1492
1494
  };
@@ -1520,7 +1522,7 @@ function AomiRuntimeCore({
1520
1522
  cancelGeneration: orchestratorCancel,
1521
1523
  aomiClientRef
1522
1524
  } = useRuntimeOrchestrator(aomiClient, {
1523
- getPublicKey: () => getUserState().address,
1525
+ getPublicKey: () => import_client4.UserState.isConnected(getUserState()) ? import_client4.UserState.address(getUserState()) : void 0,
1524
1526
  getUserState,
1525
1527
  getApp: getCurrentThreadApp,
1526
1528
  getApiKey: () => getControlState().apiKey,
@@ -1528,17 +1530,20 @@ function AomiRuntimeCore({
1528
1530
  var _a;
1529
1531
  return (_a = getControlState().clientId) != null ? _a : void 0;
1530
1532
  },
1531
- onWalletRequest: (request) => walletHandler.enqueueRequest(request),
1533
+ onPendingRequestsChange: walletHandler.setRequests,
1532
1534
  onEvent: (event) => eventContext.dispatch(event)
1533
1535
  });
1534
1536
  sessionManagerRef.current = sessionManager;
1535
1537
  const walletSnapshot = (0, import_react9.useCallback)(
1536
- (nextUser) => ({
1537
- address: nextUser.address,
1538
- chainId: nextUser.chainId,
1539
- isConnected: nextUser.isConnected,
1540
- ensName: nextUser.ensName
1541
- }),
1538
+ (nextUser) => {
1539
+ var _a;
1540
+ return {
1541
+ address: import_client4.UserState.address(nextUser),
1542
+ chain_id: import_client4.UserState.chainId(nextUser),
1543
+ is_connected: (_a = import_client4.UserState.isConnected(nextUser)) != null ? _a : false,
1544
+ ens_name: typeof nextUser.ens_name === "string" ? nextUser.ens_name : void 0
1545
+ };
1546
+ },
1542
1547
  [getUserState]
1543
1548
  );
1544
1549
  const lastWalletStateRef = (0, import_react9.useRef)(walletSnapshot(getUserState()));
@@ -1547,7 +1552,7 @@ function AomiRuntimeCore({
1547
1552
  const unsubscribe = onUserStateChange(async (newUser) => {
1548
1553
  const nextWalletState = walletSnapshot(newUser);
1549
1554
  const prevWalletState = lastWalletStateRef.current;
1550
- if (prevWalletState.address === nextWalletState.address && prevWalletState.chainId === nextWalletState.chainId && prevWalletState.isConnected === nextWalletState.isConnected && prevWalletState.ensName === nextWalletState.ensName) {
1555
+ if (prevWalletState.address === nextWalletState.address && prevWalletState.chain_id === nextWalletState.chain_id && prevWalletState.is_connected === nextWalletState.is_connected && prevWalletState.ens_name === nextWalletState.ens_name) {
1551
1556
  return;
1552
1557
  }
1553
1558
  lastWalletStateRef.current = nextWalletState;
@@ -1568,26 +1573,50 @@ function AomiRuntimeCore({
1568
1573
  ]);
1569
1574
  const threadContextRef = (0, import_react9.useRef)(threadContext);
1570
1575
  threadContextRef.current = threadContext;
1571
- const currentThreadIdRef = (0, import_react9.useRef)(threadContext.currentThreadId);
1572
- (0, import_react9.useEffect)(() => {
1573
- currentThreadIdRef.current = threadContext.currentThreadId;
1574
- }, [threadContext.currentThreadId]);
1576
+ const remoteThreadIdsRef = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
1577
+ const warmedThreadIdsRef = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
1578
+ const warmThread = (0, import_react9.useCallback)(
1579
+ async (threadId) => {
1580
+ if (!remoteThreadIdsRef.current.has(threadId) || warmedThreadIdsRef.current.has(threadId)) {
1581
+ return;
1582
+ }
1583
+ const userState = getUserState();
1584
+ await aomiClientRef.current.createThread(
1585
+ threadId,
1586
+ import_client4.UserState.isConnected(userState) ? import_client4.UserState.address(userState) : void 0
1587
+ );
1588
+ warmedThreadIdsRef.current.add(threadId);
1589
+ },
1590
+ [aomiClientRef, getUserState]
1591
+ );
1575
1592
  (0, import_react9.useEffect)(() => {
1576
1593
  const unsubscribe = eventContext.subscribe(
1577
1594
  "user_state_request",
1578
1595
  () => {
1596
+ var _a, _b, _c;
1597
+ const session = (_b = (_a = sessionManagerRef.current) == null ? void 0 : _a.get(threadContext.currentThreadId)) != null ? _b : getSession(threadContext.currentThreadId);
1579
1598
  eventContext.sendOutboundSystem({
1580
1599
  type: "user_state_response",
1581
1600
  sessionId: threadContext.currentThreadId,
1582
- payload: getUserState()
1601
+ payload: (_c = session.getUserState()) != null ? _c : getUserState()
1583
1602
  });
1584
1603
  }
1585
1604
  );
1586
1605
  return unsubscribe;
1587
- }, [eventContext, threadContext.currentThreadId, getUserState]);
1606
+ }, [eventContext, threadContext.currentThreadId, getSession, getUserState]);
1588
1607
  (0, import_react9.useEffect)(() => {
1589
- void ensureInitialState(threadContext.currentThreadId);
1590
- }, [ensureInitialState, threadContext.currentThreadId]);
1608
+ const threadId = threadContext.currentThreadId;
1609
+ let cancelled = false;
1610
+ void (async () => {
1611
+ await warmThread(threadId);
1612
+ if (!cancelled) {
1613
+ await ensureInitialState(threadId);
1614
+ }
1615
+ })();
1616
+ return () => {
1617
+ cancelled = true;
1618
+ };
1619
+ }, [ensureInitialState, threadContext.currentThreadId, warmThread]);
1591
1620
  (0, import_react9.useEffect)(() => {
1592
1621
  const threadId = threadContext.currentThreadId;
1593
1622
  const currentMeta = threadContext.getThreadMetadata(threadId);
@@ -1603,16 +1632,22 @@ function AomiRuntimeCore({
1603
1632
  threadContext.currentThreadId
1604
1633
  );
1605
1634
  (0, import_react9.useEffect)(() => {
1606
- const userAddress = user.address;
1607
- if (!userAddress) return;
1635
+ const userAddress = import_client4.UserState.isConnected(user) ? import_client4.UserState.address(user) : void 0;
1636
+ if (!userAddress) {
1637
+ remoteThreadIdsRef.current.clear();
1638
+ warmedThreadIdsRef.current.clear();
1639
+ return;
1640
+ }
1608
1641
  const fetchThreadList = async () => {
1609
1642
  var _a, _b, _c;
1610
1643
  try {
1611
1644
  const threadList = await aomiClientRef.current.listThreads(userAddress);
1612
1645
  const currentContext = threadContextRef.current;
1646
+ const remoteThreadIds = /* @__PURE__ */ new Set();
1613
1647
  const newMetadata = new Map(currentContext.allThreadsMetadata);
1614
1648
  let maxChatNum = currentContext.threadCnt;
1615
1649
  for (const thread of threadList) {
1650
+ remoteThreadIds.add(thread.session_id);
1616
1651
  const rawTitle = (_a = thread.title) != null ? _a : "";
1617
1652
  const title = isPlaceholderTitle(rawTitle) ? "" : rawTitle;
1618
1653
  const lastActive = ((_b = newMetadata.get(thread.session_id)) == null ? void 0 : _b.lastActiveAt) || (/* @__PURE__ */ new Date()).toISOString();
@@ -1631,16 +1666,26 @@ function AomiRuntimeCore({
1631
1666
  }
1632
1667
  }
1633
1668
  }
1669
+ remoteThreadIdsRef.current = remoteThreadIds;
1670
+ warmedThreadIdsRef.current = new Set(
1671
+ Array.from(warmedThreadIdsRef.current).filter(
1672
+ (threadId) => remoteThreadIds.has(threadId)
1673
+ )
1674
+ );
1634
1675
  currentContext.setThreadMetadata(newMetadata);
1635
1676
  if (maxChatNum > currentContext.threadCnt) {
1636
1677
  currentContext.setThreadCnt(maxChatNum);
1637
1678
  }
1679
+ if (remoteThreadIds.has(currentContext.currentThreadId)) {
1680
+ await warmThread(currentContext.currentThreadId);
1681
+ await ensureInitialState(currentContext.currentThreadId);
1682
+ }
1638
1683
  } catch (error) {
1639
1684
  console.error("Failed to fetch thread list:", error);
1640
1685
  }
1641
1686
  };
1642
1687
  void fetchThreadList();
1643
- }, [user.address, aomiClientRef]);
1688
+ }, [user, aomiClientRef, ensureInitialState, warmThread]);
1644
1689
  const threadListAdapter = (0, import_react9.useMemo)(
1645
1690
  () => buildThreadListAdapter({
1646
1691
  aomiClientRef,
@@ -1828,7 +1873,7 @@ function AomiRuntimeProvider({
1828
1873
  children,
1829
1874
  backendUrl = "http://localhost:8080"
1830
1875
  }) {
1831
- const aomiClient = (0, import_react11.useMemo)(() => new import_client2.AomiClient({ baseUrl: backendUrl }), [backendUrl]);
1876
+ const aomiClient = (0, import_react11.useMemo)(() => new import_client5.AomiClient({ baseUrl: backendUrl }), [backendUrl]);
1832
1877
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThreadContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NotificationContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserContextProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AomiRuntimeInner, { aomiClient, children }) }) }) });
1833
1878
  }
1834
1879
  function AomiRuntimeInner({
@@ -1843,7 +1888,7 @@ function AomiRuntimeInner({
1843
1888
  {
1844
1889
  aomiClient,
1845
1890
  sessionId: threadContext.currentThreadId,
1846
- publicKey: (_a = user.address) != null ? _a : void 0,
1891
+ publicKey: import_client5.UserState.isConnected(user) ? (_a = import_client5.UserState.address(user)) != null ? _a : void 0 : void 0,
1847
1892
  getThreadMetadata: threadContext.getThreadMetadata,
1848
1893
  updateThreadMetadata: threadContext.updateThreadMetadata,
1849
1894
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(