@aomi-labs/react 0.3.1 → 0.3.3

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.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { AomiSystemEvent, AomiClient } from '@aomi-labs/client';
2
- export { AomiChatResponse, AomiClient, AomiClientOptions, AomiCreateThreadResponse, AomiInterruptResponse, AomiMessage, AomiSSEEvent, AomiStateResponse, AomiSystemEvent, AomiSystemResponse, AomiThread } from '@aomi-labs/client';
1
+ import { WalletTxPayload, WalletEip712Payload, AomiSystemEvent, AomiClient } from '@aomi-labs/client';
2
+ export { AomiChatResponse, AomiClient, AomiClientOptions, AomiCreateThreadResponse, AomiInterruptResponse, AomiMessage, AomiSSEEvent, AomiStateResponse, AomiSystemEvent, AomiSystemResponse, AomiThread, WalletEip712Payload, WalletTxPayload, toViemSignTypedDataArgs } from '@aomi-labs/client';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, SetStateAction } from 'react';
5
5
  import { ThreadMessageLike } from '@assistant-ui/react';
@@ -16,10 +16,13 @@ type UserState = {
16
16
  chainId?: number;
17
17
  isConnected: boolean;
18
18
  ensName?: string;
19
+ ext?: Record<string, unknown>;
19
20
  };
20
21
  declare function useUser(): {
21
22
  user: UserState;
22
23
  setUser: (data: Partial<UserState>) => void;
24
+ addExtValue: (key: string, value: unknown) => void;
25
+ removeExtValue: (key: string) => void;
23
26
  getUserState: () => UserState;
24
27
  onUserStateChange: (callback: (user: UserState) => void) => () => void;
25
28
  };
@@ -123,26 +126,6 @@ type NotificationContextProviderProps = {
123
126
  declare function NotificationContextProvider({ children, }: NotificationContextProviderProps): react_jsx_runtime.JSX.Element;
124
127
 
125
128
  type WalletRequestKind = "transaction" | "eip712_sign";
126
- type WalletTxPayload = {
127
- to: string;
128
- value?: string;
129
- data?: string;
130
- chainId?: number;
131
- };
132
- type WalletEip712Payload = {
133
- typed_data?: {
134
- domain?: {
135
- chainId?: number | string;
136
- };
137
- types?: Record<string, Array<{
138
- name: string;
139
- type: string;
140
- }>>;
141
- primaryType?: string;
142
- message?: Record<string, unknown>;
143
- };
144
- description?: string;
145
- };
146
129
  type WalletRequestStatus = "pending" | "processing";
147
130
  type WalletRequest = {
148
131
  id: string;
@@ -186,6 +169,10 @@ type AomiRuntimeApi = {
186
169
  getUserState: () => UserState;
187
170
  /** Update user state (partial updates merged with existing state) */
188
171
  setUser: (data: Partial<UserState>) => void;
172
+ /** Add or overwrite a value in user_state.ext */
173
+ addExtValue: (key: string, value: unknown) => void;
174
+ /** Remove a value from user_state.ext */
175
+ removeExtValue: (key: string) => void;
189
176
  /** Subscribe to user state changes. Returns unsubscribe function. */
190
177
  onUserStateChange: (callback: (user: UserState) => void) => () => void;
191
178
  /** ID of the currently active thread */
@@ -358,6 +345,8 @@ type ControlContextApi = {
358
345
  getAuthorizedApps: () => Promise<string[]>;
359
346
  /** Get current thread's control state */
360
347
  getCurrentThreadControl: () => ThreadControlState;
348
+ /** Get the current thread's effective app after auth fallback */
349
+ getCurrentThreadApp: () => string;
361
350
  /** Select a model for the current thread (updates metadata + calls backend) */
362
351
  onModelSelect: (model: string) => Promise<void>;
363
352
  /** Select an app for the current thread (updates metadata only) */
@@ -389,4 +378,4 @@ type ControlContextProviderProps = {
389
378
  };
390
379
  declare function ControlContextProvider({ children, aomiClient, sessionId, publicKey, getThreadMetadata, updateThreadMetadata, }: ControlContextProviderProps): react_jsx_runtime.JSX.Element;
391
380
 
392
- export { type AomiRuntimeApi, AomiRuntimeProvider, type AomiRuntimeProviderProps, type ChainInfo, type ControlContextApi, ControlContextProvider, type ControlContextProviderProps, type ControlState, type EventBuffer, type EventContext, EventContextProvider, type EventContextProviderProps, type EventSubscriber, type InboundEvent, type Notification$1 as Notification, type NotificationApi, NotificationContextProvider, type NotificationContextProviderProps, type NotificationContextApi as NotificationContextValue, type NotificationHandlerConfig, type NotificationType, type OutboundEvent, type SSEStatus, SUPPORTED_CHAINS, type NotificationData as ShowNotificationParams, type ThreadContext, ThreadContextProvider, type ThreadControlState, type ThreadMetadata, type UserConfig, UserContextProvider, type UserState, type WalletBuffer, type WalletEip712Payload, type WalletHandlerApi, type WalletHandlerConfig, type WalletRequest, type WalletRequestKind, type WalletRequestResult, type WalletRequestStatus, type WalletTxPayload, cn, formatAddress, getChainInfo, getNetworkName, initThreadControl, useAomiRuntime, useControl, useCurrentThreadMessages, useCurrentThreadMetadata, useEventContext, useNotification, useNotificationHandler, useThreadContext, useUser, useWalletHandler };
381
+ export { type AomiRuntimeApi, AomiRuntimeProvider, type AomiRuntimeProviderProps, type ChainInfo, type ControlContextApi, ControlContextProvider, type ControlContextProviderProps, type ControlState, type EventBuffer, type EventContext, EventContextProvider, type EventContextProviderProps, type EventSubscriber, type InboundEvent, type Notification$1 as Notification, type NotificationApi, NotificationContextProvider, type NotificationContextProviderProps, type NotificationContextApi as NotificationContextValue, type NotificationHandlerConfig, type NotificationType, type OutboundEvent, type SSEStatus, SUPPORTED_CHAINS, type NotificationData as ShowNotificationParams, type ThreadContext, ThreadContextProvider, type ThreadControlState, type ThreadMetadata, type UserConfig, UserContextProvider, type UserState, type WalletBuffer, type WalletHandlerApi, type WalletHandlerConfig, type WalletRequest, type WalletRequestKind, type WalletRequestResult, type WalletRequestStatus, cn, formatAddress, getChainInfo, getNetworkName, initThreadControl, useAomiRuntime, useControl, useCurrentThreadMessages, useCurrentThreadMetadata, useEventContext, useNotification, useNotificationHandler, useThreadContext, useUser, useWalletHandler };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { AomiSystemEvent, AomiClient } from '@aomi-labs/client';
2
- export { AomiChatResponse, AomiClient, AomiClientOptions, AomiCreateThreadResponse, AomiInterruptResponse, AomiMessage, AomiSSEEvent, AomiStateResponse, AomiSystemEvent, AomiSystemResponse, AomiThread } from '@aomi-labs/client';
1
+ import { WalletTxPayload, WalletEip712Payload, AomiSystemEvent, AomiClient } from '@aomi-labs/client';
2
+ export { AomiChatResponse, AomiClient, AomiClientOptions, AomiCreateThreadResponse, AomiInterruptResponse, AomiMessage, AomiSSEEvent, AomiStateResponse, AomiSystemEvent, AomiSystemResponse, AomiThread, WalletEip712Payload, WalletTxPayload, toViemSignTypedDataArgs } from '@aomi-labs/client';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, SetStateAction } from 'react';
5
5
  import { ThreadMessageLike } from '@assistant-ui/react';
@@ -16,10 +16,13 @@ type UserState = {
16
16
  chainId?: number;
17
17
  isConnected: boolean;
18
18
  ensName?: string;
19
+ ext?: Record<string, unknown>;
19
20
  };
20
21
  declare function useUser(): {
21
22
  user: UserState;
22
23
  setUser: (data: Partial<UserState>) => void;
24
+ addExtValue: (key: string, value: unknown) => void;
25
+ removeExtValue: (key: string) => void;
23
26
  getUserState: () => UserState;
24
27
  onUserStateChange: (callback: (user: UserState) => void) => () => void;
25
28
  };
@@ -123,26 +126,6 @@ type NotificationContextProviderProps = {
123
126
  declare function NotificationContextProvider({ children, }: NotificationContextProviderProps): react_jsx_runtime.JSX.Element;
124
127
 
125
128
  type WalletRequestKind = "transaction" | "eip712_sign";
126
- type WalletTxPayload = {
127
- to: string;
128
- value?: string;
129
- data?: string;
130
- chainId?: number;
131
- };
132
- type WalletEip712Payload = {
133
- typed_data?: {
134
- domain?: {
135
- chainId?: number | string;
136
- };
137
- types?: Record<string, Array<{
138
- name: string;
139
- type: string;
140
- }>>;
141
- primaryType?: string;
142
- message?: Record<string, unknown>;
143
- };
144
- description?: string;
145
- };
146
129
  type WalletRequestStatus = "pending" | "processing";
147
130
  type WalletRequest = {
148
131
  id: string;
@@ -186,6 +169,10 @@ type AomiRuntimeApi = {
186
169
  getUserState: () => UserState;
187
170
  /** Update user state (partial updates merged with existing state) */
188
171
  setUser: (data: Partial<UserState>) => void;
172
+ /** Add or overwrite a value in user_state.ext */
173
+ addExtValue: (key: string, value: unknown) => void;
174
+ /** Remove a value from user_state.ext */
175
+ removeExtValue: (key: string) => void;
189
176
  /** Subscribe to user state changes. Returns unsubscribe function. */
190
177
  onUserStateChange: (callback: (user: UserState) => void) => () => void;
191
178
  /** ID of the currently active thread */
@@ -358,6 +345,8 @@ type ControlContextApi = {
358
345
  getAuthorizedApps: () => Promise<string[]>;
359
346
  /** Get current thread's control state */
360
347
  getCurrentThreadControl: () => ThreadControlState;
348
+ /** Get the current thread's effective app after auth fallback */
349
+ getCurrentThreadApp: () => string;
361
350
  /** Select a model for the current thread (updates metadata + calls backend) */
362
351
  onModelSelect: (model: string) => Promise<void>;
363
352
  /** Select an app for the current thread (updates metadata only) */
@@ -389,4 +378,4 @@ type ControlContextProviderProps = {
389
378
  };
390
379
  declare function ControlContextProvider({ children, aomiClient, sessionId, publicKey, getThreadMetadata, updateThreadMetadata, }: ControlContextProviderProps): react_jsx_runtime.JSX.Element;
391
380
 
392
- export { type AomiRuntimeApi, AomiRuntimeProvider, type AomiRuntimeProviderProps, type ChainInfo, type ControlContextApi, ControlContextProvider, type ControlContextProviderProps, type ControlState, type EventBuffer, type EventContext, EventContextProvider, type EventContextProviderProps, type EventSubscriber, type InboundEvent, type Notification$1 as Notification, type NotificationApi, NotificationContextProvider, type NotificationContextProviderProps, type NotificationContextApi as NotificationContextValue, type NotificationHandlerConfig, type NotificationType, type OutboundEvent, type SSEStatus, SUPPORTED_CHAINS, type NotificationData as ShowNotificationParams, type ThreadContext, ThreadContextProvider, type ThreadControlState, type ThreadMetadata, type UserConfig, UserContextProvider, type UserState, type WalletBuffer, type WalletEip712Payload, type WalletHandlerApi, type WalletHandlerConfig, type WalletRequest, type WalletRequestKind, type WalletRequestResult, type WalletRequestStatus, type WalletTxPayload, cn, formatAddress, getChainInfo, getNetworkName, initThreadControl, useAomiRuntime, useControl, useCurrentThreadMessages, useCurrentThreadMetadata, useEventContext, useNotification, useNotificationHandler, useThreadContext, useUser, useWalletHandler };
381
+ export { type AomiRuntimeApi, AomiRuntimeProvider, type AomiRuntimeProviderProps, type ChainInfo, type ControlContextApi, ControlContextProvider, type ControlContextProviderProps, type ControlState, type EventBuffer, type EventContext, EventContextProvider, type EventContextProviderProps, type EventSubscriber, type InboundEvent, type Notification$1 as Notification, type NotificationApi, NotificationContextProvider, type NotificationContextProviderProps, type NotificationContextApi as NotificationContextValue, type NotificationHandlerConfig, type NotificationType, type OutboundEvent, type SSEStatus, SUPPORTED_CHAINS, type NotificationData as ShowNotificationParams, type ThreadContext, ThreadContextProvider, type ThreadControlState, type ThreadMetadata, type UserConfig, UserContextProvider, type UserState, type WalletBuffer, type WalletHandlerApi, type WalletHandlerConfig, type WalletRequest, type WalletRequestKind, type WalletRequestResult, type WalletRequestStatus, cn, formatAddress, getChainInfo, getNetworkName, initThreadControl, useAomiRuntime, useControl, useCurrentThreadMessages, useCurrentThreadMetadata, useEventContext, useNotification, useNotificationHandler, useThreadContext, useUser, useWalletHandler };
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
 
21
21
  // packages/react/src/index.ts
22
22
  import { AomiClient as AomiClient2 } from "@aomi-labs/client";
23
+ import { toViemSignTypedDataArgs } from "@aomi-labs/client";
23
24
 
24
25
  // packages/react/src/runtime/aomi-runtime.tsx
25
26
  import { useMemo as useMemo3 } from "react";
@@ -209,6 +210,16 @@ var ThreadStore = class {
209
210
  // packages/react/src/contexts/control-context.tsx
210
211
  import { jsx } from "react/jsx-runtime";
211
212
  var API_KEY_STORAGE_KEY = "aomi_api_key";
213
+ function getDefaultApp(apps) {
214
+ var _a;
215
+ return apps.includes("default") ? "default" : (_a = apps[0]) != null ? _a : null;
216
+ }
217
+ function resolveAuthorizedApp(app, authorizedApps, defaultApp) {
218
+ if (app && authorizedApps.includes(app)) {
219
+ return app;
220
+ }
221
+ return defaultApp;
222
+ }
212
223
  var ControlContext = createContext(null);
213
224
  function useControl() {
214
225
  const ctx = useContext(ControlContext);
@@ -271,13 +282,16 @@ function ControlContextProvider({
271
282
  }, [state.apiKey]);
272
283
  useEffect(() => {
273
284
  const fetchApps = async () => {
274
- var _a2, _b2;
285
+ var _a2;
275
286
  try {
276
287
  const apps = await aomiClientRef.current.getApps(
277
288
  sessionIdRef.current,
278
- { publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
289
+ {
290
+ publicKey: publicKeyRef.current,
291
+ apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
292
+ }
279
293
  );
280
- const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
294
+ const defaultApp = getDefaultApp(apps);
281
295
  setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
282
296
  authorizedApps: apps,
283
297
  defaultApp
@@ -291,7 +305,7 @@ function ControlContextProvider({
291
305
  }
292
306
  };
293
307
  void fetchApps();
294
- }, [state.apiKey]);
308
+ }, [state.apiKey, publicKey, sessionId]);
295
309
  useEffect(() => {
296
310
  const fetchModels = async () => {
297
311
  try {
@@ -337,13 +351,16 @@ function ControlContextProvider({
337
351
  }
338
352
  }, []);
339
353
  const getAuthorizedApps = useCallback(async () => {
340
- var _a2, _b2;
354
+ var _a2;
341
355
  try {
342
356
  const apps = await aomiClientRef.current.getApps(
343
357
  sessionIdRef.current,
344
- { publicKey: publicKeyRef.current, apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0 }
358
+ {
359
+ publicKey: publicKeyRef.current,
360
+ apiKey: (_a2 = stateRef.current.apiKey) != null ? _a2 : void 0
361
+ }
345
362
  );
346
- const defaultApp = apps.includes("default") ? "default" : (_b2 = apps[0]) != null ? _b2 : null;
363
+ const defaultApp = getDefaultApp(apps);
347
364
  setStateInternal((prev) => __spreadProps(__spreadValues({}, prev), {
348
365
  authorizedApps: apps,
349
366
  defaultApp
@@ -363,8 +380,17 @@ function ControlContextProvider({
363
380
  const metadata = getThreadMetadataRef.current(sessionIdRef.current);
364
381
  return (_a2 = metadata == null ? void 0 : metadata.control) != null ? _a2 : initThreadControl();
365
382
  }, []);
383
+ const getCurrentThreadApp = useCallback(() => {
384
+ var _a2, _b2, _c;
385
+ const currentControl = (_b2 = (_a2 = getThreadMetadataRef.current(sessionIdRef.current)) == null ? void 0 : _a2.control) != null ? _b2 : initThreadControl();
386
+ return (_c = resolveAuthorizedApp(
387
+ currentControl.app,
388
+ stateRef.current.authorizedApps,
389
+ stateRef.current.defaultApp
390
+ )) != null ? _c : "default";
391
+ }, []);
366
392
  const onModelSelect = useCallback(async (model) => {
367
- var _a2, _b2, _c, _d, _e;
393
+ var _a2, _b2, _c, _d;
368
394
  const threadId = sessionIdRef.current;
369
395
  const currentControl = (_b2 = (_a2 = getThreadMetadataRef.current(threadId)) == null ? void 0 : _a2.control) != null ? _b2 : initThreadControl();
370
396
  const isProcessing2 = currentControl.isProcessing;
@@ -377,7 +403,11 @@ function ControlContextProvider({
377
403
  console.warn("[control-context] Cannot switch model while processing");
378
404
  return;
379
405
  }
380
- const app = (_d = (_c = currentControl.app) != null ? _c : stateRef.current.defaultApp) != null ? _d : "default";
406
+ const app = (_c = resolveAuthorizedApp(
407
+ currentControl.app,
408
+ stateRef.current.authorizedApps,
409
+ stateRef.current.defaultApp
410
+ )) != null ? _c : "default";
381
411
  console.log("[control-context] onModelSelect updating metadata", {
382
412
  threadId,
383
413
  model,
@@ -401,7 +431,7 @@ function ControlContextProvider({
401
431
  const result = await aomiClientRef.current.setModel(
402
432
  threadId,
403
433
  model,
404
- { app, apiKey: (_e = stateRef.current.apiKey) != null ? _e : void 0 }
434
+ { app, apiKey: (_d = stateRef.current.apiKey) != null ? _d : void 0 }
405
435
  );
406
436
  console.log("[control-context] onModelSelect backend result", result);
407
437
  } catch (err) {
@@ -425,6 +455,10 @@ function ControlContextProvider({
425
455
  );
426
456
  return;
427
457
  }
458
+ if (stateRef.current.authorizedApps.length > 0 && !stateRef.current.authorizedApps.includes(app)) {
459
+ console.warn("[control-context] Cannot select unauthorized app", { app });
460
+ return;
461
+ }
428
462
  console.log("[control-context] onAppSelect updating metadata", {
429
463
  threadId,
430
464
  app,
@@ -481,6 +515,7 @@ function ControlContextProvider({
481
515
  getAvailableModels,
482
516
  getAuthorizedApps,
483
517
  getCurrentThreadControl,
518
+ getCurrentThreadApp,
484
519
  onModelSelect,
485
520
  onAppSelect,
486
521
  isProcessing,
@@ -797,6 +832,8 @@ function useUser() {
797
832
  return {
798
833
  user: context.user,
799
834
  setUser: context.setUser,
835
+ addExtValue: context.addExtValue,
836
+ removeExtValue: context.removeExtValue,
800
837
  getUserState: context.getUserState,
801
838
  onUserStateChange: context.onUserStateChange
802
839
  };
@@ -806,7 +843,8 @@ function UserContextProvider({ children }) {
806
843
  isConnected: false,
807
844
  address: void 0,
808
845
  chainId: void 0,
809
- ensName: void 0
846
+ ensName: void 0,
847
+ ext: void 0
810
848
  });
811
849
  const userRef = useRef4(user);
812
850
  userRef.current = user;
@@ -822,6 +860,36 @@ function UserContextProvider({ children }) {
822
860
  return next;
823
861
  });
824
862
  }, []);
863
+ const addExtValue = useCallback4((key, value) => {
864
+ setUserState((prev) => {
865
+ var _a;
866
+ const next = __spreadProps(__spreadValues({}, prev), {
867
+ ext: __spreadProps(__spreadValues({}, (_a = prev.ext) != null ? _a : {}), {
868
+ [key]: value
869
+ })
870
+ });
871
+ StateChangeCallbacks.current.forEach((callback) => {
872
+ callback(next);
873
+ });
874
+ return next;
875
+ });
876
+ }, []);
877
+ const removeExtValue = useCallback4((key) => {
878
+ setUserState((prev) => {
879
+ if (!prev.ext || !(key in prev.ext)) {
880
+ return prev;
881
+ }
882
+ const nextExt = __spreadValues({}, prev.ext);
883
+ delete nextExt[key];
884
+ const next = __spreadProps(__spreadValues({}, prev), {
885
+ ext: Object.keys(nextExt).length > 0 ? nextExt : void 0
886
+ });
887
+ StateChangeCallbacks.current.forEach((callback) => {
888
+ callback(next);
889
+ });
890
+ return next;
891
+ });
892
+ }, []);
825
893
  const getUserState = useCallback4(() => userRef.current, []);
826
894
  const onUserStateChange = useCallback4(
827
895
  (callback) => {
@@ -838,6 +906,8 @@ function UserContextProvider({ children }) {
838
906
  value: {
839
907
  user,
840
908
  setUser,
909
+ addExtValue,
910
+ removeExtValue,
841
911
  getUserState,
842
912
  onUserStateChange
843
913
  },
@@ -1382,6 +1452,10 @@ function useAomiRuntime() {
1382
1452
 
1383
1453
  // packages/react/src/handlers/wallet-handler.ts
1384
1454
  import { useCallback as useCallback6, useEffect as useEffect3, useRef as useRef6, useState as useState6 } from "react";
1455
+ import {
1456
+ normalizeEip712Payload,
1457
+ normalizeTxPayload
1458
+ } from "@aomi-labs/client";
1385
1459
 
1386
1460
  // packages/react/src/state/wallet-buffer.ts
1387
1461
  function createWalletBuffer() {
@@ -1414,68 +1488,6 @@ function getAll(buffer) {
1414
1488
  }
1415
1489
 
1416
1490
  // packages/react/src/handlers/wallet-handler.ts
1417
- function asRecord(value) {
1418
- if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
1419
- return value;
1420
- }
1421
- function getToolArgs(payload) {
1422
- const root = asRecord(payload);
1423
- const nestedArgs = asRecord(root == null ? void 0 : root.args);
1424
- return nestedArgs != null ? nestedArgs : root != null ? root : {};
1425
- }
1426
- function parseChainId(value) {
1427
- if (typeof value === "number" && Number.isFinite(value)) return value;
1428
- if (typeof value !== "string") return void 0;
1429
- const trimmed = value.trim();
1430
- if (!trimmed) return void 0;
1431
- if (trimmed.startsWith("0x")) {
1432
- const parsedHex = Number.parseInt(trimmed.slice(2), 16);
1433
- return Number.isFinite(parsedHex) ? parsedHex : void 0;
1434
- }
1435
- const parsed = Number.parseInt(trimmed, 10);
1436
- return Number.isFinite(parsed) ? parsed : void 0;
1437
- }
1438
- function normalizeTxPayload(payload) {
1439
- var _a, _b, _c;
1440
- const root = asRecord(payload);
1441
- const args = getToolArgs(payload);
1442
- const ctx = asRecord(root == null ? void 0 : root.ctx);
1443
- const to = typeof args.to === "string" ? args.to : void 0;
1444
- if (!to) return null;
1445
- const valueRaw = args.value;
1446
- const value = typeof valueRaw === "string" ? valueRaw : typeof valueRaw === "number" && Number.isFinite(valueRaw) ? String(Math.trunc(valueRaw)) : void 0;
1447
- const data = typeof args.data === "string" ? args.data : void 0;
1448
- const chainId = (_c = (_b = (_a = parseChainId(args.chainId)) != null ? _a : parseChainId(args.chain_id)) != null ? _b : parseChainId(ctx == null ? void 0 : ctx.user_chain_id)) != null ? _c : parseChainId(ctx == null ? void 0 : ctx.userChainId);
1449
- return {
1450
- to,
1451
- value,
1452
- data,
1453
- chainId
1454
- };
1455
- }
1456
- function normalizeEip712Payload(payload) {
1457
- var _a;
1458
- const args = getToolArgs(payload);
1459
- const typedDataRaw = (_a = args.typed_data) != null ? _a : args.typedData;
1460
- let typedData;
1461
- if (typeof typedDataRaw === "string") {
1462
- try {
1463
- const parsed = JSON.parse(typedDataRaw);
1464
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1465
- typedData = parsed;
1466
- }
1467
- } catch (e) {
1468
- typedData = void 0;
1469
- }
1470
- } else if (typedDataRaw && typeof typedDataRaw === "object" && !Array.isArray(typedDataRaw)) {
1471
- typedData = typedDataRaw;
1472
- }
1473
- const description = typeof args.description === "string" ? args.description : void 0;
1474
- return {
1475
- typed_data: typedData,
1476
- description
1477
- };
1478
- }
1479
1491
  function useWalletHandler({
1480
1492
  sessionId,
1481
1493
  onRequestComplete
@@ -1603,7 +1615,7 @@ function AomiRuntimeCore({
1603
1615
  const notificationContext = useNotification();
1604
1616
  const { dispatchInboundSystem: dispatchSystemEvents } = eventContext;
1605
1617
  const { user, onUserStateChange, getUserState } = useUser();
1606
- const { getControlState, getCurrentThreadControl } = useControl();
1618
+ const { getControlState, getCurrentThreadApp } = useControl();
1607
1619
  const {
1608
1620
  backendStateRef,
1609
1621
  polling,
@@ -1616,28 +1628,43 @@ function AomiRuntimeCore({
1616
1628
  onSyncEvents: dispatchSystemEvents,
1617
1629
  getPublicKey: () => getUserState().address,
1618
1630
  getUserState,
1619
- getApp: () => {
1620
- var _a, _b;
1621
- return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
1622
- },
1631
+ getApp: getCurrentThreadApp,
1623
1632
  getApiKey: () => getControlState().apiKey
1624
1633
  });
1634
+ const walletSnapshot = useCallback7(
1635
+ (nextUser) => ({
1636
+ address: nextUser.address,
1637
+ chainId: nextUser.chainId,
1638
+ isConnected: nextUser.isConnected,
1639
+ ensName: nextUser.ensName
1640
+ }),
1641
+ [getUserState]
1642
+ );
1643
+ const lastWalletStateRef = useRef7(walletSnapshot(getUserState()));
1625
1644
  useEffect4(() => {
1645
+ lastWalletStateRef.current = walletSnapshot(getUserState());
1626
1646
  const unsubscribe = onUserStateChange(async (newUser) => {
1647
+ const nextWalletState = walletSnapshot(newUser);
1648
+ const prevWalletState = lastWalletStateRef.current;
1649
+ if (prevWalletState.address === nextWalletState.address && prevWalletState.chainId === nextWalletState.chainId && prevWalletState.isConnected === nextWalletState.isConnected && prevWalletState.ensName === nextWalletState.ensName) {
1650
+ return;
1651
+ }
1652
+ lastWalletStateRef.current = nextWalletState;
1627
1653
  const sessionId = threadContext.currentThreadId;
1628
1654
  const message = JSON.stringify({
1629
1655
  type: "wallet:state_changed",
1630
- payload: {
1631
- address: newUser.address,
1632
- chainId: newUser.chainId,
1633
- isConnected: newUser.isConnected,
1634
- ensName: newUser.ensName
1635
- }
1656
+ payload: nextWalletState
1636
1657
  });
1637
1658
  await aomiClientRef.current.sendSystemMessage(sessionId, message);
1638
1659
  });
1639
1660
  return unsubscribe;
1640
- }, [onUserStateChange, aomiClientRef, threadContext.currentThreadId]);
1661
+ }, [
1662
+ onUserStateChange,
1663
+ aomiClientRef,
1664
+ threadContext.currentThreadId,
1665
+ getUserState,
1666
+ walletSnapshot
1667
+ ]);
1641
1668
  const threadContextRef = useRef7(threadContext);
1642
1669
  threadContextRef.current = threadContext;
1643
1670
  const currentThreadIdRef = useRef7(threadContext.currentThreadId);
@@ -1733,10 +1760,7 @@ function AomiRuntimeCore({
1733
1760
  polling,
1734
1761
  userAddress: user.address,
1735
1762
  setIsRunning,
1736
- getApp: () => {
1737
- var _a, _b;
1738
- return (_b = (_a = getCurrentThreadControl().app) != null ? _a : getControlState().defaultApp) != null ? _b : "default";
1739
- },
1763
+ getApp: getCurrentThreadApp,
1740
1764
  getApiKey: () => getControlState().apiKey,
1741
1765
  getUserState
1742
1766
  }),
@@ -1750,6 +1774,7 @@ function AomiRuntimeCore({
1750
1774
  threadContext.currentThreadId,
1751
1775
  threadContext.allThreadsMetadata,
1752
1776
  getControlState,
1777
+ getCurrentThreadApp,
1753
1778
  getUserState
1754
1779
  ]
1755
1780
  );
@@ -1895,6 +1920,8 @@ function AomiRuntimeCore({
1895
1920
  user: userContext.user,
1896
1921
  getUserState: userContext.getUserState,
1897
1922
  setUser: userContext.setUser,
1923
+ addExtValue: userContext.addExtValue,
1924
+ removeExtValue: userContext.removeExtValue,
1898
1925
  onUserStateChange: userContext.onUserStateChange,
1899
1926
  // Thread API
1900
1927
  currentThreadId: threadContext.currentThreadId,
@@ -2040,6 +2067,7 @@ export {
2040
2067
  getChainInfo,
2041
2068
  getNetworkName,
2042
2069
  initThreadControl,
2070
+ toViemSignTypedDataArgs,
2043
2071
  useAomiRuntime,
2044
2072
  useControl,
2045
2073
  useCurrentThreadMessages,